@adminide-stack/marketplace-module-server 13.1.2-alpha.9 → 13.1.3-alpha.2

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 (27) hide show
  1. package/lib/graphql/resolvers/installed-extension-resolver.d.ts.map +1 -1
  2. package/lib/graphql/resolvers/installed-extension-resolver.js +13 -2
  3. package/lib/graphql/resolvers/installed-extension-resolver.js.map +1 -1
  4. package/lib/graphql/schemas/installed-extension.graphql +16 -1
  5. package/lib/graphql/schemas/installed-extension.graphql.js +1 -1
  6. package/lib/services/installed-extension-service-ext.d.ts +2 -2
  7. package/lib/services/installed-extension-service-ext.d.ts.map +1 -1
  8. package/lib/services/installed-extension-service-ext.js +52 -3
  9. package/lib/services/installed-extension-service-ext.js.map +1 -1
  10. package/lib/services/installed-extension-service.d.ts +23 -5
  11. package/lib/services/installed-extension-service.d.ts.map +1 -1
  12. package/lib/services/installed-extension-service.js +233 -77
  13. package/lib/services/installed-extension-service.js.map +1 -1
  14. package/lib/store/repositories/installed-extension-repository.d.ts +7 -1
  15. package/lib/store/repositories/installed-extension-repository.d.ts.map +1 -1
  16. package/lib/store/repositories/installed-extension-repository.js +40 -1
  17. package/lib/store/repositories/installed-extension-repository.js.map +1 -1
  18. package/lib/templates/services/InstalledExtensionService.ts.template +15 -3
  19. package/package.json +5 -5
  20. package/lib/services/installed-extension-service.test.d.ts +0 -1
  21. package/lib/services/installed-extension-service.test.d.ts.map +0 -1
  22. package/lib/tests/extension-integration.test.d.ts +0 -1
  23. package/lib/tests/extension-integration.test.d.ts.map +0 -1
  24. package/lib/tests/install-extension-graphql.test.d.ts +0 -2
  25. package/lib/tests/install-extension-graphql.test.d.ts.map +0 -1
  26. package/lib/tests/test-extension-services.d.ts +0 -1
  27. package/lib/tests/test-extension-services.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-resolver.d.ts","sourceRoot":"","sources":["../../../src/graphql/resolvers/installed-extension-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAuB,UAAU,EAA0C,MAAM,eAAe,CAAC;AAExG,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC,OAAO,KAAG,UAsZpE,CAAC"}
1
+ {"version":3,"file":"installed-extension-resolver.d.ts","sourceRoot":"","sources":["../../../src/graphql/resolvers/installed-extension-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAuB,UAAU,EAA0C,MAAM,eAAe,CAAC;AAExG,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC,OAAO,KAAG,UAkapE,CAAC"}
@@ -315,7 +315,12 @@ const resolver = (pubsub, logger) => ({
315
315
  };
316
316
  },
317
317
  /**
318
- * Clean up orphaned extensions that exist in installed_extensions but not in system_extension registry
318
+ * Clean up orphaned extensions from configuration registry.
319
+ *
320
+ * Identifies and cleans up:
321
+ * 1. Extensions in configuration_registry but NOT in extension registry (deleted extensions)
322
+ * 2. Extensions in configuration_registry but NOT installed for the organization
323
+ * 3. Reports installed extensions without contributions in configuration_registry
319
324
  */
320
325
  async cleanupOrphanedExtensions(root, args, {
321
326
  userContext,
@@ -327,11 +332,17 @@ const resolver = (pubsub, logger) => ({
327
332
  orgId = await slugService.resolveOrganizationSlug(args.orgName);
328
333
  }
329
334
  const result = await installedExtensionService.cleanupOrphanedExtensions(orgId, userContext.tenantId, args.dryRun || false);
335
+ const totalOrphans = result.notInRegistry.length + result.notInstalled.length;
330
336
  return {
331
337
  success: true,
332
338
  removed: result.removed,
333
339
  warnings: result.warnings,
334
- message: args.dryRun ? `Preview: ${result.removed.length} orphaned extension(s) would be removed` : `Cleanup completed: ${result.removed.length} orphaned extension(s) removed`
340
+ notInRegistry: result.notInRegistry,
341
+ notInstalled: result.notInstalled,
342
+ missingContributions: result.missingContributions,
343
+ orphanedInstalledExtensionsRemoved: result.orphanedInstalledExtensionsRemoved,
344
+ orphanedPropertiesRemoved: result.orphanedPropertiesRemoved,
345
+ message: args.dryRun ? `Preview: ${totalOrphans} orphaned extension(s) found - ${result.notInRegistry.length} deleted from registry, ${result.notInstalled.length} not installed, ${result.missingContributions.length} missing contributions, ${result.orphanedPropertiesRemoved.length} orphaned properties in system_extension` : `Cleanup completed: ${result.removed.length} orphaned extension(s) removed, ${result.orphanedPropertiesRemoved.length} orphaned properties removed from system_extension. ${result.missingContributions.length} installed extensions are missing contributions.`
335
346
  };
336
347
  }
337
348
  }
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-resolver.js","sources":["../../../src/graphql/resolvers/installed-extension-resolver.ts"],"sourcesContent":[null],"names":[],"mappings":"AAES,MAAA,QAAQ;AACjB,EAAA,kBAAoB,EAAA;AACpB,IAAA,YAA8B,EAAA,CAAU,IAA0C,EAAA,mBAAsB,KAAA;AAExG,MAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"installed-extension-resolver.js","sources":["../../../src/graphql/resolvers/installed-extension-resolver.ts"],"sourcesContent":[null],"names":[],"mappings":"AAES,MAAA,QAAQ;AACjB,EAAA,kBAAoB,EAAA;AACpB,IAAA,YAA8B,EAAA,CAAU,IAA0C,EAAA,mBAAsB,KAAA;AAExG,MAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -250,13 +250,28 @@ type ExtensionSyncResponse {
250
250
  }
251
251
 
252
252
  """
253
- Response type for orphaned extension cleanup
253
+ Response type for orphaned extension cleanup.
254
+ Provides detailed information about different types of orphaned extensions found.
254
255
  """
255
256
  type OrphanedExtensionCleanupResponse {
257
+ """Whether the cleanup operation was successful"""
256
258
  success: Boolean!
259
+ """Summary message of the cleanup operation"""
257
260
  message: String!
261
+ """List of extensions that were removed (or would be removed in dry run)"""
258
262
  removed: [String!]!
263
+ """List of warning messages encountered during cleanup"""
259
264
  warnings: [String!]!
265
+ """Extensions found in configuration_registry but NOT in extension registry (deleted extensions)"""
266
+ notInRegistry: [String!]!
267
+ """Extensions found in configuration_registry but NOT installed for the organization"""
268
+ notInstalled: [String!]!
269
+ """Installed extensions that have NO contributions in configuration_registry (informational only, not cleaned)"""
270
+ missingContributions: [String!]!
271
+ """Orphaned installed_extensions entries removed (where referenced extension no longer exists)"""
272
+ orphanedInstalledExtensionsRemoved: [String!]!
273
+ """Orphaned properties removed from system_extension document (e.g., extensions.CDM/CDM/workflow-extension)"""
274
+ orphanedPropertiesRemoved: [String!]!
260
275
  }
261
276
 
262
277
  extend type Query {
@@ -1 +1 @@
1
- var installedExtensionSchema = "\"\"\"\nInstalled extension status enumeration\n\"\"\"\nenum InstalledExtensionStatus {\n installed\n deprecated_installed\n suspended\n orphaned\n force_disabled\n}\n\n\"\"\"\nRegistry status cached from extensionRegistry\n\"\"\"\nenum ExtensionRegistryStatus {\n active\n deprecated\n suspended\n removed\n emergency_removed\n}\n\n\"\"\"\nRuntime activation state\n\"\"\"\nenum ExtensionActivationState {\n enabled\n disabled\n disabled_by_user\n disabled_by_admin\n disabled_by_policy\n}\n\n\"\"\"\nExtension lifecycle management information\n\"\"\"\ntype ExtensionLifecycle @entity(embedded: true) {\n registryStatus: ExtensionRegistryStatus! @column\n isOrphaned: Boolean! @column\n deprecationWarningShown: Boolean! @column\n autoUpdateBlocked: Boolean! @column\n lastRegistryCheck: String! @column\n}\n\n\"\"\"\nAdmin policies for extension behavior\n\"\"\"\ntype ExtensionPolicies @entity(embedded: true) {\n allowOrphanedExecution: Boolean! @column\n requireSecurityUpdates: Boolean! @column\n autoRemoveDeprecated: Boolean! @column\n deprecationGracePeriod: Int! @column\n}\n\n\"\"\"\nExtension settings for user preferences and system state\n\"\"\"\ntype ExtensionSettings @entity(embedded: true) {\n userEnabled: Boolean! @column\n systemEnabled: Boolean! @column\n effectiveEnabled: Boolean! @column\n userConfig: JSON @column\n systemConfig: JSON @column\n}\n\n\"\"\"\nRuntime activation error information\n\"\"\"\ntype ExtensionActivationError @entity(embedded: true) {\n message: String! @column\n code: String! @column\n timestamp: String! @column\n}\n\n\"\"\"\nPerformance metrics\n\"\"\"\ntype ExtensionMetrics @entity(embedded: true) {\n activationTime: Float! @column\n memoryUsage: Float! @column\n lastMeasured: String! @column\n}\n\n\"\"\"\nRuntime information about extension execution\n\"\"\"\ntype ExtensionRuntime @entity(embedded: true) {\n activationState: ExtensionActivationState! @column\n lastActivated: DateTime @column(overrideType: \"Date\")\n lastDeactivated: DateTime @column(overrideType: \"Date\")\n activationError: ExtensionActivationError @embedded\n metrics: ExtensionMetrics @embedded\n}\n\n\"\"\"\nAudit log entry for extension actions\n\"\"\"\ntype ExtensionAuditEntry @entity(embedded: true) {\n action: String! @column\n timestamp: DateTime! @column(overrideType: \"Date\")\n user: UserAccount! @column(overrideType: \"ObjectId\")\n details: JSON @column\n}\n\n\"\"\"\nMain installed extension type\n\"\"\"\ntype InstalledExtension implements Node @entity {\n id: ID! @id\n organization: Organization @column(overrideType: \"ObjectId\")\n extension: RegistryExtension! @column(overrideType: \"ObjectId\")\n installedVersion: String! @column\n status: InstalledExtensionStatus! @column\n lifecycle: ExtensionLifecycle! @embedded\n policies: ExtensionPolicies! @embedded\n settings: ExtensionSettings! @embedded\n runtime: ExtensionRuntime! @embedded\n installedAt: DateTime! @column(overrideType: \"Date\")\n installedBy: UserAccount! @column(overrideType: \"ObjectId\")\n lastUpdated: DateTime @column(overrideType: \"Date\")\n lastUpdatedBy: UserAccount @column(overrideType: \"ObjectId\")\n availableVersion: String @column\n dependencies: [String!] @column\n dependents: [String!] @column\n auditLog: [ExtensionAuditEntry!] @embedded\n \"\"\"The source database collection this installed extension references\"\"\"\n sourceCollection: String @column\n \"\"\"The ObjectId of the specific document in the source collection\"\"\"\n sourceDocumentId: String @column\n \"\"\"Additional metadata for the installed extension\"\"\"\n metadata: JSON @column\n \"\"\"The actual document from the source collection (resolved via DataLoader, returns null if not found or no reference)\"\"\"\n sourceDocument: JSON\n}\n\n\"\"\"\nRegistry information for display\n\"\"\"\ntype ExtensionRegistryInfo {\n displayName: String!\n description: String!\n publisher: String!\n latestVersion: String!\n tags: [String!]!\n categories: [String!]!\n deprecation: JSON\n suspension: JSON\n}\n\n\"\"\"\nNotification action\n\"\"\"\ntype NotificationAction {\n label: String!\n action: String!\n url: String\n extensionSlug: String\n}\n\n\"\"\"\nExtension notification\n\"\"\"\ntype ExtensionNotification {\n type: String!\n severity: String!\n message: String!\n actions: [NotificationAction!]\n}\n\n\"\"\"\nExtension update information\n\"\"\"\ntype ExtensionUpdate {\n extensionSlug: String!\n currentVersion: String!\n availableVersion: String!\n isSecurityUpdate: Boolean!\n}\n\n\"\"\"\nExtension cleanup result\n\"\"\"\ntype ExtensionCleanupResult {\n removed: [String!]!\n deprecated: [String!]!\n warnings: [String!]!\n}\n\n\"\"\"\nInput for installing an extension\n\"\"\"\ninput InstallExtensionInput {\n extensionSlug: String!\n version: String!\n orgName: String\n policies: ExtensionPoliciesInput\n settings: ExtensionSettingsInput\n \"\"\"The source database collection this extension references\"\"\"\n sourceCollection: String\n \"\"\"The ObjectId of the specific document in the source collection\"\"\"\n sourceDocumentId: String\n \"\"\"Additional metadata for the installation\"\"\"\n metadata: JSON\n}\n\n\"\"\"\nInput for extension policies\n\"\"\"\ninput ExtensionPoliciesInput {\n allowOrphanedExecution: Boolean\n requireSecurityUpdates: Boolean\n autoRemoveDeprecated: Boolean\n deprecationGracePeriod: Int\n}\n\n\"\"\"\nInput for extension settings\n\"\"\"\ninput ExtensionSettingsInput {\n userEnabled: Boolean\n systemEnabled: Boolean\n userConfig: JSON\n systemConfig: JSON\n}\n\n\"\"\"\nResponse type for extension mutations\n\"\"\"\ntype ExtensionMutationResponse {\n success: Boolean!\n extension: InstalledExtension\n message: String!\n}\n\n\"\"\"\nResponse type for cleanup operations\n\"\"\"\ntype ExtensionCleanupResponse {\n success: Boolean!\n result: ExtensionCleanupResult\n message: String!\n}\n\n\"\"\"\nResponse type for sync operations\n\"\"\"\ntype ExtensionSyncResponse {\n success: Boolean!\n message: String!\n}\n\n\"\"\"\nResponse type for orphaned extension cleanup\n\"\"\"\ntype OrphanedExtensionCleanupResponse {\n success: Boolean!\n message: String!\n removed: [String!]!\n warnings: [String!]!\n}\n\nextend type Query {\n \"\"\"\n Get all installed extensions for the current tenant\n \"\"\"\n installedExtensions(enabled: Boolean, orgName: String): [InstalledExtension!]!\n\n \"\"\"\n Get a specific installed extension\n \"\"\"\n installedExtension(extensionSlug: String!): InstalledExtension\n\n \"\"\"\n Get installed extensions that need attention\n \"\"\"\n extensionsNeedingAttention: [InstalledExtension!]!\n\n \"\"\"\n Check for available updates\n \"\"\"\n extensionUpdates(extensionSlug: String): [ExtensionUpdate!]!\n}\n\nextend type Mutation {\n \"\"\"\n Install an extension from the registry\n \"\"\"\n installExtension(input: InstallExtensionInput!): ExtensionMutationResponse!\n\n \"\"\"\n Uninstall an extension\n \"\"\"\n uninstallExtension(extensionSlug: String!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Enable or disable an extension\n \"\"\"\n toggleExtension(extensionSlug: String!, enabled: Boolean!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Update extension settings\n \"\"\"\n updateExtensionSettings(extensionSlug: String!, settings: JSON!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Update an extension to a newer version\n \"\"\"\n updateExtensionVersion(extensionSlug: String!, version: String!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Sync installed extensions with registry\n \"\"\"\n syncExtensionsWithRegistry: ExtensionSyncResponse!\n\n \"\"\"\n Clean up deprecated or removed extensions\n \"\"\"\n cleanupExtensions(dryRun: Boolean): ExtensionCleanupResponse!\n \n \"\"\"\n Clean up orphaned extensions that exist in installed_extensions but not in system_extension registry\n \"\"\"\n cleanupOrphanedExtensions(dryRun: Boolean, orgName: String): OrphanedExtensionCleanupResponse!\n}\n";export{installedExtensionSchema as default};//# sourceMappingURL=installed-extension.graphql.js.map
1
+ var installedExtensionSchema = "\"\"\"\nInstalled extension status enumeration\n\"\"\"\nenum InstalledExtensionStatus {\n installed\n deprecated_installed\n suspended\n orphaned\n force_disabled\n}\n\n\"\"\"\nRegistry status cached from extensionRegistry\n\"\"\"\nenum ExtensionRegistryStatus {\n active\n deprecated\n suspended\n removed\n emergency_removed\n}\n\n\"\"\"\nRuntime activation state\n\"\"\"\nenum ExtensionActivationState {\n enabled\n disabled\n disabled_by_user\n disabled_by_admin\n disabled_by_policy\n}\n\n\"\"\"\nExtension lifecycle management information\n\"\"\"\ntype ExtensionLifecycle @entity(embedded: true) {\n registryStatus: ExtensionRegistryStatus! @column\n isOrphaned: Boolean! @column\n deprecationWarningShown: Boolean! @column\n autoUpdateBlocked: Boolean! @column\n lastRegistryCheck: String! @column\n}\n\n\"\"\"\nAdmin policies for extension behavior\n\"\"\"\ntype ExtensionPolicies @entity(embedded: true) {\n allowOrphanedExecution: Boolean! @column\n requireSecurityUpdates: Boolean! @column\n autoRemoveDeprecated: Boolean! @column\n deprecationGracePeriod: Int! @column\n}\n\n\"\"\"\nExtension settings for user preferences and system state\n\"\"\"\ntype ExtensionSettings @entity(embedded: true) {\n userEnabled: Boolean! @column\n systemEnabled: Boolean! @column\n effectiveEnabled: Boolean! @column\n userConfig: JSON @column\n systemConfig: JSON @column\n}\n\n\"\"\"\nRuntime activation error information\n\"\"\"\ntype ExtensionActivationError @entity(embedded: true) {\n message: String! @column\n code: String! @column\n timestamp: String! @column\n}\n\n\"\"\"\nPerformance metrics\n\"\"\"\ntype ExtensionMetrics @entity(embedded: true) {\n activationTime: Float! @column\n memoryUsage: Float! @column\n lastMeasured: String! @column\n}\n\n\"\"\"\nRuntime information about extension execution\n\"\"\"\ntype ExtensionRuntime @entity(embedded: true) {\n activationState: ExtensionActivationState! @column\n lastActivated: DateTime @column(overrideType: \"Date\")\n lastDeactivated: DateTime @column(overrideType: \"Date\")\n activationError: ExtensionActivationError @embedded\n metrics: ExtensionMetrics @embedded\n}\n\n\"\"\"\nAudit log entry for extension actions\n\"\"\"\ntype ExtensionAuditEntry @entity(embedded: true) {\n action: String! @column\n timestamp: DateTime! @column(overrideType: \"Date\")\n user: UserAccount! @column(overrideType: \"ObjectId\")\n details: JSON @column\n}\n\n\"\"\"\nMain installed extension type\n\"\"\"\ntype InstalledExtension implements Node @entity {\n id: ID! @id\n organization: Organization @column(overrideType: \"ObjectId\")\n extension: RegistryExtension! @column(overrideType: \"ObjectId\")\n installedVersion: String! @column\n status: InstalledExtensionStatus! @column\n lifecycle: ExtensionLifecycle! @embedded\n policies: ExtensionPolicies! @embedded\n settings: ExtensionSettings! @embedded\n runtime: ExtensionRuntime! @embedded\n installedAt: DateTime! @column(overrideType: \"Date\")\n installedBy: UserAccount! @column(overrideType: \"ObjectId\")\n lastUpdated: DateTime @column(overrideType: \"Date\")\n lastUpdatedBy: UserAccount @column(overrideType: \"ObjectId\")\n availableVersion: String @column\n dependencies: [String!] @column\n dependents: [String!] @column\n auditLog: [ExtensionAuditEntry!] @embedded\n \"\"\"The source database collection this installed extension references\"\"\"\n sourceCollection: String @column\n \"\"\"The ObjectId of the specific document in the source collection\"\"\"\n sourceDocumentId: String @column\n \"\"\"Additional metadata for the installed extension\"\"\"\n metadata: JSON @column\n \"\"\"The actual document from the source collection (resolved via DataLoader, returns null if not found or no reference)\"\"\"\n sourceDocument: JSON\n}\n\n\"\"\"\nRegistry information for display\n\"\"\"\ntype ExtensionRegistryInfo {\n displayName: String!\n description: String!\n publisher: String!\n latestVersion: String!\n tags: [String!]!\n categories: [String!]!\n deprecation: JSON\n suspension: JSON\n}\n\n\"\"\"\nNotification action\n\"\"\"\ntype NotificationAction {\n label: String!\n action: String!\n url: String\n extensionSlug: String\n}\n\n\"\"\"\nExtension notification\n\"\"\"\ntype ExtensionNotification {\n type: String!\n severity: String!\n message: String!\n actions: [NotificationAction!]\n}\n\n\"\"\"\nExtension update information\n\"\"\"\ntype ExtensionUpdate {\n extensionSlug: String!\n currentVersion: String!\n availableVersion: String!\n isSecurityUpdate: Boolean!\n}\n\n\"\"\"\nExtension cleanup result\n\"\"\"\ntype ExtensionCleanupResult {\n removed: [String!]!\n deprecated: [String!]!\n warnings: [String!]!\n}\n\n\"\"\"\nInput for installing an extension\n\"\"\"\ninput InstallExtensionInput {\n extensionSlug: String!\n version: String!\n orgName: String\n policies: ExtensionPoliciesInput\n settings: ExtensionSettingsInput\n \"\"\"The source database collection this extension references\"\"\"\n sourceCollection: String\n \"\"\"The ObjectId of the specific document in the source collection\"\"\"\n sourceDocumentId: String\n \"\"\"Additional metadata for the installation\"\"\"\n metadata: JSON\n}\n\n\"\"\"\nInput for extension policies\n\"\"\"\ninput ExtensionPoliciesInput {\n allowOrphanedExecution: Boolean\n requireSecurityUpdates: Boolean\n autoRemoveDeprecated: Boolean\n deprecationGracePeriod: Int\n}\n\n\"\"\"\nInput for extension settings\n\"\"\"\ninput ExtensionSettingsInput {\n userEnabled: Boolean\n systemEnabled: Boolean\n userConfig: JSON\n systemConfig: JSON\n}\n\n\"\"\"\nResponse type for extension mutations\n\"\"\"\ntype ExtensionMutationResponse {\n success: Boolean!\n extension: InstalledExtension\n message: String!\n}\n\n\"\"\"\nResponse type for cleanup operations\n\"\"\"\ntype ExtensionCleanupResponse {\n success: Boolean!\n result: ExtensionCleanupResult\n message: String!\n}\n\n\"\"\"\nResponse type for sync operations\n\"\"\"\ntype ExtensionSyncResponse {\n success: Boolean!\n message: String!\n}\n\n\"\"\"\nResponse type for orphaned extension cleanup.\nProvides detailed information about different types of orphaned extensions found.\n\"\"\"\ntype OrphanedExtensionCleanupResponse {\n \"\"\"Whether the cleanup operation was successful\"\"\"\n success: Boolean!\n \"\"\"Summary message of the cleanup operation\"\"\"\n message: String!\n \"\"\"List of extensions that were removed (or would be removed in dry run)\"\"\"\n removed: [String!]!\n \"\"\"List of warning messages encountered during cleanup\"\"\"\n warnings: [String!]!\n \"\"\"Extensions found in configuration_registry but NOT in extension registry (deleted extensions)\"\"\"\n notInRegistry: [String!]!\n \"\"\"Extensions found in configuration_registry but NOT installed for the organization\"\"\"\n notInstalled: [String!]!\n \"\"\"Installed extensions that have NO contributions in configuration_registry (informational only, not cleaned)\"\"\"\n missingContributions: [String!]!\n \"\"\"Orphaned installed_extensions entries removed (where referenced extension no longer exists)\"\"\"\n orphanedInstalledExtensionsRemoved: [String!]!\n \"\"\"Orphaned properties removed from system_extension document (e.g., extensions.CDM/CDM/workflow-extension)\"\"\"\n orphanedPropertiesRemoved: [String!]!\n}\n\nextend type Query {\n \"\"\"\n Get all installed extensions for the current tenant\n \"\"\"\n installedExtensions(enabled: Boolean, orgName: String): [InstalledExtension!]!\n\n \"\"\"\n Get a specific installed extension\n \"\"\"\n installedExtension(extensionSlug: String!): InstalledExtension\n\n \"\"\"\n Get installed extensions that need attention\n \"\"\"\n extensionsNeedingAttention: [InstalledExtension!]!\n\n \"\"\"\n Check for available updates\n \"\"\"\n extensionUpdates(extensionSlug: String): [ExtensionUpdate!]!\n}\n\nextend type Mutation {\n \"\"\"\n Install an extension from the registry\n \"\"\"\n installExtension(input: InstallExtensionInput!): ExtensionMutationResponse!\n\n \"\"\"\n Uninstall an extension\n \"\"\"\n uninstallExtension(extensionSlug: String!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Enable or disable an extension\n \"\"\"\n toggleExtension(extensionSlug: String!, enabled: Boolean!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Update extension settings\n \"\"\"\n updateExtensionSettings(extensionSlug: String!, settings: JSON!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Update an extension to a newer version\n \"\"\"\n updateExtensionVersion(extensionSlug: String!, version: String!, orgName: String): ExtensionMutationResponse!\n\n \"\"\"\n Sync installed extensions with registry\n \"\"\"\n syncExtensionsWithRegistry: ExtensionSyncResponse!\n\n \"\"\"\n Clean up deprecated or removed extensions\n \"\"\"\n cleanupExtensions(dryRun: Boolean): ExtensionCleanupResponse!\n \n \"\"\"\n Clean up orphaned extensions that exist in installed_extensions but not in system_extension registry\n \"\"\"\n cleanupOrphanedExtensions(dryRun: Boolean, orgName: String): OrphanedExtensionCleanupResponse!\n}\n";export{installedExtensionSchema as default};//# sourceMappingURL=installed-extension.graphql.js.map
@@ -1,6 +1,6 @@
1
1
  import { ServiceBroker } from 'moleculer';
2
2
  import { CdmLogger } from '@cdm-logger/core';
3
- import { IRegistryExtensionService, IInstalledExtensionRepository, ISlugService, IRedisCacheManager } from 'common/server';
3
+ import { IRegistryExtensionService, IInstalledExtensionRepository, ISlugService, IRedisCacheManager, IConfigurationRegistryService } from 'common/server';
4
4
  import { InstalledExtensionService } from './installed-extension-service';
5
5
  /**
6
6
  * Extended InstalledExtensionService that handles Moleculer event broadcasting
@@ -9,7 +9,7 @@ import { InstalledExtensionService } from './installed-extension-service';
9
9
  export declare class InstalledExtensionServiceExt extends InstalledExtensionService {
10
10
  protected slugService: ISlugService;
11
11
  protected readonly redisCacheManager: IRedisCacheManager;
12
- constructor(repository: IInstalledExtensionRepository, registryService: IRegistryExtensionService, slugService: ISlugService, redisCacheManager: IRedisCacheManager, broker: ServiceBroker, logger: CdmLogger.ILogger);
12
+ constructor(repository: IInstalledExtensionRepository, registryService: IRegistryExtensionService, slugService: ISlugService, redisCacheManager: IRedisCacheManager, broker: ServiceBroker, configurationRegistryService: IConfigurationRegistryService, logger: CdmLogger.ILogger);
13
13
  private setupEventListeners;
14
14
  private dropCache;
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-service-ext.d.ts","sourceRoot":"","sources":["../../src/services/installed-extension-service-ext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAgBH,yBAAyB,EACzB,6BAA6B,EAO7B,YAAY,EACZ,kBAAkB,EACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AA0D1E;;;GAGG;AACH,qBACa,4BAA6B,SAAQ,yBAAyB;IAKnE,SAAS,CAAC,WAAW,EAAE,YAAY;IAEnC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,kBAAkB;gBALJ,UAAU,EAAE,6BAA6B,EAC7C,eAAe,EAAE,yBAAyB,EAEhF,WAAW,EAAE,YAAY,EAEhB,iBAAiB,EAAE,kBAAkB,EACnB,MAAM,EAAE,aAAa,EAC/B,MAAM,EAAE,SAAS,CAAC,OAAO;IAMxD,OAAO,CAAC,mBAAmB;YA6gBb,SAAS;CA8C1B"}
1
+ {"version":3,"file":"installed-extension-service-ext.d.ts","sourceRoot":"","sources":["../../src/services/installed-extension-service-ext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAgBH,yBAAyB,EACzB,6BAA6B,EAO7B,YAAY,EACZ,kBAAkB,EAClB,6BAA6B,EAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AA0D1E;;;GAGG;AACH,qBACa,4BAA6B,SAAQ,yBAAyB;IAKnE,SAAS,CAAC,WAAW,EAAE,YAAY;IAEnC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,kBAAkB;gBALJ,UAAU,EAAE,6BAA6B,EAC7C,eAAe,EAAE,yBAAyB,EAEhF,WAAW,EAAE,YAAY,EAEhB,iBAAiB,EAAE,kBAAkB,EACnB,MAAM,EAAE,aAAa,EAE1D,4BAA4B,EAAE,6BAA6B,EAChC,MAAM,EAAE,SAAS,CAAC,OAAO;IAMxD,OAAO,CAAC,mBAAmB;YAmlBb,SAAS;CA8C1B"}
@@ -52,8 +52,8 @@ function processConfigurationProperties(properties) {
52
52
  let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends InstalledExtensionService {
53
53
  slugService;
54
54
  redisCacheManager;
55
- constructor(repository, registryService, slugService, redisCacheManager, broker, logger) {
56
- super(repository, registryService, slugService, broker, logger);
55
+ constructor(repository, registryService, slugService, redisCacheManager, broker, configurationRegistryService, logger) {
56
+ super(repository, registryService, slugService, broker, configurationRegistryService, logger);
57
57
  this.slugService = slugService;
58
58
  this.redisCacheManager = redisCacheManager;
59
59
  this.setupEventListeners();
@@ -81,6 +81,7 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
81
81
  parsedManifest = typeof currentRelease.manifest === 'string' ? JSON.parse(currentRelease.manifest) : currentRelease.manifest;
82
82
  console.log('Parsed manifest keys:', Object.keys(parsedManifest));
83
83
  contributes = parsedManifest.contributes;
84
+ console.log('Contributes section:', contributes);
84
85
  if (contributes) {
85
86
  console.log('Contributes keys:', Object.keys(contributes));
86
87
  console.log('Configuration exists:', !!contributes.configuration);
@@ -155,6 +156,41 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
155
156
  } else {
156
157
  console.log('No UILayout contributions found in manifest');
157
158
  }
159
+ // Extract Secrets contributions if they exist (same structure as configuration)
160
+ if (contributes && contributes.secrets) {
161
+ console.log('Secrets contributions found, processing...');
162
+ const secretsContributions = Array.isArray(contributes.secrets) ? contributes.secrets : [contributes.secrets];
163
+ console.log(`Found ${secretsContributions.length} Secrets contribution(s) in manifest`);
164
+ // Format Secrets contributions (same structure as configuration)
165
+ const secretsNodes = secretsContributions.map(secret => {
166
+ // Process properties to convert scope strings to numbers (same as configuration)
167
+ const processedProperties = processConfigurationProperties(secret.properties || {});
168
+ return {
169
+ id: ContributionFragmentName.Settings,
170
+ title: secret.title || registryExtension.name,
171
+ description: secret.description,
172
+ properties: processedProperties,
173
+ type: secret.type || ['object']
174
+ };
175
+ });
176
+ if (secretsNodes.length > 0) {
177
+ console.log(`Registering ${secretsNodes.length} Secrets configuration nodes`);
178
+ try {
179
+ // Register Secrets contributions (exact same as configuration, just different schema)
180
+ await this.broker.call('ConfigurationRegistryService.registerSecretsContributions', {
181
+ tenantId: event.tenantId,
182
+ extensionID: event.extensionSlug,
183
+ secretsNodes
184
+ });
185
+ console.log(`✅ Secrets contributions registered successfully for ${event.extensionSlug}`);
186
+ } catch (secretsError) {
187
+ console.error('❌ Failed to register Secrets contributions:', secretsError);
188
+ // This is not fatal, log and continue
189
+ }
190
+ }
191
+ } else {
192
+ console.log('No Secrets contributions found in manifest');
193
+ }
158
194
  } else {
159
195
  console.log('No current release or manifest found for version:', registryExtension.version);
160
196
  }
@@ -328,6 +364,19 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
328
364
  console.warn('⚠️ STEP 1.5 WARNING: UILayout contributions removal failed (may not exist):', uiLayoutError);
329
365
  // This is not fatal - extension might not have had UILayout contributions
330
366
  }
367
+ // STEP 1.6: Remove Secrets contributions (if any exist)
368
+ console.log('\n🗑️ STEP 1.6: Removing Secrets contributions (if exist)');
369
+ try {
370
+ console.log('Attempting to remove Secrets contributions...');
371
+ await this.broker.call('ConfigurationRegistryService.removeSecretsContributions', {
372
+ tenantId: event.tenantId,
373
+ extensionID: event.extensionSlug
374
+ });
375
+ console.log('✅ STEP 1.6 SUCCESS: Secrets contributions removed');
376
+ } catch (secretsError) {
377
+ console.warn('⚠️ STEP 1.6 WARNING: Secrets contributions removal failed (may not exist):', secretsError);
378
+ // This is not fatal - extension might not have had Secrets contributions
379
+ }
331
380
  // STEP 2: MANDATORY - Remove extension node from system_extension document
332
381
  console.log('\n🔧 STEP 2: Unregistering extension from SYSTEM_EXTENSION (MANDATORY)');
333
382
  try {
@@ -515,4 +564,4 @@ let InstalledExtensionServiceExt = class InstalledExtensionServiceExt extends In
515
564
  }
516
565
  }
517
566
  };
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
567
+ 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(SERVER_TYPES.ContributionNodeRegistryService)), __param(6, inject(CommonType.LOGGER)), __metadata("design:paramtypes", [Object, Object, Object, Object, ServiceBroker, Object, 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":"qbA4FG;AACH;;AAQQ;;AAQJ,EAAA,IAAA,OAAQ,KAAA,KAAA,QAAmB,EAAA;gBA6gBb,CAAA;AA8CjB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"installed-extension-service-ext.js","sources":["../../src/services/installed-extension-service-ext.ts"],"sourcesContent":[null],"names":[],"mappings":"qbA6FG;AACH;;AAQQ;mCALgE,CAAA,KAAA,EAAA;AAepE,EAAA,IAAA,OAAQ,KAAA,KAAA,QAAmB,EAAA;gBAmlBb,CAAA;AA8CjB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,12 +2,13 @@ import { CdmLogger } from '@cdm-logger/core';
2
2
  import { ServiceBroker } from 'moleculer';
3
3
  import { Disposable, DisposableCollection, Emitter } from '@adminide-stack/core';
4
4
  import { BaseService2 } from '@common-stack/store-mongo';
5
- import { IInstalledExtensionModel, ICreateInstalledExtensionInput, IUpdateInstalledExtensionInput, IRegistryExtensionService, IInstalledExtensionFilter, IInstalledExtensionService, IInstalledExtensionRepository, IExtensionInstalledEvent, IExtensionUninstalledEvent, IExtensionEnabledEvent, IExtensionDisabledEvent, IExtensionUpdatedEvent, IExtensionVersionUpdatedEvent, IExtensionStatusChangedEvent, IExtensionActivationFailedEvent, IExtensionDeprecatedEvent, IExtensionOrphanedEvent, IExtensionConfigurationUpdatedEvent, IExtensionSyncCompletedEvent, IExtensionCleanupCompletedEvent, AsDomainType, ISlugService } from 'common/server';
5
+ import { IInstalledExtensionModel, ICreateInstalledExtensionInput, IUpdateInstalledExtensionInput, IRegistryExtensionService, IInstalledExtensionFilter, IInstalledExtensionService, IInstalledExtensionRepository, IExtensionInstalledEvent, IExtensionUninstalledEvent, IExtensionEnabledEvent, IExtensionDisabledEvent, IExtensionUpdatedEvent, IExtensionVersionUpdatedEvent, IExtensionStatusChangedEvent, IExtensionActivationFailedEvent, IExtensionDeprecatedEvent, IExtensionOrphanedEvent, IExtensionConfigurationUpdatedEvent, IExtensionSyncCompletedEvent, IExtensionCleanupCompletedEvent, AsDomainType, ISlugService, IConfigurationRegistryService } from 'common/server';
6
6
  export declare class InstalledExtensionService extends BaseService2<IInstalledExtensionModel> implements IInstalledExtensionService, Disposable {
7
7
  private installedExtensionRepository;
8
8
  protected registryExtensionService: IRegistryExtensionService;
9
9
  protected slugService: ISlugService;
10
10
  protected broker: ServiceBroker;
11
+ protected configurationRegistryService: IConfigurationRegistryService;
11
12
  protected readonly onExtensionInstalled: Emitter<IExtensionInstalledEvent>;
12
13
  protected readonly onExtensionUninstalled: Emitter<IExtensionUninstalledEvent>;
13
14
  protected readonly onExtensionEnabled: Emitter<IExtensionEnabledEvent>;
@@ -23,7 +24,7 @@ export declare class InstalledExtensionService extends BaseService2<IInstalledEx
23
24
  protected readonly onExtensionOrphaned: Emitter<IExtensionOrphanedEvent>;
24
25
  protected readonly toDispose: DisposableCollection;
25
26
  private logger;
26
- constructor(installedExtensionRepository: IInstalledExtensionRepository, registryExtensionService: IRegistryExtensionService, slugService: ISlugService, broker: ServiceBroker, logger: CdmLogger.ILogger);
27
+ constructor(installedExtensionRepository: IInstalledExtensionRepository, registryExtensionService: IRegistryExtensionService, slugService: ISlugService, broker: ServiceBroker, configurationRegistryService: IConfigurationRegistryService, logger: CdmLogger.ILogger);
27
28
  dispose(): void;
28
29
  private resolveExtensionSlug;
29
30
  /**
@@ -94,14 +95,31 @@ export declare class InstalledExtensionService extends BaseService2<IInstalledEx
94
95
  warnings: string[];
95
96
  }>;
96
97
  /**
97
- * Sync installed_extensions with system_extension registry
98
- * Removes extensions from installed_extensions and configuration_registries
99
- * if they are not present in system_extension registry
98
+ * Comprehensive cleanup of orphaned extensions.
99
+ *
100
+ * This method identifies and cleans up extensions that are:
101
+ * 1. In configuration_registry but NOT in extension registry (deleted extensions)
102
+ * 2. In configuration_registry but NOT installed for the organization
103
+ * 3. Reports installed extensions without contributions in configuration_registry
104
+ *
105
+ * @param orgId - The organization ID
106
+ * @param tenantId - The tenant ID
107
+ * @param dryRun - If true, only reports what would be cleaned without actually cleaning
108
+ * @returns Cleanup result with removed extensions, warnings, and missing contributions
100
109
  */
101
110
  cleanupOrphanedExtensions(orgId: string, tenantId: string, dryRun?: boolean): Promise<{
102
111
  removed: string[];
103
112
  warnings: string[];
113
+ notInRegistry: string[];
114
+ notInstalled: string[];
115
+ missingContributions: string[];
116
+ orphanedInstalledExtensionsRemoved: string[];
117
+ orphanedPropertiesRemoved: string[];
104
118
  }>;
119
+ /**
120
+ * Check if an extension slug is a system extension that should not be cleaned up
121
+ */
122
+ private isSystemExtension;
105
123
  /**
106
124
  * Check if update is a security update (simplified logic)
107
125
  */
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-service.d.ts","sourceRoot":"","sources":["../../src/services/installed-extension-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"installed-extension-service.d.ts","sourceRoot":"","sources":["../../src/services/installed-extension-service.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
- import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import'@cdm-logger/core';import {ServiceBroker}from'moleculer';import {CommonType}from'@common-stack/core';import {Emitter,DisposableCollection}from'@adminide-stack/core';import {BaseService2}from'@common-stack/store-mongo';import {SERVER_TYPES,DB_COLL_NAMES,ExtensionActivationState}from'common/server';var InstalledExtensionService_1;
1
+ import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import'@cdm-logger/core';import {ServiceBroker}from'moleculer';import {CommonType}from'@common-stack/core';import {Emitter,DisposableCollection}from'@adminide-stack/core';import {BaseService2}from'@common-stack/store-mongo';import {SERVER_TYPES,DB_COLL_NAMES,ExtensionActivationState,ContributionSchemaId}from'common/server';var InstalledExtensionService_1;
2
2
  let InstalledExtensionService = InstalledExtensionService_1 = class InstalledExtensionService extends BaseService2 {
3
3
  installedExtensionRepository;
4
4
  registryExtensionService;
5
5
  slugService;
6
6
  broker;
7
+ configurationRegistryService;
7
8
  onExtensionInstalled = new Emitter();
8
9
  onExtensionUninstalled = new Emitter();
9
10
  onExtensionEnabled = new Emitter();
@@ -19,12 +20,13 @@ let InstalledExtensionService = InstalledExtensionService_1 = class InstalledExt
19
20
  onExtensionOrphaned = new Emitter();
20
21
  toDispose = new DisposableCollection(this.onExtensionInstalled, this.onExtensionUninstalled, this.onExtensionEnabled, this.onExtensionDisabled, this.onExtensionUpdated, this.onExtensionVersionUpdated, this.onExtensionConfigurationUpdated, this.onExtensionSyncCompleted, this.onExtensionCleanupCompleted, this.onExtensionStatusChanged, this.onExtensionActivationFailed, this.onExtensionDeprecated, this.onExtensionOrphaned);
21
22
  logger;
22
- constructor(installedExtensionRepository, registryExtensionService, slugService, broker, logger) {
23
+ constructor(installedExtensionRepository, registryExtensionService, slugService, broker, configurationRegistryService, logger) {
23
24
  super(installedExtensionRepository);
24
25
  this.installedExtensionRepository = installedExtensionRepository;
25
26
  this.registryExtensionService = registryExtensionService;
26
27
  this.slugService = slugService;
27
28
  this.broker = broker;
29
+ this.configurationRegistryService = configurationRegistryService;
28
30
  this.logger = logger.child({
29
31
  className: InstalledExtensionService_1.name
30
32
  });
@@ -527,99 +529,253 @@ let InstalledExtensionService = InstalledExtensionService_1 = class InstalledExt
527
529
  return result;
528
530
  }
529
531
  /**
530
- * Sync installed_extensions with system_extension registry
531
- * Removes extensions from installed_extensions and configuration_registries
532
- * if they are not present in system_extension registry
532
+ * Comprehensive cleanup of orphaned extensions.
533
+ *
534
+ * This method identifies and cleans up extensions that are:
535
+ * 1. In configuration_registry but NOT in extension registry (deleted extensions)
536
+ * 2. In configuration_registry but NOT installed for the organization
537
+ * 3. Reports installed extensions without contributions in configuration_registry
538
+ *
539
+ * @param orgId - The organization ID
540
+ * @param tenantId - The tenant ID
541
+ * @param dryRun - If true, only reports what would be cleaned without actually cleaning
542
+ * @returns Cleanup result with removed extensions, warnings, and missing contributions
533
543
  */
534
544
  async cleanupOrphanedExtensions(orgId, tenantId, dryRun) {
535
545
  const result = {
536
546
  removed: [],
537
- warnings: []
547
+ warnings: [],
548
+ notInRegistry: [],
549
+ notInstalled: [],
550
+ missingContributions: [],
551
+ orphanedInstalledExtensionsRemoved: [],
552
+ orphanedPropertiesRemoved: []
538
553
  };
539
- console.log('🔍 SYNC: Starting extension registry sync...');
540
- console.log(` OrgId: ${orgId}, TenantId: ${tenantId}, DryRun: ${dryRun}`);
541
- // Get all installed extensions
542
- const extensions = await this.installedExtensionRepository.findExtensions({
543
- orgId
544
- });
545
- console.log(` Found ${extensions.length} installed extensions`);
546
- // Get system_extension document
547
- const systemExtensionDoc = await this.broker.call('ConfigurationRegistryService.getConfigurationNodeRegistry', {
548
- context: {
549
- schemaId: 'configuration',
550
- tenantId,
551
- extensionName: 'system_extension'
554
+ this.logger.info('🔍 [ORPHAN CLEANUP] Starting comprehensive orphaned extension cleanup...');
555
+ this.logger.info(' OrgId: %s, TenantId: %s, DryRun: %s', orgId, tenantId, dryRun);
556
+ try {
557
+ // Step 1: Get all extensions from the extension registry
558
+ const registryExtensions = await this.registryExtensionService.findExtensions(1000, '', true, true, []);
559
+ const registryExtensionSlugs = new Set();
560
+ for (const ext of registryExtensions || []) {
561
+ if (ext.extensionSlug) {
562
+ registryExtensionSlugs.add(ext.extensionSlug);
563
+ }
552
564
  }
553
- });
554
- // Get list of extensions in system_extension
555
- const systemExtensionSlugs = new Set();
556
- if (systemExtensionDoc && typeof systemExtensionDoc === 'object' && 'configurationNodes' in systemExtensionDoc) {
557
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
558
- const configNodes = systemExtensionDoc.configurationNodes || [];
559
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
560
- const settingsNode = configNodes.find(node => node.id === 'settings');
561
- if (settingsNode?.properties) {
562
- Object.keys(settingsNode.properties).forEach(key => {
563
- if (key.startsWith('extensions.')) {
564
- const slug = key.replace('extensions.', '');
565
- systemExtensionSlugs.add(slug);
565
+ this.logger.info(' 📦 Found %d extensions in extension registry', registryExtensionSlugs.size);
566
+ // Step 2: Get all installed extensions for this organization
567
+ const installedExtensions = await this.installedExtensionRepository.findExtensions({
568
+ orgId
569
+ });
570
+ const installedExtensionSlugs = new Set();
571
+ const installedExtensionMap = new Map();
572
+ // Track orphaned installed_extensions entries (where extension doesn't exist in extensions collection)
573
+ const orphanedInstalledExtensions = [];
574
+ for (const ext of installedExtensions) {
575
+ // Get the slug from registry for this extension
576
+ let extensionSlug = null;
577
+ // The repository returns objects with 'id' (via toJSON virtuals), not '_id'
578
+ const installedExtId = ext.id || ext._id;
579
+ try {
580
+ const registryExt = await this.registryExtensionService.get(String(ext.extension));
581
+ if (registryExt) {
582
+ extensionSlug = registryExt.extensionSlug;
583
+ } else {
584
+ // Extension doesn't exist in extensions collection - this is an orphan
585
+ orphanedInstalledExtensions.push({
586
+ installedExtensionId: String(installedExtId),
587
+ extensionId: String(ext.extension),
588
+ reason: 'Extension not found in extensions collection'
589
+ });
590
+ this.logger.warn(' ⚠️ Orphaned installed_extension: %s references non-existent extension: %s', installedExtId, ext.extension);
566
591
  }
567
- });
592
+ } catch (error) {
593
+ // If we get an error looking up the extension, it's likely orphaned
594
+ orphanedInstalledExtensions.push({
595
+ installedExtensionId: String(installedExtId),
596
+ extensionId: String(ext.extension),
597
+ reason: `Registry lookup failed: ${error.message}`
598
+ });
599
+ this.logger.warn(' ⚠️ Orphaned installed_extension: %s - lookup failed for extension: %s', installedExtId, ext.extension);
600
+ }
601
+ if (extensionSlug) {
602
+ installedExtensionSlugs.add(extensionSlug);
603
+ installedExtensionMap.set(extensionSlug, ext);
604
+ }
568
605
  }
569
- }
570
- console.log(` Found ${systemExtensionSlugs.size} extensions in system_extension registry`);
571
- console.log(` System extensions:`, Array.from(systemExtensionSlugs));
572
- // Check each installed extension
573
- for (const extension of extensions) {
574
- const extensionId = String(extension.extension);
575
- // Get the registry extension to find its slug
576
- let extensionSlug = null;
577
- try {
578
- const registryExtension = await this.registryExtensionService.get(extensionId);
579
- if (registryExtension) {
580
- extensionSlug = registryExtension.extensionSlug || extensionId;
606
+ this.logger.info(' 📥 Found %d installed extensions', installedExtensionSlugs.size);
607
+ this.logger.info(' 🗑️ Found %d orphaned installed_extension entries', orphanedInstalledExtensions.length);
608
+ // Step 3: Get extensions from configuration registry (system_extension document)
609
+ // Scan both configuration and uiLayout schemas
610
+ const configExtensionSlugs = new Set();
611
+ const schemas = [ContributionSchemaId.Configuration, ContributionSchemaId.UiLayout];
612
+ for (const schemaId of schemas) {
613
+ try {
614
+ const systemExtensionDoc = await this.configurationRegistryService.getConfigurationNodeRegistry({
615
+ schemaId,
616
+ tenantId,
617
+ extensionName: 'system_extension'
618
+ });
619
+ if (systemExtensionDoc && typeof systemExtensionDoc === 'object' && 'configurationNodes' in systemExtensionDoc) {
620
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
621
+ const configNodes = systemExtensionDoc.configurationNodes || [];
622
+ // Extract from settings node properties
623
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
624
+ const settingsNode = configNodes.find(node => node.id === 'settings');
625
+ if (settingsNode?.properties) {
626
+ Object.keys(settingsNode.properties).forEach(key => {
627
+ if (key.startsWith('extensions.')) {
628
+ configExtensionSlugs.add(key.replace('extensions.', ''));
629
+ }
630
+ });
631
+ }
632
+ // Also extract from extensionInfo of each node
633
+ for (const node of configNodes) {
634
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
635
+ if (node.extensionInfo?.id) {
636
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
637
+ configExtensionSlugs.add(node.extensionInfo.id);
638
+ }
639
+ }
640
+ }
641
+ this.logger.info(' 📋 Found extensions in %s schema (total: %d)', schemaId, configExtensionSlugs.size);
642
+ } catch (error) {
643
+ this.logger.error(' ❌ Failed to get %s configuration registry:', schemaId, error);
644
+ result.warnings.push(`Failed to get ${schemaId} configuration registry: ${error.message}`);
645
+ }
646
+ }
647
+ this.logger.info(' 📋 Total unique extensions in configuration registry: %d', configExtensionSlugs.size);
648
+ // Step 4: Identify orphans
649
+ // 4a. Extensions in config registry but NOT in extension registry (deleted)
650
+ for (const configSlug of configExtensionSlugs) {
651
+ // Skip system extensions
652
+ if (this.isSystemExtension(configSlug)) {
653
+ continue;
654
+ }
655
+ if (!registryExtensionSlugs.has(configSlug)) {
656
+ this.logger.warn(' ⚠️ Extension in config but NOT in registry: %s', configSlug);
657
+ result.notInRegistry.push(configSlug);
581
658
  }
582
- } catch (error) {
583
- this.logger.warn(`Failed to fetch registry extension ${extensionId}:`, error);
584
659
  }
585
- if (!extensionSlug) {
586
- console.log(`⚠️ Could not determine slug for extension ID: ${extensionId}`);
587
- result.warnings.push(`Could not determine slug for extension ID: ${extensionId}`);
588
- } else if (!systemExtensionSlugs.has(extensionSlug)) {
589
- // If extension is in installed_extensions but NOT in system_extension, it's orphaned
590
- const orphanMsg = `⚠️ Found orphaned installed_extension: ${extensionSlug} (ID: ${extensionId}) (not in system_extension)`;
591
- console.log(orphanMsg);
660
+ // 4b. Extensions in config registry but NOT installed for this org
661
+ for (const configSlug of configExtensionSlugs) {
662
+ if (this.isSystemExtension(configSlug)) {
663
+ continue;
664
+ }
665
+ // Only check if it's in the registry (not already flagged as deleted)
666
+ if (registryExtensionSlugs.has(configSlug) && !installedExtensionSlugs.has(configSlug)) {
667
+ this.logger.warn(' ⚠️ Extension in config but NOT installed: %s', configSlug);
668
+ result.notInstalled.push(configSlug);
669
+ }
670
+ }
671
+ // 4c. Installed extensions without contributions in config registry
672
+ for (const installedSlug of installedExtensionSlugs) {
673
+ if (!configExtensionSlugs.has(installedSlug) && !this.isSystemExtension(installedSlug)) {
674
+ this.logger.warn(' ⚠️ Installed extension missing contributions: %s', installedSlug);
675
+ result.missingContributions.push(installedSlug);
676
+ }
677
+ }
678
+ // Step 5: Clean up orphaned extensions from configuration registry
679
+ const orphansToClean = [...result.notInRegistry, ...result.notInstalled];
680
+ for (const orphanSlug of orphansToClean) {
592
681
  if (!dryRun) {
593
682
  try {
594
- // Remove from installed_extensions
595
- await this.installedExtensionRepository.deleteExtension(orgId, extensionId);
596
- console.log(` ✅ Deleted from installed_extensions: ${extensionSlug}`);
597
- // Remove uiLayout configuration from configuration_registries
598
- await this.broker.call('ConfigurationRegistryService.removeConfigurationNodeRegistry', {
599
- context: {
600
- schemaId: 'uiLayout',
601
- tenantId,
602
- extensionName: extensionSlug
603
- }
683
+ // Remove from configuration registry (all schemas) - removes extension-specific documents
684
+ await this.configurationRegistryService.removeConfigurationNodeRegistry({
685
+ schemaId: ContributionSchemaId.Configuration,
686
+ tenantId,
687
+ extensionName: orphanSlug
688
+ });
689
+ this.logger.info(' ✅ Removed %s from configuration schema', orphanSlug);
690
+ await this.configurationRegistryService.removeConfigurationNodeRegistry({
691
+ schemaId: ContributionSchemaId.UiLayout,
692
+ tenantId,
693
+ extensionName: orphanSlug
604
694
  });
605
- console.log(`Deleted uiLayout config: ${extensionSlug}`);
606
- result.removed.push(extensionSlug);
695
+ this.logger.info('Removed %s from uiLayout schema', orphanSlug);
696
+ // If extension exists in installed_extensions but not in registry, remove it
697
+ if (result.notInRegistry.includes(orphanSlug) && installedExtensionMap.has(orphanSlug)) {
698
+ const installedExt = installedExtensionMap.get(orphanSlug);
699
+ if (installedExt) {
700
+ await this.installedExtensionRepository.deleteExtension(orgId, String(installedExt.extension));
701
+ this.logger.info(' ✅ Removed %s from installed_extensions', orphanSlug);
702
+ }
703
+ }
704
+ result.removed.push(orphanSlug);
607
705
  } catch (cleanupError) {
608
- console.error(` ❌ Failed to cleanup ${extensionSlug}:`, cleanupError);
609
- result.warnings.push(`Failed to cleanup ${extensionSlug}: ${cleanupError.message}`);
706
+ this.logger.error(' ❌ Failed to cleanup %s:', orphanSlug, cleanupError);
707
+ result.warnings.push(`Failed to cleanup ${orphanSlug}: ${cleanupError.message}`);
610
708
  }
611
709
  } else {
612
- console.log(` [DRY RUN] Would remove: ${extensionSlug}`);
613
- result.removed.push(extensionSlug);
710
+ this.logger.info(' [DRY RUN] Would remove: %s', orphanSlug);
711
+ result.removed.push(orphanSlug);
712
+ }
713
+ }
714
+ // Step 5b: Clean up orphaned properties from system_extension document
715
+ // Using the dedicated method in ConfigurationRegistryService
716
+ this.logger.info('🧹 Cleaning up orphaned properties from system_extension document...');
717
+ if (orphansToClean.length > 0) {
718
+ try {
719
+ const propertyCleanupResult = await this.configurationRegistryService.cleanupOrphanedExtensionProperties(tenantId, orphansToClean, dryRun);
720
+ if (propertyCleanupResult.success) {
721
+ result.orphanedPropertiesRemoved.push(...propertyCleanupResult.removedProperties);
722
+ for (const prop of propertyCleanupResult.removedProperties) {
723
+ if (dryRun) {
724
+ this.logger.info(' [DRY RUN] Would remove property: %s from system_extension', prop);
725
+ } else {
726
+ this.logger.info(' ✅ Removed property: %s from system_extension', prop);
727
+ }
728
+ }
729
+ }
730
+ if (propertyCleanupResult.warnings.length > 0) {
731
+ result.warnings.push(...propertyCleanupResult.warnings);
732
+ }
733
+ } catch (systemDocError) {
734
+ this.logger.error(' ❌ Failed to clean up system_extension properties:', systemDocError);
735
+ result.warnings.push(`Failed to clean up system_extension properties: ${systemDocError.message}`);
614
736
  }
615
- } else {
616
- console.log(`✅ Extension ${extensionSlug} is registered in system_extension`);
617
737
  }
738
+ // Step 6: Clean up orphaned installed_extensions entries
739
+ // (entries where the referenced extension doesn't exist in extensions collection)
740
+ this.logger.info('🗑️ Cleaning up %d orphaned installed_extension entries...', orphanedInstalledExtensions.length);
741
+ for (const orphan of orphanedInstalledExtensions) {
742
+ if (!dryRun) {
743
+ try {
744
+ // Cast to any to access deleteById method which may not be in interface
745
+ await this.installedExtensionRepository.deleteById(orphan.installedExtensionId);
746
+ this.logger.info(' ✅ Removed orphaned installed_extension: %s (extension: %s)', orphan.installedExtensionId, orphan.extensionId);
747
+ result.orphanedInstalledExtensionsRemoved.push(orphan.extensionId);
748
+ } catch (deleteError) {
749
+ this.logger.error(' ❌ Failed to delete orphaned installed_extension %s:', orphan.installedExtensionId, deleteError);
750
+ result.warnings.push(`Failed to delete orphaned installed_extension ${orphan.installedExtensionId}: ${deleteError.message}`);
751
+ }
752
+ } else {
753
+ this.logger.info(' [DRY RUN] Would remove orphaned installed_extension: %s (extension: %s)', orphan.installedExtensionId, orphan.extensionId);
754
+ result.orphanedInstalledExtensionsRemoved.push(orphan.extensionId);
755
+ }
756
+ }
757
+ this.logger.info('✅ [ORPHAN CLEANUP] Complete');
758
+ this.logger.info(' 📊 Summary:');
759
+ this.logger.info(' - Not in registry (deleted): %d', result.notInRegistry.length);
760
+ this.logger.info(' - Not installed: %d', result.notInstalled.length);
761
+ this.logger.info(' - Missing contributions: %d', result.missingContributions.length);
762
+ this.logger.info(' - Removed from config: %d', result.removed.length);
763
+ this.logger.info(' - Orphaned properties removed from system_extension: %d', result.orphanedPropertiesRemoved.length);
764
+ this.logger.info(' - Orphaned installed_extensions removed: %d', result.orphanedInstalledExtensionsRemoved.length);
765
+ this.logger.info(' - Warnings: %d', result.warnings.length);
766
+ return result;
767
+ } catch (error) {
768
+ this.logger.error('❌ [ORPHAN CLEANUP] Failed:', error);
769
+ result.warnings.push(`Cleanup failed: ${error.message}`);
770
+ return result;
618
771
  }
619
- console.log('\n✅ SYNC COMPLETE');
620
- console.log(` Removed: ${result.removed.length} extensions`);
621
- console.log(` Warnings: ${result.warnings.length} items`);
622
- return result;
772
+ }
773
+ /**
774
+ * Check if an extension slug is a system extension that should not be cleaned up
775
+ */
776
+ isSystemExtension(extensionSlug) {
777
+ const systemExtensions = ['vscode', 'system', 'core', 'default', 'settings', 'preferences', 'extensions', 'system_extension'];
778
+ return systemExtensions.some(sys => extensionSlug === sys || extensionSlug.startsWith(`${sys}.`) || extensionSlug.startsWith(`${sys}/`));
623
779
  }
624
780
  /**
625
781
  * Check if update is a security update (simplified logic)
@@ -630,4 +786,4 @@ let InstalledExtensionService = InstalledExtensionService_1 = class InstalledExt
630
786
  return false;
631
787
  }
632
788
  };
633
- InstalledExtensionService = InstalledExtensionService_1 = __decorate([injectable(), __param(0, inject(SERVER_TYPES.IInstalledExtensionRepository)), __param(1, inject(SERVER_TYPES.IRegistryExtensionService)), __param(2, inject(SERVER_TYPES.SlugService)), __param(3, inject(CommonType.MOLECULER_BROKER)), __param(4, inject(CommonType.LOGGER)), __metadata("design:paramtypes", [Object, Object, Object, ServiceBroker, Object])], InstalledExtensionService);export{InstalledExtensionService};//# sourceMappingURL=installed-extension-service.js.map
789
+ InstalledExtensionService = InstalledExtensionService_1 = __decorate([injectable(), __param(0, inject(SERVER_TYPES.IInstalledExtensionRepository)), __param(1, inject(SERVER_TYPES.IRegistryExtensionService)), __param(2, inject(SERVER_TYPES.SlugService)), __param(3, inject(CommonType.MOLECULER_BROKER)), __param(4, inject(SERVER_TYPES.ContributionNodeRegistryService)), __param(5, inject(CommonType.LOGGER)), __metadata("design:paramtypes", [Object, Object, Object, ServiceBroker, Object, Object])], InstalledExtensionService);export{InstalledExtensionService};//# sourceMappingURL=installed-extension-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-service.js","sources":["../../src/services/installed-extension-service.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"installed-extension-service.js","sources":["../../src/services/installed-extension-service.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -29,7 +29,13 @@ export declare class InstalledExtensionRepository extends BaseMongoRepository<II
29
29
  */
30
30
  findExtensions(query: IInstalledExtensionFilter): Promise<AsDomainType<IInstalledExtensionModel>[]>;
31
31
  /**
32
- * Delete an installed extension
32
+ * Delete an installed extension by its document _id
33
+ * Used for orphan cleanup when extension reference is invalid
34
+ * @param id - Can be a MongoDB ObjectId string, UUID string, or any valid document _id
35
+ */
36
+ deleteById(id: string): Promise<boolean>;
37
+ /**
38
+ * Delete an installed extension by organization and extension IDs
33
39
  */
34
40
  deleteExtension(orgId: string, extensionId: string): Promise<boolean>;
35
41
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-repository.d.ts","sourceRoot":"","sources":["../../../src/store/repositories/installed-extension-repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"installed-extension-repository.d.ts","sourceRoot":"","sources":["../../../src/store/repositories/installed-extension-repository.ts"],"names":[],"mappings":"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"}
@@ -252,7 +252,46 @@ import {__decorate,__param,__metadata}from'tslib';import {injectable,inject,opti
252
252
  }
253
253
  }
254
254
  /**
255
- * Delete an installed extension
255
+ * Delete an installed extension by its document _id
256
+ * Used for orphan cleanup when extension reference is invalid
257
+ * @param id - Can be a MongoDB ObjectId string, UUID string, or any valid document _id
258
+ */
259
+ async deleteById(id) {
260
+ try {
261
+ this.logger.info('deleteById called', {
262
+ id,
263
+ idType: typeof id
264
+ });
265
+ // Check if it's a valid MongoDB ObjectId (24 hex characters)
266
+ const isValidObjectId = /^[a-fA-F0-9]{24}$/.test(id);
267
+ const query = isValidObjectId ? {
268
+ _id: new mongoose.Types.ObjectId(id)
269
+ } : {
270
+ _id: id
271
+ }; // Use as-is for UUID or other string IDs
272
+ this.logger.info('deleteById query', {
273
+ query: JSON.stringify(query),
274
+ isValidObjectId
275
+ });
276
+ // Use the base class delete method which is known to work
277
+ const result = await this.delete(query);
278
+ this.logger.info('Deleted installed extension by id', {
279
+ id,
280
+ isValidObjectId,
281
+ deleted: result
282
+ });
283
+ return result;
284
+ } catch (error) {
285
+ this.logger.error('Error deleting installed extension by id', {
286
+ error: error instanceof Error ? error.message : String(error),
287
+ stack: error instanceof Error ? error.stack : undefined,
288
+ id
289
+ });
290
+ return false;
291
+ }
292
+ }
293
+ /**
294
+ * Delete an installed extension by organization and extension IDs
256
295
  */
257
296
  async deleteExtension(orgId, extensionId) {
258
297
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"installed-extension-repository.js","sources":["../../../src/store/repositories/installed-extension-repository.ts"],"sourcesContent":[null],"names":[],"mappings":"mWAiCU,IAAA,4BAA4B,qCAAkC,SAAY;AAe1E,EAAA,WAAA,CAAA,EAAA,EAAA,MAAA,EAAA,OACF,EAAA;IAeE,KAAA,CAAA,2BAAwB,EAAA,EAAA,EAAA,MAAA,EAAA,OAA4B,CAAA;AA+B1D,IAAA,IAAA,CAAA,EAAA,EAAA;;AAEG,IAAA;IACU,IAAA,CAAA,MAAA,GAAA,MACT,CAAK,KAAE,CAAA;AAwDX,MAAA,SAAA,EAAA;;AAEG,EAAA;QACU,oBACF,EAAA,aACP,EAAA;AAyBJ,IAAA,IAAA;;AAEG;AACU,MAAA,IAAA,CAAO,MAAM,CAAA,IAAE,CAAA;AAY5B,QAAA,KAAA;;AAEG,OAAA,CAAA;AACU,MAAA,OAAA,IAAA;AAab,IAAA,CAAA,CAAA,OAAA,KAAA,EAAA;;;AAGG,QAAA,KAAA;AACU,QAAA;AAgDb,OAAA,CAAA;;AAEG,IAAA;AACU,EAAA;AAYb,EAAA,MAAA,uBAAA,CAAA,cAAA,EAAA,WAAA,EAAA;;AAEG;MACU,OAAA,MAAA,IAAA,CAAoB;AAkCjC,QAAA,YAAA,EAAA,IAAA,QAAA,CAAA,KAAA,CAAA,QAAA,CAAA,cAAA,CAAA;;AAEG,OAAA,CAAA;AACU,IAAA,CAAA,CAAA,OAAO,KAAA,EAAA;AAgBpB,MAAA,IAAA,CAAA,MAAA,CAAA,KAAA,CAAA,kCAAA,EAAA;;AAEG,QAAA,cAAA;QACU;AAeb,OAAA,CAAA;;AAEG,IAAA;AACU,EAAA;AACT,EAAA,MAAA,eAAY,CAAA,MAAA,EAAY;QACxB;YACI,UAAA,GAAa;gBACb,CAAA,KAAS,EAAE;;AAEd,QAAA,UAAE,CAAA,YAAA,GAAA,IAAA,QAAA,CAAA,KAAA,CAAA,QAAA,CAAA,MAAA,CAAA,KAAA,CAAA;MACL;AAoBF,MAAA,IAAA,MAAA,CAAA,MAAA,EAAA;;AAEG,UAAA,GAAA,EAAA,MAAA,CAAA;SACU,GAAA,aAAoB;AAmBjC,MAAA;;AAEG,QAAA,UAAA,CAAA,0BAAA,CAAA,GAAA,KAAA,CAAA,OAAA,CAAA,MAAA,CAAA,0BAAA,CAAA,CAAA,GAAA;AACU,UAAA,GAAA,EAAA,MAAA,CAAA,0BAEH;AAkBV,SAAA,GAAA,MAAA,CAAA,0BAAA,CAAA;;AAEG,MAAA,IAAA,MAAA,CAAA,sBAAA,CAAA,KAAA,SAAA,EAAA;AACU,QAAA,UAAA,CAAA,sBACM,CAAA,GAAA,MAAA,CAAA,sBAAA,CAAA;;UAEX,MAAA,CAAA,2BAAoB,CAAA,KAAA,SAAA,EAAA;QACpB,UAAA,CAAA,2BAAuB,CAAA,GAAA,MAAA,CAAA,2BAAA,CAAA;;UAEvB,MAAA,CAAA,WAAoB,EAAA;AACvB,QAAC,UACK,CAAA,WAAK,GAAA,MAAA,CAAA,WAAA;AAyBnB,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"installed-extension-repository.js","sources":["../../../src/store/repositories/installed-extension-repository.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -186,14 +186,26 @@ export interface IInstalledExtensionService extends IBaseService<IInstalledExten
186
186
  }>;
187
187
 
188
188
  /**
189
- * Clean up orphaned extensions that exist in installed_extensions but not in system_extension registry
189
+ * Comprehensive cleanup of orphaned extensions from configuration registry.
190
+ *
191
+ * Identifies and cleans up:
192
+ * 1. Extensions in configuration_registry but NOT in extension registry (deleted extensions)
193
+ * 2. Extensions in configuration_registry but NOT installed for the organization
194
+ * 3. Reports installed extensions without contributions in configuration_registry
195
+ * 4. Orphaned installed_extension records pointing to non-existent extensions
196
+ * 5. Orphaned extension properties in system_extension document
190
197
  */
191
198
  cleanupOrphanedExtensions(
192
199
  orgId: string,
193
200
  tenantId: string,
194
201
  dryRun?: boolean,
195
202
  ): Promise<{
196
- removed: string[]; // Array of extension slugs
197
- warnings: string[];
203
+ removed: string[]; // Array of extension slugs that were removed
204
+ warnings: string[]; // Warning messages encountered during cleanup
205
+ notInRegistry: string[]; // Extensions in config but not in extension registry (deleted)
206
+ notInstalled: string[]; // Extensions in config but not installed for org
207
+ missingContributions: string[]; // Installed extensions without config contributions
208
+ orphanedInstalledExtensionsRemoved: string[]; // Orphaned installed_extension records removed
209
+ orphanedPropertiesRemoved: string[]; // Orphaned properties removed from system_extension
198
210
  }>;
199
211
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminide-stack/marketplace-module-server",
3
- "version": "13.1.2-alpha.9",
3
+ "version": "13.1.3-alpha.2",
4
4
  "description": "Sample core for higher packages to depend on",
5
5
  "license": "UNLICENSED",
6
6
  "author": "CDMBase LLC",
@@ -21,11 +21,11 @@
21
21
  "watch": "yarn build:lib:watch"
22
22
  },
23
23
  "dependencies": {
24
- "@adminide-stack/extension-api": "13.1.2-alpha.9",
24
+ "@adminide-stack/extension-api": "13.1.3-alpha.2",
25
25
  "nanoid": "^5.1.5"
26
26
  },
27
27
  "devDependencies": {
28
- "common": "13.1.2-alpha.9"
28
+ "common": "13.1.3-alpha.2"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "graphql-tag": ">=2.0.0"
@@ -55,8 +55,8 @@
55
55
  ]
56
56
  }
57
57
  },
58
- "gitHead": "1049eb9b6d34f64db1d0e1a85a21924eda9d4ff9",
59
58
  "typescript": {
60
59
  "definition": "lib/index.d.ts"
61
- }
60
+ },
61
+ "gitHead": "394adad29e2a114eb360b13076eab61df7d2d14a"
62
62
  }
@@ -1 +0,0 @@
1
- //# sourceMappingURL=installed-extension-service.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"installed-extension-service.test.d.ts","sourceRoot":"","sources":["../../src/services/installed-extension-service.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=extension-integration.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extension-integration.test.d.ts","sourceRoot":"","sources":["../../src/tests/extension-integration.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=install-extension-graphql.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install-extension-graphql.test.d.ts","sourceRoot":"","sources":["../../src/tests/install-extension-graphql.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=test-extension-services.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-extension-services.d.ts","sourceRoot":"","sources":["../../src/tests/test-extension-services.ts"],"names":[],"mappings":""}