@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,981 @@
|
|
|
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 { createSuccessResult, createFailureResult } from '../models/service-result.js';
|
|
9
|
+
import { ServiceErrorCodes } from '../adapters/errors.js';
|
|
10
|
+
import { CuneiformQueryBuilder } from '../adapters/soql/cuneiform-query-builder.js';
|
|
11
|
+
import { validateSalesforceId, validateObjectName, validateNamespace, validatePagination, validateRequiredString, } from './validation.js';
|
|
12
|
+
import { MAX_PAGINATION_LIMIT } from './constants.js';
|
|
13
|
+
/**
|
|
14
|
+
* Default pagination limit for listDefinitions.
|
|
15
|
+
* Distinct from the general DEFAULT_PAGINATION_LIMIT (50) used by getDefinitions.
|
|
16
|
+
*/
|
|
17
|
+
const LIST_DEFAULT_LIMIT = 25;
|
|
18
|
+
/** Empty/zero ListSummary used for failure-path returns. */
|
|
19
|
+
const EMPTY_LIST_SUMMARY = {
|
|
20
|
+
activeCount: 0,
|
|
21
|
+
inactiveCount: 0,
|
|
22
|
+
profiledCount: 0,
|
|
23
|
+
notProfiledCount: 0,
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Maps a listDefinitions sort field to the corresponding Salesforce field API name.
|
|
27
|
+
*/
|
|
28
|
+
const SORT_FIELD_MAP = {
|
|
29
|
+
key: 'Name',
|
|
30
|
+
name: 'pnova__Prop_Name__c',
|
|
31
|
+
objectName: 'pnova__Prop_SObjectApiName__c',
|
|
32
|
+
lastProfiledDate: 'pnova__PFx_LastDateProfiled__c',
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* SOQL field list for Profiling_Definition__c queries.
|
|
36
|
+
* Field names match actual Salesforce schema.
|
|
37
|
+
*/
|
|
38
|
+
// Query building, validation, and constants extracted to DefinitionQueryBuilder
|
|
39
|
+
import { DefinitionQueryBuilder, DEFINITION_FIELDS } from './DefinitionQueryBuilder.js';
|
|
40
|
+
/**
|
|
41
|
+
* Domain service for querying Cuneiform profiling definitions.
|
|
42
|
+
*
|
|
43
|
+
* Provides methods to retrieve profiling definitions from the
|
|
44
|
+
* Profiling_Definition__c custom object with filtering and pagination.
|
|
45
|
+
*
|
|
46
|
+
* @design
|
|
47
|
+
* **Read-Only Service**: This service only queries definitions; it does not
|
|
48
|
+
* create or update them. Definition management is handled through the
|
|
49
|
+
* Cuneiform UI or separate admin operations.
|
|
50
|
+
*
|
|
51
|
+
* @design
|
|
52
|
+
* **Field Mapping**: Maps Salesforce custom field names (e.g., `Definition_Key__c`)
|
|
53
|
+
* to TypeScript-friendly camelCase (e.g., `key`). This isolates consumers from
|
|
54
|
+
* Salesforce naming conventions and enables cleaner TypeScript interfaces.
|
|
55
|
+
*
|
|
56
|
+
* @design
|
|
57
|
+
* **Validation Strategy**: Validates filter parameters (type, status, objectName)
|
|
58
|
+
* before building SOQL to fail fast with clear error messages rather than
|
|
59
|
+
* letting Salesforce return cryptic query errors.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const service = new ProfilingDefinitionService({ soqlAdapter });
|
|
64
|
+
* const result = await service.getDefinitions({ objectName: 'Account', isActive: true });
|
|
65
|
+
* if (result.success) {
|
|
66
|
+
* result.data.forEach(def => console.log(def.name));
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
// NOTE: GlobalProfilingServiceResponse type and DEFINITION_RESPONSE_MARKER removed
|
|
71
|
+
// during REST API migration (CLI-1150). Apex routing now uses REST endpoints.
|
|
72
|
+
/**
|
|
73
|
+
* Base path for Cuneiform profiling REST API endpoints.
|
|
74
|
+
*/
|
|
75
|
+
// Apex urlMapping is '/v1/profiling/*' — Salesforce auto-prepends namespace (pnova),
|
|
76
|
+
// so the actual URL is /services/apexrest/pnova/v1/profiling/*
|
|
77
|
+
const PROFILING_DEFINITION_REST_BASE = '/services/apexrest/pnova/v1/profiling';
|
|
78
|
+
export class ProfilingDefinitionService {
|
|
79
|
+
soqlAdapter;
|
|
80
|
+
restAdapter;
|
|
81
|
+
logger;
|
|
82
|
+
constructor(config) {
|
|
83
|
+
this.soqlAdapter = config.soqlAdapter;
|
|
84
|
+
this.restAdapter = config.restAdapter;
|
|
85
|
+
this.logger = config.logger;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Derives the definition type from boolean flags.
|
|
89
|
+
*
|
|
90
|
+
* Logic:
|
|
91
|
+
* - comparative: isFilteredSetB is true (comparing two data sets)
|
|
92
|
+
* - metadata: isMetadataOnly is true (metadata-only profiling)
|
|
93
|
+
* - historical: default (standard profiling)
|
|
94
|
+
*
|
|
95
|
+
* @param isFilteredSetB - Whether Set B is filtered
|
|
96
|
+
* @param isMetadataOnly - Whether metadata-only profiling
|
|
97
|
+
* @returns The derived definition type
|
|
98
|
+
*/
|
|
99
|
+
static deriveDefinitionType(isFilteredSetB, isMetadataOnly) {
|
|
100
|
+
if (isFilteredSetB) {
|
|
101
|
+
return 'comparative';
|
|
102
|
+
}
|
|
103
|
+
if (isMetadataOnly) {
|
|
104
|
+
return 'metadata';
|
|
105
|
+
}
|
|
106
|
+
return 'historical';
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Maps a raw Salesforce Profiling_Definition__c record to a ProfilingDefinition.
|
|
110
|
+
*
|
|
111
|
+
* @param record - The raw SOQL query result record
|
|
112
|
+
* @returns Mapped ProfilingDefinition with camelCase field names
|
|
113
|
+
*/
|
|
114
|
+
static mapToProfilingDefinition(record) {
|
|
115
|
+
const isFilteredSetB = record.pnova__Prop_IsFiltered_SetB__c ?? false;
|
|
116
|
+
const isMetadataOnly = record.pnova__PropFx_IsMetadataProfilingOnly__c ?? false;
|
|
117
|
+
return {
|
|
118
|
+
id: record.Id,
|
|
119
|
+
key: record.Name,
|
|
120
|
+
name: record.pnova__Prop_Name__c,
|
|
121
|
+
objectName: record.pnova__Prop_SObjectApiName__c,
|
|
122
|
+
objectLabel: record.pnova__Prop_SObjectLabel__c ?? undefined,
|
|
123
|
+
type: ProfilingDefinitionService.deriveDefinitionType(isFilteredSetB, isMetadataOnly),
|
|
124
|
+
status: record.pnova__Agg_Status__c ?? 'NOT PROFILED',
|
|
125
|
+
category: record.pnova__Prop_Category__c ?? undefined,
|
|
126
|
+
description: record.pnova__Prop_Description__c ?? undefined,
|
|
127
|
+
isActive: record.pnova__Prop_IsActive__c ?? false,
|
|
128
|
+
isFilteredSetA: record.pnova__Prop_IsFiltered_SetA__c ?? false,
|
|
129
|
+
isFilteredSetB,
|
|
130
|
+
isMetadataOnly,
|
|
131
|
+
isProfilingAllRecords: record.pnova__PropFx_IsProfilingAllRecords__c ?? false,
|
|
132
|
+
hasRelatedSummaries: record.pnova__PFx_HasRelatedSummaries__c ?? false,
|
|
133
|
+
lastProfiledDate: record.pnova__PFx_LastDateProfiled__c ?? undefined,
|
|
134
|
+
timeCategory: record.pnova__Prop_TimeCategory__c ?? undefined,
|
|
135
|
+
segmentCategory: record.pnova__Prop_SegmentCategory__c ?? undefined,
|
|
136
|
+
createdDate: record.CreatedDate ?? undefined,
|
|
137
|
+
lastModifiedDate: record.LastModifiedDate ?? undefined,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Builds a complete SOQL query string for Profiling_Definition__c using CuneiformQueryBuilder.
|
|
142
|
+
*
|
|
143
|
+
* Type filtering is pushed to SOQL using the underlying boolean fields:
|
|
144
|
+
* - comparative: isFilteredSetB = true
|
|
145
|
+
* - metadata: isMetadataOnly = true AND isFilteredSetB = false
|
|
146
|
+
* - historical: isMetadataOnly = false AND isFilteredSetB = false
|
|
147
|
+
*
|
|
148
|
+
* @param options - The filter and pagination options
|
|
149
|
+
* @returns Complete SOQL query string
|
|
150
|
+
*/
|
|
151
|
+
// Static query building methods delegated to DefinitionQueryBuilder
|
|
152
|
+
static buildSoqlQuery(options) {
|
|
153
|
+
return DefinitionQueryBuilder.buildSoqlQuery(options);
|
|
154
|
+
}
|
|
155
|
+
static validateType(type) {
|
|
156
|
+
return DefinitionQueryBuilder.validateType(type);
|
|
157
|
+
}
|
|
158
|
+
static validateStatus(status) {
|
|
159
|
+
return DefinitionQueryBuilder.validateStatus(status);
|
|
160
|
+
}
|
|
161
|
+
static buildCreateDefinitionRequestBody(input) {
|
|
162
|
+
return DefinitionQueryBuilder.buildCreateDefinitionRequestBody(input);
|
|
163
|
+
}
|
|
164
|
+
static buildListWhereConditions(filter) {
|
|
165
|
+
return DefinitionQueryBuilder.buildListWhereConditions(filter);
|
|
166
|
+
}
|
|
167
|
+
static applyWhereConditions(builder, conditions) {
|
|
168
|
+
DefinitionQueryBuilder.applyWhereConditions(builder, conditions);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Folds aggregate rows from the GROUP BY query into a totalCount and named
|
|
172
|
+
* bucket counts. Status taxonomy preserves the prior in-memory display logic:
|
|
173
|
+
* profiledCount covers SUCCESS and COMPLETE w/ FAILURES; notProfiledCount
|
|
174
|
+
* covers NOT PROFILED and ERROR; IN PROGRESS and null statuses contribute to
|
|
175
|
+
* totalCount and the active/inactive split but are excluded from
|
|
176
|
+
* profiled/notProfiled.
|
|
177
|
+
*/
|
|
178
|
+
static foldAggregateRows(rows) {
|
|
179
|
+
const summary = { activeCount: 0, inactiveCount: 0, profiledCount: 0, notProfiledCount: 0 };
|
|
180
|
+
let totalCount = 0;
|
|
181
|
+
for (const row of rows) {
|
|
182
|
+
const cnt = row.cnt;
|
|
183
|
+
totalCount += cnt;
|
|
184
|
+
if (row.pnova__Prop_IsActive__c) {
|
|
185
|
+
summary.activeCount += cnt;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
summary.inactiveCount += cnt;
|
|
189
|
+
}
|
|
190
|
+
const status = row.pnova__Agg_Status__c;
|
|
191
|
+
if (status === 'SUCCESS' || status === 'COMPLETE w/ FAILURES') {
|
|
192
|
+
summary.profiledCount += cnt;
|
|
193
|
+
}
|
|
194
|
+
else if (status === 'NOT PROFILED' || status === 'ERROR') {
|
|
195
|
+
summary.notProfiledCount += cnt;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return { totalCount, summary };
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Retrieves profiling definitions with optional filtering and pagination.
|
|
202
|
+
*
|
|
203
|
+
* Note: Type filtering is applied client-side after the query since the type
|
|
204
|
+
* is derived from boolean flags (Prop_IsFiltered_SetB__c, PropFx_IsMetadataProfilingOnly__c).
|
|
205
|
+
*
|
|
206
|
+
* @param options - Filter and pagination options
|
|
207
|
+
* @returns ServiceResult containing an array of ProfilingDefinition records
|
|
208
|
+
*/
|
|
209
|
+
async getDefinitions(options = {}) {
|
|
210
|
+
const startTime = Date.now();
|
|
211
|
+
const emptyResult = [];
|
|
212
|
+
// Validate type filter if provided
|
|
213
|
+
if (options.type !== undefined) {
|
|
214
|
+
const typeError = ProfilingDefinitionService.validateType(options.type);
|
|
215
|
+
if (typeError) {
|
|
216
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, typeError, {
|
|
217
|
+
metadata: { duration: Date.now() - startTime },
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Validate status filter if provided
|
|
222
|
+
if (options.status !== undefined) {
|
|
223
|
+
const statusError = ProfilingDefinitionService.validateStatus(options.status);
|
|
224
|
+
if (statusError) {
|
|
225
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, statusError, {
|
|
226
|
+
metadata: { duration: Date.now() - startTime },
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Validate objectNames filter if provided (takes precedence over objectName)
|
|
231
|
+
if (options.objectNames !== undefined) {
|
|
232
|
+
for (const name of options.objectNames) {
|
|
233
|
+
const objectNameError = validateObjectName(name);
|
|
234
|
+
if (objectNameError) {
|
|
235
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
|
|
236
|
+
metadata: { duration: Date.now() - startTime },
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Validate objectName filter if provided
|
|
242
|
+
if (options.objectName !== undefined) {
|
|
243
|
+
const objectNameError = validateObjectName(options.objectName);
|
|
244
|
+
if (objectNameError) {
|
|
245
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
|
|
246
|
+
metadata: { duration: Date.now() - startTime },
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Validate pagination
|
|
251
|
+
const paginationError = validatePagination(options.limit, options.offset, MAX_PAGINATION_LIMIT);
|
|
252
|
+
if (paginationError) {
|
|
253
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.INVALID_PAGINATION, paginationError, {
|
|
254
|
+
metadata: { duration: Date.now() - startTime },
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
const soql = ProfilingDefinitionService.buildSoqlQuery(options);
|
|
259
|
+
this.logger?.log(`Querying profiling definitions: ${soql}`);
|
|
260
|
+
const queryResult = await this.soqlAdapter.query(soql);
|
|
261
|
+
if (!queryResult.success) {
|
|
262
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
|
|
263
|
+
}
|
|
264
|
+
const definitions = queryResult.data.records.map((record) => ProfilingDefinitionService.mapToProfilingDefinition(record));
|
|
265
|
+
// Note: Type filtering is now done in SOQL via underlying boolean fields.
|
|
266
|
+
// No client-side filtering needed since SOQL already applied the filter.
|
|
267
|
+
const duration = Date.now() - startTime;
|
|
268
|
+
this.logger?.log(`Found ${String(definitions.length)} profiling definitions`);
|
|
269
|
+
return createSuccessResult(definitions, {
|
|
270
|
+
message: `Found ${String(definitions.length)} profiling definitions`,
|
|
271
|
+
metadata: { duration },
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
276
|
+
this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
|
|
277
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
|
|
278
|
+
metadata: { duration: Date.now() - startTime },
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Retrieves all profiling definitions matching the given filters, with automatic pagination.
|
|
284
|
+
*
|
|
285
|
+
* Fetches pages of MAX_PAGINATION_LIMIT (200) until a short page is returned.
|
|
286
|
+
* The limit and offset options are ignored — pagination is handled internally.
|
|
287
|
+
*
|
|
288
|
+
* @param options - Filter options (limit/offset are overridden)
|
|
289
|
+
* @returns ServiceResult containing all matching ProfilingDefinition records
|
|
290
|
+
*/
|
|
291
|
+
async getAllDefinitions(options = {}) {
|
|
292
|
+
const startTime = Date.now();
|
|
293
|
+
const allDefinitions = [];
|
|
294
|
+
let offset = 0;
|
|
295
|
+
const pageSize = MAX_PAGINATION_LIMIT;
|
|
296
|
+
// eslint-disable-next-line no-constant-condition -- Pagination loop exits on short page or failure
|
|
297
|
+
while (true) {
|
|
298
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential pagination: each page depends on knowing if more exist
|
|
299
|
+
const pageResult = await this.getDefinitions({ ...options, limit: pageSize, offset });
|
|
300
|
+
if (!pageResult.success) {
|
|
301
|
+
if (allDefinitions.length > 0) {
|
|
302
|
+
this.logger?.log(`Pagination failed at offset ${offset}, using ${allDefinitions.length} definitions fetched so far`);
|
|
303
|
+
return createSuccessResult(allDefinitions, {
|
|
304
|
+
warnings: [`Pagination incomplete: failed at offset ${offset}. Results may be partial.`],
|
|
305
|
+
metadata: { duration: Date.now() - startTime },
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return pageResult;
|
|
309
|
+
}
|
|
310
|
+
allDefinitions.push(...pageResult.data);
|
|
311
|
+
if (pageResult.data.length < pageSize) {
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
offset += pageSize;
|
|
315
|
+
}
|
|
316
|
+
this.logger?.log(`Fetched ${allDefinitions.length} total definitions across pagination`);
|
|
317
|
+
return createSuccessResult(allDefinitions, {
|
|
318
|
+
message: `Found ${allDefinitions.length} definitions`,
|
|
319
|
+
metadata: { duration: Date.now() - startTime },
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Lists profiling definitions with filtering, pagination, and sorting.
|
|
324
|
+
*
|
|
325
|
+
* Executes two SOQL queries:
|
|
326
|
+
*
|
|
327
|
+
* - An aggregate GROUP BY query over the full filter set (no pagination) that
|
|
328
|
+
* yields totalCount and per-status / per-active bucket counts in one round-trip.
|
|
329
|
+
* - A data query with SELECT, WHERE, ORDER BY, LIMIT, OFFSET for the page.
|
|
330
|
+
*
|
|
331
|
+
* @param options - Filter, pagination, and sort options
|
|
332
|
+
* @returns ServiceResult containing definitions, totalCount, and aggregate summary
|
|
333
|
+
*/
|
|
334
|
+
async listDefinitions(options) {
|
|
335
|
+
const startTime = Date.now();
|
|
336
|
+
const emptyResult = {
|
|
337
|
+
definitions: [],
|
|
338
|
+
totalCount: 0,
|
|
339
|
+
summary: { ...EMPTY_LIST_SUMMARY },
|
|
340
|
+
};
|
|
341
|
+
// Validate pagination
|
|
342
|
+
const limit = options.pagination?.limit ?? LIST_DEFAULT_LIMIT;
|
|
343
|
+
const offset = options.pagination?.offset ?? 0;
|
|
344
|
+
const paginationError = validatePagination(limit, offset, MAX_PAGINATION_LIMIT);
|
|
345
|
+
if (paginationError) {
|
|
346
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.INVALID_PAGINATION, paginationError, {
|
|
347
|
+
metadata: { duration: Date.now() - startTime },
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
// Validate objects filter if provided
|
|
351
|
+
if (options.filter?.objects !== undefined) {
|
|
352
|
+
for (const name of options.filter.objects) {
|
|
353
|
+
const objectNameError = validateObjectName(name);
|
|
354
|
+
if (objectNameError) {
|
|
355
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
|
|
356
|
+
metadata: { duration: Date.now() - startTime },
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Validate namespace filter if provided
|
|
362
|
+
if (options.filter?.namespace !== undefined) {
|
|
363
|
+
const namespaceError = validateNamespace(options.filter.namespace);
|
|
364
|
+
if (namespaceError) {
|
|
365
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, namespaceError, {
|
|
366
|
+
metadata: { duration: Date.now() - startTime },
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
try {
|
|
371
|
+
// Build WHERE conditions (shared by both aggregate and data queries)
|
|
372
|
+
const whereBuilder = ProfilingDefinitionService.buildListWhereConditions(options.filter);
|
|
373
|
+
// 1. Aggregate GROUP BY query for totalCount AND summary buckets
|
|
374
|
+
const aggregateBuilder = new CuneiformQueryBuilder()
|
|
375
|
+
.select(['COUNT(Id) cnt', 'pnova__Agg_Status__c', 'pnova__Prop_IsActive__c'])
|
|
376
|
+
.from('pnova__Profiling_Definition__c');
|
|
377
|
+
ProfilingDefinitionService.applyWhereConditions(aggregateBuilder, whereBuilder);
|
|
378
|
+
aggregateBuilder.groupBy(['pnova__Agg_Status__c', 'pnova__Prop_IsActive__c']);
|
|
379
|
+
const aggregateSoql = aggregateBuilder.toSOQL();
|
|
380
|
+
this.logger?.log(`Aggregating profiling definitions: ${aggregateSoql}`);
|
|
381
|
+
const aggregateResult = await this.soqlAdapter.query(aggregateSoql);
|
|
382
|
+
if (!aggregateResult.success) {
|
|
383
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, aggregateResult.message ?? 'Profiling definition aggregate query failed', { metadata: { duration: Date.now() - startTime } });
|
|
384
|
+
}
|
|
385
|
+
const { totalCount, summary } = ProfilingDefinitionService.foldAggregateRows(aggregateResult.data.records);
|
|
386
|
+
// 2. Data query with pagination and sort
|
|
387
|
+
const dataBuilder = new CuneiformQueryBuilder()
|
|
388
|
+
.select(DEFINITION_FIELDS.split(', '))
|
|
389
|
+
.from('pnova__Profiling_Definition__c');
|
|
390
|
+
ProfilingDefinitionService.applyWhereConditions(dataBuilder, whereBuilder);
|
|
391
|
+
// Sort
|
|
392
|
+
const sortField = options.sort?.field ?? 'name';
|
|
393
|
+
const sortDirection = (options.sort?.direction ?? 'asc').toUpperCase();
|
|
394
|
+
const soqlSortField = SORT_FIELD_MAP[sortField] ?? 'pnova__Prop_Name__c';
|
|
395
|
+
if (sortField === 'lastProfiledDate') {
|
|
396
|
+
dataBuilder.orderBy(soqlSortField, sortDirection, 'NULLS LAST');
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
dataBuilder.orderBy(soqlSortField, sortDirection);
|
|
400
|
+
}
|
|
401
|
+
dataBuilder.limit(limit);
|
|
402
|
+
dataBuilder.offset(offset);
|
|
403
|
+
const dataSoql = dataBuilder.toSOQL();
|
|
404
|
+
this.logger?.log(`Querying profiling definitions: ${dataSoql}`);
|
|
405
|
+
const queryResult = await this.soqlAdapter.query(dataSoql);
|
|
406
|
+
if (!queryResult.success) {
|
|
407
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
|
|
408
|
+
}
|
|
409
|
+
const definitions = queryResult.data.records.map((record) => ProfilingDefinitionService.mapToProfilingDefinition(record));
|
|
410
|
+
const duration = Date.now() - startTime;
|
|
411
|
+
this.logger?.log(`Listed ${String(definitions.length)} of ${String(totalCount)} profiling definitions`);
|
|
412
|
+
return createSuccessResult({ definitions, totalCount, summary }, {
|
|
413
|
+
message: `Listed ${String(definitions.length)} of ${String(totalCount)} profiling definitions`,
|
|
414
|
+
metadata: { duration },
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
419
|
+
this.logger?.log(`Profiling definition list failed: ${errorMessage}`);
|
|
420
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
|
|
421
|
+
metadata: { duration: Date.now() - startTime },
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Retrieves a single profiling definition by its Salesforce ID.
|
|
427
|
+
*
|
|
428
|
+
* @param id - The Salesforce record ID (15 or 18 characters)
|
|
429
|
+
* @returns ServiceResult containing the ProfilingDefinition or null if not found
|
|
430
|
+
*/
|
|
431
|
+
async getDefinitionById(id) {
|
|
432
|
+
const startTime = Date.now();
|
|
433
|
+
const emptyResult = null;
|
|
434
|
+
// Validate ID format
|
|
435
|
+
const idError = validateSalesforceId(id);
|
|
436
|
+
if (idError) {
|
|
437
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, idError, {
|
|
438
|
+
metadata: { duration: Date.now() - startTime },
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
const soql = new CuneiformQueryBuilder()
|
|
443
|
+
.select(DEFINITION_FIELDS.split(', '))
|
|
444
|
+
.from('pnova__Profiling_Definition__c')
|
|
445
|
+
.where('Id', '=', id)
|
|
446
|
+
.limit(1)
|
|
447
|
+
.toSOQL();
|
|
448
|
+
this.logger?.log(`Querying profiling definition by ID: ${id}`);
|
|
449
|
+
const queryResult = await this.soqlAdapter.query(soql);
|
|
450
|
+
if (!queryResult.success) {
|
|
451
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
|
|
452
|
+
}
|
|
453
|
+
const duration = Date.now() - startTime;
|
|
454
|
+
if (queryResult.data.records.length === 0) {
|
|
455
|
+
this.logger?.log(`Profiling definition not found: ${id}`);
|
|
456
|
+
return createSuccessResult(emptyResult, {
|
|
457
|
+
message: `Profiling definition not found: ${id}`,
|
|
458
|
+
warnings: [`No profiling definition found with ID: ${id}`],
|
|
459
|
+
metadata: { duration },
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
const definition = ProfilingDefinitionService.mapToProfilingDefinition(queryResult.data.records[0]);
|
|
463
|
+
this.logger?.log(`Found profiling definition: ${definition.name}`);
|
|
464
|
+
return createSuccessResult(definition, {
|
|
465
|
+
message: `Found profiling definition: ${definition.name}`,
|
|
466
|
+
metadata: { duration },
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
471
|
+
this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
|
|
472
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
|
|
473
|
+
metadata: { duration: Date.now() - startTime },
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Retrieves a single profiling definition by its definition key (e.g., "PD-0001").
|
|
479
|
+
*
|
|
480
|
+
* The key is stored in the standard Name field as an AutoNumber.
|
|
481
|
+
*
|
|
482
|
+
* @param key - The definition key (e.g., "PD-0001")
|
|
483
|
+
* @returns ServiceResult containing the ProfilingDefinition or null if not found
|
|
484
|
+
*/
|
|
485
|
+
async getDefinitionByKey(key) {
|
|
486
|
+
const startTime = Date.now();
|
|
487
|
+
const emptyResult = null;
|
|
488
|
+
// Validate key is provided
|
|
489
|
+
const keyError = validateRequiredString(key, 'Definition key');
|
|
490
|
+
if (keyError) {
|
|
491
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, keyError, {
|
|
492
|
+
metadata: { duration: Date.now() - startTime },
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
try {
|
|
496
|
+
// Name is the standard AutoNumber field (format: PD-{0000})
|
|
497
|
+
const soql = new CuneiformQueryBuilder()
|
|
498
|
+
.select(DEFINITION_FIELDS.split(', '))
|
|
499
|
+
.from('pnova__Profiling_Definition__c')
|
|
500
|
+
.where('Name', '=', key.trim())
|
|
501
|
+
.limit(1)
|
|
502
|
+
.toSOQL();
|
|
503
|
+
this.logger?.log(`Querying profiling definition by key: ${key}`);
|
|
504
|
+
const queryResult = await this.soqlAdapter.query(soql);
|
|
505
|
+
if (!queryResult.success) {
|
|
506
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
|
|
507
|
+
}
|
|
508
|
+
const duration = Date.now() - startTime;
|
|
509
|
+
if (queryResult.data.records.length === 0) {
|
|
510
|
+
this.logger?.log(`Profiling definition not found: ${key}`);
|
|
511
|
+
return createSuccessResult(emptyResult, {
|
|
512
|
+
message: `Profiling definition not found: ${key}`,
|
|
513
|
+
warnings: [`No profiling definition found with key: ${key}`],
|
|
514
|
+
metadata: { duration },
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
const definition = ProfilingDefinitionService.mapToProfilingDefinition(queryResult.data.records[0]);
|
|
518
|
+
this.logger?.log(`Found profiling definition: ${definition.name} (key: ${key})`);
|
|
519
|
+
return createSuccessResult(definition, {
|
|
520
|
+
message: `Found profiling definition: ${definition.name}`,
|
|
521
|
+
metadata: { duration },
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
526
|
+
this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
|
|
527
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
|
|
528
|
+
metadata: { duration: Date.now() - startTime },
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Retrieves multiple profiling definitions by their human-readable keys in a single SOQL query.
|
|
534
|
+
*
|
|
535
|
+
* Replaces the N+1 pattern of calling getDefinitionByKey() per key with a single
|
|
536
|
+
* `WHERE Name IN (...)` query. Returns a Map keyed by the requested key values.
|
|
537
|
+
*
|
|
538
|
+
* @param keys - Array of definition keys (e.g., ['PD-0001', 'PD-0002'])
|
|
539
|
+
* @returns ServiceResult containing a Map of key → ProfilingDefinition (missing keys have null)
|
|
540
|
+
*/
|
|
541
|
+
async getDefinitionsByKeys(keys) {
|
|
542
|
+
const startTime = Date.now();
|
|
543
|
+
const emptyResult = new Map();
|
|
544
|
+
if (keys.length === 0) {
|
|
545
|
+
return createSuccessResult(emptyResult, {
|
|
546
|
+
message: 'No keys provided',
|
|
547
|
+
metadata: { duration: Date.now() - startTime },
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
try {
|
|
551
|
+
const trimmedKeys = keys.map((k) => k.trim());
|
|
552
|
+
const soql = new CuneiformQueryBuilder()
|
|
553
|
+
.select(DEFINITION_FIELDS.split(', '))
|
|
554
|
+
.from('pnova__Profiling_Definition__c')
|
|
555
|
+
.andWhereIn('Name', trimmedKeys)
|
|
556
|
+
.toSOQL();
|
|
557
|
+
this.logger?.log(`Querying profiling definitions by keys: ${trimmedKeys.join(', ')}`);
|
|
558
|
+
const queryResult = await this.soqlAdapter.query(soql);
|
|
559
|
+
if (!queryResult.success) {
|
|
560
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition batch query failed', { metadata: { duration: Date.now() - startTime } });
|
|
561
|
+
}
|
|
562
|
+
const duration = Date.now() - startTime;
|
|
563
|
+
// Build result map: key → definition or null
|
|
564
|
+
const resultMap = new Map();
|
|
565
|
+
const recordsByKey = new Map();
|
|
566
|
+
for (const record of queryResult.data.records) {
|
|
567
|
+
recordsByKey.set(record.Name, record);
|
|
568
|
+
}
|
|
569
|
+
for (const key of trimmedKeys) {
|
|
570
|
+
const record = recordsByKey.get(key);
|
|
571
|
+
resultMap.set(key, record ? ProfilingDefinitionService.mapToProfilingDefinition(record) : null);
|
|
572
|
+
}
|
|
573
|
+
const foundCount = queryResult.data.records.length;
|
|
574
|
+
this.logger?.log(`Found ${foundCount}/${trimmedKeys.length} profiling definitions`);
|
|
575
|
+
return createSuccessResult(resultMap, {
|
|
576
|
+
message: `Found ${foundCount} of ${trimmedKeys.length} requested definitions`,
|
|
577
|
+
metadata: { duration },
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
catch (error) {
|
|
581
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
582
|
+
this.logger?.log(`Profiling definition batch query failed: ${errorMessage}`);
|
|
583
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
|
|
584
|
+
metadata: { duration: Date.now() - startTime },
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Retrieves profiling definitions filtered by type.
|
|
590
|
+
*
|
|
591
|
+
* Convenience method that delegates to getDefinitions() with the type filter.
|
|
592
|
+
*
|
|
593
|
+
* @param type - The definition type to filter by
|
|
594
|
+
* @param options - Additional filter and pagination options
|
|
595
|
+
* @returns ServiceResult containing an array of ProfilingDefinition records
|
|
596
|
+
*/
|
|
597
|
+
async getDefinitionsByType(type, options = {}) {
|
|
598
|
+
return this.getDefinitions({ ...options, type });
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Retrieves profiling definitions filtered by status.
|
|
602
|
+
*
|
|
603
|
+
* Convenience method that delegates to getDefinitions() with the status filter.
|
|
604
|
+
*
|
|
605
|
+
* @param status - The profiling status to filter by
|
|
606
|
+
* @param options - Additional filter and pagination options
|
|
607
|
+
* @returns ServiceResult containing an array of ProfilingDefinition records
|
|
608
|
+
*/
|
|
609
|
+
async getDefinitionsByStatus(status, options = {}) {
|
|
610
|
+
return this.getDefinitions({ ...options, status });
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Creates a new profiling definition via the Cuneiform REST API.
|
|
614
|
+
*
|
|
615
|
+
* Definition creation is routed through the REST endpoint which enforces
|
|
616
|
+
* server-side permission checks in GlobalProfilingService.
|
|
617
|
+
*
|
|
618
|
+
* @param input - The definition input containing name, objectName, and optional fields
|
|
619
|
+
* @returns ServiceResult containing the created ProfilingDefinition or null on failure
|
|
620
|
+
*/
|
|
621
|
+
async createDefinition(input) {
|
|
622
|
+
const startTime = Date.now();
|
|
623
|
+
const emptyResult = null;
|
|
624
|
+
if (!this.restAdapter) {
|
|
625
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'restAdapter is required for create operations.', { metadata: { duration: Date.now() - startTime } });
|
|
626
|
+
}
|
|
627
|
+
return this.createDefinitionViaRest(input, startTime);
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Creates multiple profiling definitions via the Cuneiform REST API.
|
|
631
|
+
*
|
|
632
|
+
* Each definition is created individually since the REST endpoint
|
|
633
|
+
* currently supports single creation per request.
|
|
634
|
+
*
|
|
635
|
+
* @param inputs - Array of definition inputs (1-10 items)
|
|
636
|
+
* @returns ServiceResult containing succeeded and failed arrays
|
|
637
|
+
*/
|
|
638
|
+
async createDefinitions(inputs) {
|
|
639
|
+
const startTime = Date.now();
|
|
640
|
+
const emptyResult = { succeeded: [], failed: [] };
|
|
641
|
+
if (!this.restAdapter) {
|
|
642
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'restAdapter is required for create operations.', { metadata: { duration: Date.now() - startTime } });
|
|
643
|
+
}
|
|
644
|
+
return this.createDefinitionsViaRest(inputs, startTime);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Updates metadata attributes on a profiling definition.
|
|
648
|
+
*
|
|
649
|
+
* Writes only the supplied attributes; untouched columns are preserved.
|
|
650
|
+
* At least one attribute must be provided.
|
|
651
|
+
*
|
|
652
|
+
* @param definitionId - The Salesforce record ID of the definition to update
|
|
653
|
+
* @param attributes - Partial attribute set to write
|
|
654
|
+
* @returns ServiceResult containing the update result
|
|
655
|
+
*/
|
|
656
|
+
async updateAttributes(definitionId, attributes) {
|
|
657
|
+
const startTime = Date.now();
|
|
658
|
+
const emptyResult = { id: definitionId, updated: false, updatedAttributes: [] };
|
|
659
|
+
// Validate definition ID
|
|
660
|
+
const idError = validateSalesforceId(definitionId);
|
|
661
|
+
if (idError) {
|
|
662
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, idError, {
|
|
663
|
+
metadata: { duration: Date.now() - startTime },
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
// Check that REST adapter is configured
|
|
667
|
+
if (!this.restAdapter) {
|
|
668
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, 'REST adapter required for update operations', { metadata: { duration: Date.now() - startTime } });
|
|
669
|
+
}
|
|
670
|
+
// Build the partial update payload — only supplied attributes
|
|
671
|
+
// eslint-disable-next-line camelcase -- Salesforce custom field API names require this casing
|
|
672
|
+
const payload = {};
|
|
673
|
+
const updatedAttributes = [];
|
|
674
|
+
if (attributes.name !== undefined) {
|
|
675
|
+
// eslint-disable-next-line camelcase -- Salesforce custom field API name
|
|
676
|
+
payload.pnova__Prop_Name__c = attributes.name;
|
|
677
|
+
updatedAttributes.push('name');
|
|
678
|
+
}
|
|
679
|
+
if (attributes.category !== undefined) {
|
|
680
|
+
// eslint-disable-next-line camelcase -- Salesforce custom field API name
|
|
681
|
+
payload.pnova__Prop_Category__c = attributes.category;
|
|
682
|
+
updatedAttributes.push('category');
|
|
683
|
+
}
|
|
684
|
+
if (attributes.timeCategory !== undefined) {
|
|
685
|
+
// eslint-disable-next-line camelcase -- Salesforce custom field API name
|
|
686
|
+
payload.pnova__Prop_TimeCategory__c = attributes.timeCategory;
|
|
687
|
+
updatedAttributes.push('timeCategory');
|
|
688
|
+
}
|
|
689
|
+
if (attributes.segmentCategory !== undefined) {
|
|
690
|
+
// eslint-disable-next-line camelcase -- Salesforce custom field API name
|
|
691
|
+
payload.pnova__Prop_SegmentCategory__c = attributes.segmentCategory;
|
|
692
|
+
updatedAttributes.push('segmentCategory');
|
|
693
|
+
}
|
|
694
|
+
if (attributes.description !== undefined) {
|
|
695
|
+
// eslint-disable-next-line camelcase -- Salesforce custom field API name
|
|
696
|
+
payload.pnova__Prop_Description__c = attributes.description;
|
|
697
|
+
updatedAttributes.push('description');
|
|
698
|
+
}
|
|
699
|
+
try {
|
|
700
|
+
this.logger?.log(`Updating definition ${definitionId}: ${updatedAttributes.join(', ')}`);
|
|
701
|
+
const updateResult = await this.restAdapter.updateRecord('pnova__Profiling_Definition__c', definitionId, payload);
|
|
702
|
+
const duration = Date.now() - startTime;
|
|
703
|
+
if (!updateResult.success) {
|
|
704
|
+
this.logger?.log(`Definition attribute update failed: ${updateResult.message ?? 'Unknown error'}`);
|
|
705
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, updateResult.message ?? 'Definition attribute update failed', { metadata: { duration } });
|
|
706
|
+
}
|
|
707
|
+
this.logger?.log(`Definition ${definitionId} attributes updated successfully`);
|
|
708
|
+
return createSuccessResult({ id: definitionId, updated: true, updatedAttributes }, {
|
|
709
|
+
message: `Updated definition attributes: ${updatedAttributes.join(', ')}`,
|
|
710
|
+
metadata: { duration },
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
715
|
+
this.logger?.log(`Definition attribute update failed: ${errorMessage}`);
|
|
716
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, errorMessage, {
|
|
717
|
+
metadata: { duration: Date.now() - startTime },
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Deletes profiling definitions by their Salesforce IDs.
|
|
723
|
+
*
|
|
724
|
+
* Safety checks are applied before deletion:
|
|
725
|
+
* - Definition must exist
|
|
726
|
+
* - Definition must have no associated summaries (hasRelatedSummaries field)
|
|
727
|
+
*
|
|
728
|
+
* Definitions can be deleted regardless of profiling status when no
|
|
729
|
+
* associated summaries exist.
|
|
730
|
+
*
|
|
731
|
+
* Definitions that fail safety checks are skipped with reasons provided.
|
|
732
|
+
*
|
|
733
|
+
* @param ids - Array of Salesforce record IDs to delete (1-200 items)
|
|
734
|
+
* @param options - Optional progress callback and configuration
|
|
735
|
+
* @returns ServiceResult containing deletion counts and skip/failure details
|
|
736
|
+
*/
|
|
737
|
+
async deleteDefinitions(ids, options) {
|
|
738
|
+
const startTime = Date.now();
|
|
739
|
+
const emptyResult = {
|
|
740
|
+
deleted: 0,
|
|
741
|
+
skipped: 0,
|
|
742
|
+
failed: 0,
|
|
743
|
+
skipReasons: [],
|
|
744
|
+
failures: [],
|
|
745
|
+
};
|
|
746
|
+
// Validate ids array is not empty
|
|
747
|
+
if (ids.length === 0) {
|
|
748
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_DELETE_FAILED, 'Definition IDs array cannot be empty', { metadata: { duration: Date.now() - startTime } });
|
|
749
|
+
}
|
|
750
|
+
// Validate REST adapter is available
|
|
751
|
+
if (!this.restAdapter) {
|
|
752
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_DELETE_FAILED, 'REST adapter required for delete operations', { metadata: { duration: Date.now() - startTime } });
|
|
753
|
+
}
|
|
754
|
+
// Validate all IDs have valid format
|
|
755
|
+
for (const id of ids) {
|
|
756
|
+
const idError = validateSalesforceId(id);
|
|
757
|
+
if (idError) {
|
|
758
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, `Invalid ID "${id}": ${idError}`, {
|
|
759
|
+
metadata: { duration: Date.now() - startTime },
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
const result = {
|
|
764
|
+
deleted: 0,
|
|
765
|
+
skipped: 0,
|
|
766
|
+
failed: 0,
|
|
767
|
+
skipReasons: [],
|
|
768
|
+
failures: [],
|
|
769
|
+
};
|
|
770
|
+
const total = ids.length;
|
|
771
|
+
let current = 0;
|
|
772
|
+
// Process each ID sequentially - intentional for safe deletion with proper error handling
|
|
773
|
+
// Each operation depends on the previous (safety checks before delete)
|
|
774
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential processing for safe deletion with individual error handling
|
|
775
|
+
for (const id of ids) {
|
|
776
|
+
current++;
|
|
777
|
+
try {
|
|
778
|
+
// Look up the definition
|
|
779
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential: must verify existence before deletion
|
|
780
|
+
const lookupResult = await this.getDefinitionById(id);
|
|
781
|
+
if (!lookupResult.success) {
|
|
782
|
+
result.failed++;
|
|
783
|
+
result.failures.push({
|
|
784
|
+
id,
|
|
785
|
+
error: lookupResult.message ?? 'Failed to lookup definition',
|
|
786
|
+
});
|
|
787
|
+
options?.onProgress?.({ id, name: id, status: 'failed', reason: 'lookup_failed', current, total });
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
// Check if definition exists
|
|
791
|
+
if (lookupResult.data === null) {
|
|
792
|
+
result.skipped++;
|
|
793
|
+
result.skipReasons.push({
|
|
794
|
+
id,
|
|
795
|
+
reason: 'not_found',
|
|
796
|
+
});
|
|
797
|
+
options?.onProgress?.({ id, name: id, status: 'skipped', reason: 'not_found', current, total });
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
const definition = lookupResult.data;
|
|
801
|
+
const defMeta = {
|
|
802
|
+
key: definition.key,
|
|
803
|
+
objectName: definition.objectName,
|
|
804
|
+
objectLabel: definition.objectLabel,
|
|
805
|
+
category: definition.category,
|
|
806
|
+
timeCategory: definition.timeCategory,
|
|
807
|
+
segmentCategory: definition.segmentCategory,
|
|
808
|
+
profilingStatus: definition.status,
|
|
809
|
+
};
|
|
810
|
+
// Safety check: Check for associated summaries
|
|
811
|
+
// Use hasRelatedSummaries field (formula field on the definition object)
|
|
812
|
+
const hasSummaries = definition.hasRelatedSummaries === true;
|
|
813
|
+
if (hasSummaries) {
|
|
814
|
+
result.skipped++;
|
|
815
|
+
result.skipReasons.push({
|
|
816
|
+
id,
|
|
817
|
+
name: definition.name,
|
|
818
|
+
reason: 'has_summaries',
|
|
819
|
+
});
|
|
820
|
+
options?.onProgress?.({
|
|
821
|
+
id,
|
|
822
|
+
...defMeta,
|
|
823
|
+
name: definition.name,
|
|
824
|
+
status: 'skipped',
|
|
825
|
+
reason: 'has_summaries',
|
|
826
|
+
current,
|
|
827
|
+
total,
|
|
828
|
+
});
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
// All safety checks passed - delete the definition
|
|
832
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential: dependent on prior safety checks passing
|
|
833
|
+
const deleteResult = await this.restAdapter.deleteRecord('pnova__Profiling_Definition__c', id);
|
|
834
|
+
if (!deleteResult.success) {
|
|
835
|
+
const deleteError = deleteResult.message ?? 'Failed to delete definition';
|
|
836
|
+
result.failed++;
|
|
837
|
+
result.failures.push({
|
|
838
|
+
id,
|
|
839
|
+
name: definition.name,
|
|
840
|
+
error: deleteError,
|
|
841
|
+
});
|
|
842
|
+
options?.onProgress?.({
|
|
843
|
+
id,
|
|
844
|
+
...defMeta,
|
|
845
|
+
name: definition.name,
|
|
846
|
+
status: 'failed',
|
|
847
|
+
reason: deleteError,
|
|
848
|
+
current,
|
|
849
|
+
total,
|
|
850
|
+
});
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
result.deleted++;
|
|
854
|
+
this.logger?.log(`Deleted profiling definition: ${id}`);
|
|
855
|
+
options?.onProgress?.({ id, ...defMeta, name: definition.name, status: 'deleted', current, total });
|
|
856
|
+
}
|
|
857
|
+
catch (error) {
|
|
858
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
859
|
+
result.failed++;
|
|
860
|
+
result.failures.push({
|
|
861
|
+
id,
|
|
862
|
+
error: errorMessage,
|
|
863
|
+
});
|
|
864
|
+
options?.onProgress?.({ id, name: id, status: 'failed', reason: errorMessage, current, total });
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
const duration = Date.now() - startTime;
|
|
868
|
+
const totalProcessed = result.deleted + result.skipped + result.failed;
|
|
869
|
+
const summaryMessage = `Deleted ${result.deleted}/${totalProcessed} definitions (${result.skipped} skipped, ${result.failed} failed)`;
|
|
870
|
+
this.logger?.log(summaryMessage);
|
|
871
|
+
return createSuccessResult(result, {
|
|
872
|
+
message: summaryMessage,
|
|
873
|
+
warnings: result.skipped > 0 || result.failed > 0 ? [`${result.skipped} skipped, ${result.failed} failed`] : undefined,
|
|
874
|
+
metadata: { duration },
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
// NOTE: createDefinitionViaApex and createDefinitionsViaApex removed during REST API migration (CLI-1150).
|
|
878
|
+
// These methods used anonymous Apex routing via GlobalProfilingService and have been replaced
|
|
879
|
+
// by createDefinitionViaRest and createDefinitionsViaRest.
|
|
880
|
+
/**
|
|
881
|
+
* Creates a single definition via the Cuneiform REST API.
|
|
882
|
+
*/
|
|
883
|
+
async createDefinitionViaRest(input, startTime) {
|
|
884
|
+
const emptyResult = null;
|
|
885
|
+
// Validate objectName
|
|
886
|
+
const objectNameError = validateObjectName(input.objectName);
|
|
887
|
+
if (objectNameError) {
|
|
888
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
|
|
889
|
+
metadata: { duration: Date.now() - startTime },
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
try {
|
|
893
|
+
this.logger?.log(`Creating profiling definition for object: ${input.objectName}`);
|
|
894
|
+
const requestBody = ProfilingDefinitionService.buildCreateDefinitionRequestBody(input);
|
|
895
|
+
const restResult = await this.restAdapter.request({
|
|
896
|
+
url: `${PROFILING_DEFINITION_REST_BASE}/create-definition`,
|
|
897
|
+
method: 'POST',
|
|
898
|
+
body: requestBody,
|
|
899
|
+
});
|
|
900
|
+
if (!restResult.success) {
|
|
901
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, restResult.message ?? 'REST API call failed', { metadata: { duration: Date.now() - startTime } });
|
|
902
|
+
}
|
|
903
|
+
const response = restResult.data;
|
|
904
|
+
if (!response.success) {
|
|
905
|
+
const errorMsg = response.errors && response.errors.length > 0 ? response.errors.join('; ') : 'Definition creation failed';
|
|
906
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMsg, {
|
|
907
|
+
metadata: { duration: Date.now() - startTime },
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
if (!response.results || response.results.length === 0) {
|
|
911
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'No results returned from profiling definition REST API', { metadata: { duration: Date.now() - startTime } });
|
|
912
|
+
}
|
|
913
|
+
const createdId = response.results[0].id;
|
|
914
|
+
this.logger?.log(`Created profiling definition with ID: ${createdId}`);
|
|
915
|
+
// Query back the full definition record
|
|
916
|
+
const queryResult = await this.getDefinitionById(createdId);
|
|
917
|
+
if (!queryResult.success || queryResult.data === null) {
|
|
918
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, queryResult.message ?? 'Failed to retrieve created definition', { metadata: { duration: Date.now() - startTime } });
|
|
919
|
+
}
|
|
920
|
+
const duration = Date.now() - startTime;
|
|
921
|
+
this.logger?.log(`Created profiling definition: ${queryResult.data.name} (${queryResult.data.key})`);
|
|
922
|
+
return createSuccessResult(queryResult.data, {
|
|
923
|
+
message: `Created profiling definition: ${queryResult.data.name}`,
|
|
924
|
+
metadata: { duration },
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
catch (error) {
|
|
928
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
929
|
+
this.logger?.log(`Failed to create profiling definition: ${errorMessage}`);
|
|
930
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMessage, {
|
|
931
|
+
metadata: { duration: Date.now() - startTime },
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Creates multiple definitions via the Cuneiform REST API.
|
|
937
|
+
*
|
|
938
|
+
* The REST endpoint supports single creation, so definitions are created sequentially.
|
|
939
|
+
*/
|
|
940
|
+
async createDefinitionsViaRest(inputs, startTime) {
|
|
941
|
+
const emptyResult = { succeeded: [], failed: [] };
|
|
942
|
+
if (inputs.length === 0) {
|
|
943
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'Inputs array must contain at least one definition.', { metadata: { duration: Date.now() - startTime } });
|
|
944
|
+
}
|
|
945
|
+
try {
|
|
946
|
+
this.logger?.log(`Creating ${inputs.length} profiling definitions via REST API`);
|
|
947
|
+
const succeeded = [];
|
|
948
|
+
const failed = [];
|
|
949
|
+
/* eslint-disable no-await-in-loop -- Sequential creation to avoid overwhelming the org */
|
|
950
|
+
for (const input of inputs) {
|
|
951
|
+
const result = await this.createDefinitionViaRest(input, Date.now());
|
|
952
|
+
if (result.success && result.data) {
|
|
953
|
+
succeeded.push(result.data);
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
failed.push({
|
|
957
|
+
input,
|
|
958
|
+
error: result.message ?? 'Creation failed',
|
|
959
|
+
errorCode: result.errorCode ?? ServiceErrorCodes.DEFINITION_CREATE_FAILED,
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
/* eslint-enable no-await-in-loop */
|
|
964
|
+
const duration = Date.now() - startTime;
|
|
965
|
+
this.logger?.log(`Created ${succeeded.length}/${inputs.length} definitions (${failed.length} failed)`);
|
|
966
|
+
return createSuccessResult({ succeeded, failed }, {
|
|
967
|
+
message: `Created ${succeeded.length}/${inputs.length} definitions`,
|
|
968
|
+
warnings: failed.length > 0 ? [`${failed.length} definition(s) failed to create`] : undefined,
|
|
969
|
+
metadata: { duration },
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
catch (error) {
|
|
973
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
974
|
+
this.logger?.log(`Bulk create operation failed: ${errorMessage}`);
|
|
975
|
+
return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMessage, {
|
|
976
|
+
metadata: { duration: Date.now() - startTime },
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
//# sourceMappingURL=ProfilingDefinitionService.js.map
|