@vida-global/apps-tools 1.0.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.
@@ -0,0 +1,218 @@
1
+ const { logger } = require('@vida-global/core');
2
+ const _ = require("lodash");
3
+
4
+
5
+ class VaderUserContext {
6
+ constructor(
7
+ manager
8
+ ) {
9
+ this.manager = manager;
10
+ this.context = {};
11
+ }
12
+
13
+ APPID_VERSION_KEY (appId, appVersion) {
14
+ return `${appId}:${appVersion}`
15
+ }
16
+
17
+ USER_CONFIG_KEY () {
18
+ return `vader:user:${this.get('user').id}:config`
19
+ }
20
+
21
+ USER_APPS_KEY(user) {
22
+ return `vader:user:${this.get('user').id}:installed`
23
+ }
24
+
25
+ async load(ctx) {
26
+ ctx = ctx || {}
27
+ for (const [key, value] of Object.entries(ctx)) {
28
+ this.set(key, value)
29
+ }
30
+ if (ctx.user && !this.manager.attachedToAppServer) {
31
+ const userConfig = await this.manager.redisClient.hgetall(this.USER_CONFIG_KEY())
32
+ if (userConfig) {
33
+ for (const [key, value] of Object.entries(userConfig)) {
34
+ try {
35
+ this.set(key, JSON.parse(value))
36
+ } catch (e) {
37
+ this.set(key, value)
38
+ }
39
+ }
40
+ }
41
+ // Load installed apps
42
+ const userAppsKey = this.USER_APPS_KEY()
43
+ const installedApps = await this.manager.redisClient.hgetall(userAppsKey) || {}
44
+ const installedAppIds = Object.keys(installedApps)
45
+ this.set('installedApps', installedAppIds)
46
+
47
+ // Load appVersionIds
48
+ const appVersionIds = await this.getAppVersionIds()
49
+ this.set('appVersionIds', appVersionIds)
50
+
51
+ // Load enabled functions for each installed app
52
+ const enabledFunctions = {}
53
+ for (const appVersionId of installedAppIds) {
54
+ const [appId, appVersion] = appVersionId.split(':')
55
+ enabledFunctions[appVersionId] = this.getEnabledFunctions(appId, appVersion)
56
+ }
57
+ this.set('enabledFunctions', enabledFunctions)
58
+ }
59
+ }
60
+
61
+ get(name) {
62
+ // && name !== 'customVaderUrl' && name !== 'customVaderToken'
63
+ if (!this.context.hasOwnProperty(name)) {
64
+ // logger.warn(`VADER: User Context Missing Key: ${name}`);
65
+ return null;
66
+ }
67
+ return this.context[name];
68
+ }
69
+
70
+ set(name, value) {
71
+ this.context[name] = value;
72
+ }
73
+
74
+ toDict() {
75
+ return {...this.context}
76
+ }
77
+
78
+ toJSON() {
79
+ return JSON.stringify(this.context)
80
+ }
81
+
82
+ async getProviderConfig (providerType, providerName, appId = null, appVersion = null) {
83
+ let providerKey = `${providerType}:${providerName}`
84
+ if (appId && appVersion) {
85
+ providerKey = `${appId}:${appVersion}:${providerKey}`
86
+ }
87
+
88
+ // Only local context is available
89
+ if (this.manager.attachedToAppServer) {
90
+ return this.context[providerKey];
91
+ }
92
+
93
+ const config = await this.manager.redisClient.hget(
94
+ this.USER_CONFIG_KEY(), providerKey
95
+ ) || '{}'
96
+ const parsedConfig = JSON.parse(config);
97
+ this.context[providerKey] = parsedConfig;
98
+ return parsedConfig;
99
+ }
100
+
101
+ async setProviderConfig (providerType, providerName, config, appId = null, appVersion = null) {
102
+ let providerKey = `${providerType}:${providerName}`
103
+ if (appId && appVersion) {
104
+ providerKey = `${appId}:${appVersion}:${providerKey}`
105
+ }
106
+ return await this.manager.redisClient.hset(
107
+ this.USER_CONFIG_KEY(), providerKey, JSON.stringify(config)
108
+ )
109
+ }
110
+
111
+ async deleteProviderConfig (providerType, providerName, appId = null, appVersion = null) {
112
+ let providerKey = `${providerType}:${providerName}`
113
+ if (appId && appVersion) {
114
+ providerKey = `${appId}:${appVersion}:${providerKey}`
115
+ }
116
+ return await this.manager.redisClient.hdel(
117
+ this.USER_CONFIG_KEY(), providerKey
118
+ )
119
+ }
120
+
121
+ async fetchAgentAppManifest(appId, appVersion) {
122
+ const agent = this.get('agent')
123
+ const manifest = _.find(agent.apps, a => a.appId === appId && a.version === appVersion)
124
+ return manifest ? manifest : null
125
+ }
126
+
127
+ async installApp(appId, appVersion) {
128
+ // Store the installed app manifest
129
+ const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
130
+ const userAppsKey = this.USER_APPS_KEY()
131
+
132
+ await this.manager.redisClient.hset(userAppsKey, appVersionKey, 1)
133
+ }
134
+
135
+ async uninstallApp (appId, appVersion) {
136
+ const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
137
+ await this.manager.redisClient.hdel(this.USER_APPS_KEY(), appVersionKey)
138
+ }
139
+
140
+ async isAppInstalled (appId, appVersion) {
141
+ if (this.manager.attachedToAppServer) {
142
+ return (this.get('installedApps') || []).includes(`${appId}:${appVersion}`)
143
+ }
144
+ const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
145
+ return !!await this.manager.redisClient.hexists(this.USER_APPS_KEY(), appVersionKey)
146
+ }
147
+
148
+ async getAppVersionIds() {
149
+ if (this.manager.attachedToAppServer) {
150
+ return this.get('appVersionIds')
151
+ }
152
+ let appVersionIds
153
+ let agent = this.get('agent')
154
+ if (agent) {
155
+ appVersionIds = _.map(agent.apps, a => `${a.appId}:${a.version}`)
156
+ } else {
157
+ const userToAppsKey = this.USER_APPS_KEY()
158
+ appVersionIds = await this.manager.redisClient.hkeys(userToAppsKey)
159
+ if (!appVersionIds) {
160
+ appVersionIds = []
161
+ }
162
+ }
163
+ return appVersionIds
164
+ }
165
+
166
+ getEnabledFunctions (appId, appVersion) {
167
+ if (this.manager.attachedToAppServer) {
168
+ return this.get('enabledFunctions')[this.APPID_VERSION_KEY(appId, appVersion)] || []
169
+ }
170
+ const agent = this.get('agent')
171
+ const apps = agent?.apps || []
172
+ const appVersionKey = this.APPID_VERSION_KEY(appId, appVersion)
173
+ if (agent && apps.some(a => a.appId === appId && a.version === appVersion)) {
174
+ const enabledFunctions = agent['enabledFunctions'] || {}
175
+ return enabledFunctions[appVersionKey] || []
176
+ } else {
177
+ return []
178
+ }
179
+ }
180
+ }
181
+
182
+ /**
183
+ * A proxy class that adds vader user context to manager function calls
184
+ */
185
+ class VaderUserContextProxy {
186
+ constructor(target, context) {
187
+ this.target = target;
188
+ this.context = context;
189
+
190
+ // Create a proxy to intercept function calls
191
+ return new Proxy(this, {
192
+ get: (obj, prop) => {
193
+ // If the property exists on the target and is a function
194
+ if (typeof this.target[prop] === 'function') {
195
+ return this._wrapFunction(prop);
196
+ }
197
+ // For non-function properties, return the target's property
198
+ return this.target[prop];
199
+ }
200
+ });
201
+ }
202
+ _wrapFunction(functionName) {
203
+ return async (...args) => {
204
+ const vaderUserContext = new VaderUserContext(this.target);
205
+ await vaderUserContext.load(this.context)
206
+ return await this.target[functionName](
207
+ ...args,
208
+ vaderUserContext,
209
+ );
210
+ };
211
+ }
212
+ }
213
+
214
+ module.exports = {
215
+ VaderUserContext,
216
+ VaderUserContextProxy
217
+ }
218
+
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@vida-global/apps-tools",
3
+ "version": "1.0.1",
4
+ "description": "Classes for creating vida apps",
5
+ "author": "",
6
+ "license": "ISC",
7
+ "main": "index.js",
8
+ "directories": {
9
+ "doc": "lib",
10
+ "test": "test"
11
+ },
12
+ "scripts": {
13
+ "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules node_modules/jest/bin/jest.js"
14
+ },
15
+ "jest": {
16
+ "collectCoverage": true,
17
+ "coveragePathIgnorePatterns": [
18
+ "/test/helpers"
19
+ ]
20
+ },
21
+ "dependencies": {
22
+ "axios": "^1.8.1",
23
+ "googleapis": "^146.0.0",
24
+ "lodash": "^4.17.21",
25
+ "mcp-client": "^1.13.1",
26
+ "swagger-ui-express": "^5.0.1",
27
+ "@vida-global/core": "^1.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "jest": "^29.6.2"
31
+ }
32
+ }
33
+