@kapeta/local-cluster-service 0.0.0-96f91ef
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +25 -0
- package/.github/workflows/check-license.yml +17 -0
- package/.github/workflows/main.yml +26 -0
- package/.prettierignore +4 -0
- package/.vscode/launch.json +19 -0
- package/CHANGELOG.md +920 -0
- package/LICENSE +38 -0
- package/README.md +36 -0
- package/definitions.d.ts +35 -0
- package/dist/cjs/index.d.ts +34 -0
- package/dist/cjs/index.js +263 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/RepositoryWatcher.d.ts +30 -0
- package/dist/cjs/src/RepositoryWatcher.js +332 -0
- package/dist/cjs/src/ai/aiClient.d.ts +20 -0
- package/dist/cjs/src/ai/aiClient.js +74 -0
- package/dist/cjs/src/ai/routes.d.ts +7 -0
- package/dist/cjs/src/ai/routes.js +37 -0
- package/dist/cjs/src/ai/transform.d.ts +11 -0
- package/dist/cjs/src/ai/transform.js +239 -0
- package/dist/cjs/src/ai/types.d.ts +40 -0
- package/dist/cjs/src/ai/types.js +2 -0
- package/dist/cjs/src/api.d.ts +7 -0
- package/dist/cjs/src/api.js +29 -0
- package/dist/cjs/src/assetManager.d.ts +41 -0
- package/dist/cjs/src/assetManager.js +274 -0
- package/dist/cjs/src/assets/routes.d.ts +7 -0
- package/dist/cjs/src/assets/routes.js +165 -0
- package/dist/cjs/src/attachments/routes.d.ts +7 -0
- package/dist/cjs/src/attachments/routes.js +72 -0
- package/dist/cjs/src/authManager.d.ts +16 -0
- package/dist/cjs/src/authManager.js +64 -0
- package/dist/cjs/src/cacheManager.d.ts +20 -0
- package/dist/cjs/src/cacheManager.js +51 -0
- package/dist/cjs/src/clusterService.d.ts +44 -0
- package/dist/cjs/src/clusterService.js +120 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +14 -0
- package/dist/cjs/src/codeGeneratorManager.js +93 -0
- package/dist/cjs/src/config/routes.d.ts +7 -0
- package/dist/cjs/src/config/routes.js +160 -0
- package/dist/cjs/src/configManager.d.ts +42 -0
- package/dist/cjs/src/configManager.js +136 -0
- package/dist/cjs/src/containerManager.d.ts +148 -0
- package/dist/cjs/src/containerManager.js +958 -0
- package/dist/cjs/src/definitionsManager.d.ts +20 -0
- package/dist/cjs/src/definitionsManager.js +171 -0
- package/dist/cjs/src/filesystem/routes.d.ts +7 -0
- package/dist/cjs/src/filesystem/routes.js +105 -0
- package/dist/cjs/src/filesystemManager.d.ts +27 -0
- package/dist/cjs/src/filesystemManager.js +118 -0
- package/dist/cjs/src/identities/routes.d.ts +7 -0
- package/dist/cjs/src/identities/routes.js +37 -0
- package/dist/cjs/src/instanceManager.d.ts +69 -0
- package/dist/cjs/src/instanceManager.js +910 -0
- package/dist/cjs/src/instances/routes.d.ts +7 -0
- package/dist/cjs/src/instances/routes.js +179 -0
- package/dist/cjs/src/middleware/cors.d.ts +6 -0
- package/dist/cjs/src/middleware/cors.js +14 -0
- package/dist/cjs/src/middleware/kapeta.d.ts +15 -0
- package/dist/cjs/src/middleware/kapeta.js +28 -0
- package/dist/cjs/src/middleware/stringBody.d.ts +9 -0
- package/dist/cjs/src/middleware/stringBody.js +18 -0
- package/dist/cjs/src/networkManager.d.ts +37 -0
- package/dist/cjs/src/networkManager.js +119 -0
- package/dist/cjs/src/operatorManager.d.ts +41 -0
- package/dist/cjs/src/operatorManager.js +211 -0
- package/dist/cjs/src/progressListener.d.ts +31 -0
- package/dist/cjs/src/progressListener.js +133 -0
- package/dist/cjs/src/providerManager.d.ts +11 -0
- package/dist/cjs/src/providerManager.js +84 -0
- package/dist/cjs/src/providers/routes.d.ts +7 -0
- package/dist/cjs/src/providers/routes.js +46 -0
- package/dist/cjs/src/proxy/routes.d.ts +7 -0
- package/dist/cjs/src/proxy/routes.js +115 -0
- package/dist/cjs/src/proxy/types/rest.d.ts +10 -0
- package/dist/cjs/src/proxy/types/rest.js +123 -0
- package/dist/cjs/src/proxy/types/web.d.ts +8 -0
- package/dist/cjs/src/proxy/types/web.js +61 -0
- package/dist/cjs/src/repositoryManager.d.ts +35 -0
- package/dist/cjs/src/repositoryManager.js +247 -0
- package/dist/cjs/src/serviceManager.d.ts +36 -0
- package/dist/cjs/src/serviceManager.js +106 -0
- package/dist/cjs/src/socketManager.d.ts +32 -0
- package/dist/cjs/src/socketManager.js +125 -0
- package/dist/cjs/src/storageService.d.ts +21 -0
- package/dist/cjs/src/storageService.js +81 -0
- package/dist/cjs/src/taskManager.d.ts +70 -0
- package/dist/cjs/src/taskManager.js +181 -0
- package/dist/cjs/src/tasks/routes.d.ts +7 -0
- package/dist/cjs/src/tasks/routes.js +39 -0
- package/dist/cjs/src/traffic/routes.d.ts +7 -0
- package/dist/cjs/src/traffic/routes.js +22 -0
- package/dist/cjs/src/types.d.ts +99 -0
- package/dist/cjs/src/types.js +39 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +28 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +432 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.d.ts +15 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.js +136 -0
- package/dist/cjs/src/utils/InternalConfigProvider.d.ts +38 -0
- package/dist/cjs/src/utils/InternalConfigProvider.js +146 -0
- package/dist/cjs/src/utils/LogData.d.ts +23 -0
- package/dist/cjs/src/utils/LogData.js +46 -0
- package/dist/cjs/src/utils/commandLineUtils.d.ts +8 -0
- package/dist/cjs/src/utils/commandLineUtils.js +39 -0
- package/dist/cjs/src/utils/pathTemplateParser.d.ts +30 -0
- package/dist/cjs/src/utils/pathTemplateParser.js +135 -0
- package/dist/cjs/src/utils/utils.d.ts +40 -0
- package/dist/cjs/src/utils/utils.js +148 -0
- package/dist/cjs/start.d.ts +5 -0
- package/dist/cjs/start.js +17 -0
- package/dist/cjs/test/proxy/types/rest.test.d.ts +5 -0
- package/dist/cjs/test/proxy/types/rest.test.js +48 -0
- package/dist/cjs/test/utils/pathTemplateParser.test.d.ts +5 -0
- package/dist/cjs/test/utils/pathTemplateParser.test.js +27 -0
- package/dist/esm/index.d.ts +34 -0
- package/dist/esm/index.js +263 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/src/RepositoryWatcher.d.ts +30 -0
- package/dist/esm/src/RepositoryWatcher.js +332 -0
- package/dist/esm/src/ai/aiClient.d.ts +20 -0
- package/dist/esm/src/ai/aiClient.js +74 -0
- package/dist/esm/src/ai/routes.d.ts +7 -0
- package/dist/esm/src/ai/routes.js +37 -0
- package/dist/esm/src/ai/transform.d.ts +11 -0
- package/dist/esm/src/ai/transform.js +239 -0
- package/dist/esm/src/ai/types.d.ts +40 -0
- package/dist/esm/src/ai/types.js +2 -0
- package/dist/esm/src/api.d.ts +7 -0
- package/dist/esm/src/api.js +29 -0
- package/dist/esm/src/assetManager.d.ts +41 -0
- package/dist/esm/src/assetManager.js +274 -0
- package/dist/esm/src/assets/routes.d.ts +7 -0
- package/dist/esm/src/assets/routes.js +165 -0
- package/dist/esm/src/attachments/routes.d.ts +7 -0
- package/dist/esm/src/attachments/routes.js +72 -0
- package/dist/esm/src/authManager.d.ts +16 -0
- package/dist/esm/src/authManager.js +64 -0
- package/dist/esm/src/cacheManager.d.ts +20 -0
- package/dist/esm/src/cacheManager.js +51 -0
- package/dist/esm/src/clusterService.d.ts +44 -0
- package/dist/esm/src/clusterService.js +120 -0
- package/dist/esm/src/codeGeneratorManager.d.ts +14 -0
- package/dist/esm/src/codeGeneratorManager.js +93 -0
- package/dist/esm/src/config/routes.d.ts +7 -0
- package/dist/esm/src/config/routes.js +160 -0
- package/dist/esm/src/configManager.d.ts +42 -0
- package/dist/esm/src/configManager.js +136 -0
- package/dist/esm/src/containerManager.d.ts +148 -0
- package/dist/esm/src/containerManager.js +958 -0
- package/dist/esm/src/definitionsManager.d.ts +20 -0
- package/dist/esm/src/definitionsManager.js +171 -0
- package/dist/esm/src/filesystem/routes.d.ts +7 -0
- package/dist/esm/src/filesystem/routes.js +105 -0
- package/dist/esm/src/filesystemManager.d.ts +27 -0
- package/dist/esm/src/filesystemManager.js +118 -0
- package/dist/esm/src/identities/routes.d.ts +7 -0
- package/dist/esm/src/identities/routes.js +37 -0
- package/dist/esm/src/instanceManager.d.ts +69 -0
- package/dist/esm/src/instanceManager.js +910 -0
- package/dist/esm/src/instances/routes.d.ts +7 -0
- package/dist/esm/src/instances/routes.js +179 -0
- package/dist/esm/src/middleware/cors.d.ts +6 -0
- package/dist/esm/src/middleware/cors.js +14 -0
- package/dist/esm/src/middleware/kapeta.d.ts +15 -0
- package/dist/esm/src/middleware/kapeta.js +28 -0
- package/dist/esm/src/middleware/stringBody.d.ts +9 -0
- package/dist/esm/src/middleware/stringBody.js +18 -0
- package/dist/esm/src/networkManager.d.ts +37 -0
- package/dist/esm/src/networkManager.js +119 -0
- package/dist/esm/src/operatorManager.d.ts +41 -0
- package/dist/esm/src/operatorManager.js +211 -0
- package/dist/esm/src/progressListener.d.ts +31 -0
- package/dist/esm/src/progressListener.js +133 -0
- package/dist/esm/src/providerManager.d.ts +11 -0
- package/dist/esm/src/providerManager.js +84 -0
- package/dist/esm/src/providers/routes.d.ts +7 -0
- package/dist/esm/src/providers/routes.js +46 -0
- package/dist/esm/src/proxy/routes.d.ts +7 -0
- package/dist/esm/src/proxy/routes.js +115 -0
- package/dist/esm/src/proxy/types/rest.d.ts +10 -0
- package/dist/esm/src/proxy/types/rest.js +123 -0
- package/dist/esm/src/proxy/types/web.d.ts +8 -0
- package/dist/esm/src/proxy/types/web.js +61 -0
- package/dist/esm/src/repositoryManager.d.ts +35 -0
- package/dist/esm/src/repositoryManager.js +247 -0
- package/dist/esm/src/serviceManager.d.ts +36 -0
- package/dist/esm/src/serviceManager.js +106 -0
- package/dist/esm/src/socketManager.d.ts +32 -0
- package/dist/esm/src/socketManager.js +125 -0
- package/dist/esm/src/storageService.d.ts +21 -0
- package/dist/esm/src/storageService.js +81 -0
- package/dist/esm/src/taskManager.d.ts +70 -0
- package/dist/esm/src/taskManager.js +181 -0
- package/dist/esm/src/tasks/routes.d.ts +7 -0
- package/dist/esm/src/tasks/routes.js +39 -0
- package/dist/esm/src/traffic/routes.d.ts +7 -0
- package/dist/esm/src/traffic/routes.js +22 -0
- package/dist/esm/src/types.d.ts +99 -0
- package/dist/esm/src/types.js +39 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +28 -0
- package/dist/esm/src/utils/BlockInstanceRunner.js +432 -0
- package/dist/esm/src/utils/DefaultProviderInstaller.d.ts +15 -0
- package/dist/esm/src/utils/DefaultProviderInstaller.js +136 -0
- package/dist/esm/src/utils/InternalConfigProvider.d.ts +38 -0
- package/dist/esm/src/utils/InternalConfigProvider.js +146 -0
- package/dist/esm/src/utils/LogData.d.ts +23 -0
- package/dist/esm/src/utils/LogData.js +46 -0
- package/dist/esm/src/utils/commandLineUtils.d.ts +8 -0
- package/dist/esm/src/utils/commandLineUtils.js +39 -0
- package/dist/esm/src/utils/pathTemplateParser.d.ts +30 -0
- package/dist/esm/src/utils/pathTemplateParser.js +135 -0
- package/dist/esm/src/utils/utils.d.ts +40 -0
- package/dist/esm/src/utils/utils.js +148 -0
- package/dist/esm/start.d.ts +5 -0
- package/dist/esm/start.js +17 -0
- package/dist/esm/test/proxy/types/rest.test.d.ts +5 -0
- package/dist/esm/test/proxy/types/rest.test.js +48 -0
- package/dist/esm/test/utils/pathTemplateParser.test.d.ts +5 -0
- package/dist/esm/test/utils/pathTemplateParser.test.js +27 -0
- package/index.ts +280 -0
- package/jest.config.js +8 -0
- package/package.json +134 -0
- package/src/RepositoryWatcher.ts +363 -0
- package/src/ai/aiClient.ts +93 -0
- package/src/ai/routes.ts +39 -0
- package/src/ai/transform.ts +275 -0
- package/src/ai/types.ts +45 -0
- package/src/api.ts +32 -0
- package/src/assetManager.ts +355 -0
- package/src/assets/routes.ts +183 -0
- package/src/attachments/routes.ts +79 -0
- package/src/authManager.ts +67 -0
- package/src/cacheManager.ts +59 -0
- package/src/clusterService.ts +142 -0
- package/src/codeGeneratorManager.ts +109 -0
- package/src/config/routes.ts +201 -0
- package/src/configManager.ts +180 -0
- package/src/containerManager.ts +1178 -0
- package/src/definitionsManager.ts +212 -0
- package/src/filesystem/routes.ts +123 -0
- package/src/filesystemManager.ts +133 -0
- package/src/identities/routes.ts +38 -0
- package/src/instanceManager.ts +1160 -0
- package/src/instances/routes.ts +203 -0
- package/src/middleware/cors.ts +14 -0
- package/src/middleware/kapeta.ts +41 -0
- package/src/middleware/stringBody.ts +21 -0
- package/src/networkManager.ts +148 -0
- package/src/operatorManager.ts +294 -0
- package/src/progressListener.ts +151 -0
- package/src/providerManager.ts +97 -0
- package/src/providers/routes.ts +51 -0
- package/src/proxy/routes.ts +153 -0
- package/src/proxy/types/rest.ts +172 -0
- package/src/proxy/types/web.ts +70 -0
- package/src/repositoryManager.ts +291 -0
- package/src/serviceManager.ts +133 -0
- package/src/socketManager.ts +138 -0
- package/src/storageService.ts +97 -0
- package/src/taskManager.ts +247 -0
- package/src/tasks/routes.ts +43 -0
- package/src/traffic/routes.ts +23 -0
- package/src/types.ts +112 -0
- package/src/utils/BlockInstanceRunner.ts +577 -0
- package/src/utils/DefaultProviderInstaller.ts +150 -0
- package/src/utils/InternalConfigProvider.ts +214 -0
- package/src/utils/LogData.ts +50 -0
- package/src/utils/commandLineUtils.ts +45 -0
- package/src/utils/pathTemplateParser.ts +157 -0
- package/src/utils/utils.ts +155 -0
- package/start.ts +14 -0
- package/test/proxy/types/rest.test.ts +54 -0
- package/test/utils/pathTemplateParser.test.ts +29 -0
- package/tsconfig.json +15 -0
@@ -0,0 +1,183 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import Router from 'express-promise-router';
|
7
|
+
import { Request, Response } from 'express';
|
8
|
+
import YAML from 'yaml';
|
9
|
+
import { assetManager } from '../assetManager';
|
10
|
+
|
11
|
+
import { corsHandler } from '../middleware/cors';
|
12
|
+
|
13
|
+
import { stringBody, StringBodyRequest } from '../middleware/stringBody';
|
14
|
+
import { definitionsManager } from '../definitionsManager';
|
15
|
+
|
16
|
+
function parseBody(req: StringBodyRequest) {
|
17
|
+
switch (req.headers['content-type']) {
|
18
|
+
case 'application/json':
|
19
|
+
case 'application/x-json':
|
20
|
+
case 'text/json':
|
21
|
+
return JSON.parse(req.stringBody ?? '{}');
|
22
|
+
|
23
|
+
case 'application/yaml':
|
24
|
+
case 'application/x-yaml':
|
25
|
+
case 'text/yaml':
|
26
|
+
case 'text/x-yaml':
|
27
|
+
default:
|
28
|
+
return YAML.parse(req.stringBody ?? '{}');
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
const router = Router();
|
33
|
+
|
34
|
+
router.use('/', corsHandler);
|
35
|
+
router.use('/', stringBody);
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Get all local assets available
|
39
|
+
*/
|
40
|
+
router.get('/', async (req: Request, res: Response) => {
|
41
|
+
res.send(await assetManager.getAssets([]));
|
42
|
+
});
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Get single asset
|
46
|
+
*/
|
47
|
+
router.get('/read', async (req: Request, res: Response) => {
|
48
|
+
if (!req.query.ref) {
|
49
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
50
|
+
return;
|
51
|
+
}
|
52
|
+
|
53
|
+
const ensure = req.query.ensure !== 'false';
|
54
|
+
|
55
|
+
try {
|
56
|
+
const asset = await assetManager.getAsset(req.query.ref as string, true, ensure);
|
57
|
+
if (asset) {
|
58
|
+
res.send(asset);
|
59
|
+
} else {
|
60
|
+
res.status(404).send({ error: 'Asset not found' });
|
61
|
+
}
|
62
|
+
} catch (err: any) {
|
63
|
+
res.status(400).send({ error: err.message });
|
64
|
+
}
|
65
|
+
});
|
66
|
+
|
67
|
+
/**
|
68
|
+
* Get all versions for asset name
|
69
|
+
*/
|
70
|
+
router.get('/versions', async (req: Request, res: Response) => {
|
71
|
+
if (!req.query.ref) {
|
72
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
|
76
|
+
const ensure = req.query.ensure !== 'false';
|
77
|
+
|
78
|
+
try {
|
79
|
+
const versions = await definitionsManager.getVersions(req.query.ref as string);
|
80
|
+
if (versions) {
|
81
|
+
res.send(versions);
|
82
|
+
} else {
|
83
|
+
res.status(404).send({ error: 'Asset not found' });
|
84
|
+
}
|
85
|
+
} catch (err: any) {
|
86
|
+
res.status(400).send({ error: err.message });
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Creates a new local file and registers it as an asset
|
92
|
+
*/
|
93
|
+
router.post('/create', async (req: Request, res: Response) => {
|
94
|
+
if (!req.query.path) {
|
95
|
+
res.status(400).send({ error: 'Query parameter "path" is missing' });
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
|
99
|
+
const content = parseBody(req);
|
100
|
+
|
101
|
+
try {
|
102
|
+
const assets = await assetManager.createAsset(req.query.path as string, content, 'user');
|
103
|
+
|
104
|
+
res.status(200).send(assets);
|
105
|
+
} catch (err: any) {
|
106
|
+
console.log('Failed while creating asset', req.query.path, err.message);
|
107
|
+
res.status(400).send({ error: err.message });
|
108
|
+
}
|
109
|
+
});
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Updates reference with new content
|
113
|
+
*/
|
114
|
+
router.put('/update', async (req: Request, res: Response) => {
|
115
|
+
if (!req.query.ref) {
|
116
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
|
120
|
+
const content = parseBody(req);
|
121
|
+
|
122
|
+
try {
|
123
|
+
await assetManager.updateAsset(req.query.ref as string, content, 'user');
|
124
|
+
|
125
|
+
res.sendStatus(204);
|
126
|
+
} catch (err: any) {
|
127
|
+
console.log('Failed while updating asset', req.query.ref, err.message);
|
128
|
+
res.status(400).send({ error: err.message });
|
129
|
+
}
|
130
|
+
});
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Unregisters an asset (doesn't delete the asset)
|
134
|
+
*/
|
135
|
+
router.delete('/', async (req: Request, res: Response) => {
|
136
|
+
if (!req.query.ref) {
|
137
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
138
|
+
return;
|
139
|
+
}
|
140
|
+
|
141
|
+
try {
|
142
|
+
await assetManager.unregisterAsset(req.query.ref as string);
|
143
|
+
|
144
|
+
res.status(204).send();
|
145
|
+
} catch (err: any) {
|
146
|
+
res.status(400).send({ error: err.message });
|
147
|
+
}
|
148
|
+
});
|
149
|
+
|
150
|
+
/**
|
151
|
+
* Registers an existing file as an asset
|
152
|
+
*/
|
153
|
+
router.put('/import', async (req: Request, res: Response) => {
|
154
|
+
if (!req.query.ref) {
|
155
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
|
159
|
+
try {
|
160
|
+
const assets = await assetManager.importFile(req.query.ref as string);
|
161
|
+
|
162
|
+
res.status(200).send(assets);
|
163
|
+
} catch (err: any) {
|
164
|
+
res.status(400).send({ error: err.message });
|
165
|
+
}
|
166
|
+
});
|
167
|
+
|
168
|
+
router.put('/install', async (req: Request, res: Response) => {
|
169
|
+
if (!req.query.ref) {
|
170
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
171
|
+
return;
|
172
|
+
}
|
173
|
+
|
174
|
+
try {
|
175
|
+
const tasks = await assetManager.installAsset(req.query.ref as string, !!req.query.wait);
|
176
|
+
const taskIds = tasks?.map((t) => t.id) ?? [];
|
177
|
+
res.status(200).send(taskIds);
|
178
|
+
} catch (err: any) {
|
179
|
+
res.status(400).send({ error: err.message });
|
180
|
+
}
|
181
|
+
});
|
182
|
+
|
183
|
+
export default router;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import Router from 'express-promise-router';
|
7
|
+
import { KapetaAPI } from '@kapeta/nodejs-api-client';
|
8
|
+
|
9
|
+
import { corsHandler } from '../middleware/cors';
|
10
|
+
import { Request, Response } from 'express';
|
11
|
+
import { storageService } from '../storageService';
|
12
|
+
|
13
|
+
const router = Router();
|
14
|
+
const api = new KapetaAPI();
|
15
|
+
|
16
|
+
const DEFAULT_REGISTRY_BASE = 'https://registry.kapeta.com';
|
17
|
+
|
18
|
+
function getBaseUrl() {
|
19
|
+
const endpoint = storageService.get('endpoints', 'registry', DEFAULT_REGISTRY_BASE);
|
20
|
+
return `${endpoint}/v1/registry`;
|
21
|
+
}
|
22
|
+
|
23
|
+
router.use('/', corsHandler);
|
24
|
+
|
25
|
+
router.put('/:handle/:name', async (req: Request, res: Response) => {
|
26
|
+
if (!api.hasToken()) {
|
27
|
+
res.status(401).send({
|
28
|
+
status: 401,
|
29
|
+
error: 'Unauthorized',
|
30
|
+
});
|
31
|
+
return;
|
32
|
+
}
|
33
|
+
|
34
|
+
const endpoint = getBaseUrl();
|
35
|
+
if (!req.headers['content-type']) {
|
36
|
+
res.status(400).send({
|
37
|
+
status: 400,
|
38
|
+
error: 'Missing content-type header',
|
39
|
+
});
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
|
43
|
+
if (!req.headers['content-length']) {
|
44
|
+
res.status(400).send({
|
45
|
+
status: 400,
|
46
|
+
error: 'Missing content-length header',
|
47
|
+
});
|
48
|
+
return;
|
49
|
+
}
|
50
|
+
|
51
|
+
if (!req.headers['content-disposition']) {
|
52
|
+
res.status(400).send({
|
53
|
+
status: 400,
|
54
|
+
error: 'Missing content-disposition header',
|
55
|
+
});
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
try {
|
60
|
+
const { handle, name } = req.params;
|
61
|
+
const url = `${endpoint}/${handle}/${name}/attachments`;
|
62
|
+
const result = await api.send<{ url: string }>({
|
63
|
+
method: 'PUT',
|
64
|
+
url,
|
65
|
+
auth: true,
|
66
|
+
headers: {
|
67
|
+
'content-type': req.headers['content-type'],
|
68
|
+
'content-length': req.headers['content-length'],
|
69
|
+
'content-disposition': req.headers['content-disposition'],
|
70
|
+
},
|
71
|
+
body: req,
|
72
|
+
});
|
73
|
+
res.send(result);
|
74
|
+
} catch (e: any) {
|
75
|
+
res.status(e.status ?? 500).send(e);
|
76
|
+
}
|
77
|
+
});
|
78
|
+
|
79
|
+
export default router;
|
@@ -0,0 +1,67 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { EventEmitter } from 'node:events';
|
7
|
+
import Path from 'node:path';
|
8
|
+
import chokidar, { FSWatcher } from 'chokidar';
|
9
|
+
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
10
|
+
import { WatchEventName } from './types';
|
11
|
+
import { definitionsManager } from './definitionsManager';
|
12
|
+
import { KapetaAPI } from '@kapeta/nodejs-api-client';
|
13
|
+
import { socketManager } from './socketManager';
|
14
|
+
|
15
|
+
class AuthManager extends EventEmitter {
|
16
|
+
private watcher?: FSWatcher;
|
17
|
+
|
18
|
+
private hadToken: boolean;
|
19
|
+
|
20
|
+
constructor() {
|
21
|
+
super();
|
22
|
+
this.hadToken = this.hasToken();
|
23
|
+
}
|
24
|
+
|
25
|
+
public listenForChanges() {
|
26
|
+
const parentDir = Path.dirname(ClusterConfiguration.getKapetaBasedir());
|
27
|
+
//We watch the parent dir to catch changes to the base dir itself
|
28
|
+
this.watcher = chokidar.watch(parentDir, {
|
29
|
+
followSymlinks: false,
|
30
|
+
ignorePermissionErrors: true,
|
31
|
+
disableGlobbing: true,
|
32
|
+
persistent: true,
|
33
|
+
ignoreInitial: true,
|
34
|
+
depth: 1,
|
35
|
+
ignored: (path) => {
|
36
|
+
return !path.startsWith(ClusterConfiguration.getKapetaBasedir());
|
37
|
+
},
|
38
|
+
});
|
39
|
+
this.watcher.add(ClusterConfiguration.getKapetaBasedir());
|
40
|
+
this.watcher.on('all', this.handleFileChange.bind(this));
|
41
|
+
this.watcher.on('error', (error) => {
|
42
|
+
console.log('Error watching repository', error);
|
43
|
+
});
|
44
|
+
this.watcher.on('ready', () => {
|
45
|
+
console.log('Watching for auth changes: %s', ClusterConfiguration.getKapetaBasedir());
|
46
|
+
});
|
47
|
+
}
|
48
|
+
|
49
|
+
private hasToken() {
|
50
|
+
const api = new KapetaAPI();
|
51
|
+
return api.hasToken();
|
52
|
+
}
|
53
|
+
|
54
|
+
private async handleFileChange(eventName: WatchEventName, path: string) {
|
55
|
+
const hasTokenNow = this.hasToken();
|
56
|
+
if (this.hadToken !== hasTokenNow) {
|
57
|
+
socketManager.emitGlobal('auth-change', {});
|
58
|
+
if (hasTokenNow) {
|
59
|
+
// Clear the cache in case we need to rewrite the sample plan
|
60
|
+
definitionsManager.clearCache();
|
61
|
+
}
|
62
|
+
this.hadToken = hasTokenNow;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
export const authManager = new AuthManager();
|
@@ -0,0 +1,59 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import NodeCache from 'node-cache';
|
7
|
+
|
8
|
+
const DEFAULT_CACHE_TTL = 60 * 1000; // 1 min
|
9
|
+
export interface CacheEntry<T = any> {
|
10
|
+
expires: number;
|
11
|
+
data: T;
|
12
|
+
}
|
13
|
+
export class CacheManager {
|
14
|
+
private cache: NodeCache = new NodeCache();
|
15
|
+
|
16
|
+
public flush() {
|
17
|
+
this.cache.flushAll();
|
18
|
+
}
|
19
|
+
|
20
|
+
public doCached<T>(key: string, getter: () => T, ttl = DEFAULT_CACHE_TTL) {
|
21
|
+
const data = this.cache.get<T>(key);
|
22
|
+
if (data !== undefined) {
|
23
|
+
return data;
|
24
|
+
}
|
25
|
+
const result = getter();
|
26
|
+
this.cache.set(key, result, ttl);
|
27
|
+
return result;
|
28
|
+
}
|
29
|
+
|
30
|
+
public get<T>(key: string): T | undefined {
|
31
|
+
return this.cache.get<T>(key);
|
32
|
+
}
|
33
|
+
|
34
|
+
public set<T>(key: string, data: T, ttl = DEFAULT_CACHE_TTL) {
|
35
|
+
this.cache.set(key, data, ttl);
|
36
|
+
}
|
37
|
+
|
38
|
+
public has(key: string): boolean {
|
39
|
+
return this.cache.has(key);
|
40
|
+
}
|
41
|
+
|
42
|
+
public remove(key: string) {
|
43
|
+
return this.cache.del(key);
|
44
|
+
}
|
45
|
+
|
46
|
+
public removePrefix(key: string) {
|
47
|
+
const keys = this.cache.keys();
|
48
|
+
for (const k of keys) {
|
49
|
+
if (k.startsWith(key)) {
|
50
|
+
this.remove(k);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
export const cacheManager = new CacheManager();
|
57
|
+
|
58
|
+
export const doCached = <T>(key: string, getter: () => T, ttl = DEFAULT_CACHE_TTL) =>
|
59
|
+
cacheManager.doCached(key, getter, ttl);
|
@@ -0,0 +1,142 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { normalizeKapetaUri } from '@kapeta/nodejs-utils';
|
7
|
+
|
8
|
+
const net = require('net');
|
9
|
+
const DEFAULT_SERVER_PORT = 35100;
|
10
|
+
const DEFAULT_START_PORT = 40000;
|
11
|
+
const DEFAULT_HOST = '127.0.0.1';
|
12
|
+
|
13
|
+
class ClusterService {
|
14
|
+
private _port: number;
|
15
|
+
private _currentPort: number;
|
16
|
+
private _initialized: boolean;
|
17
|
+
private _reservedPorts: number[];
|
18
|
+
private _host: string;
|
19
|
+
|
20
|
+
constructor() {
|
21
|
+
this._port = DEFAULT_SERVER_PORT;
|
22
|
+
this._currentPort = DEFAULT_START_PORT;
|
23
|
+
this._initialized = false;
|
24
|
+
this._reservedPorts = [];
|
25
|
+
this._host = DEFAULT_HOST;
|
26
|
+
}
|
27
|
+
|
28
|
+
reservePort(port: number | string) {
|
29
|
+
const intPort = parseInt(port as string);
|
30
|
+
if (this._reservedPorts.indexOf(intPort) > -1) {
|
31
|
+
throw new Error('Port already reserved: ' + intPort);
|
32
|
+
}
|
33
|
+
|
34
|
+
this._reservedPorts.push(intPort);
|
35
|
+
}
|
36
|
+
|
37
|
+
async init() {
|
38
|
+
if (this._initialized) {
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
|
42
|
+
this._initialized = true;
|
43
|
+
await this._findClusterServicePort();
|
44
|
+
}
|
45
|
+
|
46
|
+
async _findClusterServicePort() {
|
47
|
+
while (true) {
|
48
|
+
const isUsed = await this._checkIfPortIsUsed(this._port);
|
49
|
+
if (!isUsed) {
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
|
53
|
+
this._port++;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Gets next available port
|
59
|
+
* @return {Promise<number>}
|
60
|
+
*/
|
61
|
+
async getNextAvailablePort() {
|
62
|
+
while (true) {
|
63
|
+
while (this._reservedPorts.indexOf(this._currentPort) > -1) {
|
64
|
+
this._currentPort++;
|
65
|
+
}
|
66
|
+
|
67
|
+
const nextPort = this._currentPort++;
|
68
|
+
const isUsed = await this._checkIfPortIsUsed(nextPort);
|
69
|
+
if (!isUsed) {
|
70
|
+
return nextPort;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
_checkIfPortIsUsed(port: number, host: string = this._host) {
|
76
|
+
return new Promise((resolve, reject) => {
|
77
|
+
const server = net.createServer();
|
78
|
+
|
79
|
+
server.once('error', function (err: any) {
|
80
|
+
if (err.code === 'EADDRINUSE') {
|
81
|
+
server.close();
|
82
|
+
resolve(true);
|
83
|
+
return;
|
84
|
+
}
|
85
|
+
|
86
|
+
server.close();
|
87
|
+
reject(err);
|
88
|
+
});
|
89
|
+
|
90
|
+
server.once('listening', function () {
|
91
|
+
server.close();
|
92
|
+
resolve(false);
|
93
|
+
});
|
94
|
+
|
95
|
+
server.listen(port, host);
|
96
|
+
});
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* The port of this local cluster service itself
|
101
|
+
*/
|
102
|
+
getClusterServicePort() {
|
103
|
+
return this._port;
|
104
|
+
}
|
105
|
+
|
106
|
+
/*
|
107
|
+
*Gets the host name ( 127.0.0.1 ) on which Express JS is listening
|
108
|
+
*/
|
109
|
+
getClusterServiceHost() {
|
110
|
+
return this._host;
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Set the port to be used for this local service
|
115
|
+
* @param port
|
116
|
+
*/
|
117
|
+
setClusterServicePort(port: number) {
|
118
|
+
this._port = port;
|
119
|
+
}
|
120
|
+
|
121
|
+
setClusterServiceHost(host: string) {
|
122
|
+
this._host = host;
|
123
|
+
}
|
124
|
+
|
125
|
+
/**
|
126
|
+
* Gets that proxy path of a given request
|
127
|
+
*
|
128
|
+
* @param systemId
|
129
|
+
* @param consumerInstanceId
|
130
|
+
* @param consumerResourceName
|
131
|
+
* @param portType
|
132
|
+
* @return {string}
|
133
|
+
*/
|
134
|
+
getProxyPath(systemId: string, consumerInstanceId: string, consumerResourceName: string, portType: string) {
|
135
|
+
systemId = normalizeKapetaUri(systemId);
|
136
|
+
return `/proxy/${encodeURIComponent(systemId)}/${encodeURIComponent(consumerInstanceId)}/${encodeURIComponent(
|
137
|
+
consumerResourceName
|
138
|
+
)}/${encodeURIComponent(portType)}/`;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
export const clusterService = new ClusterService();
|
@@ -0,0 +1,109 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import Path from 'path';
|
7
|
+
import { registry as Targets, BlockCodeGenerator, CodeWriter } from '@kapeta/codegen';
|
8
|
+
import { BlockDefinition } from '@kapeta/schemas';
|
9
|
+
import { definitionsManager } from './definitionsManager';
|
10
|
+
import { Definition } from '@kapeta/local-cluster-config';
|
11
|
+
import { assetManager } from './assetManager';
|
12
|
+
import { normalizeKapetaUri, parseKapetaUri } from '@kapeta/nodejs-utils';
|
13
|
+
import { repositoryManager } from './repositoryManager';
|
14
|
+
|
15
|
+
const TARGET_KIND = 'core/language-target';
|
16
|
+
const BLOCK_TYPE_KIND = 'core/block-type';
|
17
|
+
|
18
|
+
class CodeGeneratorManager {
|
19
|
+
private async ensureLanguageTargetInRegistry(path: string, version: string, definition: Definition) {
|
20
|
+
const key = `${definition.metadata.name}:${version}`;
|
21
|
+
|
22
|
+
try {
|
23
|
+
if (await Targets.get(key)) {
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
} catch (e) {}
|
27
|
+
|
28
|
+
try {
|
29
|
+
const target = require(path);
|
30
|
+
if (target.default) {
|
31
|
+
Targets.register(key, target.default);
|
32
|
+
} else {
|
33
|
+
Targets.register(key, target);
|
34
|
+
}
|
35
|
+
} catch (e) {
|
36
|
+
console.error('Failed to load target: %s', key, e);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
async reload() {
|
40
|
+
Targets.reset();
|
41
|
+
const languageTargets = await definitionsManager.getDefinitions(TARGET_KIND);
|
42
|
+
for (const languageTarget of languageTargets) {
|
43
|
+
await this.ensureLanguageTargetInRegistry(
|
44
|
+
languageTarget.path,
|
45
|
+
languageTarget.version,
|
46
|
+
languageTarget.definition
|
47
|
+
);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
async initialize() {
|
52
|
+
await this.reload();
|
53
|
+
repositoryManager.on('change', async () => {
|
54
|
+
// Reload code generators when the repository changes
|
55
|
+
try {
|
56
|
+
await this.reload();
|
57
|
+
} catch (e) {
|
58
|
+
console.error('Failed to reload code generators', e);
|
59
|
+
}
|
60
|
+
});
|
61
|
+
}
|
62
|
+
|
63
|
+
async canGenerateCode(yamlContent: Definition): Promise<boolean> {
|
64
|
+
if (!yamlContent.spec?.target?.kind || !yamlContent.kind) {
|
65
|
+
//Not all block types have targets
|
66
|
+
return false;
|
67
|
+
}
|
68
|
+
|
69
|
+
const kindUri = parseKapetaUri(yamlContent.kind);
|
70
|
+
|
71
|
+
const blockTypes = await definitionsManager.getDefinitions(BLOCK_TYPE_KIND);
|
72
|
+
const blockTypeKinds = blockTypes.map(
|
73
|
+
(blockType) => parseKapetaUri(blockType.definition.metadata.name).fullName
|
74
|
+
);
|
75
|
+
return blockTypeKinds.includes(kindUri.fullName);
|
76
|
+
}
|
77
|
+
|
78
|
+
async generate(yamlFile: string, yamlContent: Definition) {
|
79
|
+
if (!yamlContent.spec.target?.kind) {
|
80
|
+
//Not all block types have targets
|
81
|
+
return;
|
82
|
+
}
|
83
|
+
|
84
|
+
const targetRef = normalizeKapetaUri(yamlContent.spec.target?.kind);
|
85
|
+
|
86
|
+
// Automatically downloads target if not available
|
87
|
+
const targetAsset = await assetManager.getAsset(targetRef);
|
88
|
+
|
89
|
+
if (!targetAsset) {
|
90
|
+
console.error('Language target not found: %s', yamlContent.spec.target?.kind);
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
|
94
|
+
await this.ensureLanguageTargetInRegistry(targetAsset?.path, targetAsset?.version, targetAsset?.data);
|
95
|
+
const baseDir = Path.dirname(yamlFile);
|
96
|
+
console.log('Generating code for path: %s', baseDir);
|
97
|
+
const codeGenerator = new BlockCodeGenerator(yamlContent as BlockDefinition);
|
98
|
+
|
99
|
+
const output = await codeGenerator.generate();
|
100
|
+
const writer = new CodeWriter(baseDir, {});
|
101
|
+
const assets = writer.write(output);
|
102
|
+
|
103
|
+
await codeGenerator.postprocess(baseDir, assets);
|
104
|
+
|
105
|
+
console.log('Code generated for path: %s', baseDir);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
export const codeGeneratorManager = new CodeGeneratorManager();
|