@adminide-stack/marketplace-module-server 12.0.4-alpha.92 → 12.0.4-alpha.95
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/Readme.md +321 -0
- package/lib/constants/extension-events.d.ts +136 -0
- package/lib/constants/extension-events.d.ts.map +1 -0
- package/lib/containers/module.d.ts +8 -0
- package/lib/containers/module.d.ts.map +1 -1
- package/lib/containers/module.js +9 -3
- package/lib/containers/module.js.map +1 -1
- package/lib/dataloaders/index.d.ts +2 -0
- package/lib/dataloaders/index.d.ts.map +1 -0
- package/lib/dataloaders/registry-extension-data-loader.d.ts +6 -0
- package/lib/dataloaders/registry-extension-data-loader.d.ts.map +1 -0
- package/lib/dataloaders/registry-extension-data-loader.js +6 -0
- package/lib/dataloaders/registry-extension-data-loader.js.map +1 -0
- package/lib/graphql/resolvers/index.d.ts +1 -1
- package/lib/graphql/resolvers/index.d.ts.map +1 -1
- package/lib/graphql/resolvers/index.js +1 -0
- package/lib/graphql/resolvers/index.js.map +1 -0
- package/lib/graphql/resolvers/installed-extension-resolver.d.ts +5 -0
- package/lib/graphql/resolvers/installed-extension-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/installed-extension-resolver.js +183 -0
- package/lib/graphql/resolvers/installed-extension-resolver.js.map +1 -0
- package/lib/graphql/resolvers/registry-extension-resolver.d.ts +5 -0
- package/lib/graphql/resolvers/registry-extension-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/{resolvers.js → registry-extension-resolver.js} +59 -47
- package/lib/graphql/resolvers/registry-extension-resolver.js.map +1 -0
- package/lib/graphql/schemas/extension-registry.graphql +74 -0
- package/lib/graphql/schemas/extension-registry.graphql.js +1 -0
- package/lib/graphql/schemas/extension-registry.graphql.js.map +1 -0
- package/lib/graphql/schemas/index.d.ts.map +1 -1
- package/lib/graphql/schemas/index.js +1 -4
- package/lib/graphql/schemas/index.js.map +1 -1
- package/lib/graphql/schemas/installed-extension.graphql +294 -0
- package/lib/graphql/schemas/installed-extension.graphql.js +1 -0
- package/lib/graphql/schemas/installed-extension.graphql.js.map +1 -0
- package/lib/graphql/schemas/service.graphql +181 -0
- package/lib/graphql/schemas/service.graphql.js +1 -0
- package/lib/graphql/schemas/service.graphql.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/module.d.ts.map +1 -1
- package/lib/module.js +6 -4
- package/lib/module.js.map +1 -1
- package/lib/plugins/extension-moleculer-service.d.ts +86 -0
- package/lib/plugins/extension-moleculer-service.d.ts.map +1 -0
- package/lib/plugins/index.d.ts +2 -0
- package/lib/plugins/index.d.ts.map +1 -0
- package/lib/services/extension-service.d.ts +35 -47
- package/lib/services/extension-service.d.ts.map +1 -1
- package/lib/services/extension-service.js +33 -15
- package/lib/services/extension-service.js.map +1 -1
- package/lib/services/index.d.ts +2 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/installed-extension-service-ext.d.ts +13 -0
- package/lib/services/installed-extension-service-ext.d.ts.map +1 -0
- package/lib/services/installed-extension-service-ext.js +271 -0
- package/lib/services/installed-extension-service-ext.js.map +1 -0
- package/lib/services/installed-extension-service.d.ts +93 -0
- package/lib/services/installed-extension-service.d.ts.map +1 -0
- package/lib/services/installed-extension-service.js +400 -0
- package/lib/services/installed-extension-service.js.map +1 -0
- package/lib/services/installed-extension-service.test.d.ts +2 -0
- package/lib/services/installed-extension-service.test.d.ts.map +1 -0
- package/lib/store/index.d.ts +1 -1
- package/lib/store/index.d.ts.map +1 -1
- package/lib/store/models/index.d.ts +1 -0
- package/lib/store/models/index.d.ts.map +1 -1
- package/lib/store/models/installed-extension-model.d.ts +4 -0
- package/lib/store/models/installed-extension-model.d.ts.map +1 -0
- package/lib/store/models/installed-extension-model.js +297 -0
- package/lib/store/models/installed-extension-model.js.map +1 -0
- package/lib/store/models/registry-extension-model.d.ts +2 -7
- package/lib/store/models/registry-extension-model.d.ts.map +1 -1
- package/lib/store/models/registry-extension-model.js +40 -19
- package/lib/store/models/registry-extension-model.js.map +1 -1
- package/lib/store/repositories/index.d.ts +3 -0
- package/lib/store/repositories/index.d.ts.map +1 -0
- package/lib/store/repositories/installed-extension-repository.d.ts +71 -0
- package/lib/store/repositories/installed-extension-repository.d.ts.map +1 -0
- package/lib/store/repositories/installed-extension-repository.js +414 -0
- package/lib/store/repositories/installed-extension-repository.js.map +1 -0
- package/lib/store/repositories/registry-extension-repository.d.ts +54 -0
- package/lib/store/repositories/registry-extension-repository.d.ts.map +1 -0
- package/lib/store/{repository → repositories}/registry-extension-repository.js +44 -42
- package/lib/store/repositories/registry-extension-repository.js.map +1 -0
- package/lib/templates/constants/DB_COLL_NAMES.ts.template +5 -0
- package/lib/templates/constants/SERVER_TYPES.ts.template +3 -0
- package/lib/templates/repositories/InstalledExtensionRepository.ts.template +94 -0
- package/lib/templates/repositories/RegistryExtensionRepository.ts.template +10 -15
- package/lib/templates/services/InstalledExtensionDataLoader.ts.template +2 -0
- package/lib/templates/services/InstalledExtensionService.ts.template +168 -0
- package/lib/templates/services/RegistryExtensionDataLoader.ts.template +2 -0
- package/lib/templates/services/RegistryExtensionService.ts.template +10 -10
- package/lib/tests/extension-integration.test.d.ts +2 -0
- package/lib/tests/extension-integration.test.d.ts.map +1 -0
- package/lib/tests/test-extension-services.d.ts +1 -0
- package/lib/tests/test-extension-services.d.ts.map +1 -0
- package/package.json +12 -7
- package/lib/graphql/resolvers/resolvers.d.ts +0 -2
- package/lib/graphql/resolvers/resolvers.d.ts.map +0 -1
- package/lib/graphql/resolvers/resolvers.js.map +0 -1
- package/lib/graphql/schemas/extension.graphql +0 -57
- package/lib/graphql/schemas/extension.graphql.js +0 -1
- package/lib/graphql/schemas/extension.graphql.js.map +0 -1
- package/lib/store/repository/index.d.ts +0 -2
- package/lib/store/repository/index.d.ts.map +0 -1
- package/lib/store/repository/registry-extension-repository.d.ts +0 -31
- package/lib/store/repository/registry-extension-repository.d.ts.map +0 -1
- package/lib/store/repository/registry-extension-repository.js.map +0 -1
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import {__decorate,__param,__metadata}from'tslib';import {injectable,inject,optional}from'inversify';import {BaseMongoRepository}from'@common-stack/store-mongo';import*as mongoose from'mongoose';import'../models/registry-extension-model.js';import {InstalledExtensionModelFunc}from'../models/installed-extension-model.js';let InstalledExtensionRepository = class InstalledExtensionRepository extends BaseMongoRepository {
|
|
2
|
+
constructor(db, logger, options) {
|
|
3
|
+
super(InstalledExtensionModelFunc, db, logger, options);
|
|
4
|
+
if (!db) {
|
|
5
|
+
throw new Error('A database connection is required');
|
|
6
|
+
}
|
|
7
|
+
this.logger = logger.child({
|
|
8
|
+
className: 'InstalledExtensionRepository'
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async findByTenantAndId(tenantId, extensionSlug) {
|
|
12
|
+
try {
|
|
13
|
+
const extension = await this.model.findOne({
|
|
14
|
+
tenantId,
|
|
15
|
+
extensionSlug
|
|
16
|
+
});
|
|
17
|
+
return extension?.toObject();
|
|
18
|
+
} catch (error) {
|
|
19
|
+
this.logger.error('Error in findByTenantAndId', {
|
|
20
|
+
error,
|
|
21
|
+
tenantId,
|
|
22
|
+
extensionSlug
|
|
23
|
+
});
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async countExtensions(filter) {
|
|
28
|
+
try {
|
|
29
|
+
const mongoQuery = {};
|
|
30
|
+
if (filter.tenantId) {
|
|
31
|
+
mongoQuery.tenantId = filter.tenantId;
|
|
32
|
+
}
|
|
33
|
+
if (filter.extensionSlug) {
|
|
34
|
+
mongoQuery.extensionSlug = filter.extensionSlug;
|
|
35
|
+
}
|
|
36
|
+
if (filter.status) {
|
|
37
|
+
mongoQuery.status = Array.isArray(filter.status) ? {
|
|
38
|
+
$in: filter.status
|
|
39
|
+
} : filter.status;
|
|
40
|
+
}
|
|
41
|
+
if (filter['lifecycle.registryStatus']) {
|
|
42
|
+
mongoQuery['lifecycle.registryStatus'] = Array.isArray(filter['lifecycle.registryStatus']) ? {
|
|
43
|
+
$in: filter['lifecycle.registryStatus']
|
|
44
|
+
} : filter['lifecycle.registryStatus'];
|
|
45
|
+
}
|
|
46
|
+
if (filter['lifecycle.isOrphaned'] !== undefined) {
|
|
47
|
+
mongoQuery['lifecycle.isOrphaned'] = filter['lifecycle.isOrphaned'];
|
|
48
|
+
}
|
|
49
|
+
if (filter['settings.effectiveEnabled'] !== undefined) {
|
|
50
|
+
mongoQuery['settings.effectiveEnabled'] = filter['settings.effectiveEnabled'];
|
|
51
|
+
}
|
|
52
|
+
if (filter.installedBy) {
|
|
53
|
+
mongoQuery.installedBy = filter.installedBy;
|
|
54
|
+
}
|
|
55
|
+
return await this.model.countDocuments(mongoQuery);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
this.logger.error('Error in countExtensions', {
|
|
58
|
+
error,
|
|
59
|
+
filter
|
|
60
|
+
});
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a new installed extension record
|
|
66
|
+
*/
|
|
67
|
+
async createExtension(input) {
|
|
68
|
+
try {
|
|
69
|
+
this.logger.trace('Creating installed extension with params (%j)', input);
|
|
70
|
+
const extensionData = {
|
|
71
|
+
...input,
|
|
72
|
+
tenantId: input.tenantId,
|
|
73
|
+
extension: input.extensionId,
|
|
74
|
+
// Store extensionSlug directly since it's a string
|
|
75
|
+
installedBy: new mongoose.Types.ObjectId(input.installedBy),
|
|
76
|
+
installedAt: new Date(),
|
|
77
|
+
status: 'installed',
|
|
78
|
+
lifecycle: {
|
|
79
|
+
registryStatus: 'active',
|
|
80
|
+
isOrphaned: false,
|
|
81
|
+
deprecationWarningShown: false,
|
|
82
|
+
autoUpdateBlocked: false,
|
|
83
|
+
lastRegistryCheck: new Date().toISOString()
|
|
84
|
+
},
|
|
85
|
+
policies: {
|
|
86
|
+
allowOrphanedExecution: false,
|
|
87
|
+
requireSecurityUpdates: true,
|
|
88
|
+
autoRemoveDeprecated: false,
|
|
89
|
+
deprecationGracePeriod: 30,
|
|
90
|
+
...input.policies
|
|
91
|
+
},
|
|
92
|
+
settings: {
|
|
93
|
+
userEnabled: true,
|
|
94
|
+
systemEnabled: true,
|
|
95
|
+
effectiveEnabled: true,
|
|
96
|
+
userConfig: {},
|
|
97
|
+
systemConfig: {},
|
|
98
|
+
...input.settings
|
|
99
|
+
},
|
|
100
|
+
runtime: {
|
|
101
|
+
activationState: 'enabled'
|
|
102
|
+
},
|
|
103
|
+
auditLog: [{
|
|
104
|
+
action: 'installed',
|
|
105
|
+
timestamp: new Date(),
|
|
106
|
+
user: new mongoose.Types.ObjectId(input.installedBy),
|
|
107
|
+
details: {
|
|
108
|
+
version: input.version,
|
|
109
|
+
source: 'manual'
|
|
110
|
+
}
|
|
111
|
+
}]
|
|
112
|
+
};
|
|
113
|
+
const extension = await this.model.create(extensionData);
|
|
114
|
+
return extension.toObject();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
this.logger.error('Error creating installed extension', {
|
|
117
|
+
error,
|
|
118
|
+
input
|
|
119
|
+
});
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Update an existing installed extension
|
|
125
|
+
*/
|
|
126
|
+
async updateExtension(tenantId, extensionSlug, update) {
|
|
127
|
+
try {
|
|
128
|
+
const extension = await this.model.findOneAndUpdate({
|
|
129
|
+
tenantId,
|
|
130
|
+
extensionSlug
|
|
131
|
+
}, {
|
|
132
|
+
$set: {
|
|
133
|
+
...update,
|
|
134
|
+
lastUpdated: new Date(),
|
|
135
|
+
...(update.lastUpdatedBy && {
|
|
136
|
+
lastUpdatedBy: new mongoose.Types.ObjectId(update.lastUpdatedBy)
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}, {
|
|
140
|
+
new: true
|
|
141
|
+
});
|
|
142
|
+
return extension?.toObject();
|
|
143
|
+
} catch (error) {
|
|
144
|
+
this.logger.error('Error updating installed extension', {
|
|
145
|
+
error,
|
|
146
|
+
tenantId,
|
|
147
|
+
extensionSlug
|
|
148
|
+
});
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Find a specific installed extension
|
|
154
|
+
*/
|
|
155
|
+
async findOne(tenantId, extensionSlug) {
|
|
156
|
+
try {
|
|
157
|
+
const extension = await this.model.findOne({
|
|
158
|
+
tenantId,
|
|
159
|
+
extensionSlug
|
|
160
|
+
});
|
|
161
|
+
return extension?.toObject();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.logger.error('Error finding installed extension', {
|
|
164
|
+
error,
|
|
165
|
+
tenantId,
|
|
166
|
+
extensionSlug
|
|
167
|
+
});
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Find installed extensions with optional filtering
|
|
173
|
+
*/
|
|
174
|
+
async findExtensions(query) {
|
|
175
|
+
try {
|
|
176
|
+
const mongoQuery = {};
|
|
177
|
+
if (query.tenantId) {
|
|
178
|
+
mongoQuery.tenantId = query.tenantId;
|
|
179
|
+
}
|
|
180
|
+
if (query.extensionSlug) {
|
|
181
|
+
mongoQuery.extensionSlug = query.extensionSlug;
|
|
182
|
+
}
|
|
183
|
+
if (query.status) {
|
|
184
|
+
mongoQuery.status = Array.isArray(query.status) ? {
|
|
185
|
+
$in: query.status
|
|
186
|
+
} : query.status;
|
|
187
|
+
}
|
|
188
|
+
if (query['lifecycle.registryStatus']) {
|
|
189
|
+
mongoQuery['lifecycle.registryStatus'] = Array.isArray(query['lifecycle.registryStatus']) ? {
|
|
190
|
+
$in: query['lifecycle.registryStatus']
|
|
191
|
+
} : query['lifecycle.registryStatus'];
|
|
192
|
+
}
|
|
193
|
+
if (query['lifecycle.isOrphaned'] !== undefined) {
|
|
194
|
+
mongoQuery['lifecycle.isOrphaned'] = query['lifecycle.isOrphaned'];
|
|
195
|
+
}
|
|
196
|
+
if (query['settings.effectiveEnabled'] !== undefined) {
|
|
197
|
+
mongoQuery['settings.effectiveEnabled'] = query['settings.effectiveEnabled'];
|
|
198
|
+
}
|
|
199
|
+
if (query.installedBy) {
|
|
200
|
+
mongoQuery.installedBy = query.installedBy;
|
|
201
|
+
}
|
|
202
|
+
const extensions = await this.model.find(mongoQuery);
|
|
203
|
+
return extensions.map(ext => ext.toObject());
|
|
204
|
+
} catch (error) {
|
|
205
|
+
this.logger.error('Error finding installed extensions', {
|
|
206
|
+
error,
|
|
207
|
+
query
|
|
208
|
+
});
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Delete an installed extension
|
|
214
|
+
*/
|
|
215
|
+
async deleteExtension(tenantId, extensionSlug) {
|
|
216
|
+
try {
|
|
217
|
+
const result = await this.model.deleteOne({
|
|
218
|
+
tenantId,
|
|
219
|
+
extensionSlug
|
|
220
|
+
});
|
|
221
|
+
return result.deletedCount > 0;
|
|
222
|
+
} catch (error) {
|
|
223
|
+
this.logger.error('Error deleting installed extension', {
|
|
224
|
+
error,
|
|
225
|
+
tenantId,
|
|
226
|
+
extensionSlug
|
|
227
|
+
});
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get installed extensions joined with registry information
|
|
233
|
+
*/
|
|
234
|
+
async findWithRegistryInfo(query) {
|
|
235
|
+
try {
|
|
236
|
+
const mongoQuery = {};
|
|
237
|
+
if (query.tenantId) {
|
|
238
|
+
mongoQuery.tenantId = query.tenantId;
|
|
239
|
+
}
|
|
240
|
+
const pipeline = [{
|
|
241
|
+
$match: mongoQuery
|
|
242
|
+
}, {
|
|
243
|
+
$lookup: {
|
|
244
|
+
from: 'extensionregistry',
|
|
245
|
+
localField: 'extension',
|
|
246
|
+
foreignField: '_id',
|
|
247
|
+
as: 'registryInfo'
|
|
248
|
+
}
|
|
249
|
+
}, {
|
|
250
|
+
$unwind: {
|
|
251
|
+
path: '$registryInfo',
|
|
252
|
+
preserveNullAndEmptyArrays: true
|
|
253
|
+
}
|
|
254
|
+
}];
|
|
255
|
+
const extensions = await this.model.aggregate(pipeline);
|
|
256
|
+
return extensions;
|
|
257
|
+
} catch (error) {
|
|
258
|
+
this.logger.error('Error finding extensions with registry info', {
|
|
259
|
+
error,
|
|
260
|
+
query
|
|
261
|
+
});
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Check if extension exists for tenant
|
|
267
|
+
*/
|
|
268
|
+
async exists(tenantId, extensionSlug) {
|
|
269
|
+
try {
|
|
270
|
+
const count = await this.model.countDocuments({
|
|
271
|
+
tenantId,
|
|
272
|
+
extensionSlug
|
|
273
|
+
});
|
|
274
|
+
return count > 0;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
this.logger.error('Error checking extension existence', {
|
|
277
|
+
error,
|
|
278
|
+
tenantId,
|
|
279
|
+
extensionSlug
|
|
280
|
+
});
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Bulk update multiple extensions
|
|
286
|
+
*/
|
|
287
|
+
async bulkUpdateExtensions(tenantId, filter, update) {
|
|
288
|
+
try {
|
|
289
|
+
const mongoQuery = {
|
|
290
|
+
tenantId,
|
|
291
|
+
...filter
|
|
292
|
+
};
|
|
293
|
+
const result = await this.model.updateMany(mongoQuery, {
|
|
294
|
+
$set: update
|
|
295
|
+
});
|
|
296
|
+
return result.modifiedCount;
|
|
297
|
+
} catch (error) {
|
|
298
|
+
this.logger.error('Error bulk updating extensions', {
|
|
299
|
+
error,
|
|
300
|
+
tenantId,
|
|
301
|
+
filter,
|
|
302
|
+
update
|
|
303
|
+
});
|
|
304
|
+
return 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get extension dependency graph for a tenant
|
|
309
|
+
*/
|
|
310
|
+
async getDependencyGraph(tenantId) {
|
|
311
|
+
try {
|
|
312
|
+
const extensions = await this.model.find({
|
|
313
|
+
tenantId
|
|
314
|
+
});
|
|
315
|
+
const extensionObjects = extensions.map(ext => ext.toObject());
|
|
316
|
+
const dependencies = extensionObjects.map(ext => ({
|
|
317
|
+
extensionSlug: ext.extension?.toString() || '',
|
|
318
|
+
dependsOn: ext.dependencies || [],
|
|
319
|
+
dependents: ext.dependents || []
|
|
320
|
+
}));
|
|
321
|
+
return {
|
|
322
|
+
extensions: extensionObjects,
|
|
323
|
+
dependencies
|
|
324
|
+
};
|
|
325
|
+
} catch (error) {
|
|
326
|
+
this.logger.error('Error getting dependency graph', {
|
|
327
|
+
error,
|
|
328
|
+
tenantId
|
|
329
|
+
});
|
|
330
|
+
return {
|
|
331
|
+
extensions: [],
|
|
332
|
+
dependencies: []
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Count installed extensions matching query
|
|
338
|
+
*/
|
|
339
|
+
async count(query) {
|
|
340
|
+
try {
|
|
341
|
+
const mongoQuery = {};
|
|
342
|
+
if (query.tenantId) {
|
|
343
|
+
mongoQuery.tenantId = query.tenantId;
|
|
344
|
+
}
|
|
345
|
+
if (query.status) {
|
|
346
|
+
mongoQuery.status = Array.isArray(query.status) ? {
|
|
347
|
+
$in: query.status
|
|
348
|
+
} : query.status;
|
|
349
|
+
}
|
|
350
|
+
return await this.model.countDocuments(mongoQuery);
|
|
351
|
+
} catch (error) {
|
|
352
|
+
this.logger.error('Error counting extensions', {
|
|
353
|
+
error,
|
|
354
|
+
query
|
|
355
|
+
});
|
|
356
|
+
return 0;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Find extensions that need registry sync
|
|
361
|
+
*/
|
|
362
|
+
async findStaleExtensions(tenantId, maxAge) {
|
|
363
|
+
try {
|
|
364
|
+
const staleDate = new Date(Date.now() - maxAge);
|
|
365
|
+
const extensions = await this.model.find({
|
|
366
|
+
tenantId,
|
|
367
|
+
'lifecycle.lastRegistryCheck': {
|
|
368
|
+
$lt: staleDate.toISOString()
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
return extensions.map(ext => ext.toObject());
|
|
372
|
+
} catch (error) {
|
|
373
|
+
this.logger.error('Error finding stale extensions', {
|
|
374
|
+
error,
|
|
375
|
+
tenantId,
|
|
376
|
+
maxAge
|
|
377
|
+
});
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Update registry status for multiple extensions
|
|
383
|
+
*/
|
|
384
|
+
async syncRegistryStatus(updates) {
|
|
385
|
+
try {
|
|
386
|
+
const bulkOps = updates.map(update => ({
|
|
387
|
+
updateOne: {
|
|
388
|
+
filter: {
|
|
389
|
+
tenantId: update.tenantId,
|
|
390
|
+
extensionSlug: update.extensionSlug
|
|
391
|
+
},
|
|
392
|
+
update: {
|
|
393
|
+
$set: {
|
|
394
|
+
'lifecycle.registryStatus': update.registryStatus,
|
|
395
|
+
'lifecycle.isOrphaned': update.isOrphaned,
|
|
396
|
+
'lifecycle.lastRegistryCheck': new Date().toISOString(),
|
|
397
|
+
...(update.latestVersion && {
|
|
398
|
+
availableVersion: update.latestVersion
|
|
399
|
+
})
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}));
|
|
404
|
+
await this.model.bulkWrite(bulkOps);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
this.logger.error('Error syncing registry status', {
|
|
407
|
+
error,
|
|
408
|
+
updates
|
|
409
|
+
});
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
InstalledExtensionRepository = __decorate([injectable(), __param(0, inject('MongoDBConnection')), __param(1, inject('Logger')), __param(2, inject('MongoOptions')), __param(2, optional()), __metadata("design:paramtypes", [mongoose.Connection, Object, Object])], InstalledExtensionRepository);export{InstalledExtensionRepository};//# sourceMappingURL=installed-extension-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installed-extension-repository.js","sources":["../../../src/store/repositories/installed-extension-repository.ts"],"sourcesContent":[null],"names":[],"mappings":"kUAqBqC,IAAA,4BAAa,GAAA,MACxB,4BACyB,SAAG,mBAAG,CAAA;AAS/C,EAAA,WAAA,CAAA,EAAA,EAAA,MACM,EAAA,OAAQ,EAAA;IAYd,KAAe,CAAA,2BAAS,EAAA,EAAA,EAAA,MAAA,EAAA,OAAmC,CAAA;AAiCjE,IAAA,IAAA,CAAA,EAAA,EAAA;;AAEG;IACU,IAAe,CAAA,MAAA,GAAA,MACnB,CAAA,KAAgC,CAAA;AAyDzC,MAAA,SAAA,EAAA;;AAEG;QACyB,0BACd,EAAM,aACH,EAAA;AA4BjB,IAAA,IAAA;;AAEG,QAAA,QAAA;AACU,QAAA;AAab,OAAA,CAAA;;AAEG,KAAA,CAAA,OAAA,KAAA,EAAA;AACU,MAAA,IAAA,CAAA,MAAA,CAAc,KAAC,CAAK,4BAA8B,EAAA;AA0C/D,QAAA,KAAA;;AAEG,QAAA;AACU,OAAA,CAAA;AAUb,MAAA,OAAA,IAAA;;AAEG;QAC8B,eAAA,CAAA,MAAM,EAAE;AAkCzC,IAAA,IAAA;;AAEG,MAAA,IAAA,MAAA,CAAA,QAAA,EAAA;AACU,QAAA,UAAO,CAAQ,QAAQ,GAAE,MAAA,CAAA,QAAe;AAUrD;;AAEG,QAAA,UAAA,CAAA,aAAA,GAAA,MAAA,CAAA,aAAA;;AAgBH,MAAA,IAAA,MAAA,CAAA,MAAA,EAAA;;AAEG,UAAA,GAAA,EAAA,MAAA,CAAA;AACU,SAAA,GAAA,MAAA,CAAA,MAA2B;AACpC;UACY,MAAA,CAAA,0BAAQ,CAAA,EAAA;kBACH,CAAA,0BAAS,CAAA,GAAA,KAAA,CAAA,OAAA,CAAA,MAAA,CAAA,0BAAA,CAAA,CAAA,GAAA;aACb,EAAA,MAAA,CAAA,0BAAW;YACpB,MAAU,CAAA,0BAAW,CAAA;AACxB;MACH,IAAA,MAAA,CAAA,sBAAA,CAAA,KAAA,SAAA,EAAA;AAoBF,QAAA,UAAA,CAAA,sBAAA,CAAA,GAAA,MAAA,CAAA,sBAAA,CAAA;;AAEG,MAAA,IAAA,MAAA,CAAA,2BAAA,CAAA,KAAA,SAAA,EAAA;QACe,UAAQ,CAAA,2BAAmC,CAAA,GAAA,kCAAQ,CAAA;AAmBrE;;AAEG,QAAA,UAAA,CAAA,WAAA,GAAA,MAAA,CAAA,WAAA;AACU;AAkBb,MAAA,OAAA,MAAA,IAAA,CAAA,KAAA,CAAA,cAAA,CAAA,UAAA,CAAA;;AAEG,MAAA,IAAA,CAAA,MAAA,CAAA,KAAA,CAAA,0BAAA,EAAA;AACU,QAAA,KAAA;QAEL;QACA;aACc,CAAA;;;AAGjB;AA0BR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as mongoose from 'mongoose';
|
|
2
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
3
|
+
import { IExtensionRelease, IRegistryExtensionRepository, IRegistryExtensionModel, AsDomainType } from 'common/server';
|
|
4
|
+
import { BaseMongoRepository } from '@common-stack/store-mongo';
|
|
5
|
+
export declare class RegistryExtensionRepository extends BaseMongoRepository<IRegistryExtensionModel> implements IRegistryExtensionRepository {
|
|
6
|
+
constructor(db: mongoose.Connection, logger: CdmLogger.ILogger, options?: any);
|
|
7
|
+
createExtension(publisherId: string, name: string): Promise<mongoose.Document<unknown, any, IRegistryExtensionModel & {
|
|
8
|
+
id: string;
|
|
9
|
+
}> & Omit<IRegistryExtensionModel & {
|
|
10
|
+
id: string;
|
|
11
|
+
} & Required<{
|
|
12
|
+
_id: import("bson").ObjectID;
|
|
13
|
+
}>, never>>;
|
|
14
|
+
updateExtensionName(extensionSlug: string, name: string): Promise<mongoose.Document<unknown, any, IRegistryExtensionModel & {
|
|
15
|
+
id: string;
|
|
16
|
+
}> & Omit<IRegistryExtensionModel & {
|
|
17
|
+
id: string;
|
|
18
|
+
} & Required<{
|
|
19
|
+
_id: import("bson").ObjectID;
|
|
20
|
+
}>, never>>;
|
|
21
|
+
updateExtension(extensionSlug: string, update: {
|
|
22
|
+
installed?: boolean;
|
|
23
|
+
}): Promise<mongoose.Document<unknown, any, IRegistryExtensionModel & {
|
|
24
|
+
id: string;
|
|
25
|
+
}> & Omit<IRegistryExtensionModel & {
|
|
26
|
+
id: string;
|
|
27
|
+
} & Required<{
|
|
28
|
+
_id: import("bson").ObjectID;
|
|
29
|
+
}>, never>>;
|
|
30
|
+
deleteExtension(extensionSlug: any): Promise<boolean>;
|
|
31
|
+
extensionReleases(extensionSlug: string): Promise<AsDomainType<IExtensionRelease>[]>;
|
|
32
|
+
publishExtension(request: any): Promise<mongoose.Document<unknown, any, IRegistryExtensionModel & {
|
|
33
|
+
id: string;
|
|
34
|
+
}> & Omit<IRegistryExtensionModel & {
|
|
35
|
+
id: string;
|
|
36
|
+
} & Required<{
|
|
37
|
+
_id: import("bson").ObjectID;
|
|
38
|
+
}>, never>>;
|
|
39
|
+
findExtensions(first: number, query: string, local?: boolean, remote?: boolean, prioritizeExtensionIDs?: string[]): Promise<(mongoose.Document<unknown, any, IRegistryExtensionModel & {
|
|
40
|
+
id: string;
|
|
41
|
+
}> & Omit<IRegistryExtensionModel & {
|
|
42
|
+
id: string;
|
|
43
|
+
} & Required<{
|
|
44
|
+
_id: import("bson").ObjectID;
|
|
45
|
+
}>, never>)[]>;
|
|
46
|
+
findExtension(extensionSlug: string, version?: string): Promise<mongoose.Document<unknown, any, IRegistryExtensionModel & {
|
|
47
|
+
id: string;
|
|
48
|
+
}> & Omit<IRegistryExtensionModel & {
|
|
49
|
+
id: string;
|
|
50
|
+
} & Required<{
|
|
51
|
+
_id: import("bson").ObjectID;
|
|
52
|
+
}>, never>>;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=registry-extension-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-extension-repository.d.ts","sourceRoot":"","sources":["../../../src/store/repositories/registry-extension-repository.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACvH,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGhE,qBACa,2BACT,SAAQ,mBAAmB,CAAC,uBAAuB,CACnD,YAAW,4BAA4B;gBAGN,EAAE,EAAE,QAAQ,CAAC,UAAU,EAClC,MAAM,EAAE,SAAS,CAAC,OAAO,EACP,OAAO,CAAC,EAAE,GAAG;IASxC,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;;;;;IAcjD,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;;;;;IAMvD,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE;;;;;;;IAMtE,eAAe,CAAC,aAAa,KAAA;IAW7B,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAMpF,gBAAgB,CAAC,OAAO,EAAE,GAAG;;;;;;;IA0D7B,cAAc,CACvB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,OAAO,EACf,MAAM,CAAC,EAAE,OAAO,EAChB,sBAAsB,CAAC,EAAE,MAAM,EAAE;;;;;;;IAKxB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;;;;;;;CASrE"}
|
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
import {__decorate,__param,__metadata}from'tslib';import {pick,get,isEmpty,filter}from'lodash-es';import {injectable,inject,optional}from'inversify';import*as mongoose from'mongoose';import'@cdm-logger/core';import {
|
|
2
|
-
let RegistryExtensionRepository = RegistryExtensionRepository_1 = class RegistryExtensionRepository {
|
|
3
|
-
logger;
|
|
4
|
-
repositoryExtensionModel;
|
|
1
|
+
import {__decorate,__param,__metadata}from'tslib';import {pick,get,isEmpty,filter}from'lodash-es';import {injectable,inject,optional}from'inversify';import*as mongoose from'mongoose';import'@cdm-logger/core';import {BaseMongoRepository}from'@common-stack/store-mongo';import {RegistryExtensionModelFunc}from'../models/registry-extension-model.js';import'../models/installed-extension-model.js';var RegistryExtensionRepository_1;
|
|
2
|
+
let RegistryExtensionRepository = RegistryExtensionRepository_1 = class RegistryExtensionRepository extends BaseMongoRepository {
|
|
5
3
|
constructor(db, logger, options) {
|
|
4
|
+
super(RegistryExtensionModelFunc, db, logger, options);
|
|
5
|
+
if (!db) {
|
|
6
|
+
throw new Error('MongoDB connection is not provided');
|
|
7
|
+
}
|
|
6
8
|
this.logger = logger.child({
|
|
7
9
|
className: RegistryExtensionRepository_1.name
|
|
8
10
|
});
|
|
9
|
-
this.repositoryExtensionModel = RegistryExtensionModelFunc(db);
|
|
10
11
|
}
|
|
11
12
|
async createExtension(publisherId, name) {
|
|
12
13
|
this.logger.trace('createExtension with publisherId [%s], name [%s]', publisherId, name);
|
|
13
|
-
|
|
14
|
+
const result = await this.model.create({
|
|
14
15
|
publisherId,
|
|
15
16
|
name,
|
|
16
17
|
manifest: null,
|
|
17
18
|
uuid: '',
|
|
18
19
|
releases: null,
|
|
19
|
-
|
|
20
|
+
extensionSlug: ''
|
|
20
21
|
});
|
|
22
|
+
return result;
|
|
21
23
|
}
|
|
22
|
-
async updateExtensionName(
|
|
23
|
-
this.logger.trace('updateExtensionName with extension [%s], name [%s]',
|
|
24
|
-
await this.
|
|
25
|
-
|
|
24
|
+
async updateExtensionName(extensionSlug, name) {
|
|
25
|
+
this.logger.trace('updateExtensionName with extension [%s], name [%s]', extensionSlug, name);
|
|
26
|
+
await this.model.update({
|
|
27
|
+
extensionSlug
|
|
26
28
|
}, {
|
|
27
29
|
$set: {
|
|
28
30
|
name
|
|
@@ -30,45 +32,45 @@ let RegistryExtensionRepository = RegistryExtensionRepository_1 = class Registry
|
|
|
30
32
|
}, {
|
|
31
33
|
upsert: true
|
|
32
34
|
});
|
|
33
|
-
return this.
|
|
34
|
-
|
|
35
|
+
return this.model.findOne({
|
|
36
|
+
extensionSlug
|
|
35
37
|
}).exec();
|
|
36
38
|
}
|
|
37
|
-
async updateExtension(
|
|
38
|
-
this.logger.trace('updateExtension with extension [%s], update [%j]',
|
|
39
|
-
await this.
|
|
40
|
-
|
|
39
|
+
async updateExtension(extensionSlug, update) {
|
|
40
|
+
this.logger.trace('updateExtension with extension [%s], update [%j]', extensionSlug, update);
|
|
41
|
+
await this.model.update({
|
|
42
|
+
extensionSlug
|
|
41
43
|
}, {
|
|
42
44
|
$set: update
|
|
43
45
|
}, {
|
|
44
46
|
upsert: true
|
|
45
47
|
});
|
|
46
|
-
return this.
|
|
47
|
-
|
|
48
|
+
return this.model.findOne({
|
|
49
|
+
extensionSlug
|
|
48
50
|
}).exec();
|
|
49
51
|
}
|
|
50
|
-
async deleteExtension(
|
|
52
|
+
async deleteExtension(extensionSlug) {
|
|
51
53
|
try {
|
|
52
|
-
this.logger.trace('deleteExtension with
|
|
53
|
-
const deleteRecord = await this.
|
|
54
|
-
|
|
54
|
+
this.logger.trace('deleteExtension with extensionSlug [%s]', extensionSlug);
|
|
55
|
+
const deleteRecord = await this.model.deleteOne({
|
|
56
|
+
extensionSlug
|
|
55
57
|
}).exec();
|
|
56
58
|
return deleteRecord.acknowledged && deleteRecord.deletedCount === 1;
|
|
57
59
|
} catch (err) {
|
|
58
|
-
this.logger.error(err, 'delete account with payload [%s] failed due to [%o]',
|
|
60
|
+
this.logger.error(err, 'delete account with payload [%s] failed due to [%o]', extensionSlug);
|
|
59
61
|
return false;
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
|
-
async extensionReleases(
|
|
63
|
-
const extension = await this.findExtension(
|
|
64
|
+
async extensionReleases(extensionSlug) {
|
|
65
|
+
const extension = await this.findExtension(extensionSlug);
|
|
64
66
|
return extension.releases;
|
|
65
67
|
}
|
|
66
68
|
// TODO: change param to IPublishRequest
|
|
67
69
|
async publishExtension(request) {
|
|
68
|
-
let extension = await this.
|
|
69
|
-
|
|
70
|
+
let extension = await this.model.findOne({
|
|
71
|
+
extensionSlug: request.extensionSlug
|
|
70
72
|
}).exec();
|
|
71
|
-
const obj = pick(request, ['
|
|
73
|
+
const obj = pick(request, ['extensionSlug', 'name', 'description', 'publisher']);
|
|
72
74
|
let manifest = {};
|
|
73
75
|
try {
|
|
74
76
|
manifest = JSON.parse(request.manifest);
|
|
@@ -77,20 +79,20 @@ let RegistryExtensionRepository = RegistryExtensionRepository_1 = class Registry
|
|
|
77
79
|
obj.activationEvents = manifest.activationEvents || [];
|
|
78
80
|
if (!extension) {
|
|
79
81
|
this.logger.debug('New extension created...');
|
|
80
|
-
extension = await this.
|
|
82
|
+
extension = await this.model.create(obj);
|
|
81
83
|
}
|
|
82
84
|
const release = {
|
|
83
85
|
bundle: request.bundle,
|
|
84
86
|
version: request.version,
|
|
85
87
|
manifest: request.manifest,
|
|
86
88
|
sourceMap: request.sourceMap,
|
|
87
|
-
|
|
89
|
+
extensionSlug: request.extensionSlug,
|
|
88
90
|
activationEvents: manifest.activationEvents
|
|
89
91
|
};
|
|
90
92
|
try {
|
|
91
93
|
this.logger.trace('publishExtension with request [%j]', request);
|
|
92
|
-
const releaseExists = await this.
|
|
93
|
-
|
|
94
|
+
const releaseExists = await this.model.findOne({
|
|
95
|
+
extensionSlug: request.extensionSlug,
|
|
94
96
|
'releases.version': request.version
|
|
95
97
|
});
|
|
96
98
|
if (!isEmpty(extension.releases) && releaseExists && !request.force) {
|
|
@@ -99,8 +101,8 @@ let RegistryExtensionRepository = RegistryExtensionRepository_1 = class Registry
|
|
|
99
101
|
} else {
|
|
100
102
|
const releases = filter(extension.releases, record => record.version !== request.version).concat([release]);
|
|
101
103
|
this.logger.trace('Release updates [%j]', releases);
|
|
102
|
-
await this.
|
|
103
|
-
|
|
104
|
+
await this.model.update({
|
|
105
|
+
extensionSlug: request.extensionSlug
|
|
104
106
|
}, {
|
|
105
107
|
$set: {
|
|
106
108
|
...obj,
|
|
@@ -111,8 +113,8 @@ let RegistryExtensionRepository = RegistryExtensionRepository_1 = class Registry
|
|
|
111
113
|
upsert: true
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
|
-
return this.
|
|
115
|
-
|
|
116
|
+
return this.model.findOne({
|
|
117
|
+
extensionSlug: request.extensionSlug
|
|
116
118
|
}).exec();
|
|
117
119
|
} catch (err) {
|
|
118
120
|
this.logger.error(err, 'publishExtension was failed for request [%j] with error[%o]', request);
|
|
@@ -120,16 +122,16 @@ let RegistryExtensionRepository = RegistryExtensionRepository_1 = class Registry
|
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
async findExtensions(first, query, local, remote, prioritizeExtensionIDs) {
|
|
123
|
-
return this.
|
|
125
|
+
return this.model.find({}).exec();
|
|
124
126
|
}
|
|
125
|
-
async findExtension(
|
|
127
|
+
async findExtension(extensionSlug, version) {
|
|
126
128
|
const q = {
|
|
127
|
-
|
|
129
|
+
extensionSlug
|
|
128
130
|
};
|
|
129
131
|
if (version) {
|
|
130
132
|
q.version = version;
|
|
131
133
|
}
|
|
132
|
-
return this.
|
|
134
|
+
return this.model.findOne(q);
|
|
133
135
|
}
|
|
134
136
|
};
|
|
135
|
-
RegistryExtensionRepository = RegistryExtensionRepository_1 = __decorate([injectable(), __param(0, inject(
|
|
137
|
+
RegistryExtensionRepository = RegistryExtensionRepository_1 = __decorate([injectable(), __param(0, inject('MongoDBConnection')), __param(1, inject('Logger')), __param(2, inject('MongoOptions')), __param(2, optional()), __metadata("design:paramtypes", [mongoose.Connection, Object, Object])], RegistryExtensionRepository);export{RegistryExtensionRepository};//# sourceMappingURL=registry-extension-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-extension-repository.js","sources":["../../../src/store/repositories/registry-extension-repository.ts"],"sourcesContent":[null],"names":[],"mappings":"0YAGA,IAAA,6BAA0B;;;;;AAqCT,MAAA,MAAA,IAAA,KAAA,CAAA,oCAAuD,CAAA;;;;;;;AAMvD,IAAA,IAAA,CAAA,MAAA,CAAA,KAA6B,CAAA,kDAAkB,EAAA,WAAA,EAAA,IAAA,CAAA;UAAW,MAAA,GAAG,MAAA,IAAO,CAAA,KAAA,CAAA,MAAA,CAAA;AAAE,MAAA,WAAA;;;;;;;IAMtE,OAAe,MAAA;AAWf;QAMgB,mBAAQ,CAAA,aAAK,EAAA,IAAA,EAAA;;;;;;;;;;;;;;;;;;;;;AA6E7C,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,4 +3,7 @@ export const SERVER_TYPES = {
|
|
|
3
3
|
IExtensionMongoConnection: Symbol('ExtensionMongoConnection'),
|
|
4
4
|
IRegistryExtensionService: Symbol('IRegistryExtensionService'),
|
|
5
5
|
IRegistryExtensionRepository: Symbol('IRegistryExtensionRepository'),
|
|
6
|
+
IRegistryExtensionDataLoader: Symbol('IRegistryExtensionDataLoader'),
|
|
7
|
+
IInstalledExtensionService: Symbol('IInstalledExtensionService'),
|
|
8
|
+
IInstalledExtensionRepository: Symbol('IInstalledExtensionRepository'),
|
|
6
9
|
};
|