@adminide-stack/marketplace-module-server 12.0.4-alpha.95 → 13.0.1-alpha.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 (175) hide show
  1. package/lib/containers/module.d.ts +4 -4
  2. package/lib/containers/module.d.ts.map +1 -1
  3. package/lib/containers/module.js +12 -7
  4. package/lib/containers/module.js.map +1 -1
  5. package/lib/dataloaders/index.d.ts +1 -1
  6. package/lib/dataloaders/index.d.ts.map +1 -1
  7. package/lib/dataloaders/publisher-data-loader.d.ts +6 -0
  8. package/lib/dataloaders/publisher-data-loader.d.ts.map +1 -0
  9. package/lib/demo/test-graphql-examples.d.ts +73 -0
  10. package/lib/demo/test-graphql-examples.d.ts.map +1 -0
  11. package/lib/graphql/resolvers/form-templates-resolver.d.ts +220 -0
  12. package/lib/graphql/resolvers/form-templates-resolver.d.ts.map +1 -0
  13. package/lib/graphql/resolvers/form-templates-resolver.js +170 -0
  14. package/lib/graphql/resolvers/form-templates-resolver.js.map +1 -0
  15. package/lib/graphql/resolvers/gallery-resolver.d.ts +15 -0
  16. package/lib/graphql/resolvers/gallery-resolver.d.ts.map +1 -0
  17. package/lib/graphql/resolvers/gallery-resolver.js +35 -0
  18. package/lib/graphql/resolvers/gallery-resolver.js.map +1 -0
  19. package/lib/graphql/resolvers/index.d.ts +247 -1
  20. package/lib/graphql/resolvers/index.d.ts.map +1 -1
  21. package/lib/graphql/resolvers/index.js +1 -1
  22. package/lib/graphql/resolvers/installed-extension-resolver.d.ts.map +1 -1
  23. package/lib/graphql/resolvers/installed-extension-resolver.js +161 -35
  24. package/lib/graphql/resolvers/installed-extension-resolver.js.map +1 -1
  25. package/lib/graphql/resolvers/marketplace-form-resolver.d.ts +13 -0
  26. package/lib/graphql/resolvers/marketplace-form-resolver.d.ts.map +1 -0
  27. package/lib/graphql/resolvers/marketplace-form-resolver.js +90 -0
  28. package/lib/graphql/resolvers/marketplace-form-resolver.js.map +1 -0
  29. package/lib/graphql/resolvers/publisher-analytics-resolver.d.ts +14 -0
  30. package/lib/graphql/resolvers/publisher-analytics-resolver.d.ts.map +1 -0
  31. package/lib/graphql/resolvers/publisher-analytics-resolver.js +221 -0
  32. package/lib/graphql/resolvers/publisher-analytics-resolver.js.map +1 -0
  33. package/lib/graphql/resolvers/publisher-resolver.d.ts +5 -0
  34. package/lib/graphql/resolvers/publisher-resolver.d.ts.map +1 -0
  35. package/lib/graphql/resolvers/publisher-resolver.js +183 -0
  36. package/lib/graphql/resolvers/publisher-resolver.js.map +1 -0
  37. package/lib/graphql/resolvers/registry-extension-resolver.d.ts.map +1 -1
  38. package/lib/graphql/resolvers/registry-extension-resolver.js +34 -167
  39. package/lib/graphql/resolvers/registry-extension-resolver.js.map +1 -1
  40. package/lib/graphql/schemas/extension-pricing.graphql +546 -0
  41. package/lib/graphql/schemas/extension-pricing.graphql.js +1 -0
  42. package/lib/graphql/schemas/extension-pricing.graphql.js.map +1 -0
  43. package/lib/graphql/schemas/extension-registry.graphql +91 -58
  44. package/lib/graphql/schemas/extension-registry.graphql.js +1 -1
  45. package/lib/graphql/schemas/form-templates.graphql +269 -0
  46. package/lib/graphql/schemas/form-templates.graphql.js +1 -0
  47. package/lib/graphql/schemas/form-templates.graphql.js.map +1 -0
  48. package/lib/graphql/schemas/gallery-schema.graphql +247 -0
  49. package/lib/graphql/schemas/gallery-schema.graphql.js +1 -0
  50. package/lib/graphql/schemas/gallery-schema.graphql.js.map +1 -0
  51. package/lib/graphql/schemas/index.d.ts.map +1 -1
  52. package/lib/graphql/schemas/index.js +3 -1
  53. package/lib/graphql/schemas/index.js.map +1 -1
  54. package/lib/graphql/schemas/installed-extension.graphql +37 -7
  55. package/lib/graphql/schemas/installed-extension.graphql.js +1 -1
  56. package/lib/graphql/schemas/publisher-analytics.graphql +305 -0
  57. package/lib/graphql/schemas/publisher-analytics.graphql.js +1 -0
  58. package/lib/graphql/schemas/publisher-analytics.graphql.js.map +1 -0
  59. package/lib/graphql/schemas/publisher.graphql +584 -0
  60. package/lib/graphql/schemas/publisher.graphql.js +1 -0
  61. package/lib/graphql/schemas/publisher.graphql.js.map +1 -0
  62. package/lib/graphql/schemas/service.graphql +15 -0
  63. package/lib/index.d.ts +1 -1
  64. package/lib/index.js +1 -1
  65. package/lib/index.js.map +1 -1
  66. package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.d.ts +20 -0
  67. package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.d.ts.map +1 -0
  68. package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.js +61 -0
  69. package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.js.map +1 -0
  70. package/lib/migrations/index.d.ts +2 -0
  71. package/lib/migrations/index.d.ts.map +1 -0
  72. package/lib/module.d.ts +1 -1
  73. package/lib/module.d.ts.map +1 -1
  74. package/lib/module.js +11 -26
  75. package/lib/module.js.map +1 -1
  76. package/lib/services/extension-gallery-repository.d.ts +17 -0
  77. package/lib/services/extension-gallery-repository.d.ts.map +1 -0
  78. package/lib/services/extension-gallery-repository.js +192 -0
  79. package/lib/services/extension-gallery-repository.js.map +1 -0
  80. package/lib/services/extension-gallery-service-new.d.ts +39 -0
  81. package/lib/services/extension-gallery-service-new.d.ts.map +1 -0
  82. package/lib/services/extension-gallery-service.d.ts +30 -0
  83. package/lib/services/extension-gallery-service.d.ts.map +1 -0
  84. package/lib/services/extension-gallery-service.js +334 -0
  85. package/lib/services/extension-gallery-service.js.map +1 -0
  86. package/lib/services/index.d.ts +4 -1
  87. package/lib/services/index.d.ts.map +1 -1
  88. package/lib/services/installed-extension-service-ext.d.ts +5 -2
  89. package/lib/services/installed-extension-service-ext.d.ts.map +1 -1
  90. package/lib/services/installed-extension-service-ext.js +364 -117
  91. package/lib/services/installed-extension-service-ext.js.map +1 -1
  92. package/lib/services/installed-extension-service.d.ts +30 -13
  93. package/lib/services/installed-extension-service.d.ts.map +1 -1
  94. package/lib/services/installed-extension-service.js +301 -68
  95. package/lib/services/installed-extension-service.js.map +1 -1
  96. package/lib/services/installed-extension-service.test.d.ts +0 -1
  97. package/lib/services/publisher-analytics-service.d.ts +128 -0
  98. package/lib/services/publisher-analytics-service.d.ts.map +1 -0
  99. package/lib/services/publisher-event-service.d.ts +48 -0
  100. package/lib/services/publisher-event-service.d.ts.map +1 -0
  101. package/lib/services/publisher-event-service.js +296 -0
  102. package/lib/services/publisher-event-service.js.map +1 -0
  103. package/lib/services/publisher-service-context.d.ts +1 -0
  104. package/lib/services/publisher-service-context.d.ts.map +1 -0
  105. package/lib/services/publisher-service.d.ts +62 -0
  106. package/lib/services/publisher-service.d.ts.map +1 -0
  107. package/lib/services/publisher-service.js +135 -0
  108. package/lib/services/publisher-service.js.map +1 -0
  109. package/lib/store/models/index.d.ts +1 -1
  110. package/lib/store/models/index.d.ts.map +1 -1
  111. package/lib/store/models/installed-extension-model.d.ts.map +1 -1
  112. package/lib/store/models/installed-extension-model.js +17 -45
  113. package/lib/store/models/installed-extension-model.js.map +1 -1
  114. package/lib/store/models/publisher-event-model.d.ts +11 -0
  115. package/lib/store/models/publisher-event-model.d.ts.map +1 -0
  116. package/lib/store/models/publisher-model.d.ts +5 -0
  117. package/lib/store/models/publisher-model.d.ts.map +1 -0
  118. package/lib/store/models/publisher-model.js +117 -0
  119. package/lib/store/models/publisher-model.js.map +1 -0
  120. package/lib/store/models/publisher-stats-model.d.ts +1 -0
  121. package/lib/store/models/publisher-stats-model.d.ts.map +1 -0
  122. package/lib/store/repositories/index.d.ts +1 -1
  123. package/lib/store/repositories/index.d.ts.map +1 -1
  124. package/lib/store/repositories/installed-extension-repository.d.ts +17 -11
  125. package/lib/store/repositories/installed-extension-repository.d.ts.map +1 -1
  126. package/lib/store/repositories/installed-extension-repository.js +123 -75
  127. package/lib/store/repositories/installed-extension-repository.js.map +1 -1
  128. package/lib/store/repositories/publisher-analytics-repository.d.ts +1 -0
  129. package/lib/store/repositories/publisher-analytics-repository.d.ts.map +1 -0
  130. package/lib/store/repositories/publisher-repository.d.ts +19 -0
  131. package/lib/store/repositories/publisher-repository.d.ts.map +1 -0
  132. package/lib/store/repositories/publisher-repository.js +87 -0
  133. package/lib/store/repositories/publisher-repository.js.map +1 -0
  134. package/lib/templates/constants/DB_COLL_NAMES.ts.template +1 -1
  135. package/lib/templates/constants/SERVER_TYPES.ts.template +8 -5
  136. package/lib/templates/repositories/ExtensionGalleryRepository.ts.template +44 -0
  137. package/lib/templates/repositories/InstalledExtensionRepository.ts.template +19 -14
  138. package/lib/templates/repositories/MarketplacePublisherRepository.ts.template +24 -0
  139. package/lib/templates/repositories/RegistryExtensionRepository.ts.template +2 -2
  140. package/lib/templates/services/ExtensionGalleryDataLoader.ts.template +2 -0
  141. package/lib/templates/services/ExtensionGalleryService.ts.template +79 -0
  142. package/lib/templates/services/InstalledExtensionService.ts.template +63 -32
  143. package/lib/templates/services/MarketplacePublisherService.ts.template +51 -0
  144. package/lib/templates/services/PublisherDataLoader.ts.template +3 -0
  145. package/lib/templates/services/PublisherEventService.ts.template +56 -0
  146. package/lib/templates/services/RegistryExtensionService.ts.template +46 -2
  147. package/lib/tests/extension-integration.test.d.ts +0 -1
  148. package/lib/tests/install-extension-graphql.test.d.ts +2 -0
  149. package/lib/tests/install-extension-graphql.test.d.ts.map +1 -0
  150. package/lib/utils/publisherValidation.d.ts +23 -0
  151. package/lib/utils/publisherValidation.d.ts.map +1 -0
  152. package/lib/utils/publisherValidation.js +144 -0
  153. package/lib/utils/publisherValidation.js.map +1 -0
  154. package/package.json +13 -9
  155. package/lib/constants/extension-events.d.ts +0 -136
  156. package/lib/constants/extension-events.d.ts.map +0 -1
  157. package/lib/dataloaders/registry-extension-data-loader.d.ts +0 -6
  158. package/lib/dataloaders/registry-extension-data-loader.d.ts.map +0 -1
  159. package/lib/dataloaders/registry-extension-data-loader.js +0 -6
  160. package/lib/dataloaders/registry-extension-data-loader.js.map +0 -1
  161. package/lib/graphql/schemas/service.graphql.js +0 -1
  162. package/lib/graphql/schemas/service.graphql.js.map +0 -1
  163. package/lib/services/extension-service.d.ts +0 -42
  164. package/lib/services/extension-service.d.ts.map +0 -1
  165. package/lib/services/extension-service.js +0 -60
  166. package/lib/services/extension-service.js.map +0 -1
  167. package/lib/store/models/registry-extension-model.d.ts +0 -5
  168. package/lib/store/models/registry-extension-model.d.ts.map +0 -1
  169. package/lib/store/models/registry-extension-model.js +0 -83
  170. package/lib/store/models/registry-extension-model.js.map +0 -1
  171. package/lib/store/repositories/registry-extension-repository.d.ts +0 -54
  172. package/lib/store/repositories/registry-extension-repository.d.ts.map +0 -1
  173. package/lib/store/repositories/registry-extension-repository.js +0 -137
  174. package/lib/store/repositories/registry-extension-repository.js.map +0 -1
  175. package/lib/templates/services/RegistryExtensionDataLoader.ts.template +0 -2
@@ -1,10 +1,61 @@
1
- import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import {ServiceBroker}from'moleculer';import {CommonType}from'@common-stack/core';import'@cdm-logger/core';import {SERVER_TYPES,ConfigurationSchemaId,ContributionRegistryServiceEvent,MoleculerServiceName,SystemContributionExtensionNames,ExtensionServiceAction}from'common/server';import {InstalledExtensionService}from'./installed-extension-service.js';/**
1
+ import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import {ServiceBroker}from'moleculer';import {CommonType}from'@common-stack/core';import'@cdm-logger/core';import {SERVER_TYPES,ContributionFragmentName,ConfigurationSchemaId,SystemContributionExtensionNames,ExtensionServiceAction,MoleculerServiceName}from'common/server';import {InstalledExtensionService}from'./installed-extension-service.js';/**
2
+ * Convert scope string values from package.json to ConfigurationScope enum numbers
3
+ * Maps: "application" -> 1, "machine" -> 2, "window" -> 3, "resource" -> 4
4
+ */
5
+ function convertScopeStringToNumber(scope) {
6
+ if (typeof scope === 'number') {
7
+ return scope; // Already a number
8
+ }
9
+ if (typeof scope === 'string') {
10
+ const scopeMap = {
11
+ application: 1 /* ConfigurationScope.APPLICATION */,
12
+ machine: 2 /* ConfigurationScope.MACHINE */,
13
+ window: 3 /* ConfigurationScope.WINDOW */,
14
+ resource: 4 /* ConfigurationScope.RESOURCE */
15
+ };
16
+ const normalizedScope = scope.toLowerCase();
17
+ if (normalizedScope in scopeMap) {
18
+ return scopeMap[normalizedScope];
19
+ }
20
+ console.warn(`Unknown scope string: "${scope}", defaulting to WINDOW`);
21
+ }
22
+ // Default to WINDOW scope if undefined or unknown
23
+ return 3 /* ConfigurationScope.WINDOW */;
24
+ }
25
+ /**
26
+ * Recursively process configuration properties to convert scope strings to numbers
27
+ */
28
+ function processConfigurationProperties(properties) {
29
+ if (!properties || typeof properties !== 'object') {
30
+ return properties;
31
+ }
32
+ const processedProperties = {
33
+ ...properties
34
+ };
35
+ for (const [key, value] of Object.entries(processedProperties)) {
36
+ if (value && typeof value === 'object') {
37
+ const objectValue = value;
38
+ // If this property has a scope, convert it
39
+ if ('scope' in objectValue) {
40
+ objectValue.scope = convertScopeStringToNumber(objectValue.scope);
41
+ }
42
+ // Recursively process nested properties
43
+ processedProperties[key] = processConfigurationProperties(objectValue);
44
+ }
45
+ }
46
+ return processedProperties;
47
+ }
48
+ /**
2
49
  * Extended InstalledExtensionService that handles Moleculer event broadcasting
3
50
  * Follows the pattern of AccountService/AccountServiceExt
4
51
  */
5
52
  let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends InstalledExtensionService {
6
- constructor(repository, registryService, broker, logger) {
7
- super(repository, registryService, broker, logger);
53
+ slugService;
54
+ redisCacheManager;
55
+ constructor(repository, registryService, slugService, redisCacheManager, broker, logger) {
56
+ super(repository, registryService, slugService, broker, logger);
57
+ this.slugService = slugService;
58
+ this.redisCacheManager = redisCacheManager;
8
59
  this.setupEventListeners();
9
60
  }
10
61
  setupEventListeners() {
@@ -16,24 +67,20 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
16
67
  const registryExtension = await this.registryExtensionService.findExtension(event.extensionSlug);
17
68
  let configurationNodes = [];
18
69
  let configurationDefaults = [];
19
- if (registryExtension && registryExtension.manifest) {
20
- console.log('Extension found with manifest:', event.extensionSlug);
21
- console.log('Manifest object keys:', Object.keys(registryExtension.manifest));
22
- // The manifest is now properly parsed by the model's virtual property
23
- let contributes = null;
24
- // Check if manifest has contributes directly (cast to access contributes property)
25
- const manifestAny = registryExtension.manifest;
26
- if (manifestAny.contributes) {
27
- contributes = manifestAny.contributes;
28
- console.log('Found parsed contributes:', Object.keys(contributes));
29
- }
30
- // Fallback: try to parse raw if contributes not found but raw exists
31
- else if (registryExtension.manifest.raw) {
70
+ if (registryExtension) {
71
+ console.log('Extension found:', event.extensionSlug);
72
+ // Get the current release to access the manifest
73
+ // The manifest is stored in the release, not directly in the registry extension
74
+ const currentRelease = registryExtension.releases?.find(release => release.version === registryExtension.version);
75
+ if (currentRelease && currentRelease.manifest) {
76
+ console.log('Found current release with manifest:', registryExtension.version);
77
+ let contributes = null;
78
+ let parsedManifest = null;
32
79
  try {
33
- const parsedManifest = JSON.parse(registryExtension.manifest.raw);
80
+ // Parse the manifest from the release (stored as JSON string)
81
+ parsedManifest = typeof currentRelease.manifest === 'string' ? JSON.parse(currentRelease.manifest) : currentRelease.manifest;
34
82
  console.log('Parsed manifest keys:', Object.keys(parsedManifest));
35
83
  contributes = parsedManifest.contributes;
36
- console.log('Parsed contributes from manifest.raw:', contributes ? 'found' : 'not found');
37
84
  if (contributes) {
38
85
  console.log('Contributes keys:', Object.keys(contributes));
39
86
  console.log('Configuration exists:', !!contributes.configuration);
@@ -42,68 +89,78 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
42
89
  }
43
90
  }
44
91
  } catch (error) {
45
- console.warn('Failed to parse extension manifest.raw:', error);
92
+ console.warn('Failed to parse release manifest:', error);
46
93
  }
47
- } else {
48
- console.log('No manifest.raw found');
49
- }
50
- // Extract configuration contributions if they exist
51
- if (contributes && contributes.configuration) {
52
- console.log('Configuration contributions found, processing...');
53
- const configurations = Array.isArray(contributes.configuration) ? contributes.configuration : [contributes.configuration];
54
- // Format contributions for configuration registry
55
- configurationNodes = configurations.map(config => ({
56
- id: `${event.extensionSlug}`,
57
- title: config.title || registryExtension.name,
58
- description: config.description || registryExtension.manifest.description,
59
- properties: config.properties || {},
60
- type: config.type || ['object'],
61
- scope: 'WINDOW',
62
- // Default scope
63
- extensionInfo: {
64
- id: event.extensionSlug,
65
- displayName: registryExtension.name
94
+ // Extract configuration contributions if they exist
95
+ if (contributes && contributes.configuration) {
96
+ console.log('Configuration contributions found, processing...');
97
+ const configurations = Array.isArray(contributes.configuration) ? contributes.configuration : [contributes.configuration];
98
+ // Format contributions for configuration registry
99
+ configurationNodes = configurations.map(config => {
100
+ // Process properties to convert scope strings to numbers
101
+ const processedProperties = processConfigurationProperties(config.properties || {});
102
+ return {
103
+ id: ContributionFragmentName.Settings,
104
+ title: config.title || registryExtension.name,
105
+ description: config.description,
106
+ properties: processedProperties,
107
+ type: config.type || ['object']
108
+ };
109
+ });
110
+ // Create configuration defaults
111
+ configurationDefaults = [{
112
+ source: {
113
+ id: event.extensionSlug,
114
+ displayName: registryExtension.name
115
+ },
116
+ overrides: {} // Default empty overrides
117
+ }];
118
+ console.log(`Processed ${configurationNodes.length} configuration nodes`);
119
+ } else {
120
+ console.log('No configuration contributions found in manifest');
121
+ }
122
+ console.log('CONTRIBUTES========>', JSON.stringify(contributes));
123
+ // Extract UILayout contributions if they exist (same structure as configuration)
124
+ if (contributes && contributes.uiLayout) {
125
+ console.log('UILayout contributions found, processing...');
126
+ const uiLayoutContributions = Array.isArray(contributes.uiLayout) ? contributes.uiLayout : [contributes.uiLayout];
127
+ console.log(`Found ${uiLayoutContributions.length} UILayout contribution(s) in manifest`);
128
+ // Format UILayout contributions (same structure as configuration)
129
+ const uiLayoutNodes = uiLayoutContributions.map(uiLayout => {
130
+ // Process properties to convert scope strings to numbers (same as configuration)
131
+ const processedProperties = processConfigurationProperties(uiLayout.properties || {});
132
+ return {
133
+ id: ContributionFragmentName.Settings,
134
+ title: uiLayout.title || registryExtension.name,
135
+ description: uiLayout.description,
136
+ properties: processedProperties,
137
+ type: uiLayout.type || ['object']
138
+ };
139
+ });
140
+ if (uiLayoutNodes.length > 0) {
141
+ console.log(`Registering ${uiLayoutNodes.length} UILayout configuration nodes`);
142
+ try {
143
+ // Register UILayout contributions (exact same as configuration, just different schema)
144
+ await this.broker.call('ConfigurationRegistryService.registerUILayoutContributions', {
145
+ tenantId: event.tenantId,
146
+ extensionID: event.extensionSlug,
147
+ uiLayoutNodes
148
+ });
149
+ console.log(`✅ UILayout contributions registered successfully for ${event.extensionSlug}`);
150
+ } catch (uiLayoutError) {
151
+ console.error('❌ Failed to register UILayout contributions:', uiLayoutError);
152
+ // This is not fatal, log and continue
153
+ }
66
154
  }
67
- }));
68
- // Create configuration defaults
69
- configurationDefaults = [{
70
- source: {
71
- id: event.extensionSlug,
72
- displayName: registryExtension.name
73
- },
74
- overrides: {} // Default empty overrides
75
- }];
76
- console.log(`Processed ${configurationNodes.length} configuration nodes`);
155
+ } else {
156
+ console.log('No UILayout contributions found in manifest');
157
+ }
77
158
  } else {
78
- console.log('No configuration contributions found in manifest');
159
+ console.log('No current release or manifest found for version:', registryExtension.version);
79
160
  }
80
161
  } else {
81
- console.log('No extension or manifest found for:', event.extensionSlug);
162
+ console.log('No extension found for:', event.extensionSlug);
82
163
  }
83
- // Add the extension's enabled/disabled state to configuration nodes
84
- // This tracks the extension status regardless of whether it has configuration contributions
85
- const extensionStatusNode = {
86
- id: `${event.extensionSlug}.status`,
87
- title: `${registryExtension?.name || event.extensionSlug} Status`,
88
- description: `Extension enabled/disabled status for ${event.extensionSlug}`,
89
- properties: {
90
- [`extensions.${event.extensionSlug}`]: {
91
- type: 'boolean',
92
- default: true,
93
- // Default to enabled when installed
94
- description: `Enable/disable ${event.extensionSlug} extension`,
95
- scope: 'window'
96
- }
97
- },
98
- type: ['object'],
99
- scope: 3 /* ConfigurationScope.WINDOW */,
100
- extensionInfo: {
101
- id: event.extensionSlug,
102
- displayName: registryExtension?.name || event.extensionSlug
103
- }
104
- };
105
- // Add the extension status node to configurationNodes
106
- // configurationNodes.push(extensionStatusNode);
107
164
  // Create the configuration node data that configuration registry expects
108
165
  const configurationNode = {
109
166
  schemaId: ConfigurationSchemaId.Configuration,
@@ -127,67 +184,224 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
127
184
  },
128
185
  context
129
186
  });
130
- this.broker.broadcast(ContributionRegistryServiceEvent.ContributionNodeRegistryAdd, {
131
- configurationNode,
132
- context,
133
- timestamp: new Date()
134
- }, [MoleculerServiceName.ConfigurationRegistryService
135
- // MoleculerServiceName.MailService, // Using MailService instead of NotificationService
136
- ]);
137
- // Create separate configuration node for system extension status
138
- const systemExtensionNode = {
139
- schemaId: ConfigurationSchemaId.Configuration,
140
- tenantId: event.tenantId,
141
- extensionName: SystemContributionExtensionNames.SystemExtension,
142
- policyConfigs: null,
143
- configurationNodes: [extensionStatusNode]
144
- };
187
+ // STEP 1: MANDATORY - Register extension in system_extension FIRST (REQUIRED FOR ALL EXTENSIONS)
188
+ console.log('\n🔧 STEP 1: Registering extension in SYSTEM_EXTENSION (MANDATORY)');
145
189
  const systemContext = {
146
190
  schemaId: ConfigurationSchemaId.Configuration,
147
191
  tenantId: event.tenantId,
148
192
  extensionName: SystemContributionExtensionNames.SystemExtension,
149
193
  accountId: event.installedBy
150
194
  };
151
- this.broker.broadcast(ContributionRegistryServiceEvent.ContributionNodeRegistryAdd, {
152
- configurationNode: systemExtensionNode,
153
- context: systemContext,
154
- timestamp: new Date()
155
- }, [MoleculerServiceName.ConfigurationRegistryService
156
- // MoleculerServiceName.MailService, // Using MailService instead of NotificationService
157
- ]);
195
+ let systemExtensionRegistered = false;
196
+ try {
197
+ console.log('Fetching current system_extension document...');
198
+ // Get existing system_extension document
199
+ const existingSystemDoc = await this.broker.call('ConfigurationRegistryService.getConfigurationNodeRegistry', {
200
+ context: systemContext
201
+ });
202
+ // Prepare the merged configuration node
203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
204
+ const mergedNode = {
205
+ id: ContributionFragmentName.Settings,
206
+ type: ['object'],
207
+ properties: {},
208
+ restrictedProperties: []
209
+ };
210
+ // If document exists, merge existing properties
211
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
212
+ if (existingSystemDoc && existingSystemDoc.configurationNodes) {
213
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
214
+ const existingNodes = existingSystemDoc.configurationNodes || [];
215
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
216
+ const existingSettingsNode = existingNodes.find(
217
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
218
+ node => node.id === ContributionFragmentName.Settings);
219
+ if (existingSettingsNode?.properties) {
220
+ mergedNode.properties = {
221
+ ...existingSettingsNode.properties
222
+ };
223
+ const existingCount = Object.keys(existingSettingsNode.properties).length;
224
+ console.log(`📝 Merging with ${existingCount} existing properties`);
225
+ }
226
+ } else {
227
+ console.log('📝 Creating new system_extension document');
228
+ }
229
+ // Add/update the property for this extension
230
+ mergedNode.properties[`extensions.${event.extensionSlug}`] = {
231
+ type: 'boolean',
232
+ default: true,
233
+ description: `Enable/disable ${event.extensionSlug} extension`,
234
+ scope: 3 /* ConfigurationScope.WINDOW */
235
+ };
236
+ // Prepare final data
237
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
238
+ const finalSystemExtensionNode = {
239
+ schemaId: ConfigurationSchemaId.Configuration,
240
+ tenantId: event.tenantId,
241
+ extensionName: SystemContributionExtensionNames.SystemExtension,
242
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
243
+ policyConfigs: existingSystemDoc?.policyConfigs || null,
244
+ configurationNodes: [mergedNode],
245
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
246
+ configurationDefaults: existingSystemDoc?.configurationDefaults || []
247
+ };
248
+ // Use update if exists, create if new
249
+ const serviceMethod = existingSystemDoc ? 'ConfigurationRegistryService.updateConfigurationNodeRegistry' : 'ConfigurationRegistryService.createConfigurationNodeRegistry';
250
+ await this.broker.call(serviceMethod, {
251
+ data: finalSystemExtensionNode,
252
+ context: systemContext
253
+ });
254
+ systemExtensionRegistered = true;
255
+ const totalExtensions = Object.keys(mergedNode.properties).length;
256
+ console.log(`✅ STEP 1 SUCCESS: Extension registered (total: ${totalExtensions} extensions)`);
257
+ } catch (systemError) {
258
+ console.error('❌ STEP 1 FAILED: System extension registration failed:', systemError);
259
+ throw new Error(`Extension installation failed: Could not register in system (${systemError.message})`);
260
+ }
261
+ // STEP 2: CONDITIONAL - Create extension configuration ONLY IF CONTRIBUTIONS EXIST
262
+ let extensionConfigCreated = false;
263
+ if (configurationNodes.length > 0) {
264
+ console.log('\n📝 STEP 2: Creating extension configuration (contributions exist)');
265
+ try {
266
+ console.log('Broadcasting extension configuration registry...');
267
+ await this.broker.call('ConfigurationRegistryService.createConfigurationNodeRegistry', {
268
+ data: configurationNode,
269
+ context
270
+ });
271
+ extensionConfigCreated = true;
272
+ console.log('✅ STEP 2 SUCCESS: Extension configuration created');
273
+ } catch (configError) {
274
+ console.error('❌ STEP 2 FAILED: Extension configuration creation failed:', configError);
275
+ // This is not fatal since system extension is already registered
276
+ console.warn('⚠️ Extension is registered in system but configuration creation failed');
277
+ }
278
+ } else {
279
+ console.log('\nℹ️ STEP 2: Skipping extension configuration (no contributions found)');
280
+ }
281
+ await this.dropCache();
282
+ console.log('\n=== EXTENSION INSTALLATION COMPLETED ===');
283
+ console.log('System Extension Registered:', systemExtensionRegistered ? '✅' : '❌');
284
+ console.log('Extension Config Created:', extensionConfigCreated ? '✅' : 'ℹ️ Not needed');
285
+ console.log('Overall Installation:', systemExtensionRegistered ? '✅ SUCCESS' : '❌ FAILED');
158
286
  } catch (error) {
159
287
  console.error('Error processing extension installed event:', error);
160
288
  }
161
289
  });
162
290
  // Listen to extension uninstalled events
163
291
  this.onExtensionUninstalled.event(async event => {
292
+ console.log('=== EXTENSION UNINSTALLATION STARTED ===');
293
+ console.log('Extension slug:', event.extensionSlug);
294
+ console.log('Tenant:', event.tenantId);
295
+ let uninstallationSuccessful = false;
296
+ let extensionConfigRemoved = false;
297
+ let systemExtensionUpdated = false;
164
298
  try {
165
- // Remove extension status from configuration registry
299
+ // STEP 1: Remove the extension's own configuration registry entry (if it exists)
300
+ console.log('\n🗑️ STEP 1: Removing extension configuration registry');
166
301
  const context = {
167
302
  schemaId: ConfigurationSchemaId.Configuration,
168
303
  tenantId: event.tenantId,
169
304
  extensionName: event.extensionSlug,
170
305
  accountId: event.uninstalledBy
171
306
  };
172
- // Remove the extension's own configuration registry entry
173
- this.broker.broadcast(ContributionRegistryServiceEvent.ContributionNodeRegistryRemove, {
174
- context,
175
- timestamp: new Date()
176
- }, [MoleculerServiceName.ConfigurationRegistryService]);
177
- // Remove the extension status from system extensions
178
- const systemContext = {
179
- schemaId: ConfigurationSchemaId.Configuration,
180
- tenantId: event.tenantId,
181
- extensionName: SystemContributionExtensionNames.SystemExtension,
182
- accountId: event.uninstalledBy
183
- };
184
- this.broker.broadcast(ContributionRegistryServiceEvent.ContributionNodeRegistryRemove, {
185
- context: systemContext,
186
- timestamp: new Date()
187
- }, [MoleculerServiceName.ConfigurationRegistryService]);
307
+ try {
308
+ console.log('Removing extension configuration document...');
309
+ await this.broker.call('ConfigurationRegistryService.removeConfigurationNodeRegistry', {
310
+ context
311
+ });
312
+ extensionConfigRemoved = true;
313
+ console.log('✅ STEP 1 SUCCESS: Extension configuration removed');
314
+ } catch (configError) {
315
+ console.warn('⚠️ STEP 1 WARNING: Extension configuration removal failed (may not exist):', configError);
316
+ // This is not fatal - extension might not have had configuration
317
+ }
318
+ // STEP 1.5: Remove UILayout contributions (if any exist)
319
+ console.log('\n🗑️ STEP 1.5: Removing UILayout contributions (if exist)');
320
+ try {
321
+ console.log('Attempting to remove UILayout contributions...');
322
+ await this.broker.call('ConfigurationRegistryService.removeUILayoutContributions', {
323
+ tenantId: event.tenantId,
324
+ extensionID: event.extensionSlug
325
+ });
326
+ console.log('✅ STEP 1.5 SUCCESS: UILayout contributions removed');
327
+ } catch (uiLayoutError) {
328
+ console.warn('⚠️ STEP 1.5 WARNING: UILayout contributions removal failed (may not exist):', uiLayoutError);
329
+ // This is not fatal - extension might not have had UILayout contributions
330
+ }
331
+ // STEP 2: MANDATORY - Remove extension node from system_extension document
332
+ console.log('\n🔧 STEP 2: Unregistering extension from SYSTEM_EXTENSION (MANDATORY)');
333
+ try {
334
+ // First, get the current system_extension document
335
+ const systemContext = {
336
+ schemaId: ConfigurationSchemaId.Configuration,
337
+ tenantId: event.tenantId,
338
+ extensionName: SystemContributionExtensionNames.SystemExtension,
339
+ accountId: event.uninstalledBy
340
+ };
341
+ console.log('Fetching current system_extension document...');
342
+ const currentSystemDoc = await this.broker.call('ConfigurationRegistryService.getConfigurationNodeRegistry', {
343
+ context: systemContext
344
+ });
345
+ if (currentSystemDoc && currentSystemDoc.configurationNodes) {
346
+ const systemDoc = currentSystemDoc;
347
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
348
+ const configurationNodes = systemDoc.configurationNodes;
349
+ // Find the settings node and remove the extension property
350
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
351
+ const settingsNode = configurationNodes.find(
352
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
353
+ node => node.id === ContributionFragmentName.Settings);
354
+ if (settingsNode?.properties) {
355
+ const propertyKey = `extensions.${event.extensionSlug}`;
356
+ delete settingsNode.properties[propertyKey];
357
+ console.log(`Removing extension property: ${propertyKey}`);
358
+ console.log(`Remaining properties: ${Object.keys(settingsNode.properties).length}`);
359
+ }
360
+ const updatedConfigurationNodes = configurationNodes;
361
+ // Update the system_extension document with the updated nodes
362
+ const updatedSystemExtensionNode = {
363
+ schemaId: ConfigurationSchemaId.Configuration,
364
+ tenantId: event.tenantId,
365
+ extensionName: SystemContributionExtensionNames.SystemExtension,
366
+ policyConfigs: systemDoc.policyConfigs || null,
367
+ configurationNodes: updatedConfigurationNodes,
368
+ configurationDefaults: systemDoc.configurationDefaults || []
369
+ };
370
+ console.log('Updating system_extension document...');
371
+ await this.broker.call('ConfigurationRegistryService.updateConfigurationNodeRegistry', {
372
+ data: updatedSystemExtensionNode,
373
+ context: systemContext
374
+ });
375
+ systemExtensionUpdated = true;
376
+ console.log('✅ STEP 2 SUCCESS: Extension unregistered from system_extension');
377
+ } else {
378
+ console.warn('⚠️ STEP 2 WARNING: No system_extension document found or no configuration nodes');
379
+ systemExtensionUpdated = true; // Consider it successful if document doesn't exist
380
+ }
381
+ } catch (systemError) {
382
+ console.error('❌ STEP 2 FAILED: System extension unregistration failed:', systemError);
383
+ throw new Error(`Extension uninstallation failed: Could not unregister from system (${systemError.message})`);
384
+ }
385
+ // Uninstallation is successful if system extension is updated
386
+ uninstallationSuccessful = systemExtensionUpdated;
387
+ await this.dropCache();
388
+ console.log('\n=== EXTENSION UNINSTALLATION COMPLETED ===');
389
+ console.log('Extension Config Removed:', extensionConfigRemoved ? '✅' : 'ℹ️ Not found');
390
+ console.log('System Extension Updated:', systemExtensionUpdated ? '✅' : '❌');
391
+ console.log('Overall Uninstallation:', uninstallationSuccessful ? '✅ SUCCESS' : '❌ FAILED');
188
392
  } catch (error) {
189
- console.error('Error processing extension uninstalled event:', error);
393
+ console.error(' EXTENSION UNINSTALLATION FAILED:', error);
394
+ console.error('Error details:', {
395
+ message: error.message,
396
+ stack: error.stack,
397
+ extensionSlug: event.extensionSlug,
398
+ tenantId: event.tenantId,
399
+ extensionConfigRemoved,
400
+ systemExtensionUpdated
401
+ });
402
+ throw error; // Re-throw to ensure calling code knows uninstallation failed
190
403
  }
404
+ // Notify other services about the uninstallation
191
405
  this.broker.broadcast(ExtensionServiceAction.OnExtensionUninstalled, {
192
406
  event
193
407
  }, [MoleculerServiceName.ConfigurationService, 'WorkbenchService',
@@ -239,9 +453,9 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
239
453
  ]);
240
454
  });
241
455
  // Listen to extension cleanup completed events
242
- this.onExtensionCleanupCompleted.event(event => {
456
+ this.onExtensionCleanupCompleted.event(e => {
243
457
  this.broker.broadcast(ExtensionServiceAction.OnExtensionCleanupCompleted, {
244
- event
458
+ event: e
245
459
  }, [MoleculerServiceName.MailService // Using MailService instead of NotificationService
246
460
  ]);
247
461
  });
@@ -267,5 +481,38 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
267
481
  ]);
268
482
  });
269
483
  }
484
+ async dropCache() {
485
+ console.log('Start dropping GraphQL query cache keys');
486
+ try {
487
+ // Get Redis client from redisCacheManager
488
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
489
+ const {
490
+ redisClient
491
+ } = this.redisCacheManager;
492
+ if (!redisClient) {
493
+ console.error('❌ Redis client not found in redisCacheManager');
494
+ return;
495
+ }
496
+ const appName = process.env.APP_NAME || 'adminide-stack';
497
+ // Only delete GraphQL query caches, not session/auth data
498
+ // These are the specific queries we want to invalidate
499
+ const queryPatterns = [`${appName}*pageSettings*`, `${appName}*GetPageSettings*`, `${appName}*CurrentPagePermissions*`, `${appName}*IntegrationConfigurations*`, `${appName}*ContributionRoles*`];
500
+ let totalDeleted = 0;
501
+ for (const pattern of queryPatterns) {
502
+ console.log(`🔍 Searching for keys matching: ${pattern}`);
503
+ const keys = await redisClient.keys(pattern);
504
+ if (keys.length > 0) {
505
+ console.log(`📋 Found ${keys.length} keys for pattern: ${pattern}`);
506
+ console.log(`📝 Sample keys:`, keys.slice(0, 3));
507
+ await redisClient.del(...keys);
508
+ totalDeleted += keys.length;
509
+ }
510
+ }
511
+ console.log(`✅ Successfully deleted ${totalDeleted} query cache keys`);
512
+ } catch (error) {
513
+ console.error('❌ Failed to drop cache:', error);
514
+ // Don't throw - cache clearing failure shouldn't break extension installation
515
+ }
516
+ }
270
517
  };
271
- InstalledExtensionServiceExt = __decorate([injectable(), __param(0, inject(SERVER_TYPES.IInstalledExtensionRepository)), __param(1, inject(SERVER_TYPES.IRegistryExtensionService)), __param(2, inject(CommonType.MOLECULER_BROKER)), __param(3, inject(CommonType.LOGGER)), __metadata("design:paramtypes", [Object, Object, ServiceBroker, Object])], InstalledExtensionServiceExt);export{InstalledExtensionServiceExt};//# sourceMappingURL=installed-extension-service-ext.js.map
518
+ InstalledExtensionServiceExt = __decorate([injectable(), __param(0, inject(SERVER_TYPES.IInstalledExtensionRepository)), __param(1, inject(SERVER_TYPES.IRegistryExtensionService)), __param(2, inject(SERVER_TYPES.SlugService)), __param(3, inject(SERVER_TYPES.IRedisCacheManager)), __param(4, inject(CommonType.MOLECULER_BROKER)), __param(5, inject(CommonType.LOGGER)), __metadata("design:paramtypes", [Object, Object, Object, Object, ServiceBroker, Object])], InstalledExtensionServiceExt);export{InstalledExtensionServiceExt};//# sourceMappingURL=installed-extension-service-ext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-service-ext.js","sources":["../../src/services/installed-extension-service-ext.ts"],"sourcesContent":[null],"names":[],"mappings":"6bAkCG;AACH;AAG4D;AASxD;AAsTH,IAAA,4BAAA,GAAA,MAAA,4BAAA,SAAA,yBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"installed-extension-service-ext.js","sources":["../../src/services/installed-extension-service-ext.ts"],"sourcesContent":[null],"names":[],"mappings":"qbA4FG;AACH;;AAQQ;;AAQJ,EAAA,IAAA,OAAQ,KAAA,KAAA,QAAmB,EAAA;gBA6gBb,CAAA;AA8CjB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}