@peernova/cuneiform-sf 1.0.2 → 1.0.4-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +81 -30
- package/README.md +59 -95
- package/lib/adapters/connection-facade.d.ts +458 -0
- package/lib/adapters/connection-facade.js +379 -0
- package/lib/adapters/connection-facade.js.map +1 -0
- package/lib/adapters/errors.d.ts +547 -0
- package/lib/adapters/errors.js +937 -0
- package/lib/adapters/errors.js.map +1 -0
- package/lib/adapters/index.d.ts +33 -0
- package/lib/adapters/index.js +50 -0
- package/lib/adapters/index.js.map +1 -0
- package/lib/adapters/lifecycle.d.ts +119 -0
- package/lib/adapters/lifecycle.js +94 -0
- package/lib/adapters/lifecycle.js.map +1 -0
- package/lib/adapters/rest/cache.d.ts +69 -0
- package/lib/adapters/rest/cache.js +133 -0
- package/lib/adapters/rest/cache.js.map +1 -0
- package/lib/adapters/rest/index.d.ts +11 -0
- package/lib/adapters/rest/index.js +18 -0
- package/lib/adapters/rest/index.js.map +1 -0
- package/lib/adapters/rest/profiling-rest-client.d.ts +137 -0
- package/lib/adapters/rest/profiling-rest-client.js +115 -0
- package/lib/adapters/rest/profiling-rest-client.js.map +1 -0
- package/lib/adapters/rest/rest-api-adapter.d.ts +389 -0
- package/lib/adapters/rest/rest-api-adapter.js +747 -0
- package/lib/adapters/rest/rest-api-adapter.js.map +1 -0
- package/lib/adapters/rest/types.d.ts +34 -0
- package/lib/adapters/rest/types.js +9 -0
- package/lib/adapters/rest/types.js.map +1 -0
- package/lib/adapters/retry.d.ts +91 -0
- package/lib/adapters/retry.js +215 -0
- package/lib/adapters/retry.js.map +1 -0
- package/lib/adapters/soql/cuneiform-query-builder.d.ts +391 -0
- package/lib/adapters/soql/cuneiform-query-builder.js +559 -0
- package/lib/adapters/soql/cuneiform-query-builder.js.map +1 -0
- package/lib/adapters/soql/index.d.ts +13 -0
- package/lib/adapters/soql/index.js +21 -0
- package/lib/adapters/soql/index.js.map +1 -0
- package/lib/adapters/soql/soql-query-adapter.d.ts +141 -0
- package/lib/adapters/soql/soql-query-adapter.js +259 -0
- package/lib/adapters/soql/soql-query-adapter.js.map +1 -0
- package/lib/adapters/soql/types.d.ts +37 -0
- package/lib/adapters/soql/types.js +19 -0
- package/lib/adapters/soql/types.js.map +1 -0
- package/lib/adapters/testing/index.d.ts +37 -0
- package/lib/adapters/testing/index.js +20 -0
- package/lib/adapters/testing/index.js.map +1 -0
- package/lib/adapters/testing/mock-connection.d.ts +77 -0
- package/lib/adapters/testing/mock-connection.js +207 -0
- package/lib/adapters/testing/mock-connection.js.map +1 -0
- package/lib/adapters/testing/mock-logger.d.ts +29 -0
- package/lib/adapters/testing/mock-logger.js +57 -0
- package/lib/adapters/testing/mock-logger.js.map +1 -0
- package/lib/adapters/testing/mock-mcp-adapters.d.ts +32 -0
- package/lib/adapters/testing/mock-mcp-adapters.js +52 -0
- package/lib/adapters/testing/mock-mcp-adapters.js.map +1 -0
- package/lib/adapters/testing/mock-oclif-config.d.ts +22 -0
- package/lib/adapters/testing/mock-oclif-config.js +90 -0
- package/lib/adapters/testing/mock-oclif-config.js.map +1 -0
- package/lib/adapters/testing/mock-rest-adapter.d.ts +26 -0
- package/lib/adapters/testing/mock-rest-adapter.js +243 -0
- package/lib/adapters/testing/mock-rest-adapter.js.map +1 -0
- package/lib/adapters/testing/mock-salesforce-connection.d.ts +40 -0
- package/lib/adapters/testing/mock-salesforce-connection.js +61 -0
- package/lib/adapters/testing/mock-salesforce-connection.js.map +1 -0
- package/lib/adapters/testing/mock-soql-adapter.d.ts +30 -0
- package/lib/adapters/testing/mock-soql-adapter.js +120 -0
- package/lib/adapters/testing/mock-soql-adapter.js.map +1 -0
- package/lib/adapters/testing/mock-tooling-adapter.d.ts +24 -0
- package/lib/adapters/testing/mock-tooling-adapter.js +163 -0
- package/lib/adapters/testing/mock-tooling-adapter.js.map +1 -0
- package/lib/adapters/testing/stub-connection.d.ts +93 -0
- package/lib/adapters/testing/stub-connection.js +97 -0
- package/lib/adapters/testing/stub-connection.js.map +1 -0
- package/lib/adapters/testing/stub-rest-adapter.d.ts +52 -0
- package/lib/adapters/testing/stub-rest-adapter.js +58 -0
- package/lib/adapters/testing/stub-rest-adapter.js.map +1 -0
- package/lib/adapters/testing/stub-soql-adapter.d.ts +56 -0
- package/lib/adapters/testing/stub-soql-adapter.js +50 -0
- package/lib/adapters/testing/stub-soql-adapter.js.map +1 -0
- package/lib/adapters/testing/types.d.ts +71 -0
- package/lib/adapters/testing/types.js +9 -0
- package/lib/adapters/testing/types.js.map +1 -0
- package/lib/adapters/tooling/index.d.ts +10 -0
- package/lib/adapters/tooling/index.js +17 -0
- package/lib/adapters/tooling/index.js.map +1 -0
- package/lib/adapters/tooling/tooling-api-adapter.d.ts +157 -0
- package/lib/adapters/tooling/tooling-api-adapter.js +339 -0
- package/lib/adapters/tooling/tooling-api-adapter.js.map +1 -0
- package/lib/adapters/tooling/types.d.ts +81 -0
- package/lib/adapters/tooling/types.js +9 -0
- package/lib/adapters/tooling/types.js.map +1 -0
- package/lib/adapters/types.d.ts +112 -0
- package/lib/adapters/types.js +169 -0
- package/lib/adapters/types.js.map +1 -0
- package/lib/base/cuneiform-command.d.ts +152 -0
- package/lib/base/cuneiform-command.js +243 -0
- package/lib/base/cuneiform-command.js.map +1 -0
- package/lib/commands/cuneiform/compatibility/check.d.ts +43 -0
- package/lib/commands/cuneiform/compatibility/check.js +114 -0
- package/lib/commands/cuneiform/compatibility/check.js.map +1 -0
- package/lib/commands/cuneiform/definition/create.d.ts +119 -0
- package/lib/commands/cuneiform/definition/create.js +693 -0
- package/lib/commands/cuneiform/definition/create.js.map +1 -0
- package/lib/commands/cuneiform/definition/export.d.ts +57 -0
- package/lib/commands/cuneiform/definition/export.js +133 -0
- package/lib/commands/cuneiform/definition/export.js.map +1 -0
- package/lib/commands/cuneiform/definition/get.d.ts +86 -0
- package/lib/commands/cuneiform/definition/get.js +270 -0
- package/lib/commands/cuneiform/definition/get.js.map +1 -0
- package/lib/commands/cuneiform/definition/import.d.ts +54 -0
- package/lib/commands/cuneiform/definition/import.js +118 -0
- package/lib/commands/cuneiform/definition/import.js.map +1 -0
- package/lib/commands/cuneiform/definition/list.d.ts +110 -0
- package/lib/commands/cuneiform/definition/list.js +344 -0
- package/lib/commands/cuneiform/definition/list.js.map +1 -0
- package/lib/commands/cuneiform/definition/purge.d.ts +105 -0
- package/lib/commands/cuneiform/definition/purge.js +533 -0
- package/lib/commands/cuneiform/definition/purge.js.map +1 -0
- package/lib/commands/cuneiform/definition/update.d.ts +58 -0
- package/lib/commands/cuneiform/definition/update.js +206 -0
- package/lib/commands/cuneiform/definition/update.js.map +1 -0
- package/lib/commands/cuneiform/mcp/serve.d.ts +56 -0
- package/lib/commands/cuneiform/mcp/serve.js +109 -0
- package/lib/commands/cuneiform/mcp/serve.js.map +1 -0
- package/lib/commands/cuneiform/object/describe.d.ts +61 -0
- package/lib/commands/cuneiform/object/describe.js +461 -0
- package/lib/commands/cuneiform/object/describe.js.map +1 -0
- package/lib/commands/cuneiform/object/list.d.ts +111 -0
- package/lib/commands/cuneiform/object/list.js +239 -0
- package/lib/commands/cuneiform/object/list.js.map +1 -0
- package/lib/commands/cuneiform/org/details.d.ts +99 -0
- package/lib/commands/cuneiform/org/details.js +521 -0
- package/lib/commands/cuneiform/org/details.js.map +1 -0
- package/lib/commands/cuneiform/org/reset.d.ts +46 -0
- package/lib/commands/cuneiform/org/reset.js +135 -0
- package/lib/commands/cuneiform/org/reset.js.map +1 -0
- package/lib/commands/cuneiform/profile/request/cancel.d.ts +59 -0
- package/lib/commands/cuneiform/profile/request/cancel.js +202 -0
- package/lib/commands/cuneiform/profile/request/cancel.js.map +1 -0
- package/lib/commands/cuneiform/profile/request/delete.d.ts +59 -0
- package/lib/commands/cuneiform/profile/request/delete.js +223 -0
- package/lib/commands/cuneiform/profile/request/delete.js.map +1 -0
- package/lib/commands/cuneiform/profile/request/list.d.ts +35 -0
- package/lib/commands/cuneiform/profile/request/list.js +102 -0
- package/lib/commands/cuneiform/profile/request/list.js.map +1 -0
- package/lib/commands/cuneiform/profile.d.ts +90 -0
- package/lib/commands/cuneiform/profile.js +322 -0
- package/lib/commands/cuneiform/profile.js.map +1 -0
- package/lib/commands/cuneiform/summary/purge.d.ts +77 -0
- package/lib/commands/cuneiform/summary/purge.js +429 -0
- package/lib/commands/cuneiform/summary/purge.js.map +1 -0
- package/lib/commands/cuneiform/summary/reprofile.d.ts +60 -0
- package/lib/commands/cuneiform/summary/reprofile.js +236 -0
- package/lib/commands/cuneiform/summary/reprofile.js.map +1 -0
- package/lib/commands/cuneiform/summary/stop.d.ts +59 -0
- package/lib/commands/cuneiform/summary/stop.js +234 -0
- package/lib/commands/cuneiform/summary/stop.js.map +1 -0
- package/lib/commands/cuneiform/user/details.d.ts +73 -0
- package/lib/commands/cuneiform/user/details.js +391 -0
- package/lib/commands/cuneiform/user/details.js.map +1 -0
- package/lib/constants/index.d.ts +8 -0
- package/lib/constants/index.js +16 -0
- package/lib/constants/index.js.map +1 -0
- package/lib/constants/namespace-constants.d.ts +91 -0
- package/lib/constants/namespace-constants.js +211 -0
- package/lib/constants/namespace-constants.js.map +1 -0
- package/lib/debug/command-debug-proxy.d.ts +101 -0
- package/lib/debug/command-debug-proxy.js +171 -0
- package/lib/debug/command-debug-proxy.js.map +1 -0
- package/lib/debug/debug-logger.d.ts +85 -0
- package/lib/debug/debug-logger.js +133 -0
- package/lib/debug/debug-logger.js.map +1 -0
- package/lib/debug/index.d.ts +12 -0
- package/lib/debug/index.js +20 -0
- package/lib/debug/index.js.map +1 -0
- package/lib/debug/service-debug-proxy.d.ts +30 -0
- package/lib/debug/service-debug-proxy.js +102 -0
- package/lib/debug/service-debug-proxy.js.map +1 -0
- package/lib/hooks/prerun.d.ts +25 -0
- package/lib/hooks/prerun.js +47 -0
- package/lib/hooks/prerun.js.map +1 -0
- package/lib/mcp/config/mcp-config.d.ts +55 -0
- package/lib/mcp/config/mcp-config.js +51 -0
- package/lib/mcp/config/mcp-config.js.map +1 -0
- package/lib/mcp/config/pagination.d.ts +96 -0
- package/lib/mcp/config/pagination.js +108 -0
- package/lib/mcp/config/pagination.js.map +1 -0
- package/lib/mcp/config/system-prompts.d.ts +18 -0
- package/lib/mcp/config/system-prompts.js +92 -0
- package/lib/mcp/config/system-prompts.js.map +1 -0
- package/lib/mcp/errors.d.ts +23 -0
- package/lib/mcp/errors.js +27 -0
- package/lib/mcp/errors.js.map +1 -0
- package/lib/mcp/schemas/input-schemas.d.ts +327 -0
- package/lib/mcp/schemas/input-schemas.js +302 -0
- package/lib/mcp/schemas/input-schemas.js.map +1 -0
- package/lib/mcp/server.d.ts +40 -0
- package/lib/mcp/server.js +316 -0
- package/lib/mcp/server.js.map +1 -0
- package/lib/mcp/tools/contactpoint-tools.d.ts +14 -0
- package/lib/mcp/tools/contactpoint-tools.js +34 -0
- package/lib/mcp/tools/contactpoint-tools.js.map +1 -0
- package/lib/mcp/tools/definition-io-tools.d.ts +19 -0
- package/lib/mcp/tools/definition-io-tools.js +152 -0
- package/lib/mcp/tools/definition-io-tools.js.map +1 -0
- package/lib/mcp/tools/definition-tools.d.ts +51 -0
- package/lib/mcp/tools/definition-tools.js +199 -0
- package/lib/mcp/tools/definition-tools.js.map +1 -0
- package/lib/mcp/tools/index.d.ts +37 -0
- package/lib/mcp/tools/index.js +88 -0
- package/lib/mcp/tools/index.js.map +1 -0
- package/lib/mcp/tools/object-tools.d.ts +22 -0
- package/lib/mcp/tools/object-tools.js +306 -0
- package/lib/mcp/tools/object-tools.js.map +1 -0
- package/lib/mcp/tools/org-tools.d.ts +14 -0
- package/lib/mcp/tools/org-tools.js +177 -0
- package/lib/mcp/tools/org-tools.js.map +1 -0
- package/lib/mcp/tools/profile-tools.d.ts +59 -0
- package/lib/mcp/tools/profile-tools.js +213 -0
- package/lib/mcp/tools/profile-tools.js.map +1 -0
- package/lib/mcp/tools/summary-tools.d.ts +14 -0
- package/lib/mcp/tools/summary-tools.js +38 -0
- package/lib/mcp/tools/summary-tools.js.map +1 -0
- package/lib/mcp/tools/tool-factory.d.ts +63 -0
- package/lib/mcp/tools/tool-factory.js +146 -0
- package/lib/mcp/tools/tool-factory.js.map +1 -0
- package/lib/mcp/tools/user-tools.d.ts +25 -0
- package/lib/mcp/tools/user-tools.js +167 -0
- package/lib/mcp/tools/user-tools.js.map +1 -0
- package/lib/models/date-literal.d.ts +211 -0
- package/lib/models/date-literal.js +615 -0
- package/lib/models/date-literal.js.map +1 -0
- package/lib/models/object-describe-types.d.ts +173 -0
- package/lib/models/object-describe-types.js +9 -0
- package/lib/models/object-describe-types.js.map +1 -0
- package/lib/models/profile-request-types.d.ts +118 -0
- package/lib/models/profile-request-types.js +23 -0
- package/lib/models/profile-request-types.js.map +1 -0
- package/lib/models/profiling-execution-types.d.ts +154 -0
- package/lib/models/profiling-execution-types.js +14 -0
- package/lib/models/profiling-execution-types.js.map +1 -0
- package/lib/models/service-result.d.ts +114 -0
- package/lib/models/service-result.js +81 -0
- package/lib/models/service-result.js.map +1 -0
- package/lib/models/sfdmu-types.d.ts +53 -0
- package/lib/models/sfdmu-types.js +23 -0
- package/lib/models/sfdmu-types.js.map +1 -0
- package/lib/models/status-types.d.ts +38 -0
- package/lib/models/status-types.js +12 -0
- package/lib/models/status-types.js.map +1 -0
- package/lib/models/summary-bulk-types.d.ts +61 -0
- package/lib/models/summary-bulk-types.js +23 -0
- package/lib/models/summary-bulk-types.js.map +1 -0
- package/lib/models/user-details-types.d.ts +163 -0
- package/lib/models/user-details-types.js +9 -0
- package/lib/models/user-details-types.js.map +1 -0
- package/lib/models/year-range.d.ts +78 -0
- package/lib/models/year-range.js +153 -0
- package/lib/models/year-range.js.map +1 -0
- package/lib/operations/CompatibilityCheckOperation.d.ts +62 -0
- package/lib/operations/CompatibilityCheckOperation.js +102 -0
- package/lib/operations/CompatibilityCheckOperation.js.map +1 -0
- package/lib/operations/DefinitionCreateOperation.d.ts +411 -0
- package/lib/operations/DefinitionCreateOperation.js +1121 -0
- package/lib/operations/DefinitionCreateOperation.js.map +1 -0
- package/lib/operations/DefinitionExportOperation.d.ts +155 -0
- package/lib/operations/DefinitionExportOperation.js +281 -0
- package/lib/operations/DefinitionExportOperation.js.map +1 -0
- package/lib/operations/DefinitionImportOperation.d.ts +144 -0
- package/lib/operations/DefinitionImportOperation.js +357 -0
- package/lib/operations/DefinitionImportOperation.js.map +1 -0
- package/lib/operations/DefinitionListOperation.d.ts +66 -0
- package/lib/operations/DefinitionListOperation.js +108 -0
- package/lib/operations/DefinitionListOperation.js.map +1 -0
- package/lib/operations/DefinitionPurgeOperation.d.ts +199 -0
- package/lib/operations/DefinitionPurgeOperation.js +465 -0
- package/lib/operations/DefinitionPurgeOperation.js.map +1 -0
- package/lib/operations/DefinitionUpdateOperation.d.ts +78 -0
- package/lib/operations/DefinitionUpdateOperation.js +142 -0
- package/lib/operations/DefinitionUpdateOperation.js.map +1 -0
- package/lib/operations/OrgDetailsOperation.d.ts +253 -0
- package/lib/operations/OrgDetailsOperation.js +456 -0
- package/lib/operations/OrgDetailsOperation.js.map +1 -0
- package/lib/operations/OrgResetOperation.d.ts +114 -0
- package/lib/operations/OrgResetOperation.js +209 -0
- package/lib/operations/OrgResetOperation.js.map +1 -0
- package/lib/operations/ProfileOperation.d.ts +187 -0
- package/lib/operations/ProfileOperation.js +373 -0
- package/lib/operations/ProfileOperation.js.map +1 -0
- package/lib/operations/ProfileRequestCancelOperation.d.ts +59 -0
- package/lib/operations/ProfileRequestCancelOperation.js +137 -0
- package/lib/operations/ProfileRequestCancelOperation.js.map +1 -0
- package/lib/operations/ProfileRequestDeleteOperation.d.ts +64 -0
- package/lib/operations/ProfileRequestDeleteOperation.js +134 -0
- package/lib/operations/ProfileRequestDeleteOperation.js.map +1 -0
- package/lib/operations/ProfileRequestListOperation.d.ts +39 -0
- package/lib/operations/ProfileRequestListOperation.js +61 -0
- package/lib/operations/ProfileRequestListOperation.js.map +1 -0
- package/lib/operations/SummaryPurgeOperation.d.ts +134 -0
- package/lib/operations/SummaryPurgeOperation.js +257 -0
- package/lib/operations/SummaryPurgeOperation.js.map +1 -0
- package/lib/operations/SummaryReprofileOperation.d.ts +88 -0
- package/lib/operations/SummaryReprofileOperation.js +174 -0
- package/lib/operations/SummaryReprofileOperation.js.map +1 -0
- package/lib/operations/SummaryStopOperation.d.ts +87 -0
- package/lib/operations/SummaryStopOperation.js +175 -0
- package/lib/operations/SummaryStopOperation.js.map +1 -0
- package/lib/services/BulkExecutionService.d.ts +120 -0
- package/lib/services/BulkExecutionService.js +535 -0
- package/lib/services/BulkExecutionService.js.map +1 -0
- package/lib/services/CompatibilityService.d.ts +81 -0
- package/lib/services/CompatibilityService.js +118 -0
- package/lib/services/CompatibilityService.js.map +1 -0
- package/lib/services/ConfigureMode.d.ts +85 -0
- package/lib/services/ConfigureMode.js +390 -0
- package/lib/services/ConfigureMode.js.map +1 -0
- package/lib/services/ContactPointService.d.ts +111 -0
- package/lib/services/ContactPointService.js +286 -0
- package/lib/services/ContactPointService.js.map +1 -0
- package/lib/services/DataAvailabilityService.d.ts +81 -0
- package/lib/services/DataAvailabilityService.js +128 -0
- package/lib/services/DataAvailabilityService.js.map +1 -0
- package/lib/services/DefinitionFieldGenerationService.d.ts +309 -0
- package/lib/services/DefinitionFieldGenerationService.js +795 -0
- package/lib/services/DefinitionFieldGenerationService.js.map +1 -0
- package/lib/services/DefinitionQueryBuilder.d.ts +59 -0
- package/lib/services/DefinitionQueryBuilder.js +234 -0
- package/lib/services/DefinitionQueryBuilder.js.map +1 -0
- package/lib/services/ObjectDescribeService.d.ts +436 -0
- package/lib/services/ObjectDescribeService.js +869 -0
- package/lib/services/ObjectDescribeService.js.map +1 -0
- package/lib/services/ObjectFilteringService.d.ts +400 -0
- package/lib/services/ObjectFilteringService.js +878 -0
- package/lib/services/ObjectFilteringService.js.map +1 -0
- package/lib/services/ObjectListCommandService.d.ts +429 -0
- package/lib/services/ObjectListCommandService.js +873 -0
- package/lib/services/ObjectListCommandService.js.map +1 -0
- package/lib/services/ObjectListService.d.ts +201 -0
- package/lib/services/ObjectListService.js +345 -0
- package/lib/services/ObjectListService.js.map +1 -0
- package/lib/services/OrgInfoService.d.ts +485 -0
- package/lib/services/OrgInfoService.js +1122 -0
- package/lib/services/OrgInfoService.js.map +1 -0
- package/lib/services/PollingService.d.ts +105 -0
- package/lib/services/PollingService.js +117 -0
- package/lib/services/PollingService.js.map +1 -0
- package/lib/services/ProfileRequestService.d.ts +186 -0
- package/lib/services/ProfileRequestService.js +555 -0
- package/lib/services/ProfileRequestService.js.map +1 -0
- package/lib/services/ProfilingDefinitionService.d.ts +535 -0
- package/lib/services/ProfilingDefinitionService.js +981 -0
- package/lib/services/ProfilingDefinitionService.js.map +1 -0
- package/lib/services/ProfilingExecutionService.d.ts +122 -0
- package/lib/services/ProfilingExecutionService.js +320 -0
- package/lib/services/ProfilingExecutionService.js.map +1 -0
- package/lib/services/ProfilingSummaryService.d.ts +292 -0
- package/lib/services/ProfilingSummaryService.js +685 -0
- package/lib/services/ProfilingSummaryService.js.map +1 -0
- package/lib/services/RecordTypeService.d.ts +129 -0
- package/lib/services/RecordTypeService.js +284 -0
- package/lib/services/RecordTypeService.js.map +1 -0
- package/lib/services/SFDMUService.d.ts +133 -0
- package/lib/services/SFDMUService.js +295 -0
- package/lib/services/SFDMUService.js.map +1 -0
- package/lib/services/TabDetectionService.d.ts +105 -0
- package/lib/services/TabDetectionService.js +206 -0
- package/lib/services/TabDetectionService.js.map +1 -0
- package/lib/services/UnconfigureMode.d.ts +74 -0
- package/lib/services/UnconfigureMode.js +378 -0
- package/lib/services/UnconfigureMode.js.map +1 -0
- package/lib/services/UserConfigurationService.d.ts +155 -0
- package/lib/services/UserConfigurationService.js +573 -0
- package/lib/services/UserConfigurationService.js.map +1 -0
- package/lib/services/UserConfigurationTypes.d.ts +181 -0
- package/lib/services/UserConfigurationTypes.js +14 -0
- package/lib/services/UserConfigurationTypes.js.map +1 -0
- package/lib/services/UserReadinessService.d.ts +330 -0
- package/lib/services/UserReadinessService.js +831 -0
- package/lib/services/UserReadinessService.js.map +1 -0
- package/lib/services/constants.d.ts +53 -0
- package/lib/services/constants.js +71 -0
- package/lib/services/constants.js.map +1 -0
- package/lib/services/namespace-constants.d.ts +1 -0
- package/lib/services/namespace-constants.js +11 -0
- package/lib/services/namespace-constants.js.map +1 -0
- package/lib/services/validation.d.ts +47 -0
- package/lib/services/validation.js +119 -0
- package/lib/services/validation.js.map +1 -0
- package/lib/utils/batch-processor.d.ts +13 -0
- package/lib/utils/batch-processor.js +39 -0
- package/lib/utils/batch-processor.js.map +1 -0
- package/lib/utils/formatting/availability-grid.d.ts +81 -0
- package/lib/utils/formatting/availability-grid.js +94 -0
- package/lib/utils/formatting/availability-grid.js.map +1 -0
- package/lib/utils/formatting/business-process-grid.d.ts +51 -0
- package/lib/utils/formatting/business-process-grid.js +58 -0
- package/lib/utils/formatting/business-process-grid.js.map +1 -0
- package/lib/utils/formatting/command-display.d.ts +154 -0
- package/lib/utils/formatting/command-display.js +154 -0
- package/lib/utils/formatting/command-display.js.map +1 -0
- package/lib/utils/formatting/definition-create-display.d.ts +118 -0
- package/lib/utils/formatting/definition-create-display.js +231 -0
- package/lib/utils/formatting/definition-create-display.js.map +1 -0
- package/lib/utils/formatting/empty-states.d.ts +35 -0
- package/lib/utils/formatting/empty-states.js +70 -0
- package/lib/utils/formatting/empty-states.js.map +1 -0
- package/lib/utils/formatting/errors.d.ts +33 -0
- package/lib/utils/formatting/errors.js +72 -0
- package/lib/utils/formatting/errors.js.map +1 -0
- package/lib/utils/formatting/field-types.d.ts +32 -0
- package/lib/utils/formatting/field-types.js +88 -0
- package/lib/utils/formatting/field-types.js.map +1 -0
- package/lib/utils/formatting/index.d.ts +29 -0
- package/lib/utils/formatting/index.js +28 -0
- package/lib/utils/formatting/index.js.map +1 -0
- package/lib/utils/formatting/indicators.d.ts +113 -0
- package/lib/utils/formatting/indicators.js +161 -0
- package/lib/utils/formatting/indicators.js.map +1 -0
- package/lib/utils/formatting/loading-messages.d.ts +37 -0
- package/lib/utils/formatting/loading-messages.js +50 -0
- package/lib/utils/formatting/loading-messages.js.map +1 -0
- package/lib/utils/formatting/namespace-display.d.ts +31 -0
- package/lib/utils/formatting/namespace-display.js +64 -0
- package/lib/utils/formatting/namespace-display.js.map +1 -0
- package/lib/utils/formatting/numbers.d.ts +73 -0
- package/lib/utils/formatting/numbers.js +187 -0
- package/lib/utils/formatting/numbers.js.map +1 -0
- package/lib/utils/formatting/object-describe-display.d.ts +114 -0
- package/lib/utils/formatting/object-describe-display.js +440 -0
- package/lib/utils/formatting/object-describe-display.js.map +1 -0
- package/lib/utils/formatting/object-list-display.d.ts +213 -0
- package/lib/utils/formatting/object-list-display.js +672 -0
- package/lib/utils/formatting/object-list-display.js.map +1 -0
- package/lib/utils/formatting/org-identity.d.ts +15 -0
- package/lib/utils/formatting/org-identity.js +28 -0
- package/lib/utils/formatting/org-identity.js.map +1 -0
- package/lib/utils/formatting/record-age-grid.d.ts +41 -0
- package/lib/utils/formatting/record-age-grid.js +56 -0
- package/lib/utils/formatting/record-age-grid.js.map +1 -0
- package/lib/utils/formatting/sections.d.ts +108 -0
- package/lib/utils/formatting/sections.js +150 -0
- package/lib/utils/formatting/sections.js.map +1 -0
- package/lib/utils/formatting/tables.d.ts +90 -0
- package/lib/utils/formatting/tables.js +113 -0
- package/lib/utils/formatting/tables.js.map +1 -0
- package/lib/utils/formatting/user-details-display.d.ts +101 -0
- package/lib/utils/formatting/user-details-display.js +425 -0
- package/lib/utils/formatting/user-details-display.js.map +1 -0
- package/lib/utils/pagination/index.d.ts +11 -0
- package/lib/utils/pagination/index.js +18 -0
- package/lib/utils/pagination/index.js.map +1 -0
- package/lib/utils/pagination/keypress-reader.d.ts +20 -0
- package/lib/utils/pagination/keypress-reader.js +63 -0
- package/lib/utils/pagination/keypress-reader.js.map +1 -0
- package/lib/utils/pagination/paginate-output.d.ts +48 -0
- package/lib/utils/pagination/paginate-output.js +136 -0
- package/lib/utils/pagination/paginate-output.js.map +1 -0
- package/messages/compatibility.check.md +71 -0
- package/messages/cuneiform.access.md +138 -0
- package/messages/definition.create.md +511 -0
- package/messages/definition.export.md +84 -0
- package/messages/definition.get.md +147 -0
- package/messages/definition.import.md +65 -0
- package/messages/definition.list.md +264 -0
- package/messages/definition.purge.md +318 -0
- package/messages/definition.update.md +118 -0
- package/messages/mcp.serve.md +66 -0
- package/messages/object.describe.md +201 -0
- package/messages/object.list.md +443 -0
- package/messages/org.details.md +386 -0
- package/messages/org.reset.md +71 -0
- package/messages/profile.md +231 -0
- package/messages/profile.request.cancel.md +143 -0
- package/messages/profile.request.delete.md +139 -0
- package/messages/profile.request.list.md +89 -0
- package/messages/summary.purge.md +218 -0
- package/messages/summary.reprofile.md +150 -0
- package/messages/summary.stop.md +157 -0
- package/messages/user.details.md +501 -0
- package/oclif.lock +2887 -2149
- package/oclif.manifest.json +2813 -31
- package/package.json +94 -19
- package/lib/commands/cuneiform/about.d.ts +0 -13
- package/lib/commands/cuneiform/about.js +0 -26
- package/lib/commands/cuneiform/about.js.map +0 -1
- package/lib/commands/hello/world.d.ts +0 -14
- package/lib/commands/hello/world.js +0 -27
- package/lib/commands/hello/world.js.map +0 -1
- package/lib/index.d.ts +0 -2
- package/lib/index.js +0 -2
- package/lib/index.js.map +0 -1
- package/messages/cuneiform.about.md +0 -19
- package/messages/hello.world.md +0 -29
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, PeerNova, Inc. All Rights Reserved.
|
|
3
|
+
* PROPRIETARY AND CONFIDENTIAL. Unauthorized copying, modification,
|
|
4
|
+
* or distribution is strictly prohibited. Use is governed by the
|
|
5
|
+
* Master Subscription Agreement (MSA) between PeerNova, Inc. and the
|
|
6
|
+
* licensee. See LICENSE file in the repo root.
|
|
7
|
+
*/
|
|
8
|
+
import { CuneiformQueryBuilder } from '../adapters/soql/cuneiform-query-builder.js';
|
|
9
|
+
import { createSuccessResult, createFailureResult } from '../models/service-result.js';
|
|
10
|
+
import { ServiceErrorCodes, AdapterErrorCodes } from '../adapters/errors.js';
|
|
11
|
+
import { validateRequiredString, validateObjectName } from './validation.js';
|
|
12
|
+
/**
|
|
13
|
+
* Service for retrieving comprehensive object metadata with field analysis and profiling status.
|
|
14
|
+
*
|
|
15
|
+
* This service combines REST API describe results with optional enrichment from:
|
|
16
|
+
* - RecordTypeService: Record type information
|
|
17
|
+
* - ProfilingDefinitionService: Existing profiling definitions
|
|
18
|
+
* - ProfilingSummaryService: Profiling summary statistics
|
|
19
|
+
*
|
|
20
|
+
* Object Rejection Rules:
|
|
21
|
+
* - Big Objects (__b suffix) are rejected with E4805
|
|
22
|
+
* - External Objects (__x suffix) are rejected with E4806
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const service = new ObjectDescribeService({
|
|
27
|
+
* restApiAdapter,
|
|
28
|
+
* soqlAdapter,
|
|
29
|
+
* recordTypeService,
|
|
30
|
+
* profilingDefinitionService,
|
|
31
|
+
* profilingSummaryService,
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* const result = await service.describeObject('Account');
|
|
35
|
+
* if (result.success) {
|
|
36
|
+
* console.log(`${result.data.objectName}: ${result.data.fieldClassification.totalFields} fields`);
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export class ObjectDescribeService {
|
|
41
|
+
/** Lookup table for field type to display category mapping */
|
|
42
|
+
static FIELD_TYPE_MAP = {
|
|
43
|
+
string: 'Text',
|
|
44
|
+
textarea: 'Text',
|
|
45
|
+
url: 'Text',
|
|
46
|
+
email: 'Text',
|
|
47
|
+
phone: 'Text',
|
|
48
|
+
picklist: 'Picklist',
|
|
49
|
+
multipicklist: 'Picklist',
|
|
50
|
+
reference: 'Lookup',
|
|
51
|
+
double: 'Number',
|
|
52
|
+
currency: 'Number',
|
|
53
|
+
percent: 'Number',
|
|
54
|
+
int: 'Number',
|
|
55
|
+
date: 'Date/DateTime',
|
|
56
|
+
datetime: 'Date/DateTime',
|
|
57
|
+
time: 'Date/DateTime',
|
|
58
|
+
boolean: 'Checkbox',
|
|
59
|
+
id: 'ID',
|
|
60
|
+
address: 'Address',
|
|
61
|
+
location: 'Geolocation',
|
|
62
|
+
};
|
|
63
|
+
restApiAdapter;
|
|
64
|
+
soqlAdapter;
|
|
65
|
+
recordTypeService;
|
|
66
|
+
profilingDefinitionService;
|
|
67
|
+
profilingSummaryService;
|
|
68
|
+
logger;
|
|
69
|
+
restClient;
|
|
70
|
+
constructor(config) {
|
|
71
|
+
this.restApiAdapter = config.restApiAdapter;
|
|
72
|
+
this.soqlAdapter = config.soqlAdapter;
|
|
73
|
+
this.recordTypeService = config.recordTypeService;
|
|
74
|
+
this.profilingDefinitionService = config.profilingDefinitionService;
|
|
75
|
+
this.profilingSummaryService = config.profilingSummaryService;
|
|
76
|
+
this.logger = config.logger;
|
|
77
|
+
this.restClient = config.restClient;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Calculates field type distribution from an array of fields.
|
|
81
|
+
*
|
|
82
|
+
* @param fields - Array of DescribeFieldResult from object describe
|
|
83
|
+
* @returns ServiceResult containing array of FieldTypeCount sorted by count descending
|
|
84
|
+
*/
|
|
85
|
+
static getFieldTypeDistribution(fields) {
|
|
86
|
+
const startTime = Date.now();
|
|
87
|
+
const emptyResult = [];
|
|
88
|
+
if (!fields || fields.length === 0) {
|
|
89
|
+
return createSuccessResult(emptyResult, {
|
|
90
|
+
message: 'No fields to analyze',
|
|
91
|
+
metadata: { duration: Date.now() - startTime },
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const typeCounts = new Map();
|
|
95
|
+
for (const field of fields) {
|
|
96
|
+
const displayType = ObjectDescribeService.mapFieldToDisplayType(field);
|
|
97
|
+
typeCounts.set(displayType, (typeCounts.get(displayType) ?? 0) + 1);
|
|
98
|
+
}
|
|
99
|
+
const totalFields = fields.length;
|
|
100
|
+
const distribution = [];
|
|
101
|
+
for (const [type, count] of typeCounts) {
|
|
102
|
+
const percent = Math.round((count / totalFields) * 1000) / 10;
|
|
103
|
+
distribution.push({ type, count, percent });
|
|
104
|
+
}
|
|
105
|
+
distribution.sort((a, b) => b.count - a.count);
|
|
106
|
+
return createSuccessResult(distribution, {
|
|
107
|
+
message: `Analyzed ${totalFields} fields across ${distribution.length} types`,
|
|
108
|
+
metadata: { duration: Date.now() - startTime },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Calculates namespace breakdown from an array of fields.
|
|
113
|
+
*
|
|
114
|
+
* @param fields - Array of DescribeFieldResult from object describe
|
|
115
|
+
* @returns ServiceResult containing array of NamespaceCount sorted by fieldCount descending
|
|
116
|
+
*/
|
|
117
|
+
static getNamespaceBreakdown(fields) {
|
|
118
|
+
const startTime = Date.now();
|
|
119
|
+
const emptyResult = [];
|
|
120
|
+
if (!fields || fields.length === 0) {
|
|
121
|
+
return createSuccessResult(emptyResult, {
|
|
122
|
+
message: 'No fields to analyze',
|
|
123
|
+
metadata: { duration: Date.now() - startTime },
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const namespaceCounts = new Map();
|
|
127
|
+
for (const field of fields) {
|
|
128
|
+
const namespace = ObjectDescribeService.extractNamespace(field.name);
|
|
129
|
+
namespaceCounts.set(namespace, (namespaceCounts.get(namespace) ?? 0) + 1);
|
|
130
|
+
}
|
|
131
|
+
const breakdown = [];
|
|
132
|
+
for (const [namespace, fieldCount] of namespaceCounts) {
|
|
133
|
+
breakdown.push({ namespace, fieldCount });
|
|
134
|
+
}
|
|
135
|
+
breakdown.sort((a, b) => b.fieldCount - a.fieldCount);
|
|
136
|
+
return createSuccessResult(breakdown, {
|
|
137
|
+
message: `Found ${breakdown.length} namespaces across ${fields.length} fields`,
|
|
138
|
+
metadata: { duration: Date.now() - startTime },
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Extracts external references from childRelationships array.
|
|
143
|
+
*
|
|
144
|
+
* External references represent objects that have lookup/master-detail
|
|
145
|
+
* relationships pointing TO this object.
|
|
146
|
+
*
|
|
147
|
+
* @param describeResult - The describe result containing childRelationships
|
|
148
|
+
* @returns Array of external references sorted alphabetically by object name
|
|
149
|
+
*/
|
|
150
|
+
static extractExternalReferences(describeResult) {
|
|
151
|
+
if (!describeResult.childRelationships || describeResult.childRelationships.length === 0) {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
const references = describeResult.childRelationships.map((rel) => ({
|
|
155
|
+
objectName: rel.childSObject,
|
|
156
|
+
fieldName: rel.field,
|
|
157
|
+
relationshipName: rel.relationshipName || null,
|
|
158
|
+
}));
|
|
159
|
+
// Sort alphabetically by object name for consistent output
|
|
160
|
+
return references.sort((a, b) => a.objectName.localeCompare(b.objectName));
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Extracts lookup fields from fields array with their target objects.
|
|
164
|
+
*
|
|
165
|
+
* @param fields - Array of field describe results
|
|
166
|
+
* @returns Array of lookup field info sorted alphabetically by field name
|
|
167
|
+
*/
|
|
168
|
+
static extractLookupFields(fields) {
|
|
169
|
+
if (!fields || fields.length === 0) {
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
const lookups = [];
|
|
173
|
+
for (const field of fields) {
|
|
174
|
+
if (field.referenceTo && field.referenceTo.length > 0) {
|
|
175
|
+
lookups.push({
|
|
176
|
+
fieldName: field.name,
|
|
177
|
+
label: field.label,
|
|
178
|
+
targetObjects: field.referenceTo,
|
|
179
|
+
relationshipName: field.relationshipName ?? null,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Sort alphabetically by field name for consistent output
|
|
184
|
+
return lookups.sort((a, b) => a.fieldName.localeCompare(b.fieldName));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Detects if PersonAccount is enabled for the Account object.
|
|
188
|
+
*
|
|
189
|
+
* PersonAccount is detected by checking for the presence of the IsPersonAccount field,
|
|
190
|
+
* which only exists when PersonAccount is enabled in the org.
|
|
191
|
+
*
|
|
192
|
+
* @param objectName - The object being described
|
|
193
|
+
* @param fields - The fields from the describe result
|
|
194
|
+
* @returns true if PersonAccount is enabled (only for Account object), undefined otherwise
|
|
195
|
+
*/
|
|
196
|
+
static detectPersonAccount(objectName, fields) {
|
|
197
|
+
// PersonAccount detection only applies to Account object
|
|
198
|
+
if (objectName !== 'Account') {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
// Check for IsPersonAccount field - this field only exists when PersonAccount is enabled
|
|
202
|
+
return fields.some((field) => field.name === 'IsPersonAccount');
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Builds a relationship summary from describe result.
|
|
206
|
+
*
|
|
207
|
+
* @param describeResult - The describe result
|
|
208
|
+
* @returns RelationshipSummary with external references and lookup fields
|
|
209
|
+
*/
|
|
210
|
+
static buildRelationshipSummary(describeResult) {
|
|
211
|
+
const externalRefs = ObjectDescribeService.extractExternalReferences(describeResult);
|
|
212
|
+
const lookupFields = ObjectDescribeService.extractLookupFields(describeResult.fields);
|
|
213
|
+
return {
|
|
214
|
+
referencedByCount: externalRefs.length,
|
|
215
|
+
referencedBy: externalRefs,
|
|
216
|
+
lookupFields,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// ── Server Response Mapping (ISV REST API → CLI types) ────────────
|
|
220
|
+
/** Builds RelationshipSummary from server childRelationships + fields. */
|
|
221
|
+
static mapServerRelationships(childRels, fields) {
|
|
222
|
+
const referencedBy = childRels
|
|
223
|
+
.filter((cr) => cr.relationshipName != null)
|
|
224
|
+
.map((cr) => ({
|
|
225
|
+
objectName: cr.childSObject ?? '',
|
|
226
|
+
fieldName: cr.field ?? '',
|
|
227
|
+
relationshipName: cr.relationshipName ?? null,
|
|
228
|
+
}));
|
|
229
|
+
const lookupFields = fields
|
|
230
|
+
.filter((f) => f.referenceTo && f.referenceTo.length > 0)
|
|
231
|
+
.map((f) => ({
|
|
232
|
+
fieldName: f.name,
|
|
233
|
+
label: f.label,
|
|
234
|
+
targetObjects: f.referenceTo ?? [],
|
|
235
|
+
relationshipName: f.relationshipName ?? null,
|
|
236
|
+
}));
|
|
237
|
+
return { referencedByCount: referencedBy.length, referencedBy, lookupFields };
|
|
238
|
+
}
|
|
239
|
+
/** Maps server profilingStatus block to CLI ProfilingStatus. */
|
|
240
|
+
static mapServerProfilingStatus(ps) {
|
|
241
|
+
return {
|
|
242
|
+
hasDefinitions: (ps.definitionCount ?? 0) > 0,
|
|
243
|
+
definitionCount: ps.definitionCount ?? 0,
|
|
244
|
+
// Server returns minimal definition info ({name}); cast is safe because
|
|
245
|
+
// the command layer only reads .name from these entries (describe.ts:552)
|
|
246
|
+
definitions: ps.definitions
|
|
247
|
+
? ps.definitions.map((d) => ({ name: d.name ?? '' }))
|
|
248
|
+
: undefined,
|
|
249
|
+
summaryCount: ps.summaryCount ?? 0,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/** Maps server recordTypeInfos to CLI RecordTypeInfo[], filtering out Master. */
|
|
253
|
+
static mapServerRecordTypes(rts, objectName) {
|
|
254
|
+
return rts
|
|
255
|
+
.filter((rt) => !rt.master)
|
|
256
|
+
.map((rt) => ({
|
|
257
|
+
id: rt.recordTypeId ?? '',
|
|
258
|
+
name: rt.name ?? '',
|
|
259
|
+
developerName: rt.developerName ?? '',
|
|
260
|
+
sobjectType: objectName,
|
|
261
|
+
isPersonType: false,
|
|
262
|
+
isActive: rt.active ?? true,
|
|
263
|
+
isDefault: rt.defaultRecordTypeMapping ?? false,
|
|
264
|
+
formattedReference: `${objectName}.${rt.developerName ?? rt.name ?? ''}`,
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Maps a Salesforce field type to a display category.
|
|
269
|
+
*
|
|
270
|
+
* @param field - The field describe result
|
|
271
|
+
* @returns Display category string
|
|
272
|
+
*/
|
|
273
|
+
static mapFieldToDisplayType(field) {
|
|
274
|
+
if (field.calculated) {
|
|
275
|
+
return 'Formula';
|
|
276
|
+
}
|
|
277
|
+
return ObjectDescribeService.FIELD_TYPE_MAP[field.type] ?? field.type;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Extracts the namespace from a field API name.
|
|
281
|
+
*
|
|
282
|
+
* @param fieldName - The field API name (e.g., 'Name', 'Custom__c', 'pnova__Field__c')
|
|
283
|
+
* @returns The namespace (e.g., 'pnova') or null for standard/unmanaged fields
|
|
284
|
+
*/
|
|
285
|
+
static extractNamespace(fieldName) {
|
|
286
|
+
const parts = fieldName.split('__');
|
|
287
|
+
if (parts.length >= 3) {
|
|
288
|
+
return parts[0];
|
|
289
|
+
}
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Checks if the object is a Big Object (ends with __b).
|
|
294
|
+
*
|
|
295
|
+
* @param objectName - The object API name
|
|
296
|
+
* @returns true if it's a Big Object
|
|
297
|
+
*/
|
|
298
|
+
static isBigObject(objectName) {
|
|
299
|
+
return objectName.endsWith('__b');
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Checks if the object is an External Object (ends with __x).
|
|
303
|
+
*
|
|
304
|
+
* @param objectName - The object API name
|
|
305
|
+
* @returns true if it's an External Object
|
|
306
|
+
*/
|
|
307
|
+
static isExternalObject(objectName) {
|
|
308
|
+
return objectName.endsWith('__x');
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Classifies fields from a describe result.
|
|
312
|
+
*
|
|
313
|
+
* @param fields - Array of field describe results
|
|
314
|
+
* @returns Field classification statistics
|
|
315
|
+
*/
|
|
316
|
+
static classifyFields(fields) {
|
|
317
|
+
let customFields = 0;
|
|
318
|
+
let formulaFields = 0;
|
|
319
|
+
let lookupFields = 0;
|
|
320
|
+
let requiredFields = 0;
|
|
321
|
+
let picklistFields = 0;
|
|
322
|
+
for (const field of fields) {
|
|
323
|
+
if (field.custom) {
|
|
324
|
+
customFields++;
|
|
325
|
+
}
|
|
326
|
+
if (field.calculated) {
|
|
327
|
+
formulaFields++;
|
|
328
|
+
}
|
|
329
|
+
if (field.referenceTo && field.referenceTo.length > 0) {
|
|
330
|
+
lookupFields++;
|
|
331
|
+
}
|
|
332
|
+
// Required: createable, not nillable, and no default value
|
|
333
|
+
if (field.createable && !field.nillable && field.defaultValue === undefined) {
|
|
334
|
+
requiredFields++;
|
|
335
|
+
}
|
|
336
|
+
if (field.type === 'picklist' || field.type === 'multipicklist') {
|
|
337
|
+
picklistFields++;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
totalFields: fields.length,
|
|
342
|
+
customFields,
|
|
343
|
+
formulaFields,
|
|
344
|
+
lookupFields,
|
|
345
|
+
requiredFields,
|
|
346
|
+
picklistFields,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Maps a DescribeSObjectResult to our ObjectDescribeResult base structure.
|
|
351
|
+
*
|
|
352
|
+
* @param describeResult - The raw describe result from REST API
|
|
353
|
+
* @returns ObjectDescribeResult without enrichment
|
|
354
|
+
*/
|
|
355
|
+
static mapToObjectDescribeResult(describeResult) {
|
|
356
|
+
const result = {
|
|
357
|
+
objectName: describeResult.name,
|
|
358
|
+
label: describeResult.label,
|
|
359
|
+
labelPlural: describeResult.labelPlural,
|
|
360
|
+
isCustom: describeResult.custom,
|
|
361
|
+
isQueryable: describeResult.queryable,
|
|
362
|
+
isCreateable: describeResult.createable,
|
|
363
|
+
isUpdateable: describeResult.updateable,
|
|
364
|
+
isDeletable: describeResult.deletable,
|
|
365
|
+
isSearchable: describeResult.searchable,
|
|
366
|
+
fieldClassification: ObjectDescribeService.classifyFields(describeResult.fields),
|
|
367
|
+
fields: describeResult.fields,
|
|
368
|
+
relationships: ObjectDescribeService.buildRelationshipSummary(describeResult),
|
|
369
|
+
};
|
|
370
|
+
// Add PersonAccount detection for Account object
|
|
371
|
+
const isPersonAccountEnabled = ObjectDescribeService.detectPersonAccount(describeResult.name, describeResult.fields);
|
|
372
|
+
if (isPersonAccountEnabled !== undefined) {
|
|
373
|
+
result.isPersonAccountEnabled = isPersonAccountEnabled;
|
|
374
|
+
}
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Creates an empty result for failure cases.
|
|
379
|
+
*
|
|
380
|
+
* @param objectName - The object name for the empty result
|
|
381
|
+
* @returns Empty ObjectDescribeResult
|
|
382
|
+
*/
|
|
383
|
+
static createEmptyResult(objectName) {
|
|
384
|
+
return {
|
|
385
|
+
objectName,
|
|
386
|
+
label: '',
|
|
387
|
+
labelPlural: '',
|
|
388
|
+
isCustom: false,
|
|
389
|
+
isQueryable: false,
|
|
390
|
+
isCreateable: false,
|
|
391
|
+
isUpdateable: false,
|
|
392
|
+
isDeletable: false,
|
|
393
|
+
isSearchable: false,
|
|
394
|
+
fieldClassification: {
|
|
395
|
+
totalFields: 0,
|
|
396
|
+
customFields: 0,
|
|
397
|
+
formulaFields: 0,
|
|
398
|
+
lookupFields: 0,
|
|
399
|
+
requiredFields: 0,
|
|
400
|
+
picklistFields: 0,
|
|
401
|
+
},
|
|
402
|
+
fields: [],
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Extracts a meaningful message from an unknown error.
|
|
407
|
+
*
|
|
408
|
+
* Handles the edge case where Error instances have an empty message
|
|
409
|
+
* but a meaningful name property (e.g., sinon's rejects behavior).
|
|
410
|
+
*
|
|
411
|
+
* @param error - The error to extract a message from
|
|
412
|
+
* @returns A human-readable error message
|
|
413
|
+
*/
|
|
414
|
+
static getErrorMessage(error) {
|
|
415
|
+
if (error instanceof Error) {
|
|
416
|
+
// Prefer message, fall back to name if message is empty
|
|
417
|
+
return error.message || error.name || 'Unknown error';
|
|
418
|
+
}
|
|
419
|
+
return String(error);
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Applies RecordTypeId filter to a query builder.
|
|
423
|
+
* Single string uses `=`, array uses `IN`.
|
|
424
|
+
* The builder auto-promotes to first WHERE if no prior condition exists.
|
|
425
|
+
*
|
|
426
|
+
* @param builder - The query builder to modify
|
|
427
|
+
* @param recordTypeIds - Single ID, array of IDs, or undefined (no filter)
|
|
428
|
+
*/
|
|
429
|
+
static applyRecordTypeFilter(builder, recordTypeIds) {
|
|
430
|
+
if (!recordTypeIds)
|
|
431
|
+
return;
|
|
432
|
+
if (typeof recordTypeIds === 'string') {
|
|
433
|
+
builder.andWhere('RecordTypeId', '=', recordTypeIds);
|
|
434
|
+
}
|
|
435
|
+
else if (recordTypeIds.length > 0) {
|
|
436
|
+
builder.andWhereIn('RecordTypeId', recordTypeIds);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Describes a Salesforce object with comprehensive metadata and optional enrichment.
|
|
441
|
+
*
|
|
442
|
+
* This method:
|
|
443
|
+
* 1. Validates the object name
|
|
444
|
+
* 2. Rejects Big Objects (__b) and External Objects (__x)
|
|
445
|
+
* 3. Retrieves describe metadata via REST API
|
|
446
|
+
* 4. Classifies fields (custom, formula, lookup, required, picklist)
|
|
447
|
+
* 5. Enriches with record types, record age, and profiling status (in parallel)
|
|
448
|
+
*
|
|
449
|
+
* @param objectName - The Salesforce object API name (e.g., 'Account', 'Custom_Object__c')
|
|
450
|
+
* @returns ServiceResult containing the ObjectDescribeResult
|
|
451
|
+
*/
|
|
452
|
+
async describeObject(objectName) {
|
|
453
|
+
const startTime = Date.now();
|
|
454
|
+
const emptyResult = ObjectDescribeService.createEmptyResult(objectName ?? '');
|
|
455
|
+
// Validate required
|
|
456
|
+
const requiredError = validateRequiredString(objectName, 'Object name');
|
|
457
|
+
if (requiredError) {
|
|
458
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_OBJECT_NAME_REQUIRED, requiredError, {
|
|
459
|
+
metadata: { duration: Date.now() - startTime },
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
// Validate format
|
|
463
|
+
const formatError = validateObjectName(objectName);
|
|
464
|
+
if (formatError) {
|
|
465
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_INVALID_OBJECT_NAME, formatError, {
|
|
466
|
+
metadata: { duration: Date.now() - startTime },
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
// Reject Big Objects
|
|
470
|
+
if (ObjectDescribeService.isBigObject(objectName)) {
|
|
471
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_BIG_OBJECT_REJECTED, `Big Objects are not supported: ${objectName}`, { metadata: { duration: Date.now() - startTime } });
|
|
472
|
+
}
|
|
473
|
+
// Reject External Objects
|
|
474
|
+
if (ObjectDescribeService.isExternalObject(objectName)) {
|
|
475
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_EXTERNAL_OBJECT_REJECTED, `External Objects are not supported: ${objectName}`, { metadata: { duration: Date.now() - startTime } });
|
|
476
|
+
}
|
|
477
|
+
// REST API path: delegate to server when restClient is available
|
|
478
|
+
if (this.restClient) {
|
|
479
|
+
return this.describeObjectViaRest(objectName, startTime);
|
|
480
|
+
}
|
|
481
|
+
try {
|
|
482
|
+
this.logger?.log(`Describing object: ${objectName}`);
|
|
483
|
+
// Get base describe result
|
|
484
|
+
const describeResult = await this.restApiAdapter.describeObject(objectName);
|
|
485
|
+
if (!describeResult.success) {
|
|
486
|
+
// Map adapter error codes to service error codes
|
|
487
|
+
let serviceErrorCode = ServiceErrorCodes.OBJECT_DESCRIBE_FAILED;
|
|
488
|
+
if (describeResult.errorCode === AdapterErrorCodes.OBJECT_NOT_FOUND) {
|
|
489
|
+
serviceErrorCode = ServiceErrorCodes.OBJECT_DESCRIBE_NOT_FOUND;
|
|
490
|
+
}
|
|
491
|
+
else if (describeResult.errorCode === AdapterErrorCodes.PERMISSION_DENIED) {
|
|
492
|
+
serviceErrorCode = ServiceErrorCodes.OBJECT_DESCRIBE_PERMISSION_DENIED;
|
|
493
|
+
}
|
|
494
|
+
return createFailureResult(emptyResult, serviceErrorCode, describeResult.message ?? 'Object describe failed', {
|
|
495
|
+
metadata: { duration: Date.now() - startTime },
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
// Map to our result structure
|
|
499
|
+
const result = ObjectDescribeService.mapToObjectDescribeResult(describeResult.data);
|
|
500
|
+
const warnings = [];
|
|
501
|
+
// Parallel enrichment with catch-per-promise for graceful degradation
|
|
502
|
+
// Note: Record age is NOT enriched here — the command calls getRecordAgeDistribution()
|
|
503
|
+
// separately, which provides a superset of the data (year-by-year distribution + oldest date).
|
|
504
|
+
// Enriching here would duplicate 2 SOQL queries per object with no benefit.
|
|
505
|
+
const enrichmentPromises = [
|
|
506
|
+
// Record type enrichment
|
|
507
|
+
this.enrichRecordTypes(objectName).catch((error) => {
|
|
508
|
+
warnings.push(`Record type enrichment failed: ${ObjectDescribeService.getErrorMessage(error)}`);
|
|
509
|
+
return undefined;
|
|
510
|
+
}),
|
|
511
|
+
// Profiling status enrichment
|
|
512
|
+
this.enrichProfilingStatus(objectName).catch((error) => {
|
|
513
|
+
warnings.push(`Profiling status enrichment failed: ${ObjectDescribeService.getErrorMessage(error)}`);
|
|
514
|
+
return undefined;
|
|
515
|
+
}),
|
|
516
|
+
];
|
|
517
|
+
const [recordTypes, profilingStatus] = await Promise.all(enrichmentPromises);
|
|
518
|
+
// Apply enrichments
|
|
519
|
+
if (recordTypes !== undefined) {
|
|
520
|
+
result.recordTypes = recordTypes;
|
|
521
|
+
}
|
|
522
|
+
if (profilingStatus !== undefined) {
|
|
523
|
+
result.profilingStatus = profilingStatus;
|
|
524
|
+
}
|
|
525
|
+
const duration = Date.now() - startTime;
|
|
526
|
+
this.logger?.log(`Described ${objectName}: ${result.fieldClassification.totalFields} fields, ` +
|
|
527
|
+
`${result.fieldClassification.customFields} custom, ${result.fieldClassification.formulaFields} formula`);
|
|
528
|
+
return createSuccessResult(result, {
|
|
529
|
+
message: `Described ${objectName} with ${result.fieldClassification.totalFields} fields`,
|
|
530
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
531
|
+
metadata: { duration },
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
536
|
+
this.logger?.log(`Object describe failed for ${objectName}: ${errorMessage}`);
|
|
537
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, errorMessage, {
|
|
538
|
+
metadata: { duration: Date.now() - startTime },
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Describes multiple Salesforce objects in parallel.
|
|
544
|
+
*
|
|
545
|
+
* @param objectNames - Array of Salesforce object API names to describe
|
|
546
|
+
* @returns ServiceResult containing array of ObjectDescribeResult (one per successful describe)
|
|
547
|
+
*/
|
|
548
|
+
async describeMultiple(objectNames) {
|
|
549
|
+
const startTime = Date.now();
|
|
550
|
+
const emptyResult = [];
|
|
551
|
+
if (!objectNames || objectNames.length === 0) {
|
|
552
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.INVALID_OBJECT_NAMES, 'At least one object name is required', { metadata: { duration: Date.now() - startTime } });
|
|
553
|
+
}
|
|
554
|
+
const describePromises = objectNames.map(async (objectName) => {
|
|
555
|
+
const result = await this.describeObject(objectName);
|
|
556
|
+
return { objectName, result };
|
|
557
|
+
});
|
|
558
|
+
const results = await Promise.all(describePromises);
|
|
559
|
+
const successResults = [];
|
|
560
|
+
const failureWarnings = [];
|
|
561
|
+
for (const { objectName, result } of results) {
|
|
562
|
+
if (result.success) {
|
|
563
|
+
successResults.push(result.data);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
failureWarnings.push(`${objectName}: ${result.message ?? 'Describe failed'}`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
const duration = Date.now() - startTime;
|
|
570
|
+
if (successResults.length === 0) {
|
|
571
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, `All object describes failed: ${failureWarnings.join('; ')}`, { metadata: { duration } });
|
|
572
|
+
}
|
|
573
|
+
return createSuccessResult(successResults, {
|
|
574
|
+
message: `Described ${successResults.length} of ${objectNames.length} objects`,
|
|
575
|
+
warnings: failureWarnings.length > 0 ? failureWarnings : undefined,
|
|
576
|
+
metadata: { duration },
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Retrieves record age distribution for an object showing year-by-year record existence.
|
|
581
|
+
*
|
|
582
|
+
* @param objectName - The Salesforce object API name
|
|
583
|
+
* @param recordTypeIds - Optional RecordTypeId(s) to filter. Single string uses `=`, array uses `IN`.
|
|
584
|
+
* @returns ServiceResult containing RecordAgeDistribution with year-by-year status
|
|
585
|
+
*/
|
|
586
|
+
async getRecordAgeDistribution(objectName, recordTypeIds) {
|
|
587
|
+
const startTime = Date.now();
|
|
588
|
+
const currentYear = new Date().getFullYear();
|
|
589
|
+
const years = [currentYear, currentYear - 1, currentYear - 2, currentYear - 3];
|
|
590
|
+
const emptyResult = {
|
|
591
|
+
years: years.map((year) => ({ year, hasRecords: false })),
|
|
592
|
+
oldestRecordDate: null,
|
|
593
|
+
};
|
|
594
|
+
const requiredError = validateRequiredString(objectName, 'Object name');
|
|
595
|
+
if (requiredError) {
|
|
596
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_OBJECT_NAME_REQUIRED, requiredError, {
|
|
597
|
+
metadata: { duration: Date.now() - startTime },
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
const formatError = validateObjectName(objectName);
|
|
601
|
+
if (formatError) {
|
|
602
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_INVALID_OBJECT_NAME, formatError, {
|
|
603
|
+
metadata: { duration: Date.now() - startTime },
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
try {
|
|
607
|
+
const yearCheckPromises = years.map(async (year) => {
|
|
608
|
+
const builder = CuneiformQueryBuilder.create()
|
|
609
|
+
.select(['Id'])
|
|
610
|
+
.from(objectName)
|
|
611
|
+
.whereDatetime('CreatedDate', '>=', `${year}-01-01T00:00:00Z`)
|
|
612
|
+
.andWhereDatetime('CreatedDate', '<', `${year + 1}-01-01T00:00:00Z`);
|
|
613
|
+
ObjectDescribeService.applyRecordTypeFilter(builder, recordTypeIds);
|
|
614
|
+
const query = builder.limit(1).toSOQL();
|
|
615
|
+
const result = await this.soqlAdapter.query(query);
|
|
616
|
+
return { year, hasRecords: result.success && result.data.records.length > 0 };
|
|
617
|
+
});
|
|
618
|
+
const oldestBuilder = CuneiformQueryBuilder.create().select(['CreatedDate']).from(objectName);
|
|
619
|
+
ObjectDescribeService.applyRecordTypeFilter(oldestBuilder, recordTypeIds);
|
|
620
|
+
const oldestRecordQuery = oldestBuilder.orderBy('CreatedDate', 'ASC').limit(1).toSOQL();
|
|
621
|
+
const oldestRecordPromise = this.soqlAdapter.query(oldestRecordQuery);
|
|
622
|
+
const [yearChecks, oldestResult] = await Promise.all([Promise.all(yearCheckPromises), oldestRecordPromise]);
|
|
623
|
+
const yearStatusMap = new Map(yearChecks.map((yc) => [yc.year, yc.hasRecords]));
|
|
624
|
+
const distribution = {
|
|
625
|
+
years: years.map((year) => ({ year, hasRecords: yearStatusMap.get(year) ?? false })),
|
|
626
|
+
oldestRecordDate: oldestResult.success && oldestResult.data.records.length > 0
|
|
627
|
+
? oldestResult.data.records[0].CreatedDate
|
|
628
|
+
: null,
|
|
629
|
+
};
|
|
630
|
+
return createSuccessResult(distribution, {
|
|
631
|
+
message: `Retrieved record age distribution for ${objectName}`,
|
|
632
|
+
metadata: { duration: Date.now() - startTime },
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
catch (error) {
|
|
636
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
637
|
+
this.logger?.log(`Record age distribution failed for ${objectName}: ${errorMessage}`);
|
|
638
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, errorMessage, {
|
|
639
|
+
metadata: { duration: Date.now() - startTime },
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Retrieves business processes for a specific object with their record type IDs.
|
|
645
|
+
*
|
|
646
|
+
* Only Opportunity, Case, and Lead support business processes. For other objects,
|
|
647
|
+
* returns an empty array without issuing any queries.
|
|
648
|
+
*
|
|
649
|
+
* @param objectName - The Salesforce object API name
|
|
650
|
+
* @param recordTypes - Record types already enriched (used to cross-reference BusinessProcessId)
|
|
651
|
+
* @returns ServiceResult containing array of ObjectBusinessProcessInfo
|
|
652
|
+
*/
|
|
653
|
+
async getBusinessProcesses(objectName, recordTypes) {
|
|
654
|
+
const startTime = Date.now();
|
|
655
|
+
const emptyResult = [];
|
|
656
|
+
const requiredError = validateRequiredString(objectName, 'Object name');
|
|
657
|
+
if (requiredError) {
|
|
658
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_OBJECT_NAME_REQUIRED, requiredError, {
|
|
659
|
+
metadata: { duration: Date.now() - startTime },
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
try {
|
|
663
|
+
const bpQuery = CuneiformQueryBuilder.create()
|
|
664
|
+
.select(['Id', 'Name', 'IsActive'])
|
|
665
|
+
.from('BusinessProcess')
|
|
666
|
+
.where('SobjectType', '=', objectName)
|
|
667
|
+
.orderBy('Name', 'ASC')
|
|
668
|
+
.toSOQL();
|
|
669
|
+
const bpResult = await this.soqlAdapter.query(bpQuery);
|
|
670
|
+
if (!bpResult.success) {
|
|
671
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, bpResult.message ?? 'BusinessProcess query failed', { metadata: { duration: Date.now() - startTime } });
|
|
672
|
+
}
|
|
673
|
+
const bpRecords = bpResult.data.records;
|
|
674
|
+
if (bpRecords.length === 0) {
|
|
675
|
+
return createSuccessResult(emptyResult, {
|
|
676
|
+
message: `No business processes for ${objectName}`,
|
|
677
|
+
metadata: { duration: Date.now() - startTime },
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
// Cross-reference record types by BusinessProcessId
|
|
681
|
+
const processes = bpRecords.map((bp) => {
|
|
682
|
+
const linkedRtIds = recordTypes.filter((rt) => rt.businessProcessId === bp.Id).map((rt) => rt.id);
|
|
683
|
+
return {
|
|
684
|
+
id: bp.Id,
|
|
685
|
+
name: bp.Name,
|
|
686
|
+
isActive: bp.IsActive,
|
|
687
|
+
recordTypeCount: linkedRtIds.length,
|
|
688
|
+
recordTypeIds: linkedRtIds,
|
|
689
|
+
};
|
|
690
|
+
});
|
|
691
|
+
return createSuccessResult(processes, {
|
|
692
|
+
message: `Found ${processes.length} business processes for ${objectName}`,
|
|
693
|
+
metadata: { duration: Date.now() - startTime },
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
catch (error) {
|
|
697
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
698
|
+
this.logger?.log(`Business process query failed for ${objectName}: ${errorMessage}`);
|
|
699
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, errorMessage, {
|
|
700
|
+
metadata: { duration: Date.now() - startTime },
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Delegates object describe to the ISV REST API.
|
|
706
|
+
*
|
|
707
|
+
* @param objectName - The Salesforce object API name to describe
|
|
708
|
+
* @param startTime - Timestamp for duration tracking
|
|
709
|
+
* @returns ServiceResult containing ObjectDescribeResult from REST endpoint
|
|
710
|
+
*/
|
|
711
|
+
async describeObjectViaRest(objectName, startTime) {
|
|
712
|
+
this.logger?.log(`Delegating object describe to ISV REST API (describe-object): ${objectName}`);
|
|
713
|
+
const emptyResult = ObjectDescribeService.createEmptyResult(objectName);
|
|
714
|
+
const restResult = await this.restClient.describeObject(objectName, {
|
|
715
|
+
includeRecordAge: true,
|
|
716
|
+
includeFieldDistribution: true,
|
|
717
|
+
withFields: true,
|
|
718
|
+
withRelationships: true,
|
|
719
|
+
withProfilingStatus: true,
|
|
720
|
+
});
|
|
721
|
+
if (!restResult.success) {
|
|
722
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, restResult.message ?? 'REST describe-object failed', { metadata: { duration: Date.now() - startTime } });
|
|
723
|
+
}
|
|
724
|
+
const response = restResult.data;
|
|
725
|
+
if (!response.success) {
|
|
726
|
+
const errorMsg = response.errors?.length ? response.errors[0] : 'Server-side describe failed';
|
|
727
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.OBJECT_DESCRIBE_FAILED, errorMsg, {
|
|
728
|
+
metadata: { duration: Date.now() - startTime },
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
const server = response.result;
|
|
732
|
+
if (!server) {
|
|
733
|
+
return createSuccessResult(emptyResult, {
|
|
734
|
+
message: `Object ${objectName} described via REST API (empty result)`,
|
|
735
|
+
metadata: { duration: Date.now() - startTime, strategyUsed: 'rest-api' },
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
let result = {
|
|
739
|
+
objectName: server.objectName ?? objectName,
|
|
740
|
+
label: server.label ?? objectName,
|
|
741
|
+
labelPlural: server.labelPlural ?? objectName,
|
|
742
|
+
isCustom: server.isCustom ?? false,
|
|
743
|
+
isQueryable: server.isQueryable ?? true,
|
|
744
|
+
isCreateable: false,
|
|
745
|
+
isUpdateable: false,
|
|
746
|
+
isDeletable: false,
|
|
747
|
+
isSearchable: server.isSearchable ?? false,
|
|
748
|
+
fieldClassification: server.fieldClassification ?? {
|
|
749
|
+
totalFields: 0,
|
|
750
|
+
customFields: 0,
|
|
751
|
+
formulaFields: 0,
|
|
752
|
+
lookupFields: 0,
|
|
753
|
+
requiredFields: 0,
|
|
754
|
+
picklistFields: 0,
|
|
755
|
+
},
|
|
756
|
+
fields: server.fields ?? [],
|
|
757
|
+
recordTypes: server.recordTypeInfos
|
|
758
|
+
? ObjectDescribeService.mapServerRecordTypes(server.recordTypeInfos, objectName)
|
|
759
|
+
: undefined,
|
|
760
|
+
relationships: server.childRelationships
|
|
761
|
+
? ObjectDescribeService.mapServerRelationships(server.childRelationships, server.fields ?? [])
|
|
762
|
+
: undefined,
|
|
763
|
+
profilingStatus: server.profilingStatus
|
|
764
|
+
? ObjectDescribeService.mapServerProfilingStatus(server.profilingStatus)
|
|
765
|
+
: undefined,
|
|
766
|
+
isPersonAccountEnabled: server.isPersonAccountEnabled,
|
|
767
|
+
};
|
|
768
|
+
result = {
|
|
769
|
+
...result,
|
|
770
|
+
fields: await this.resolveFieldFallback(result.fields, result.fieldClassification.totalFields, objectName),
|
|
771
|
+
};
|
|
772
|
+
const duration = Date.now() - startTime;
|
|
773
|
+
this.logger?.log(`Described ${objectName} via REST: ${result.fieldClassification.totalFields} fields, ` +
|
|
774
|
+
`${result.fieldClassification.customFields} custom`);
|
|
775
|
+
return createSuccessResult(result, {
|
|
776
|
+
message: `Object ${objectName} described via REST API`,
|
|
777
|
+
metadata: { duration, strategyUsed: 'rest-api' },
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Falls back to standard REST describe for fields when ISV REST API
|
|
782
|
+
* returns field counts but omits the individual field array.
|
|
783
|
+
*
|
|
784
|
+
* @returns The field array to use (original or fallback)
|
|
785
|
+
*/
|
|
786
|
+
async resolveFieldFallback(fields, totalFields, objectName) {
|
|
787
|
+
if (fields.length > 0 || totalFields === 0)
|
|
788
|
+
return fields;
|
|
789
|
+
this.logger?.log(`ISV REST API returned no fields for ${objectName}; falling back to standard describe`);
|
|
790
|
+
const standardDescribe = await this.restApiAdapter.describeObject(objectName);
|
|
791
|
+
return standardDescribe.success ? standardDescribe.data.fields : fields;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Enriches record type information using RecordTypeService.
|
|
795
|
+
* Errors are propagated to the caller for centralized handling.
|
|
796
|
+
*
|
|
797
|
+
* @param objectName - The object API name
|
|
798
|
+
* @returns Array of RecordTypeInfo or undefined if not configured or query fails gracefully
|
|
799
|
+
* @throws Error if service call throws
|
|
800
|
+
*/
|
|
801
|
+
async enrichRecordTypes(objectName) {
|
|
802
|
+
if (!this.recordTypeService) {
|
|
803
|
+
return undefined;
|
|
804
|
+
}
|
|
805
|
+
const result = await this.recordTypeService.getRecordTypes(objectName);
|
|
806
|
+
if (result.success) {
|
|
807
|
+
return result.data;
|
|
808
|
+
}
|
|
809
|
+
this.logger?.log(`Record type enrichment failed for ${objectName}: ${result.message ?? 'Unknown error'}`);
|
|
810
|
+
return undefined;
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Enriches profiling status using ProfilingDefinitionService and ProfilingSummaryService.
|
|
814
|
+
* Errors are propagated to the caller for centralized handling.
|
|
815
|
+
*
|
|
816
|
+
* @param objectName - The object API name
|
|
817
|
+
* @returns ProfilingStatus or undefined if not configured or query fails gracefully
|
|
818
|
+
* @throws Error if service call throws
|
|
819
|
+
*/
|
|
820
|
+
async enrichProfilingStatus(objectName) {
|
|
821
|
+
if (!this.profilingDefinitionService) {
|
|
822
|
+
return undefined;
|
|
823
|
+
}
|
|
824
|
+
const definitionsResult = await this.profilingDefinitionService.getDefinitions({ objectName });
|
|
825
|
+
if (!definitionsResult.success) {
|
|
826
|
+
this.logger?.log(`Profiling definition enrichment failed for ${objectName}: ${definitionsResult.message ?? 'Unknown error'}`);
|
|
827
|
+
return undefined;
|
|
828
|
+
}
|
|
829
|
+
const definitions = definitionsResult.data;
|
|
830
|
+
const status = {
|
|
831
|
+
hasDefinitions: definitions.length > 0,
|
|
832
|
+
definitionCount: definitions.length,
|
|
833
|
+
definitions: definitions.length > 0 ? definitions : undefined,
|
|
834
|
+
};
|
|
835
|
+
// If we have definitions and a summary service, get summary info
|
|
836
|
+
if (definitions.length > 0 && this.profilingSummaryService) {
|
|
837
|
+
let totalSummaryCount = 0;
|
|
838
|
+
let lastProfiledDate;
|
|
839
|
+
// Query summaries for each definition in parallel
|
|
840
|
+
const summaryPromises = definitions.map(async (def) => {
|
|
841
|
+
try {
|
|
842
|
+
const summaryResult = await this.profilingSummaryService.getSummaries({
|
|
843
|
+
definitionId: def.id,
|
|
844
|
+
limit: 1,
|
|
845
|
+
});
|
|
846
|
+
if (summaryResult.success && summaryResult.data.length > 0) {
|
|
847
|
+
return summaryResult.data[0];
|
|
848
|
+
}
|
|
849
|
+
return null;
|
|
850
|
+
}
|
|
851
|
+
catch {
|
|
852
|
+
return null;
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
const summaries = await Promise.all(summaryPromises);
|
|
856
|
+
const validSummaries = summaries.filter((s) => s !== null);
|
|
857
|
+
if (validSummaries.length > 0) {
|
|
858
|
+
totalSummaryCount = validSummaries.length;
|
|
859
|
+
// Find the most recent summary by creation date
|
|
860
|
+
const sortedByDate = [...validSummaries].sort((a, b) => new Date(b.createdDate).getTime() - new Date(a.createdDate).getTime());
|
|
861
|
+
lastProfiledDate = sortedByDate[0].createdDate;
|
|
862
|
+
}
|
|
863
|
+
status.summaryCount = totalSummaryCount;
|
|
864
|
+
status.lastProfiledDate = lastProfiledDate;
|
|
865
|
+
}
|
|
866
|
+
return status;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
//# sourceMappingURL=ObjectDescribeService.js.map
|