sfdx-hardis 6.9.1-alpha202510282151.0 → 6.10.1-alpha202511021043.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4422,6 +4422,135 @@
4422
4422
  "ws:work:hardis"
4423
4423
  ]
4424
4424
  },
4425
+ "hardis:git:pull-requests:extract": {
4426
+ "aliases": [],
4427
+ "args": {},
4428
+ "description": "\n## Command Behavior\n\n**Extracts pull request information from your Git server based on specified filtering criteria.**\n\nThis command provides a powerful way to query and retrieve details about pull requests (or merge requests, depending on your Git provider) in your repository. It's highly useful for reporting, auditing, and analyzing development workflows.\n\nKey functionalities include:\n\n- **Target Branch Filtering:** You can filter pull requests by their target branch using the `--target-branch` flag. If not specified, the command will prompt you to select one.\n- **Status Filtering:** Filter pull requests by their status: `open`, `merged`, or `abandoned` using the `--status` flag. An interactive prompt is provided if no status is specified.\n- **Minimum Date Filtering:** Use the `--min-date` flag to retrieve pull requests created or updated after a specific date.\n- **CSV Output:** The extracted pull request data is generated into a CSV file, which can be used for further analysis in spreadsheet software.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves interacting with a Git provider's API:\n\n- **Git Provider Abstraction:** It uses the `GitProvider.getInstance(true)` to abstract away the specifics of different Git platforms (e.g., GitHub, GitLab, Azure DevOps). This ensures the command can work across various environments.\n- **API Calls:** The `gitProvider.listPullRequests()` method is called with a `prConstraint` object that encapsulates the filtering criteria (target branch, minimum date, status).\n- **Interactive Prompts:** The `prompts` library is used to interactively gather input from the user for the target branch and pull request status if they are not provided as command-line flags.\n- **Date Handling:** The `moment` library is used to parse and handle date inputs for the `--min-date` flag.\n- **CSV Generation:** The `generateCsvFile` utility is responsible for converting the retrieved pull request data into a CSV format, and `generateReportPath` determines the output file location.\n- **Error Handling:** It includes error handling for cases where a Git provider cannot be identified.\n</details>\n",
4429
+ "examples": [
4430
+ "$ sf hardis:git:pull-requests:extract",
4431
+ "$ sf hardis:git:pull-requests:extract --target-branch main --status merged"
4432
+ ],
4433
+ "flags": {
4434
+ "json": {
4435
+ "description": "Format output as json.",
4436
+ "helpGroup": "GLOBAL",
4437
+ "name": "json",
4438
+ "allowNo": false,
4439
+ "type": "boolean"
4440
+ },
4441
+ "flags-dir": {
4442
+ "helpGroup": "GLOBAL",
4443
+ "name": "flags-dir",
4444
+ "summary": "Import flag values from a directory.",
4445
+ "hasDynamicHelp": false,
4446
+ "multiple": false,
4447
+ "type": "option"
4448
+ },
4449
+ "target-branch": {
4450
+ "char": "t",
4451
+ "description": "Target branch of PRs",
4452
+ "name": "target-branch",
4453
+ "hasDynamicHelp": false,
4454
+ "multiple": false,
4455
+ "type": "option"
4456
+ },
4457
+ "status": {
4458
+ "char": "x",
4459
+ "description": "Status of the PR",
4460
+ "name": "status",
4461
+ "hasDynamicHelp": false,
4462
+ "multiple": false,
4463
+ "options": [
4464
+ "open",
4465
+ "merged",
4466
+ "abandoned"
4467
+ ],
4468
+ "type": "option"
4469
+ },
4470
+ "min-date": {
4471
+ "char": "m",
4472
+ "description": "Minimum date for PR",
4473
+ "name": "min-date",
4474
+ "hasDynamicHelp": false,
4475
+ "multiple": false,
4476
+ "type": "option"
4477
+ },
4478
+ "outputfile": {
4479
+ "char": "f",
4480
+ "description": "Force the path and name of output report file. Must end with .csv",
4481
+ "name": "outputfile",
4482
+ "hasDynamicHelp": false,
4483
+ "multiple": false,
4484
+ "type": "option"
4485
+ },
4486
+ "debug": {
4487
+ "char": "d",
4488
+ "description": "Activate debug mode (more logs)",
4489
+ "name": "debug",
4490
+ "allowNo": false,
4491
+ "type": "boolean"
4492
+ },
4493
+ "websocket": {
4494
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
4495
+ "name": "websocket",
4496
+ "hasDynamicHelp": false,
4497
+ "multiple": false,
4498
+ "type": "option"
4499
+ },
4500
+ "skipauth": {
4501
+ "description": "Skip authentication check when a default username is required",
4502
+ "name": "skipauth",
4503
+ "allowNo": false,
4504
+ "type": "boolean"
4505
+ }
4506
+ },
4507
+ "hasDynamicHelp": false,
4508
+ "hiddenAliases": [],
4509
+ "id": "hardis:git:pull-requests:extract",
4510
+ "pluginAlias": "sfdx-hardis",
4511
+ "pluginName": "sfdx-hardis",
4512
+ "pluginType": "core",
4513
+ "strict": true,
4514
+ "enableJsonFlag": true,
4515
+ "title": "Extract pull requests",
4516
+ "requiresProject": true,
4517
+ "isESM": true,
4518
+ "relativePath": [
4519
+ "lib",
4520
+ "commands",
4521
+ "hardis",
4522
+ "git",
4523
+ "pull-requests",
4524
+ "extract.js"
4525
+ ],
4526
+ "aliasPermutations": [],
4527
+ "permutations": [
4528
+ "hardis:git:pull-requests:extract",
4529
+ "git:hardis:pull-requests:extract",
4530
+ "git:pull-requests:hardis:extract",
4531
+ "git:pull-requests:extract:hardis",
4532
+ "hardis:pull-requests:git:extract",
4533
+ "pull-requests:hardis:git:extract",
4534
+ "pull-requests:git:hardis:extract",
4535
+ "pull-requests:git:extract:hardis",
4536
+ "hardis:pull-requests:extract:git",
4537
+ "pull-requests:hardis:extract:git",
4538
+ "pull-requests:extract:hardis:git",
4539
+ "pull-requests:extract:git:hardis",
4540
+ "hardis:git:extract:pull-requests",
4541
+ "git:hardis:extract:pull-requests",
4542
+ "git:extract:hardis:pull-requests",
4543
+ "git:extract:pull-requests:hardis",
4544
+ "hardis:extract:git:pull-requests",
4545
+ "extract:hardis:git:pull-requests",
4546
+ "extract:git:hardis:pull-requests",
4547
+ "extract:git:pull-requests:hardis",
4548
+ "hardis:extract:pull-requests:git",
4549
+ "extract:hardis:pull-requests:git",
4550
+ "extract:pull-requests:hardis:git",
4551
+ "extract:pull-requests:git:hardis"
4552
+ ]
4553
+ },
4425
4554
  "hardis:doc:extract:permsetgroups": {
4426
4555
  "aliases": [],
4427
4556
  "args": {},
@@ -4612,13 +4741,12 @@
4612
4741
  "generate:plugin:doc:hardis"
4613
4742
  ]
4614
4743
  },
4615
- "hardis:git:pull-requests:extract": {
4744
+ "hardis:org:configure:data": {
4616
4745
  "aliases": [],
4617
4746
  "args": {},
4618
- "description": "\n## Command Behavior\n\n**Extracts pull request information from your Git server based on specified filtering criteria.**\n\nThis command provides a powerful way to query and retrieve details about pull requests (or merge requests, depending on your Git provider) in your repository. It's highly useful for reporting, auditing, and analyzing development workflows.\n\nKey functionalities include:\n\n- **Target Branch Filtering:** You can filter pull requests by their target branch using the `--target-branch` flag. If not specified, the command will prompt you to select one.\n- **Status Filtering:** Filter pull requests by their status: `open`, `merged`, or `abandoned` using the `--status` flag. An interactive prompt is provided if no status is specified.\n- **Minimum Date Filtering:** Use the `--min-date` flag to retrieve pull requests created or updated after a specific date.\n- **CSV Output:** The extracted pull request data is generated into a CSV file, which can be used for further analysis in spreadsheet software.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves interacting with a Git provider's API:\n\n- **Git Provider Abstraction:** It uses the `GitProvider.getInstance(true)` to abstract away the specifics of different Git platforms (e.g., GitHub, GitLab, Azure DevOps). This ensures the command can work across various environments.\n- **API Calls:** The `gitProvider.listPullRequests()` method is called with a `prConstraint` object that encapsulates the filtering criteria (target branch, minimum date, status).\n- **Interactive Prompts:** The `prompts` library is used to interactively gather input from the user for the target branch and pull request status if they are not provided as command-line flags.\n- **Date Handling:** The `moment` library is used to parse and handle date inputs for the `--min-date` flag.\n- **CSV Generation:** The `generateCsvFile` utility is responsible for converting the retrieved pull request data into a CSV format, and `generateReportPath` determines the output file location.\n- **Error Handling:** It includes error handling for cases where a Git provider cannot be identified.\n</details>\n",
4747
+ "description": "\n## Command Behavior\n\n**Configures a Salesforce Data Migration Utility (SFDMU) project for data export and import operations.**\n\nThis command assists in setting up SFDMU workspaces, which are essential for managing data within your Salesforce environments. It streamlines the creation of `export.json` files and related configurations, enabling efficient data seeding, migration, and synchronization.\n\nKey functionalities:\n\n- **Template-Based Configuration:** Allows you to choose from predefined SFDMU templates or start with a blank configuration. Templates can pre-populate `export.json` with common data migration scenarios.\n- **Interactive Setup:** Guides you through the process of defining the SFDMU project folder name, label, and description.\n- **`export.json` Generation:** Creates the `export.json` file, which is the core configuration file for SFDMU, defining objects to export/import, queries, and operations.\n- **Additional File Generation:** Can generate additional configuration files, such as a `badwords.json` file for data filtering scenarios.\n- **Scratch Org Integration:** Offers to automatically configure the SFDMU project to be used for data import when initializing a new scratch org, ensuring consistent test data across development environments.\n\nSee this article for a practical example:\n\n[![How to detect bad words in Salesforce records using SFDX Data Loader and sfdx-hardis](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/article-badwords.jpg)](https://nicolas.vuillamy.fr/how-to-detect-bad-words-in-salesforce-records-using-sfdx-data-loader-and-sfdx-hardis-171db40a9bac)\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SFDMU Integration:** It acts as a setup wizard for SFDMU, generating the necessary configuration files that the `sfdmu` plugin consumes.\n- **Interactive Prompts:** Uses the `prompts` library to gather user input for various configuration parameters, such as the data path, label, and description.\n- **File System Operations:** Employs `fs-extra` to create directories (e.g., `data/your-project-name/`) and write the `export.json` and any additional configuration files.\n- **JSON Manipulation:** Constructs the `export.json` content dynamically based on user input and selected templates, including defining objects, queries, and operations.\n- **PascalCase Conversion:** Uses `pascalcase` to format the SFDMU folder name consistently.\n- **Configuration Persistence:** Updates the project's `sfdx-hardis.yml` file (via `setConfig`) to include the newly configured data package if it's intended for scratch org initialization.\n- **WebSocket Communication:** Uses `WebSocketClient.requestOpenFile` to open the generated `export.json` file in VS Code, facilitating immediate configuration.\n- **Required Plugin Check:** Explicitly lists `sfdmu` as a required plugin, ensuring the necessary dependency is present.\n</details>\n",
4619
4748
  "examples": [
4620
- "$ sf hardis:git:pull-requests:extract",
4621
- "$ sf hardis:git:pull-requests:extract --target-branch main --status merged"
4749
+ "$ sf hardis:org:configure:data"
4622
4750
  ],
4623
4751
  "flags": {
4624
4752
  "json": {
@@ -4636,43 +4764,6 @@
4636
4764
  "multiple": false,
4637
4765
  "type": "option"
4638
4766
  },
4639
- "target-branch": {
4640
- "char": "t",
4641
- "description": "Target branch of PRs",
4642
- "name": "target-branch",
4643
- "hasDynamicHelp": false,
4644
- "multiple": false,
4645
- "type": "option"
4646
- },
4647
- "status": {
4648
- "char": "x",
4649
- "description": "Status of the PR",
4650
- "name": "status",
4651
- "hasDynamicHelp": false,
4652
- "multiple": false,
4653
- "options": [
4654
- "open",
4655
- "merged",
4656
- "abandoned"
4657
- ],
4658
- "type": "option"
4659
- },
4660
- "min-date": {
4661
- "char": "m",
4662
- "description": "Minimum date for PR",
4663
- "name": "min-date",
4664
- "hasDynamicHelp": false,
4665
- "multiple": false,
4666
- "type": "option"
4667
- },
4668
- "outputfile": {
4669
- "char": "f",
4670
- "description": "Force the path and name of output report file. Must end with .csv",
4671
- "name": "outputfile",
4672
- "hasDynamicHelp": false,
4673
- "multiple": false,
4674
- "type": "option"
4675
- },
4676
4767
  "debug": {
4677
4768
  "char": "d",
4678
4769
  "description": "Activate debug mode (more logs)",
@@ -4696,262 +4787,60 @@
4696
4787
  },
4697
4788
  "hasDynamicHelp": false,
4698
4789
  "hiddenAliases": [],
4699
- "id": "hardis:git:pull-requests:extract",
4790
+ "id": "hardis:org:configure:data",
4700
4791
  "pluginAlias": "sfdx-hardis",
4701
4792
  "pluginName": "sfdx-hardis",
4702
4793
  "pluginType": "core",
4703
4794
  "strict": true,
4704
4795
  "enableJsonFlag": true,
4705
- "title": "Extract pull requests",
4706
- "requiresProject": true,
4796
+ "title": "Configure Data project",
4797
+ "requiresProject": false,
4798
+ "requiresSfdxPlugins": [
4799
+ "sfdmu"
4800
+ ],
4707
4801
  "isESM": true,
4708
4802
  "relativePath": [
4709
4803
  "lib",
4710
4804
  "commands",
4711
4805
  "hardis",
4712
- "git",
4713
- "pull-requests",
4714
- "extract.js"
4806
+ "org",
4807
+ "configure",
4808
+ "data.js"
4715
4809
  ],
4716
4810
  "aliasPermutations": [],
4717
4811
  "permutations": [
4718
- "hardis:git:pull-requests:extract",
4719
- "git:hardis:pull-requests:extract",
4720
- "git:pull-requests:hardis:extract",
4721
- "git:pull-requests:extract:hardis",
4722
- "hardis:pull-requests:git:extract",
4723
- "pull-requests:hardis:git:extract",
4724
- "pull-requests:git:hardis:extract",
4725
- "pull-requests:git:extract:hardis",
4726
- "hardis:pull-requests:extract:git",
4727
- "pull-requests:hardis:extract:git",
4728
- "pull-requests:extract:hardis:git",
4729
- "pull-requests:extract:git:hardis",
4730
- "hardis:git:extract:pull-requests",
4731
- "git:hardis:extract:pull-requests",
4732
- "git:extract:hardis:pull-requests",
4733
- "git:extract:pull-requests:hardis",
4734
- "hardis:extract:git:pull-requests",
4735
- "extract:hardis:git:pull-requests",
4736
- "extract:git:hardis:pull-requests",
4737
- "extract:git:pull-requests:hardis",
4738
- "hardis:extract:pull-requests:git",
4739
- "extract:hardis:pull-requests:git",
4740
- "extract:pull-requests:hardis:git",
4741
- "extract:pull-requests:git:hardis"
4812
+ "hardis:org:configure:data",
4813
+ "org:hardis:configure:data",
4814
+ "org:configure:hardis:data",
4815
+ "org:configure:data:hardis",
4816
+ "hardis:configure:org:data",
4817
+ "configure:hardis:org:data",
4818
+ "configure:org:hardis:data",
4819
+ "configure:org:data:hardis",
4820
+ "hardis:configure:data:org",
4821
+ "configure:hardis:data:org",
4822
+ "configure:data:hardis:org",
4823
+ "configure:data:org:hardis",
4824
+ "hardis:org:data:configure",
4825
+ "org:hardis:data:configure",
4826
+ "org:data:hardis:configure",
4827
+ "org:data:configure:hardis",
4828
+ "hardis:data:org:configure",
4829
+ "data:hardis:org:configure",
4830
+ "data:org:hardis:configure",
4831
+ "data:org:configure:hardis",
4832
+ "hardis:data:configure:org",
4833
+ "data:hardis:configure:org",
4834
+ "data:configure:hardis:org",
4835
+ "data:configure:org:hardis"
4742
4836
  ]
4743
4837
  },
4744
- "hardis:org:community:update": {
4838
+ "hardis:org:configure:files": {
4745
4839
  "aliases": [],
4746
4840
  "args": {},
4747
- "description": "\n## Command Behavior\n\n**Updates the status of one or more Salesforce Experience Cloud (Community) networks.**\n\nThis command provides a way to programmatically change the status of your Salesforce Communities, allowing you to manage their availability. This is particularly useful for:\n\n- **Maintenance:** Taking communities offline for planned maintenance (`DownForMaintenance`).\n- **Activation/Deactivation:** Bringing communities online or offline (`Live`, `DownForMaintenance`).\n- **Automation:** Integrating community status changes into CI/CD pipelines or scheduled jobs.\n\nKey functionalities:\n\n- **Network Selection:** You can specify one or more community network names (separated by commas) using the `--name` flag.\n- **Status Update:** You can set the new status for the selected communities using the `--status` flag. Supported values are `Live` and `DownForMaintenance`.\n- **Confirmation Prompt:** In non-CI environments, it provides a confirmation prompt before executing the update, ensuring intentional changes.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce SOQL Query:** It first queries the Salesforce `Network` object using SOQL to retrieve the `Id`, `Name`, and `Status` of the specified communities. This ensures that only existing communities are targeted.\n- **SObject Update:** It then constructs an array of `Network` sObjects with their `Id` and the new `Status` and performs a DML update operation using `conn.sobject(\"Network\").update()`. The `allOrNone: false` option is used to allow partial success in case some updates fail.\n- **Error Handling and Reporting:** It iterates through the update results, logging success or failure for each community. It also provides a summary of successful and erroneous updates.\n- **User Interaction:** Uses `prompts` to confirm the update action with the user when not running in a CI environment.\n- **Salesforce Connection:** Establishes a connection to the target Salesforce org using the `target-org` flag.\n</details>\n",
4841
+ "description": "\n## Command Behavior\n\n**Configures a project for exporting file attachments from a Salesforce org.**\n\nThis command streamlines the setup of configurations for mass downloading files (such as Notes, Attachments, or Salesforce Files) associated with Salesforce records. It's particularly useful for data backups, migrations, or integrating Salesforce files with external systems.\n\nKey functionalities:\n\n- **Template-Based Configuration:** Allows you to choose from predefined templates for common file export scenarios or start with a blank configuration. Templates can pre-populate the export settings.\n- **Interactive Setup:** Guides you through defining the export project folder name and other export parameters.\n- **`export.json` Generation:** Creates an `export.json` file within the designated project folder. This file contains the configuration for the file export operation, including:\n - **SOQL Query:** A SOQL query to select the parent records from which files will be exported.\n - **File Types:** Specifies which types of files (e.g., `ContentVersion`, `Attachment`) to include.\n - **File Size Filtering:** Minimum file size in KB to filter files during export (files smaller than this will be skipped).\n - **Output Folder/File Naming:** Defines how the exported files and their containing folders will be named based on record fields.\n - **Overwrite Options:** Controls whether existing files or parent records should be overwritten during the export.\n\nSee this article for a practical example:\n\n[![How to mass download notes and attachments files from a Salesforce org](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/article-mass-download.jpg)](https://nicolas.vuillamy.fr/how-to-mass-download-notes-and-attachments-files-from-a-salesforce-org-83a028824afd)\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Template Selection:** It uses `selectTemplate` to present predefined file export templates or a blank option to the user.\n- **Interactive Prompts:** The `promptFilesExportConfiguration` utility is used to gather detailed export settings from the user, such as the SOQL query, file types, and naming conventions.\n- **File System Operations:** Employs `fs-extra` to create the project directory (`files/your-project-name/`) and write the `export.json` configuration file.\n- **PascalCase Conversion:** Uses `pascalcase` to format the files export path consistently.\n- **JSON Serialization:** Serializes the collected export configuration into a JSON string and writes it to `export.json`.\n- **WebSocket Communication:** Uses `WebSocketClient.requestOpenFile` to open the generated `export.json` file in VS Code, facilitating immediate configuration.\n</details>\n",
4748
4842
  "examples": [
4749
- "$ sf hardis:org:community:update --name 'MyNetworkName' --status DownForMaintenance",
4750
- "$ sf hardis:org:community:update --name 'MyNetworkName,MySecondNetworkName' --status Live"
4751
- ],
4752
- "flags": {
4753
- "json": {
4754
- "description": "Format output as json.",
4755
- "helpGroup": "GLOBAL",
4756
- "name": "json",
4757
- "allowNo": false,
4758
- "type": "boolean"
4759
- },
4760
- "flags-dir": {
4761
- "helpGroup": "GLOBAL",
4762
- "name": "flags-dir",
4763
- "summary": "Import flag values from a directory.",
4764
- "hasDynamicHelp": false,
4765
- "multiple": false,
4766
- "type": "option"
4767
- },
4768
- "name": {
4769
- "char": "n",
4770
- "description": "List of Networks Names that you want to update, separated by comma",
4771
- "name": "name",
4772
- "required": true,
4773
- "hasDynamicHelp": false,
4774
- "multiple": false,
4775
- "type": "option"
4776
- },
4777
- "status": {
4778
- "char": "s",
4779
- "description": "New status for the community, available values are: Live, DownForMaintenance",
4780
- "name": "status",
4781
- "required": true,
4782
- "hasDynamicHelp": false,
4783
- "multiple": false,
4784
- "type": "option"
4785
- },
4786
- "debug": {
4787
- "char": "d",
4788
- "description": "Activate debug mode (more logs)",
4789
- "name": "debug",
4790
- "allowNo": false,
4791
- "type": "boolean"
4792
- },
4793
- "target-org": {
4794
- "aliases": [
4795
- "targetusername",
4796
- "u"
4797
- ],
4798
- "char": "o",
4799
- "deprecateAliases": true,
4800
- "name": "target-org",
4801
- "noCacheDefault": true,
4802
- "required": true,
4803
- "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
4804
- "hasDynamicHelp": true,
4805
- "multiple": false,
4806
- "type": "option"
4807
- }
4808
- },
4809
- "hasDynamicHelp": true,
4810
- "hiddenAliases": [],
4811
- "id": "hardis:org:community:update",
4812
- "pluginAlias": "sfdx-hardis",
4813
- "pluginName": "sfdx-hardis",
4814
- "pluginType": "core",
4815
- "strict": true,
4816
- "summary": "Update a community status.",
4817
- "enableJsonFlag": true,
4818
- "isESM": true,
4819
- "relativePath": [
4820
- "lib",
4821
- "commands",
4822
- "hardis",
4823
- "org",
4824
- "community",
4825
- "update.js"
4826
- ],
4827
- "aliasPermutations": [],
4828
- "permutations": [
4829
- "hardis:org:community:update",
4830
- "org:hardis:community:update",
4831
- "org:community:hardis:update",
4832
- "org:community:update:hardis",
4833
- "hardis:community:org:update",
4834
- "community:hardis:org:update",
4835
- "community:org:hardis:update",
4836
- "community:org:update:hardis",
4837
- "hardis:community:update:org",
4838
- "community:hardis:update:org",
4839
- "community:update:hardis:org",
4840
- "community:update:org:hardis",
4841
- "hardis:org:update:community",
4842
- "org:hardis:update:community",
4843
- "org:update:hardis:community",
4844
- "org:update:community:hardis",
4845
- "hardis:update:org:community",
4846
- "update:hardis:org:community",
4847
- "update:org:hardis:community",
4848
- "update:org:community:hardis",
4849
- "hardis:update:community:org",
4850
- "update:hardis:community:org",
4851
- "update:community:hardis:org",
4852
- "update:community:org:hardis"
4853
- ]
4854
- },
4855
- "hardis:org:configure:data": {
4856
- "aliases": [],
4857
- "args": {},
4858
- "description": "\n## Command Behavior\n\n**Configures a Salesforce Data Migration Utility (SFDMU) project for data export and import operations.**\n\nThis command assists in setting up SFDMU workspaces, which are essential for managing data within your Salesforce environments. It streamlines the creation of `export.json` files and related configurations, enabling efficient data seeding, migration, and synchronization.\n\nKey functionalities:\n\n- **Template-Based Configuration:** Allows you to choose from predefined SFDMU templates or start with a blank configuration. Templates can pre-populate `export.json` with common data migration scenarios.\n- **Interactive Setup:** Guides you through the process of defining the SFDMU project folder name, label, and description.\n- **`export.json` Generation:** Creates the `export.json` file, which is the core configuration file for SFDMU, defining objects to export/import, queries, and operations.\n- **Additional File Generation:** Can generate additional configuration files, such as a `badwords.json` file for data filtering scenarios.\n- **Scratch Org Integration:** Offers to automatically configure the SFDMU project to be used for data import when initializing a new scratch org, ensuring consistent test data across development environments.\n\nSee this article for a practical example:\n\n[![How to detect bad words in Salesforce records using SFDX Data Loader and sfdx-hardis](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/article-badwords.jpg)](https://nicolas.vuillamy.fr/how-to-detect-bad-words-in-salesforce-records-using-sfdx-data-loader-and-sfdx-hardis-171db40a9bac)\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SFDMU Integration:** It acts as a setup wizard for SFDMU, generating the necessary configuration files that the `sfdmu` plugin consumes.\n- **Interactive Prompts:** Uses the `prompts` library to gather user input for various configuration parameters, such as the data path, label, and description.\n- **File System Operations:** Employs `fs-extra` to create directories (e.g., `data/your-project-name/`) and write the `export.json` and any additional configuration files.\n- **JSON Manipulation:** Constructs the `export.json` content dynamically based on user input and selected templates, including defining objects, queries, and operations.\n- **PascalCase Conversion:** Uses `pascalcase` to format the SFDMU folder name consistently.\n- **Configuration Persistence:** Updates the project's `sfdx-hardis.yml` file (via `setConfig`) to include the newly configured data package if it's intended for scratch org initialization.\n- **WebSocket Communication:** Uses `WebSocketClient.requestOpenFile` to open the generated `export.json` file in VS Code, facilitating immediate configuration.\n- **Required Plugin Check:** Explicitly lists `sfdmu` as a required plugin, ensuring the necessary dependency is present.\n</details>\n",
4859
- "examples": [
4860
- "$ sf hardis:org:configure:data"
4861
- ],
4862
- "flags": {
4863
- "json": {
4864
- "description": "Format output as json.",
4865
- "helpGroup": "GLOBAL",
4866
- "name": "json",
4867
- "allowNo": false,
4868
- "type": "boolean"
4869
- },
4870
- "flags-dir": {
4871
- "helpGroup": "GLOBAL",
4872
- "name": "flags-dir",
4873
- "summary": "Import flag values from a directory.",
4874
- "hasDynamicHelp": false,
4875
- "multiple": false,
4876
- "type": "option"
4877
- },
4878
- "debug": {
4879
- "char": "d",
4880
- "description": "Activate debug mode (more logs)",
4881
- "name": "debug",
4882
- "allowNo": false,
4883
- "type": "boolean"
4884
- },
4885
- "websocket": {
4886
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
4887
- "name": "websocket",
4888
- "hasDynamicHelp": false,
4889
- "multiple": false,
4890
- "type": "option"
4891
- },
4892
- "skipauth": {
4893
- "description": "Skip authentication check when a default username is required",
4894
- "name": "skipauth",
4895
- "allowNo": false,
4896
- "type": "boolean"
4897
- }
4898
- },
4899
- "hasDynamicHelp": false,
4900
- "hiddenAliases": [],
4901
- "id": "hardis:org:configure:data",
4902
- "pluginAlias": "sfdx-hardis",
4903
- "pluginName": "sfdx-hardis",
4904
- "pluginType": "core",
4905
- "strict": true,
4906
- "enableJsonFlag": true,
4907
- "title": "Configure Data project",
4908
- "requiresProject": false,
4909
- "requiresSfdxPlugins": [
4910
- "sfdmu"
4911
- ],
4912
- "isESM": true,
4913
- "relativePath": [
4914
- "lib",
4915
- "commands",
4916
- "hardis",
4917
- "org",
4918
- "configure",
4919
- "data.js"
4920
- ],
4921
- "aliasPermutations": [],
4922
- "permutations": [
4923
- "hardis:org:configure:data",
4924
- "org:hardis:configure:data",
4925
- "org:configure:hardis:data",
4926
- "org:configure:data:hardis",
4927
- "hardis:configure:org:data",
4928
- "configure:hardis:org:data",
4929
- "configure:org:hardis:data",
4930
- "configure:org:data:hardis",
4931
- "hardis:configure:data:org",
4932
- "configure:hardis:data:org",
4933
- "configure:data:hardis:org",
4934
- "configure:data:org:hardis",
4935
- "hardis:org:data:configure",
4936
- "org:hardis:data:configure",
4937
- "org:data:hardis:configure",
4938
- "org:data:configure:hardis",
4939
- "hardis:data:org:configure",
4940
- "data:hardis:org:configure",
4941
- "data:org:hardis:configure",
4942
- "data:org:configure:hardis",
4943
- "hardis:data:configure:org",
4944
- "data:hardis:configure:org",
4945
- "data:configure:hardis:org",
4946
- "data:configure:org:hardis"
4947
- ]
4948
- },
4949
- "hardis:org:configure:files": {
4950
- "aliases": [],
4951
- "args": {},
4952
- "description": "\n## Command Behavior\n\n**Configures a project for exporting file attachments from a Salesforce org.**\n\nThis command streamlines the setup of configurations for mass downloading files (such as Notes, Attachments, or Salesforce Files) associated with Salesforce records. It's particularly useful for data backups, migrations, or integrating Salesforce files with external systems.\n\nKey functionalities:\n\n- **Template-Based Configuration:** Allows you to choose from predefined templates for common file export scenarios or start with a blank configuration. Templates can pre-populate the export settings.\n- **Interactive Setup:** Guides you through defining the export project folder name and other export parameters.\n- **`export.json` Generation:** Creates an `export.json` file within the designated project folder. This file contains the configuration for the file export operation, including:\n - **SOQL Query:** A SOQL query to select the parent records from which files will be exported.\n - **File Types:** Specifies which types of files (e.g., `ContentVersion`, `Attachment`) to include.\n - **File Size Filtering:** Minimum file size in KB to filter files during export (files smaller than this will be skipped).\n - **Output Folder/File Naming:** Defines how the exported files and their containing folders will be named based on record fields.\n - **Overwrite Options:** Controls whether existing files or parent records should be overwritten during the export.\n\nSee this article for a practical example:\n\n[![How to mass download notes and attachments files from a Salesforce org](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/article-mass-download.jpg)](https://nicolas.vuillamy.fr/how-to-mass-download-notes-and-attachments-files-from-a-salesforce-org-83a028824afd)\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Template Selection:** It uses `selectTemplate` to present predefined file export templates or a blank option to the user.\n- **Interactive Prompts:** The `promptFilesExportConfiguration` utility is used to gather detailed export settings from the user, such as the SOQL query, file types, and naming conventions.\n- **File System Operations:** Employs `fs-extra` to create the project directory (`files/your-project-name/`) and write the `export.json` configuration file.\n- **PascalCase Conversion:** Uses `pascalcase` to format the files export path consistently.\n- **JSON Serialization:** Serializes the collected export configuration into a JSON string and writes it to `export.json`.\n- **WebSocket Communication:** Uses `WebSocketClient.requestOpenFile` to open the generated `export.json` file in VS Code, facilitating immediate configuration.\n</details>\n",
4953
- "examples": [
4954
- "$ sf hardis:org:configure:files"
4843
+ "$ sf hardis:org:configure:files"
4955
4844
  ],
4956
4845
  "flags": {
4957
4846
  "json": {
@@ -5153,12 +5042,13 @@
5153
5042
  "monitoring:configure:org:hardis"
5154
5043
  ]
5155
5044
  },
5156
- "hardis:org:data:delete": {
5045
+ "hardis:org:community:update": {
5157
5046
  "aliases": [],
5158
5047
  "args": {},
5159
- "description": "\n## Command Behavior\n\n**Deletes records in multiple Salesforce objects using an SFDMU (Salesforce Data Migration Utility) workspace.**\n\nThis command provides a powerful and controlled way to remove data from your Salesforce orgs based on configurations defined in an SFDMU workspace. It's particularly useful for:\n\n- **Data Cleanup:** Removing test data, obsolete records, or sensitive information.\n- **Environment Reset:** Preparing sandboxes for new development cycles by clearing specific data sets.\n- **Compliance:** Deleting data to meet regulatory requirements.\n\n**Important Considerations for Production Environments:**\n\nIf you intend to run this command in a production environment, you must:\n\n- Set `runnableInProduction` to `true` in your `export.json` file within the SFDMU workspace.\n- Define `sfdmuCanModify: YOUR_INSTANCE_URL` in your branch-specific configuration file (e.g., `config/branches/.sfdx-hardis.YOUR_BRANCH.yml`) to explicitly authorize data modification for that instance.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation relies heavily on the SFDMU plugin:\n\n- **SFDMU Integration:** It leverages the `sfdmu` plugin to perform the actual data deletion operations. The command acts as a wrapper, providing an assisted interface for SFDMU execution.\n- **Workspace Selection:** If the SFDMU workspace path is not provided via the `--path` flag, it interactively prompts the user to select a data workspace using `selectDataWorkspace`.\n- **Org Selection:** It ensures that a target Salesforce org is selected (either via the `--target-org` flag or through an interactive prompt using `promptOrgUsernameDefault`) to specify where the data deletion will occur.\n- **`deleteData` Utility:** The core logic for executing the SFDMU deletion process is encapsulated within the `deleteData` utility function, which takes the SFDMU workspace path and the target username as arguments.\n- **Environment Awareness:** It checks the `isCI` flag to determine whether to run in an interactive mode (prompting for user input) or a non-interactive mode (relying solely on command-line flags).\n- **Required Plugin:** It explicitly lists `sfdmu` as a required plugin, ensuring that the necessary dependency is in place before execution.\n</details>\n",
5048
+ "description": "\n## Command Behavior\n\n**Updates the status of one or more Salesforce Experience Cloud (Community) networks.**\n\nThis command provides a way to programmatically change the status of your Salesforce Communities, allowing you to manage their availability. This is particularly useful for:\n\n- **Maintenance:** Taking communities offline for planned maintenance (`DownForMaintenance`).\n- **Activation/Deactivation:** Bringing communities online or offline (`Live`, `DownForMaintenance`).\n- **Automation:** Integrating community status changes into CI/CD pipelines or scheduled jobs.\n\nKey functionalities:\n\n- **Network Selection:** You can specify one or more community network names (separated by commas) using the `--name` flag.\n- **Status Update:** You can set the new status for the selected communities using the `--status` flag. Supported values are `Live` and `DownForMaintenance`.\n- **Confirmation Prompt:** In non-CI environments, it provides a confirmation prompt before executing the update, ensuring intentional changes.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce SOQL Query:** It first queries the Salesforce `Network` object using SOQL to retrieve the `Id`, `Name`, and `Status` of the specified communities. This ensures that only existing communities are targeted.\n- **SObject Update:** It then constructs an array of `Network` sObjects with their `Id` and the new `Status` and performs a DML update operation using `conn.sobject(\"Network\").update()`. The `allOrNone: false` option is used to allow partial success in case some updates fail.\n- **Error Handling and Reporting:** It iterates through the update results, logging success or failure for each community. It also provides a summary of successful and erroneous updates.\n- **User Interaction:** Uses `prompts` to confirm the update action with the user when not running in a CI environment.\n- **Salesforce Connection:** Establishes a connection to the target Salesforce org using the `target-org` flag.\n</details>\n",
5160
5049
  "examples": [
5161
- "$ sf hardis:org:data:delete"
5050
+ "$ sf hardis:org:community:update --name 'MyNetworkName' --status DownForMaintenance",
5051
+ "$ sf hardis:org:community:update --name 'MyNetworkName,MySecondNetworkName' --status Live"
5162
5052
  ],
5163
5053
  "flags": {
5164
5054
  "json": {
@@ -5176,31 +5066,28 @@
5176
5066
  "multiple": false,
5177
5067
  "type": "option"
5178
5068
  },
5179
- "path": {
5180
- "char": "p",
5181
- "description": "Path to the sfdmu workspace folder",
5182
- "name": "path",
5069
+ "name": {
5070
+ "char": "n",
5071
+ "description": "List of Networks Names that you want to update, separated by comma",
5072
+ "name": "name",
5073
+ "required": true,
5183
5074
  "hasDynamicHelp": false,
5184
5075
  "multiple": false,
5185
5076
  "type": "option"
5186
5077
  },
5187
- "debug": {
5188
- "char": "d",
5189
- "description": "Activate debug mode (more logs)",
5190
- "name": "debug",
5191
- "allowNo": false,
5192
- "type": "boolean"
5193
- },
5194
- "websocket": {
5195
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
5196
- "name": "websocket",
5078
+ "status": {
5079
+ "char": "s",
5080
+ "description": "New status for the community, available values are: Live, DownForMaintenance",
5081
+ "name": "status",
5082
+ "required": true,
5197
5083
  "hasDynamicHelp": false,
5198
5084
  "multiple": false,
5199
5085
  "type": "option"
5200
5086
  },
5201
- "skipauth": {
5202
- "description": "Skip authentication check when a default username is required",
5203
- "name": "skipauth",
5087
+ "debug": {
5088
+ "char": "d",
5089
+ "description": "Activate debug mode (more logs)",
5090
+ "name": "debug",
5204
5091
  "allowNo": false,
5205
5092
  "type": "boolean"
5206
5093
  },
@@ -5222,43 +5109,156 @@
5222
5109
  },
5223
5110
  "hasDynamicHelp": true,
5224
5111
  "hiddenAliases": [],
5225
- "id": "hardis:org:data:delete",
5112
+ "id": "hardis:org:community:update",
5226
5113
  "pluginAlias": "sfdx-hardis",
5227
5114
  "pluginName": "sfdx-hardis",
5228
5115
  "pluginType": "core",
5229
5116
  "strict": true,
5117
+ "summary": "Update a community status.",
5230
5118
  "enableJsonFlag": true,
5231
- "title": "Delete data",
5232
- "requiresProject": false,
5233
- "requiresSfdxPlugins": [
5234
- "sfdmu"
5235
- ],
5236
5119
  "isESM": true,
5237
5120
  "relativePath": [
5238
5121
  "lib",
5239
5122
  "commands",
5240
5123
  "hardis",
5241
5124
  "org",
5242
- "data",
5243
- "delete.js"
5125
+ "community",
5126
+ "update.js"
5244
5127
  ],
5245
5128
  "aliasPermutations": [],
5246
5129
  "permutations": [
5247
- "hardis:org:data:delete",
5248
- "org:hardis:data:delete",
5249
- "org:data:hardis:delete",
5250
- "org:data:delete:hardis",
5251
- "hardis:data:org:delete",
5252
- "data:hardis:org:delete",
5253
- "data:org:hardis:delete",
5254
- "data:org:delete:hardis",
5255
- "hardis:data:delete:org",
5256
- "data:hardis:delete:org",
5257
- "data:delete:hardis:org",
5258
- "data:delete:org:hardis",
5259
- "hardis:org:delete:data",
5260
- "org:hardis:delete:data",
5261
- "org:delete:hardis:data",
5130
+ "hardis:org:community:update",
5131
+ "org:hardis:community:update",
5132
+ "org:community:hardis:update",
5133
+ "org:community:update:hardis",
5134
+ "hardis:community:org:update",
5135
+ "community:hardis:org:update",
5136
+ "community:org:hardis:update",
5137
+ "community:org:update:hardis",
5138
+ "hardis:community:update:org",
5139
+ "community:hardis:update:org",
5140
+ "community:update:hardis:org",
5141
+ "community:update:org:hardis",
5142
+ "hardis:org:update:community",
5143
+ "org:hardis:update:community",
5144
+ "org:update:hardis:community",
5145
+ "org:update:community:hardis",
5146
+ "hardis:update:org:community",
5147
+ "update:hardis:org:community",
5148
+ "update:org:hardis:community",
5149
+ "update:org:community:hardis",
5150
+ "hardis:update:community:org",
5151
+ "update:hardis:community:org",
5152
+ "update:community:hardis:org",
5153
+ "update:community:org:hardis"
5154
+ ]
5155
+ },
5156
+ "hardis:org:data:delete": {
5157
+ "aliases": [],
5158
+ "args": {},
5159
+ "description": "\n## Command Behavior\n\n**Deletes records in multiple Salesforce objects using an SFDMU (Salesforce Data Migration Utility) workspace.**\n\nThis command provides a powerful and controlled way to remove data from your Salesforce orgs based on configurations defined in an SFDMU workspace. It's particularly useful for:\n\n- **Data Cleanup:** Removing test data, obsolete records, or sensitive information.\n- **Environment Reset:** Preparing sandboxes for new development cycles by clearing specific data sets.\n- **Compliance:** Deleting data to meet regulatory requirements.\n\n**Important Considerations for Production Environments:**\n\nIf you intend to run this command in a production environment, you must:\n\n- Set `runnableInProduction` to `true` in your `export.json` file within the SFDMU workspace.\n- Define `sfdmuCanModify: YOUR_INSTANCE_URL` in your branch-specific configuration file (e.g., `config/branches/.sfdx-hardis.YOUR_BRANCH.yml`) to explicitly authorize data modification for that instance.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation relies heavily on the SFDMU plugin:\n\n- **SFDMU Integration:** It leverages the `sfdmu` plugin to perform the actual data deletion operations. The command acts as a wrapper, providing an assisted interface for SFDMU execution.\n- **Workspace Selection:** If the SFDMU workspace path is not provided via the `--path` flag, it interactively prompts the user to select a data workspace using `selectDataWorkspace`.\n- **Org Selection:** It ensures that a target Salesforce org is selected (either via the `--target-org` flag or through an interactive prompt using `promptOrgUsernameDefault`) to specify where the data deletion will occur.\n- **`deleteData` Utility:** The core logic for executing the SFDMU deletion process is encapsulated within the `deleteData` utility function, which takes the SFDMU workspace path and the target username as arguments.\n- **Environment Awareness:** It checks the `isCI` flag to determine whether to run in an interactive mode (prompting for user input) or a non-interactive mode (relying solely on command-line flags).\n- **Required Plugin:** It explicitly lists `sfdmu` as a required plugin, ensuring that the necessary dependency is in place before execution.\n</details>\n",
5160
+ "examples": [
5161
+ "$ sf hardis:org:data:delete"
5162
+ ],
5163
+ "flags": {
5164
+ "json": {
5165
+ "description": "Format output as json.",
5166
+ "helpGroup": "GLOBAL",
5167
+ "name": "json",
5168
+ "allowNo": false,
5169
+ "type": "boolean"
5170
+ },
5171
+ "flags-dir": {
5172
+ "helpGroup": "GLOBAL",
5173
+ "name": "flags-dir",
5174
+ "summary": "Import flag values from a directory.",
5175
+ "hasDynamicHelp": false,
5176
+ "multiple": false,
5177
+ "type": "option"
5178
+ },
5179
+ "path": {
5180
+ "char": "p",
5181
+ "description": "Path to the sfdmu workspace folder",
5182
+ "name": "path",
5183
+ "hasDynamicHelp": false,
5184
+ "multiple": false,
5185
+ "type": "option"
5186
+ },
5187
+ "debug": {
5188
+ "char": "d",
5189
+ "description": "Activate debug mode (more logs)",
5190
+ "name": "debug",
5191
+ "allowNo": false,
5192
+ "type": "boolean"
5193
+ },
5194
+ "websocket": {
5195
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
5196
+ "name": "websocket",
5197
+ "hasDynamicHelp": false,
5198
+ "multiple": false,
5199
+ "type": "option"
5200
+ },
5201
+ "skipauth": {
5202
+ "description": "Skip authentication check when a default username is required",
5203
+ "name": "skipauth",
5204
+ "allowNo": false,
5205
+ "type": "boolean"
5206
+ },
5207
+ "target-org": {
5208
+ "aliases": [
5209
+ "targetusername",
5210
+ "u"
5211
+ ],
5212
+ "char": "o",
5213
+ "deprecateAliases": true,
5214
+ "name": "target-org",
5215
+ "noCacheDefault": true,
5216
+ "required": true,
5217
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
5218
+ "hasDynamicHelp": true,
5219
+ "multiple": false,
5220
+ "type": "option"
5221
+ }
5222
+ },
5223
+ "hasDynamicHelp": true,
5224
+ "hiddenAliases": [],
5225
+ "id": "hardis:org:data:delete",
5226
+ "pluginAlias": "sfdx-hardis",
5227
+ "pluginName": "sfdx-hardis",
5228
+ "pluginType": "core",
5229
+ "strict": true,
5230
+ "enableJsonFlag": true,
5231
+ "title": "Delete data",
5232
+ "requiresProject": false,
5233
+ "requiresSfdxPlugins": [
5234
+ "sfdmu"
5235
+ ],
5236
+ "isESM": true,
5237
+ "relativePath": [
5238
+ "lib",
5239
+ "commands",
5240
+ "hardis",
5241
+ "org",
5242
+ "data",
5243
+ "delete.js"
5244
+ ],
5245
+ "aliasPermutations": [],
5246
+ "permutations": [
5247
+ "hardis:org:data:delete",
5248
+ "org:hardis:data:delete",
5249
+ "org:data:hardis:delete",
5250
+ "org:data:delete:hardis",
5251
+ "hardis:data:org:delete",
5252
+ "data:hardis:org:delete",
5253
+ "data:org:hardis:delete",
5254
+ "data:org:delete:hardis",
5255
+ "hardis:data:delete:org",
5256
+ "data:hardis:delete:org",
5257
+ "data:delete:hardis:org",
5258
+ "data:delete:org:hardis",
5259
+ "hardis:org:delete:data",
5260
+ "org:hardis:delete:data",
5261
+ "org:delete:hardis:data",
5262
5262
  "org:delete:data:hardis",
5263
5263
  "hardis:delete:org:data",
5264
5264
  "delete:hardis:org:data",
@@ -5923,15 +5923,14 @@
5923
5923
  "listviewmine:fix:org:hardis"
5924
5924
  ]
5925
5925
  },
5926
- "hardis:org:diagnose:audittrail": {
5926
+ "hardis:org:generate:packagexmlfull": {
5927
5927
  "aliases": [],
5928
5928
  "args": {},
5929
- "description": "Export Audit trail into a CSV file with selected criteria, and highlight suspect actions\n\nAlso detects updates of Custom Settings values (disable by defining `SKIP_AUDIT_TRAIL_CUSTOM_SETTINGS=true`)\n\nRegular setup actions performed in major orgs are filtered.\n\n- \"\"\n - createScratchOrg\n - changedsenderemail\n - deleteScratchOrg\n - loginasgrantedtopartnerbt\n- Certificate and Key Management\n - insertCertificate\n- Custom App Licenses\n - addeduserpackagelicense\n - granteduserpackagelicense\n - revokeduserpackagelicense\n- Customer Portal\n - createdcustomersuccessuser\n - CSPUserDisabled\n- Currency\n - updateddatedexchrate\n- Data Management\n - queueMembership\n- Email Administration\n - dkimRotationPreparationSuccessful\n - dkimRotationSuccessful\n- External Objects\n - xdsEncryptedFieldChange\n- Groups\n - groupMembership\n- Holidays\n - holiday_insert\n- Inbox mobile and legacy desktop apps\n - enableSIQUserNonEAC\n - siqUserAcceptedTOS\n- Manage Users\n - activateduser\n - createduser\n - changedcommunitynickname\n - changedemail\n - changedfederationid\n - changedpassword\n - changedinteractionuseroffon\n - changedinteractionuseronoff\n - changedmarketinguseroffon\n - changedmarketinguseronoff\n - changedofflineuseroffon\n - changedprofileforuserstdtostd\n - changedprofileforuser\n - changedprofileforusercusttostd\n - changedprofileforuserstdtocust\n - changedroleforusertonone\n - changedroleforuser\n - changedroleforuserfromnone\n - changedUserAdminVerifiedStatusVerified\n - changedUserEmailVerifiedStatusUnverified\n - changedUserEmailVerifiedStatusVerified\n - changedknowledgeuseroffon\n - changedsfcontentuseroffon\n - changedsupportuseroffon\n - changedusername\n - changedUserPhoneNumber\n - changedUserPhoneVerifiedStatusUnverified\n - changedUserPhoneVerifiedStatusVerified\n - deactivateduser\n - deleteAuthenticatorPairing\n - deleteTwoFactorInfo2\n - deleteTwoFactorTempCode\n - frozeuser\n - insertAuthenticatorPairing\n - insertTwoFactorInfo2\n - insertTwoFactorTempCode\n - lightningloginenroll\n - PermSetAssign\n - PermSetGroupAssign\n - PermSetGroupUnassign\n - PermSetLicenseAssign\n - PermSetUnassign\n - PermSetLicenseUnassign\n - registeredUserPhoneNumber\n - resetpassword\n - suNetworkAdminLogin\n - suNetworkAdminLogout\n - suOrgAdminLogin\n - suOrgAdminLogout\n - unfrozeuser\n - useremailchangesent\n- Mobile Administration\n - assigneduserstomobileconfig\n- Reporting Snapshots\n - createdReportJob\n - deletedReportJob\n- Sandboxes\n - DeleteSandbox\n\nBy default, deployment user defined in .sfdx-hardis.yml targetUsername property will be excluded.\n\nYou can define additional users to exclude in .sfdx-hardis.yml **monitoringExcludeUsernames** property.\n\nYou can also add more sections / actions considered as not suspect using property **monitoringAllowedSectionsActions**\n\nExample:\n\n```yaml\nmonitoringExcludeUsernames:\n - deploymentuser@cloudity.com\n - marketingcloud@cloudity.com\n - integration-user@cloudity.com\n\nmonitoringAllowedSectionsActions:\n \"Some section\": [] // Will ignore all actions from such section\n \"Some other section\": [\"actionType1\",\"actionType2\",\"actionType3\"] // Will ignore only those 3 actions from section \"Some other section\". Other actions in the same section will be considered as suspect.\n```\n\n## Excel output example\n\n![](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/screenshot-monitoring-audittrail-excel.jpg)\n\n## Local output example\n\n![](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/screenshot-monitoring-audittrail-local.jpg)\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-suspect-audit-trail/) and can output Grafana, Slack and MsTeams Notifications.\n",
5929
+ "description": "\n## Command Behavior\n\n**Generates a comprehensive `package.xml` file for a Salesforce org, including all metadata components, even managed ones.**\n\nThis command is essential for various Salesforce development and administration tasks, especially when you need a complete snapshot of an org's metadata. It goes beyond typical source tracking by including managed package components, which is crucial for understanding the full metadata footprint of an org.\n\nKey functionalities:\n\n- **Full Org Metadata Retrieval:** Connects to a specified Salesforce org (or prompts for one if not provided) and retrieves a complete list of all metadata types and their members.\n- **Managed Package Inclusion:** Unlike standard source retrieval, this command explicitly includes metadata from managed packages, providing a truly comprehensive `package.xml`.\n- **Customizable Output:** Allows you to specify the output file path for the generated `package.xml`.\n- **Interactive Org Selection:** If no target org is specified, it interactively prompts the user to choose an org. (or use --no-prompt to skip this step)\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce Metadata API Interaction:** It leverages the Salesforce Metadata API to list all available metadata types and then retrieve all components for each type.\n- **`buildOrgManifest` Utility:** The core logic for querying the org's metadata and constructing the `package.xml` is encapsulated within the `buildOrgManifest` utility function.\n- **XML Generation:** It dynamically builds the XML structure of the `package.xml` file, including the `types` and `members` elements for all retrieved metadata.\n- **File System Operations:** It writes the generated `package.xml` file to the specified output path.\n- **Interactive Prompts:** Uses `promptOrgUsernameDefault` to guide the user in selecting the target Salesforce org.\n</details>\n",
5930
5930
  "examples": [
5931
- "$ sf hardis:org:diagnose:audittrail",
5932
- "$ sf hardis:org:diagnose:audittrail --excludeusers baptiste@titi.com",
5933
- "$ sf hardis:org:diagnose:audittrail --excludeusers baptiste@titi.com,bertrand@titi.com",
5934
- "$ sf hardis:org:diagnose:audittrail --lastndays 5"
5931
+ "$ sf hardis:org:generate:packagexmlfull",
5932
+ "$ sf hardis:org:generate:packagexmlfull --outputfile /tmp/packagexmlfull.xml",
5933
+ "$ sf hardis:org:generate:packagexmlfull --target-org nico@example.com"
5935
5934
  ],
5936
5935
  "flags": {
5937
5936
  "json": {
@@ -5949,25 +5948,8 @@
5949
5948
  "multiple": false,
5950
5949
  "type": "option"
5951
5950
  },
5952
- "excludeusers": {
5953
- "char": "e",
5954
- "description": "Comma-separated list of usernames to exclude",
5955
- "name": "excludeusers",
5956
- "hasDynamicHelp": false,
5957
- "multiple": false,
5958
- "type": "option"
5959
- },
5960
- "lastndays": {
5961
- "char": "t",
5962
- "description": "Number of days to extract from today (included)",
5963
- "name": "lastndays",
5964
- "hasDynamicHelp": false,
5965
- "multiple": false,
5966
- "type": "option"
5967
- },
5968
5951
  "outputfile": {
5969
- "char": "f",
5970
- "description": "Force the path and name of output report file. Must end with .csv",
5952
+ "description": "Output package.xml file",
5971
5953
  "name": "outputfile",
5972
5954
  "hasDynamicHelp": false,
5973
5955
  "multiple": false,
@@ -5980,6 +5962,13 @@
5980
5962
  "allowNo": false,
5981
5963
  "type": "boolean"
5982
5964
  },
5965
+ "no-prompt": {
5966
+ "char": "n",
5967
+ "description": "Do not prompt for org username, use the default one",
5968
+ "name": "no-prompt",
5969
+ "allowNo": false,
5970
+ "type": "boolean"
5971
+ },
5983
5972
  "websocket": {
5984
5973
  "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
5985
5974
  "name": "websocket",
@@ -6011,13 +6000,13 @@
6011
6000
  },
6012
6001
  "hasDynamicHelp": true,
6013
6002
  "hiddenAliases": [],
6014
- "id": "hardis:org:diagnose:audittrail",
6003
+ "id": "hardis:org:generate:packagexmlfull",
6015
6004
  "pluginAlias": "sfdx-hardis",
6016
6005
  "pluginName": "sfdx-hardis",
6017
6006
  "pluginType": "core",
6018
6007
  "strict": true,
6019
6008
  "enableJsonFlag": true,
6020
- "title": "Diagnose content of Setup Audit Trail",
6009
+ "title": "Generate Full Org package.xml",
6021
6010
  "requiresProject": false,
6022
6011
  "isESM": true,
6023
6012
  "relativePath": [
@@ -6025,43 +6014,43 @@
6025
6014
  "commands",
6026
6015
  "hardis",
6027
6016
  "org",
6028
- "diagnose",
6029
- "audittrail.js"
6017
+ "generate",
6018
+ "packagexmlfull.js"
6030
6019
  ],
6031
6020
  "aliasPermutations": [],
6032
6021
  "permutations": [
6033
- "hardis:org:diagnose:audittrail",
6034
- "org:hardis:diagnose:audittrail",
6035
- "org:diagnose:hardis:audittrail",
6036
- "org:diagnose:audittrail:hardis",
6037
- "hardis:diagnose:org:audittrail",
6038
- "diagnose:hardis:org:audittrail",
6039
- "diagnose:org:hardis:audittrail",
6040
- "diagnose:org:audittrail:hardis",
6041
- "hardis:diagnose:audittrail:org",
6042
- "diagnose:hardis:audittrail:org",
6043
- "diagnose:audittrail:hardis:org",
6044
- "diagnose:audittrail:org:hardis",
6045
- "hardis:org:audittrail:diagnose",
6046
- "org:hardis:audittrail:diagnose",
6047
- "org:audittrail:hardis:diagnose",
6048
- "org:audittrail:diagnose:hardis",
6049
- "hardis:audittrail:org:diagnose",
6050
- "audittrail:hardis:org:diagnose",
6051
- "audittrail:org:hardis:diagnose",
6052
- "audittrail:org:diagnose:hardis",
6053
- "hardis:audittrail:diagnose:org",
6054
- "audittrail:hardis:diagnose:org",
6055
- "audittrail:diagnose:hardis:org",
6056
- "audittrail:diagnose:org:hardis"
6022
+ "hardis:org:generate:packagexmlfull",
6023
+ "org:hardis:generate:packagexmlfull",
6024
+ "org:generate:hardis:packagexmlfull",
6025
+ "org:generate:packagexmlfull:hardis",
6026
+ "hardis:generate:org:packagexmlfull",
6027
+ "generate:hardis:org:packagexmlfull",
6028
+ "generate:org:hardis:packagexmlfull",
6029
+ "generate:org:packagexmlfull:hardis",
6030
+ "hardis:generate:packagexmlfull:org",
6031
+ "generate:hardis:packagexmlfull:org",
6032
+ "generate:packagexmlfull:hardis:org",
6033
+ "generate:packagexmlfull:org:hardis",
6034
+ "hardis:org:packagexmlfull:generate",
6035
+ "org:hardis:packagexmlfull:generate",
6036
+ "org:packagexmlfull:hardis:generate",
6037
+ "org:packagexmlfull:generate:hardis",
6038
+ "hardis:packagexmlfull:org:generate",
6039
+ "packagexmlfull:hardis:org:generate",
6040
+ "packagexmlfull:org:hardis:generate",
6041
+ "packagexmlfull:org:generate:hardis",
6042
+ "hardis:packagexmlfull:generate:org",
6043
+ "packagexmlfull:hardis:generate:org",
6044
+ "packagexmlfull:generate:hardis:org",
6045
+ "packagexmlfull:generate:org:hardis"
6057
6046
  ]
6058
6047
  },
6059
- "hardis:org:diagnose:instanceupgrade": {
6048
+ "hardis:org:monitor:all": {
6060
6049
  "aliases": [],
6061
6050
  "args": {},
6062
- "description": "\n## Command Behavior\n\n**Retrieves and displays the scheduled upgrade date for a Salesforce org's instance.**\n\nThis command provides crucial information about when your Salesforce instance will be upgraded to the next major release (Spring, Summer, or Winter). This is vital for release planning, testing, and ensuring compatibility with upcoming Salesforce features.\n\nKey functionalities:\n\n- **Instance Identification:** Determines the Salesforce instance name of your target org.\n- **Upgrade Date Retrieval:** Fetches the planned start time of the next major core service upgrade for that instance from the Salesforce Status API.\n- **Days Until Upgrade:** Calculates and displays the number of days remaining until the next major upgrade.\n- **Severity-Based Logging:** Adjusts the log severity (info, warning) based on the proximity of the upgrade date, providing a visual cue for urgency.\n- **Notifications:** Sends notifications to configured channels (e.g., Slack, MS Teams, Grafana) with the upgrade information, making it suitable for automated monitoring.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce SOQL Query:** It first queries the `Organization` object in Salesforce to get the `InstanceName` of the target org.\n- **Salesforce Status API Integration:** It makes an HTTP GET request to the Salesforce Status API (`https://api.status.salesforce.com/v1/instances/{instanceName}/status`) to retrieve detailed information about the instance, including scheduled maintenances.\n- **Data Parsing:** It parses the JSON response from the Status API to extract the relevant major release upgrade information.\n- **Date Calculation:** Uses the `moment` library to calculate the difference in days between the current date and the planned upgrade date.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including the instance name, upgrade date, and days remaining, along with relevant metrics for monitoring dashboards.\n- **User Feedback:** Provides clear messages to the user about the upgrade status and proximity.\n</details>\n",
6051
+ "description": "Monitor org, generate reports and sends notifications\n\nYou can disable some commands defining either a **monitoringDisable** property in `.sfdx-hardis.yml`, or a comma separated list in env variable **MONITORING_DISABLE**\n\nExample in .sfdx-hardis.yml:\n \n```yaml\nmonitoringDisable:\n - METADATA_STATUS\n - MISSING_ATTRIBUTES\n - UNUSED_METADATAS\n```\n \nExample in env var:\n\n```sh\nMONITORING_DISABLE=METADATA_STATUS,MISSING_ATTRIBUTES,UNUSED_METADATAS\n```\n\nA [default list of monitoring commands](https://sfdx-hardis.cloudity.com/salesforce-monitoring-home/#monitoring-commands) is used, if you want to override it you can define property **monitoringCommands** in your .sfdx-hardis.yml file\n\nExample:\n\n```yaml\nmonitoringCommands:\n - title: My Custom command\n command: sf my:custom:command\n - title: My Custom command 2\n command: sf my:other:custom:command\n```\n\nYou can force the daily run of all commands by defining env var `MONITORING_IGNORE_FREQUENCY=true`\n\nThe default list of commands is the following:\n\n| Key | Description | Command | Frequency |\n| :---: | :---- | :---- | :-----: |\n| [AUDIT_TRAIL](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/audittrail) | Detect suspect setup actions in major org | [sf hardis:org:diagnose:audittrail](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/audittrail) | daily |\n| [LEGACY_API](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/legacyapi) | Detect calls to deprecated API versions | [sf hardis:org:diagnose:legacyapi](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/legacyapi) | daily |\n| [ORG_LIMITS](https://sfdx-hardis.cloudity.com/hardis/org/monitor/limits) | Detect if org limits are close to be reached | [sf hardis:org:monitor:limits](https://sfdx-hardis.cloudity.com/hardis/org/monitor/limits) | daily |\n| [UNSECURED_CONNECTED_APPS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unsecure-connected-apps) | Detect unsecured Connected Apps in an org | [sf hardis:org:diagnose:unsecure-connected-apps](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unsecure-connected-apps) | daily |\n| [LICENSES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/licenses) | Extract licenses information | [sf hardis:org:diagnose:licenses](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/licenses) | weekly |\n| [LINT_ACCESS](https://sfdx-hardis.cloudity.com/hardis/lint/access) | Detect custom elements with no access rights defined in permission sets | [sf hardis:lint:access](https://sfdx-hardis.cloudity.com/hardis/lint/access) | weekly |\n| [UNUSED_LICENSES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedlicenses) | Detect permission set licenses that are assigned to users that do not need them | [sf hardis:org:diagnose:unusedlicenses](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedlicenses) | weekly |\n| [UNUSED_USERS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | Detect active users without recent logins | [sf hardis:org:diagnose:unusedusers](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | weekly |\n| [ACTIVE_USERS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | Detect active users with recent logins | [sf hardis:org:diagnose:unusedusers --returnactiveusers](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | weekly |\n| [ORG_INFO](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/instanceupgrade) | Get org info + SF instance info + next major upgrade date | [sf hardis:org:diagnose:instanceupgrade](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/instanceupgrade) | weekly |\n| [RELEASE_UPDATES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/releaseupdates) | Gather warnings about incoming and overdue Release Updates | [sf hardis:org:diagnose:releaseupdates](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/releaseupdates) | weekly |\n| [UNUSED_METADATAS](https://sfdx-hardis.cloudity.com/hardis/lint/unusedmetadatas) | Detect custom labels and custom permissions that are not in use | [sf hardis:lint:unusedmetadatas](https://sfdx-hardis.cloudity.com/hardis/lint/unusedmetadatas) | weekly |\n| [UNUSED_APEX_CLASSES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-apex-classes) | Detect unused Apex classes in an org | [sf hardis:org:diagnose:unused-apex-classes](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-apex-classes) | weekly |\n| [CONNECTED_APPS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-connected-apps) | Detect unused Connected Apps in an org | [sf hardis:org:diagnose:unused-connected-apps](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-connected-apps) | weekly |\n| [METADATA_STATUS](https://sfdx-hardis.cloudity.com/hardis/lint/metadatastatus) | Detect inactive metadata | [sf hardis:lint:metadatastatus](https://sfdx-hardis.cloudity.com/hardis/lint/metadatastatus) | weekly |\n| [MISSING_ATTRIBUTES](https://sfdx-hardis.cloudity.com/hardis/lint/missingattributes) | Detect missing description on custom field | [sf hardis:lint:missingattributes](https://sfdx-hardis.cloudity.com/hardis/lint/missingattributes) | weekly |\n\n",
6063
6052
  "examples": [
6064
- "$ sf hardis:org:diagnose:instanceupgrade"
6053
+ "$ sf hardis:org:monitor:all"
6065
6054
  ],
6066
6055
  "flags": {
6067
6056
  "json": {
@@ -6117,35 +6106,649 @@
6117
6106
  },
6118
6107
  "hasDynamicHelp": true,
6119
6108
  "hiddenAliases": [],
6120
- "id": "hardis:org:diagnose:instanceupgrade",
6109
+ "id": "hardis:org:monitor:all",
6121
6110
  "pluginAlias": "sfdx-hardis",
6122
6111
  "pluginName": "sfdx-hardis",
6123
6112
  "pluginType": "core",
6124
6113
  "strict": true,
6125
6114
  "enableJsonFlag": true,
6126
- "title": "Get Instance Upgrade date",
6127
- "requiresProject": false,
6128
- "isESM": true,
6129
- "relativePath": [
6130
- "lib",
6131
- "commands",
6132
- "hardis",
6133
- "org",
6134
- "diagnose",
6135
- "instanceupgrade.js"
6136
- ],
6137
- "aliasPermutations": [],
6138
- "permutations": [
6139
- "hardis:org:diagnose:instanceupgrade",
6140
- "org:hardis:diagnose:instanceupgrade",
6141
- "org:diagnose:hardis:instanceupgrade",
6142
- "org:diagnose:instanceupgrade:hardis",
6143
- "hardis:diagnose:org:instanceupgrade",
6144
- "diagnose:hardis:org:instanceupgrade",
6145
- "diagnose:org:hardis:instanceupgrade",
6146
- "diagnose:org:instanceupgrade:hardis",
6147
- "hardis:diagnose:instanceupgrade:org",
6148
- "diagnose:hardis:instanceupgrade:org",
6115
+ "title": "Monitor org",
6116
+ "monitoringCommandsDefault": [
6117
+ {
6118
+ "key": "AUDIT_TRAIL",
6119
+ "title": "Detect suspect setup actions in major org",
6120
+ "command": "sf hardis:org:diagnose:audittrail",
6121
+ "frequency": "daily"
6122
+ },
6123
+ {
6124
+ "key": "LEGACY_API",
6125
+ "title": "Detect calls to deprecated API versions",
6126
+ "command": "sf hardis:org:diagnose:legacyapi",
6127
+ "frequency": "daily"
6128
+ },
6129
+ {
6130
+ "key": "ORG_LIMITS",
6131
+ "title": "Detect if org limits are close to be reached",
6132
+ "command": "sf hardis:org:monitor:limits",
6133
+ "frequency": "daily"
6134
+ },
6135
+ {
6136
+ "key": "UNSECURED_CONNECTED_APPS",
6137
+ "title": "Detect unsecured Connected Apps in an org",
6138
+ "command": "sf hardis:org:diagnose:unsecure-connected-apps",
6139
+ "frequency": "daily"
6140
+ },
6141
+ {
6142
+ "key": "LICENSES",
6143
+ "title": "Extract licenses information",
6144
+ "command": "sf hardis:org:diagnose:licenses",
6145
+ "frequency": "weekly"
6146
+ },
6147
+ {
6148
+ "key": "LINT_ACCESS",
6149
+ "title": "Detect custom elements with no access rights defined in permission sets",
6150
+ "command": "sf hardis:lint:access",
6151
+ "frequency": "weekly"
6152
+ },
6153
+ {
6154
+ "key": "UNUSED_LICENSES",
6155
+ "title": "Detect permission set licenses that are assigned to users that do not need them",
6156
+ "command": "sf hardis:org:diagnose:unusedlicenses",
6157
+ "frequency": "weekly"
6158
+ },
6159
+ {
6160
+ "key": "UNUSED_USERS",
6161
+ "title": "Detect active users without recent logins",
6162
+ "command": "sf hardis:org:diagnose:unusedusers",
6163
+ "frequency": "weekly"
6164
+ },
6165
+ {
6166
+ "key": "ACTIVE_USERS",
6167
+ "title": "Detect active users with recent logins",
6168
+ "command": "sf hardis:org:diagnose:unusedusers --returnactiveusers",
6169
+ "frequency": "weekly"
6170
+ },
6171
+ {
6172
+ "key": "ORG_INFO",
6173
+ "title": "Get org info + SF instance info + next major upgrade date",
6174
+ "command": "sf hardis:org:diagnose:instanceupgrade",
6175
+ "frequency": "weekly"
6176
+ },
6177
+ {
6178
+ "key": "RELEASE_UPDATES",
6179
+ "title": "Gather warnings about incoming and overdue Release Updates",
6180
+ "command": "sf hardis:org:diagnose:releaseupdates",
6181
+ "frequency": "weekly"
6182
+ },
6183
+ {
6184
+ "key": "UNUSED_METADATAS",
6185
+ "title": "Detect custom labels and custom permissions that are not in use",
6186
+ "command": "sf hardis:lint:unusedmetadatas",
6187
+ "frequency": "weekly"
6188
+ },
6189
+ {
6190
+ "key": "UNUSED_APEX_CLASSES",
6191
+ "title": "Detect unused Apex classes in an org",
6192
+ "command": "sf hardis:org:diagnose:unused-apex-classes",
6193
+ "frequency": "weekly"
6194
+ },
6195
+ {
6196
+ "key": "CONNECTED_APPS",
6197
+ "title": "Detect unused Connected Apps in an org",
6198
+ "command": "sf hardis:org:diagnose:unused-connected-apps",
6199
+ "frequency": "weekly"
6200
+ },
6201
+ {
6202
+ "key": "METADATA_STATUS",
6203
+ "title": "Detect inactive metadata",
6204
+ "command": "sf hardis:lint:metadatastatus",
6205
+ "frequency": "weekly"
6206
+ },
6207
+ {
6208
+ "key": "MISSING_ATTRIBUTES",
6209
+ "title": "Detect missing description on custom field",
6210
+ "command": "sf hardis:lint:missingattributes",
6211
+ "frequency": "weekly"
6212
+ }
6213
+ ],
6214
+ "requiresProject": true,
6215
+ "triggerNotification": true,
6216
+ "isESM": true,
6217
+ "relativePath": [
6218
+ "lib",
6219
+ "commands",
6220
+ "hardis",
6221
+ "org",
6222
+ "monitor",
6223
+ "all.js"
6224
+ ],
6225
+ "aliasPermutations": [],
6226
+ "permutations": [
6227
+ "hardis:org:monitor:all",
6228
+ "org:hardis:monitor:all",
6229
+ "org:monitor:hardis:all",
6230
+ "org:monitor:all:hardis",
6231
+ "hardis:monitor:org:all",
6232
+ "monitor:hardis:org:all",
6233
+ "monitor:org:hardis:all",
6234
+ "monitor:org:all:hardis",
6235
+ "hardis:monitor:all:org",
6236
+ "monitor:hardis:all:org",
6237
+ "monitor:all:hardis:org",
6238
+ "monitor:all:org:hardis",
6239
+ "hardis:org:all:monitor",
6240
+ "org:hardis:all:monitor",
6241
+ "org:all:hardis:monitor",
6242
+ "org:all:monitor:hardis",
6243
+ "hardis:all:org:monitor",
6244
+ "all:hardis:org:monitor",
6245
+ "all:org:hardis:monitor",
6246
+ "all:org:monitor:hardis",
6247
+ "hardis:all:monitor:org",
6248
+ "all:hardis:monitor:org",
6249
+ "all:monitor:hardis:org",
6250
+ "all:monitor:org:hardis"
6251
+ ]
6252
+ },
6253
+ "hardis:org:monitor:backup": {
6254
+ "aliases": [],
6255
+ "args": {},
6256
+ "description": "Retrieve sfdx sources in the context of a monitoring backup\n\nThe command exists in 2 modes: filtered(default & recommended) and full.\n\n## Filtered mode (default, better performances)\n\nAutomatically skips metadatas from installed packages with namespace. \n\nYou can remove more metadata types from backup, especially in case you have too many metadatas and that provokes a crash, using:\n\n- Manual update of `manifest/package-skip-items.xml` config file (then commit & push in the same branch)\n\n - Works with full wildcard (`<members>*</members>`) , named metadata (`<members>Account.Name</members>`) or partial wildcards names (`<members>pi__*</members>` , `<members>*__dlm</members>` , or `<members>prefix*suffix</members>`)\n\n- Environment variable MONITORING_BACKUP_SKIP_METADATA_TYPES (example: `MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation`): that will be applied to all monitoring branches.\n\n## Full mode\n\nActivate it with **--full** parameter, or variable MONITORING_BACKUP_MODE_FULL=true\n\nIgnores filters (namespaces items & manifest/package-skip-items.xml) to retrieve ALL metadatas, including those you might not care about (reports, translations...)\n\nAs we can retrieve only 10000 files by call, the list of all metadatas will be chunked to make multiple calls (and take more time than filtered mode)\n\n- if you use `--full-apply-filters` , manifest/package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES filters will be applied anyway\n- if you use `--exclude-namespaces` , namespaced items will be ignored\n\n_With those both options, it's like if you are not using --full, but with chunked metadata download_\n\n## In CI/CD\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-metadata-backup/) and can output Grafana, Slack and MsTeams Notifications.\n\n## Troubleshooting\n\nIf you have unknown errors (it happens !), you can investigate using the full command with smaller chunks.\n\nExample: `sf hardis:org:monitor:backup --full --exclude-namespaces --full-apply-filters --max-by-chunk 500`\n\nIt will allow you the identify the responsible metadata and ignore it using package-skip-items.xml or MONITORING_BACKUP_SKIP_METADATA_TYPES env variable.\n\n## Documentation\n\n[Doc generation (including visual flows)](https://sfdx-hardis.cloudity.com/hardis/doc/project2markdown/) is triggered at the end of the command.\n\nIf you want to also upload HTML Documentation on your Salesforce Org as static resource, use variable **SFDX_HARDIS_DOC_DEPLOY_TO_ORG=\"true\"**\n\nIf you want to also upload HTML Documentation on Cloudflare, use variable **SFDX_HARDIS_DOC_DEPLOY_TO_CLOUDFLARE=\"true\"**\n\n- If you want to generate the documentation in multiple languages, define variable SFDX_DOC_LANGUAGES (ex: SFDX_DOC_LANGUAGES=en,fr,de)\n- You can define one Cloudflare site by language, for example with the following variables:\n - CLOUDFLARE_PROJECT_NAME_EN=cloudity-demo-english\n - CLOUDFLARE_PROJECT_NAME_FR=cloudity-demo-french\n - CLOUDFLARE_PROJECT_NAME_DE=cloudity-demo-german\n\nIf Flow history doc always display a single state, you probably need to update your workflow configuration:\n\n- on Gitlab: Env variable [`GIT_FETCH_EXTRA_FLAGS: --depth 10000`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/.gitlab-ci.yml#L11)\n- on GitHub: [`fetch-depth: 0`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/.github/workflows/org-monitoring.yml#L58)\n- on Azure: [`fetchDepth: \"0\"`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/azure-pipelines.yml#L39)\n- on Bitbucket: [`step: clone: depth: full`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/bitbucket-pipelines.yml#L18)\n",
6257
+ "examples": [
6258
+ "$ sf hardis:org:monitor:backup",
6259
+ "$ sf hardis:org:monitor:backup --full",
6260
+ "$ sf hardis:org:monitor:backup --full --exclude-namespaces",
6261
+ "$ sf hardis:org:monitor:backup --full --exclude-namespaces --full-apply-filters"
6262
+ ],
6263
+ "flags": {
6264
+ "json": {
6265
+ "description": "Format output as json.",
6266
+ "helpGroup": "GLOBAL",
6267
+ "name": "json",
6268
+ "allowNo": false,
6269
+ "type": "boolean"
6270
+ },
6271
+ "flags-dir": {
6272
+ "helpGroup": "GLOBAL",
6273
+ "name": "flags-dir",
6274
+ "summary": "Import flag values from a directory.",
6275
+ "hasDynamicHelp": false,
6276
+ "multiple": false,
6277
+ "type": "option"
6278
+ },
6279
+ "full": {
6280
+ "description": "Dot not take in account filtering using package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES. Efficient but much much slower !",
6281
+ "name": "full",
6282
+ "allowNo": false,
6283
+ "type": "boolean"
6284
+ },
6285
+ "max-by-chunk": {
6286
+ "char": "m",
6287
+ "description": "If mode --full is activated, maximum number of metadatas in a package.xml chunk",
6288
+ "name": "max-by-chunk",
6289
+ "default": 3000,
6290
+ "hasDynamicHelp": false,
6291
+ "multiple": false,
6292
+ "type": "option"
6293
+ },
6294
+ "exclude-namespaces": {
6295
+ "char": "e",
6296
+ "description": "If mode --full is activated, exclude namespaced metadatas",
6297
+ "name": "exclude-namespaces",
6298
+ "allowNo": false,
6299
+ "type": "boolean"
6300
+ },
6301
+ "full-apply-filters": {
6302
+ "char": "z",
6303
+ "description": "If mode --full is activated, apply filters of manifest/package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES anyway",
6304
+ "name": "full-apply-filters",
6305
+ "allowNo": false,
6306
+ "type": "boolean"
6307
+ },
6308
+ "start-chunk": {
6309
+ "description": "Use this parameter to troubleshoot a specific chunk. It will be used as the first chunk to retrieve",
6310
+ "name": "start-chunk",
6311
+ "default": 1,
6312
+ "hasDynamicHelp": false,
6313
+ "multiple": false,
6314
+ "type": "option"
6315
+ },
6316
+ "skip-doc": {
6317
+ "description": "Skip the generation of project documentation at the end of the command",
6318
+ "name": "skip-doc",
6319
+ "allowNo": false,
6320
+ "type": "boolean"
6321
+ },
6322
+ "outputfile": {
6323
+ "char": "f",
6324
+ "description": "Force the path and name of output report file. Must end with .csv",
6325
+ "name": "outputfile",
6326
+ "hasDynamicHelp": false,
6327
+ "multiple": false,
6328
+ "type": "option"
6329
+ },
6330
+ "debug": {
6331
+ "char": "d",
6332
+ "description": "Activate debug mode (more logs)",
6333
+ "name": "debug",
6334
+ "allowNo": false,
6335
+ "type": "boolean"
6336
+ },
6337
+ "websocket": {
6338
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
6339
+ "name": "websocket",
6340
+ "hasDynamicHelp": false,
6341
+ "multiple": false,
6342
+ "type": "option"
6343
+ },
6344
+ "skipauth": {
6345
+ "description": "Skip authentication check when a default username is required",
6346
+ "name": "skipauth",
6347
+ "allowNo": false,
6348
+ "type": "boolean"
6349
+ },
6350
+ "target-org": {
6351
+ "aliases": [
6352
+ "targetusername",
6353
+ "u"
6354
+ ],
6355
+ "char": "o",
6356
+ "deprecateAliases": true,
6357
+ "name": "target-org",
6358
+ "noCacheDefault": true,
6359
+ "required": true,
6360
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
6361
+ "hasDynamicHelp": true,
6362
+ "multiple": false,
6363
+ "type": "option"
6364
+ }
6365
+ },
6366
+ "hasDynamicHelp": true,
6367
+ "hiddenAliases": [],
6368
+ "id": "hardis:org:monitor:backup",
6369
+ "pluginAlias": "sfdx-hardis",
6370
+ "pluginName": "sfdx-hardis",
6371
+ "pluginType": "core",
6372
+ "strict": true,
6373
+ "enableJsonFlag": true,
6374
+ "title": "Backup DX sources",
6375
+ "requiresProject": true,
6376
+ "triggerNotification": true,
6377
+ "isESM": true,
6378
+ "relativePath": [
6379
+ "lib",
6380
+ "commands",
6381
+ "hardis",
6382
+ "org",
6383
+ "monitor",
6384
+ "backup.js"
6385
+ ],
6386
+ "aliasPermutations": [],
6387
+ "permutations": [
6388
+ "hardis:org:monitor:backup",
6389
+ "org:hardis:monitor:backup",
6390
+ "org:monitor:hardis:backup",
6391
+ "org:monitor:backup:hardis",
6392
+ "hardis:monitor:org:backup",
6393
+ "monitor:hardis:org:backup",
6394
+ "monitor:org:hardis:backup",
6395
+ "monitor:org:backup:hardis",
6396
+ "hardis:monitor:backup:org",
6397
+ "monitor:hardis:backup:org",
6398
+ "monitor:backup:hardis:org",
6399
+ "monitor:backup:org:hardis",
6400
+ "hardis:org:backup:monitor",
6401
+ "org:hardis:backup:monitor",
6402
+ "org:backup:hardis:monitor",
6403
+ "org:backup:monitor:hardis",
6404
+ "hardis:backup:org:monitor",
6405
+ "backup:hardis:org:monitor",
6406
+ "backup:org:hardis:monitor",
6407
+ "backup:org:monitor:hardis",
6408
+ "hardis:backup:monitor:org",
6409
+ "backup:hardis:monitor:org",
6410
+ "backup:monitor:hardis:org",
6411
+ "backup:monitor:org:hardis"
6412
+ ]
6413
+ },
6414
+ "hardis:org:monitor:limits": {
6415
+ "aliases": [],
6416
+ "args": {},
6417
+ "description": "\n## Command Behavior\n\n**Checks the current usage of various Salesforce org limits and sends notifications if thresholds are exceeded.**\n\nThis command is a critical component of proactive Salesforce org management, helping administrators and developers monitor resource consumption and prevent hitting critical limits that could impact performance or functionality. It provides early warnings when limits are approaching their capacity.\n\nKey functionalities:\n\n- **Limit Retrieval:** Fetches a comprehensive list of all Salesforce org limits using the Salesforce CLI.\n- **Usage Calculation:** Calculates the percentage of each limit that is currently being used.\n- **Threshold-Based Alerting:** Assigns a severity (success, warning, or error) to each limit based on configurable thresholds:\n - **Warning:** If usage exceeds 50% (configurable via `LIMIT_THRESHOLD_WARNING` environment variable).\n - **Error:** If usage exceeds 75% (configurable via `LIMIT_THRESHOLD_ERROR` environment variable).\n- **CSV Report Generation:** Generates a CSV file containing all org limits, their current usage, maximum allowed, and calculated percentage used, along with the assigned severity.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of limits that have exceeded the warning or error thresholds.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-org-limits/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce CLI Integration:** It executes the `sf org limits list` command to retrieve the current org limits. It parses the JSON output of this command.\n- **Data Processing:** It iterates through the retrieved limits, calculates the `used` and `percentUsed` values, and assigns a `severity` (success, warning, error) based on the configured thresholds.\n- **Environment Variable Configuration:** Reads `LIMIT_THRESHOLD_WARNING` and `LIMIT_THRESHOLD_ERROR` environment variables to set the warning and error thresholds for limit usage.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of org limits.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and detailed metrics for each limit, which can be consumed by monitoring dashboards like Grafana.\n- **Exit Code Management:** Sets the process exit code to 1 if any limit is in an 'error' state, indicating a critical issue.\n</details>\n",
6418
+ "examples": [
6419
+ "$ sf hardis:org:monitor:limits"
6420
+ ],
6421
+ "flags": {
6422
+ "json": {
6423
+ "description": "Format output as json.",
6424
+ "helpGroup": "GLOBAL",
6425
+ "name": "json",
6426
+ "allowNo": false,
6427
+ "type": "boolean"
6428
+ },
6429
+ "flags-dir": {
6430
+ "helpGroup": "GLOBAL",
6431
+ "name": "flags-dir",
6432
+ "summary": "Import flag values from a directory.",
6433
+ "hasDynamicHelp": false,
6434
+ "multiple": false,
6435
+ "type": "option"
6436
+ },
6437
+ "outputfile": {
6438
+ "char": "f",
6439
+ "description": "Force the path and name of output report file. Must end with .csv",
6440
+ "name": "outputfile",
6441
+ "hasDynamicHelp": false,
6442
+ "multiple": false,
6443
+ "type": "option"
6444
+ },
6445
+ "debug": {
6446
+ "char": "d",
6447
+ "description": "Activate debug mode (more logs)",
6448
+ "name": "debug",
6449
+ "allowNo": false,
6450
+ "type": "boolean"
6451
+ },
6452
+ "websocket": {
6453
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
6454
+ "name": "websocket",
6455
+ "hasDynamicHelp": false,
6456
+ "multiple": false,
6457
+ "type": "option"
6458
+ },
6459
+ "skipauth": {
6460
+ "description": "Skip authentication check when a default username is required",
6461
+ "name": "skipauth",
6462
+ "allowNo": false,
6463
+ "type": "boolean"
6464
+ },
6465
+ "target-org": {
6466
+ "aliases": [
6467
+ "targetusername",
6468
+ "u"
6469
+ ],
6470
+ "char": "o",
6471
+ "deprecateAliases": true,
6472
+ "name": "target-org",
6473
+ "noCacheDefault": true,
6474
+ "required": true,
6475
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
6476
+ "hasDynamicHelp": true,
6477
+ "multiple": false,
6478
+ "type": "option"
6479
+ }
6480
+ },
6481
+ "hasDynamicHelp": true,
6482
+ "hiddenAliases": [],
6483
+ "id": "hardis:org:monitor:limits",
6484
+ "pluginAlias": "sfdx-hardis",
6485
+ "pluginName": "sfdx-hardis",
6486
+ "pluginType": "core",
6487
+ "strict": true,
6488
+ "enableJsonFlag": true,
6489
+ "title": "Check org limits",
6490
+ "requiresProject": true,
6491
+ "triggerNotification": true,
6492
+ "isESM": true,
6493
+ "relativePath": [
6494
+ "lib",
6495
+ "commands",
6496
+ "hardis",
6497
+ "org",
6498
+ "monitor",
6499
+ "limits.js"
6500
+ ],
6501
+ "aliasPermutations": [],
6502
+ "permutations": [
6503
+ "hardis:org:monitor:limits",
6504
+ "org:hardis:monitor:limits",
6505
+ "org:monitor:hardis:limits",
6506
+ "org:monitor:limits:hardis",
6507
+ "hardis:monitor:org:limits",
6508
+ "monitor:hardis:org:limits",
6509
+ "monitor:org:hardis:limits",
6510
+ "monitor:org:limits:hardis",
6511
+ "hardis:monitor:limits:org",
6512
+ "monitor:hardis:limits:org",
6513
+ "monitor:limits:hardis:org",
6514
+ "monitor:limits:org:hardis",
6515
+ "hardis:org:limits:monitor",
6516
+ "org:hardis:limits:monitor",
6517
+ "org:limits:hardis:monitor",
6518
+ "org:limits:monitor:hardis",
6519
+ "hardis:limits:org:monitor",
6520
+ "limits:hardis:org:monitor",
6521
+ "limits:org:hardis:monitor",
6522
+ "limits:org:monitor:hardis",
6523
+ "hardis:limits:monitor:org",
6524
+ "limits:hardis:monitor:org",
6525
+ "limits:monitor:hardis:org",
6526
+ "limits:monitor:org:hardis"
6527
+ ]
6528
+ },
6529
+ "hardis:org:diagnose:audittrail": {
6530
+ "aliases": [],
6531
+ "args": {},
6532
+ "description": "Export Audit trail into a CSV file with selected criteria, and highlight suspect actions\n\nAlso detects updates of Custom Settings values (disable by defining `SKIP_AUDIT_TRAIL_CUSTOM_SETTINGS=true`)\n\nRegular setup actions performed in major orgs are filtered.\n\n- \"\"\n - createScratchOrg\n - changedsenderemail\n - deleteScratchOrg\n - loginasgrantedtopartnerbt\n- Certificate and Key Management\n - insertCertificate\n- Custom App Licenses\n - addeduserpackagelicense\n - granteduserpackagelicense\n - revokeduserpackagelicense\n- Customer Portal\n - createdcustomersuccessuser\n - CSPUserDisabled\n- Currency\n - updateddatedexchrate\n- Data Management\n - queueMembership\n- Email Administration\n - dkimRotationPreparationSuccessful\n - dkimRotationSuccessful\n- External Objects\n - xdsEncryptedFieldChange\n- Groups\n - groupMembership\n- Holidays\n - holiday_insert\n- Inbox mobile and legacy desktop apps\n - enableSIQUserNonEAC\n - siqUserAcceptedTOS\n- Manage Users\n - activateduser\n - createduser\n - changedcommunitynickname\n - changedemail\n - changedfederationid\n - changedpassword\n - changedinteractionuseroffon\n - changedinteractionuseronoff\n - changedmarketinguseroffon\n - changedmarketinguseronoff\n - changedofflineuseroffon\n - changedprofileforuserstdtostd\n - changedprofileforuser\n - changedprofileforusercusttostd\n - changedprofileforuserstdtocust\n - changedroleforusertonone\n - changedroleforuser\n - changedroleforuserfromnone\n - changedUserAdminVerifiedStatusVerified\n - changedUserEmailVerifiedStatusUnverified\n - changedUserEmailVerifiedStatusVerified\n - changedknowledgeuseroffon\n - changedsfcontentuseroffon\n - changedsupportuseroffon\n - changedusername\n - changedUserPhoneNumber\n - changedUserPhoneVerifiedStatusUnverified\n - changedUserPhoneVerifiedStatusVerified\n - deactivateduser\n - deleteAuthenticatorPairing\n - deleteTwoFactorInfo2\n - deleteTwoFactorTempCode\n - frozeuser\n - insertAuthenticatorPairing\n - insertTwoFactorInfo2\n - insertTwoFactorTempCode\n - lightningloginenroll\n - PermSetAssign\n - PermSetGroupAssign\n - PermSetGroupUnassign\n - PermSetLicenseAssign\n - PermSetUnassign\n - PermSetLicenseUnassign\n - registeredUserPhoneNumber\n - resetpassword\n - suNetworkAdminLogin\n - suNetworkAdminLogout\n - suOrgAdminLogin\n - suOrgAdminLogout\n - unfrozeuser\n - useremailchangesent\n- Mobile Administration\n - assigneduserstomobileconfig\n- Reporting Snapshots\n - createdReportJob\n - deletedReportJob\n- Sandboxes\n - DeleteSandbox\n\nBy default, deployment user defined in .sfdx-hardis.yml targetUsername property will be excluded.\n\nYou can define additional users to exclude in .sfdx-hardis.yml **monitoringExcludeUsernames** property.\n\nYou can also add more sections / actions considered as not suspect using property **monitoringAllowedSectionsActions**\n\nExample:\n\n```yaml\nmonitoringExcludeUsernames:\n - deploymentuser@cloudity.com\n - marketingcloud@cloudity.com\n - integration-user@cloudity.com\n\nmonitoringAllowedSectionsActions:\n \"Some section\": [] // Will ignore all actions from such section\n \"Some other section\": [\"actionType1\",\"actionType2\",\"actionType3\"] // Will ignore only those 3 actions from section \"Some other section\". Other actions in the same section will be considered as suspect.\n```\n\n## Excel output example\n\n![](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/screenshot-monitoring-audittrail-excel.jpg)\n\n## Local output example\n\n![](https://github.com/hardisgroupcom/sfdx-hardis/raw/main/docs/assets/images/screenshot-monitoring-audittrail-local.jpg)\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-suspect-audit-trail/) and can output Grafana, Slack and MsTeams Notifications.\n",
6533
+ "examples": [
6534
+ "$ sf hardis:org:diagnose:audittrail",
6535
+ "$ sf hardis:org:diagnose:audittrail --excludeusers baptiste@titi.com",
6536
+ "$ sf hardis:org:diagnose:audittrail --excludeusers baptiste@titi.com,bertrand@titi.com",
6537
+ "$ sf hardis:org:diagnose:audittrail --lastndays 5"
6538
+ ],
6539
+ "flags": {
6540
+ "json": {
6541
+ "description": "Format output as json.",
6542
+ "helpGroup": "GLOBAL",
6543
+ "name": "json",
6544
+ "allowNo": false,
6545
+ "type": "boolean"
6546
+ },
6547
+ "flags-dir": {
6548
+ "helpGroup": "GLOBAL",
6549
+ "name": "flags-dir",
6550
+ "summary": "Import flag values from a directory.",
6551
+ "hasDynamicHelp": false,
6552
+ "multiple": false,
6553
+ "type": "option"
6554
+ },
6555
+ "excludeusers": {
6556
+ "char": "e",
6557
+ "description": "Comma-separated list of usernames to exclude",
6558
+ "name": "excludeusers",
6559
+ "hasDynamicHelp": false,
6560
+ "multiple": false,
6561
+ "type": "option"
6562
+ },
6563
+ "lastndays": {
6564
+ "char": "t",
6565
+ "description": "Number of days to extract from today (included)",
6566
+ "name": "lastndays",
6567
+ "hasDynamicHelp": false,
6568
+ "multiple": false,
6569
+ "type": "option"
6570
+ },
6571
+ "outputfile": {
6572
+ "char": "f",
6573
+ "description": "Force the path and name of output report file. Must end with .csv",
6574
+ "name": "outputfile",
6575
+ "hasDynamicHelp": false,
6576
+ "multiple": false,
6577
+ "type": "option"
6578
+ },
6579
+ "debug": {
6580
+ "char": "d",
6581
+ "description": "Activate debug mode (more logs)",
6582
+ "name": "debug",
6583
+ "allowNo": false,
6584
+ "type": "boolean"
6585
+ },
6586
+ "websocket": {
6587
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
6588
+ "name": "websocket",
6589
+ "hasDynamicHelp": false,
6590
+ "multiple": false,
6591
+ "type": "option"
6592
+ },
6593
+ "skipauth": {
6594
+ "description": "Skip authentication check when a default username is required",
6595
+ "name": "skipauth",
6596
+ "allowNo": false,
6597
+ "type": "boolean"
6598
+ },
6599
+ "target-org": {
6600
+ "aliases": [
6601
+ "targetusername",
6602
+ "u"
6603
+ ],
6604
+ "char": "o",
6605
+ "deprecateAliases": true,
6606
+ "name": "target-org",
6607
+ "noCacheDefault": true,
6608
+ "required": true,
6609
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
6610
+ "hasDynamicHelp": true,
6611
+ "multiple": false,
6612
+ "type": "option"
6613
+ }
6614
+ },
6615
+ "hasDynamicHelp": true,
6616
+ "hiddenAliases": [],
6617
+ "id": "hardis:org:diagnose:audittrail",
6618
+ "pluginAlias": "sfdx-hardis",
6619
+ "pluginName": "sfdx-hardis",
6620
+ "pluginType": "core",
6621
+ "strict": true,
6622
+ "enableJsonFlag": true,
6623
+ "title": "Diagnose content of Setup Audit Trail",
6624
+ "requiresProject": false,
6625
+ "isESM": true,
6626
+ "relativePath": [
6627
+ "lib",
6628
+ "commands",
6629
+ "hardis",
6630
+ "org",
6631
+ "diagnose",
6632
+ "audittrail.js"
6633
+ ],
6634
+ "aliasPermutations": [],
6635
+ "permutations": [
6636
+ "hardis:org:diagnose:audittrail",
6637
+ "org:hardis:diagnose:audittrail",
6638
+ "org:diagnose:hardis:audittrail",
6639
+ "org:diagnose:audittrail:hardis",
6640
+ "hardis:diagnose:org:audittrail",
6641
+ "diagnose:hardis:org:audittrail",
6642
+ "diagnose:org:hardis:audittrail",
6643
+ "diagnose:org:audittrail:hardis",
6644
+ "hardis:diagnose:audittrail:org",
6645
+ "diagnose:hardis:audittrail:org",
6646
+ "diagnose:audittrail:hardis:org",
6647
+ "diagnose:audittrail:org:hardis",
6648
+ "hardis:org:audittrail:diagnose",
6649
+ "org:hardis:audittrail:diagnose",
6650
+ "org:audittrail:hardis:diagnose",
6651
+ "org:audittrail:diagnose:hardis",
6652
+ "hardis:audittrail:org:diagnose",
6653
+ "audittrail:hardis:org:diagnose",
6654
+ "audittrail:org:hardis:diagnose",
6655
+ "audittrail:org:diagnose:hardis",
6656
+ "hardis:audittrail:diagnose:org",
6657
+ "audittrail:hardis:diagnose:org",
6658
+ "audittrail:diagnose:hardis:org",
6659
+ "audittrail:diagnose:org:hardis"
6660
+ ]
6661
+ },
6662
+ "hardis:org:diagnose:instanceupgrade": {
6663
+ "aliases": [],
6664
+ "args": {},
6665
+ "description": "\n## Command Behavior\n\n**Retrieves and displays the scheduled upgrade date for a Salesforce org's instance.**\n\nThis command provides crucial information about when your Salesforce instance will be upgraded to the next major release (Spring, Summer, or Winter). This is vital for release planning, testing, and ensuring compatibility with upcoming Salesforce features.\n\nKey functionalities:\n\n- **Instance Identification:** Determines the Salesforce instance name of your target org.\n- **Upgrade Date Retrieval:** Fetches the planned start time of the next major core service upgrade for that instance from the Salesforce Status API.\n- **Days Until Upgrade:** Calculates and displays the number of days remaining until the next major upgrade.\n- **Severity-Based Logging:** Adjusts the log severity (info, warning) based on the proximity of the upgrade date, providing a visual cue for urgency.\n- **Notifications:** Sends notifications to configured channels (e.g., Slack, MS Teams, Grafana) with the upgrade information, making it suitable for automated monitoring.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce SOQL Query:** It first queries the `Organization` object in Salesforce to get the `InstanceName` of the target org.\n- **Salesforce Status API Integration:** It makes an HTTP GET request to the Salesforce Status API (`https://api.status.salesforce.com/v1/instances/{instanceName}/status`) to retrieve detailed information about the instance, including scheduled maintenances.\n- **Data Parsing:** It parses the JSON response from the Status API to extract the relevant major release upgrade information.\n- **Date Calculation:** Uses the `moment` library to calculate the difference in days between the current date and the planned upgrade date.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including the instance name, upgrade date, and days remaining, along with relevant metrics for monitoring dashboards.\n- **User Feedback:** Provides clear messages to the user about the upgrade status and proximity.\n</details>\n",
6666
+ "examples": [
6667
+ "$ sf hardis:org:diagnose:instanceupgrade"
6668
+ ],
6669
+ "flags": {
6670
+ "json": {
6671
+ "description": "Format output as json.",
6672
+ "helpGroup": "GLOBAL",
6673
+ "name": "json",
6674
+ "allowNo": false,
6675
+ "type": "boolean"
6676
+ },
6677
+ "flags-dir": {
6678
+ "helpGroup": "GLOBAL",
6679
+ "name": "flags-dir",
6680
+ "summary": "Import flag values from a directory.",
6681
+ "hasDynamicHelp": false,
6682
+ "multiple": false,
6683
+ "type": "option"
6684
+ },
6685
+ "debug": {
6686
+ "char": "d",
6687
+ "description": "Activate debug mode (more logs)",
6688
+ "name": "debug",
6689
+ "allowNo": false,
6690
+ "type": "boolean"
6691
+ },
6692
+ "websocket": {
6693
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
6694
+ "name": "websocket",
6695
+ "hasDynamicHelp": false,
6696
+ "multiple": false,
6697
+ "type": "option"
6698
+ },
6699
+ "skipauth": {
6700
+ "description": "Skip authentication check when a default username is required",
6701
+ "name": "skipauth",
6702
+ "allowNo": false,
6703
+ "type": "boolean"
6704
+ },
6705
+ "target-org": {
6706
+ "aliases": [
6707
+ "targetusername",
6708
+ "u"
6709
+ ],
6710
+ "char": "o",
6711
+ "deprecateAliases": true,
6712
+ "name": "target-org",
6713
+ "noCacheDefault": true,
6714
+ "required": true,
6715
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
6716
+ "hasDynamicHelp": true,
6717
+ "multiple": false,
6718
+ "type": "option"
6719
+ }
6720
+ },
6721
+ "hasDynamicHelp": true,
6722
+ "hiddenAliases": [],
6723
+ "id": "hardis:org:diagnose:instanceupgrade",
6724
+ "pluginAlias": "sfdx-hardis",
6725
+ "pluginName": "sfdx-hardis",
6726
+ "pluginType": "core",
6727
+ "strict": true,
6728
+ "enableJsonFlag": true,
6729
+ "title": "Get Instance Upgrade date",
6730
+ "requiresProject": false,
6731
+ "isESM": true,
6732
+ "relativePath": [
6733
+ "lib",
6734
+ "commands",
6735
+ "hardis",
6736
+ "org",
6737
+ "diagnose",
6738
+ "instanceupgrade.js"
6739
+ ],
6740
+ "aliasPermutations": [],
6741
+ "permutations": [
6742
+ "hardis:org:diagnose:instanceupgrade",
6743
+ "org:hardis:diagnose:instanceupgrade",
6744
+ "org:diagnose:hardis:instanceupgrade",
6745
+ "org:diagnose:instanceupgrade:hardis",
6746
+ "hardis:diagnose:org:instanceupgrade",
6747
+ "diagnose:hardis:org:instanceupgrade",
6748
+ "diagnose:org:hardis:instanceupgrade",
6749
+ "diagnose:org:instanceupgrade:hardis",
6750
+ "hardis:diagnose:instanceupgrade:org",
6751
+ "diagnose:hardis:instanceupgrade:org",
6149
6752
  "diagnose:instanceupgrade:hardis:org",
6150
6753
  "diagnose:instanceupgrade:org:hardis",
6151
6754
  "hardis:org:instanceupgrade:diagnose",
@@ -6520,261 +7123,24 @@
6520
7123
  "diagnose:releaseupdates:org:hardis",
6521
7124
  "hardis:org:releaseupdates:diagnose",
6522
7125
  "org:hardis:releaseupdates:diagnose",
6523
- "org:releaseupdates:hardis:diagnose",
6524
- "org:releaseupdates:diagnose:hardis",
6525
- "hardis:releaseupdates:org:diagnose",
6526
- "releaseupdates:hardis:org:diagnose",
6527
- "releaseupdates:org:hardis:diagnose",
6528
- "releaseupdates:org:diagnose:hardis",
6529
- "hardis:releaseupdates:diagnose:org",
6530
- "releaseupdates:hardis:diagnose:org",
6531
- "releaseupdates:diagnose:hardis:org",
6532
- "releaseupdates:diagnose:org:hardis"
6533
- ]
6534
- },
6535
- "hardis:org:diagnose:unsecure-connected-apps": {
6536
- "aliases": [],
6537
- "args": {},
6538
- "description": "\n## Command Behavior\n\n**Detects unsecured Connected Apps in a Salesforce org and generates detailed reports for security analysis.**\n\nThis command is a critical security diagnostic tool that helps administrators identify Connected Apps that may pose security risks due to improper configuration. It provides comprehensive analysis of OAuth tokens and Connected App security settings to ensure proper access control.\n\nKey functionalities:\n\n- **OAuth Token Analysis:** Queries all OAuth tokens in the org using SOQL to retrieve comprehensive token information including app names, users, authorization status, and usage statistics.\n- **Security Status Assessment:** Evaluates each Connected App's security configuration by checking the `IsUsingAdminAuthorization` flag to determine if admin pre-approval is required.\n- **Unsecured App Detection:** Identifies Connected Apps that allow users to authorize themselves without admin approval, which can pose security risks.\n- **Detailed Reporting:** Generates two comprehensive CSV reports:\n - **OAuth Tokens Report:** Lists all OAuth tokens with security status, user information, and usage data\n - **Connected Apps Summary:** Aggregates unsecured Connected Apps with counts of associated OAuth tokens\n- **Visual Indicators:** Uses status icons (❌ for unsecured, ✅ for secured) to provide immediate visual feedback on security status.\n- **Security Recommendations:** Provides actionable guidance on how to secure Connected Apps through proper configuration.\n- **Notifications:** Sends alerts to configured channels (Grafana, Slack, MS Teams) with security findings and attached reports.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-org-security/) and can output Grafana, Slack and MsTeams Notifications.\n\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/jHv8yrSK8Dg\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Query Execution:** Executes a comprehensive SOQL query on the `OauthToken` object, joining with `AppMenuItem` and `User` objects to gather complete security context.\n- **Security Analysis Logic:** Analyzes the `AppMenuItem.IsUsingAdminAuthorization` field to determine if a Connected App requires admin pre-approval for user authorization.\n- **Data Transformation:** Processes raw SOQL results to add security status indicators and reorganize data for optimal reporting and analysis.\n- **Aggregation Processing:** Groups OAuth tokens by Connected App name to provide summary statistics and identify the most problematic applications.\n- **Report Generation:** Uses `generateCsvFile` to create structured CSV reports with proper formatting and metadata for easy analysis and sharing.\n- **Notification Integration:** Integrates with the `NotifProvider` to send security alerts with detailed metrics, including the number of unsecured Connected Apps and associated OAuth tokens.\n- **File Management:** Generates multiple output formats (CSV, XLSX) and manages file paths using `generateReportPath` for consistent report organization.\n- **Connection Management:** Uses `setConnectionVariables` to ensure proper authentication context for notification providers that require org connection details.\n</details>\n",
6539
- "examples": [
6540
- "$ sf hardis:org:diagnose:unsecure-connected-apps"
6541
- ],
6542
- "flags": {
6543
- "json": {
6544
- "description": "Format output as json.",
6545
- "helpGroup": "GLOBAL",
6546
- "name": "json",
6547
- "allowNo": false,
6548
- "type": "boolean"
6549
- },
6550
- "flags-dir": {
6551
- "helpGroup": "GLOBAL",
6552
- "name": "flags-dir",
6553
- "summary": "Import flag values from a directory.",
6554
- "hasDynamicHelp": false,
6555
- "multiple": false,
6556
- "type": "option"
6557
- },
6558
- "outputfile": {
6559
- "char": "f",
6560
- "description": "Force the path and name of output report file. Must end with .csv",
6561
- "name": "outputfile",
6562
- "hasDynamicHelp": false,
6563
- "multiple": false,
6564
- "type": "option"
6565
- },
6566
- "debug": {
6567
- "char": "d",
6568
- "description": "Activate debug mode (more logs)",
6569
- "name": "debug",
6570
- "allowNo": false,
6571
- "type": "boolean"
6572
- },
6573
- "websocket": {
6574
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
6575
- "name": "websocket",
6576
- "hasDynamicHelp": false,
6577
- "multiple": false,
6578
- "type": "option"
6579
- },
6580
- "skipauth": {
6581
- "description": "Skip authentication check when a default username is required",
6582
- "name": "skipauth",
6583
- "allowNo": false,
6584
- "type": "boolean"
6585
- },
6586
- "target-org": {
6587
- "aliases": [
6588
- "targetusername",
6589
- "u"
6590
- ],
6591
- "char": "o",
6592
- "deprecateAliases": true,
6593
- "name": "target-org",
6594
- "noCacheDefault": true,
6595
- "required": true,
6596
- "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
6597
- "hasDynamicHelp": true,
6598
- "multiple": false,
6599
- "type": "option"
6600
- }
6601
- },
6602
- "hasDynamicHelp": true,
6603
- "hiddenAliases": [],
6604
- "id": "hardis:org:diagnose:unsecure-connected-apps",
6605
- "pluginAlias": "sfdx-hardis",
6606
- "pluginName": "sfdx-hardis",
6607
- "pluginType": "core",
6608
- "strict": true,
6609
- "enableJsonFlag": true,
6610
- "title": "Detect Unsecured Connected Apps",
6611
- "requiresProject": false,
6612
- "isESM": true,
6613
- "relativePath": [
6614
- "lib",
6615
- "commands",
6616
- "hardis",
6617
- "org",
6618
- "diagnose",
6619
- "unsecure-connected-apps.js"
6620
- ],
6621
- "aliasPermutations": [],
6622
- "permutations": [
6623
- "hardis:org:diagnose:unsecure-connected-apps",
6624
- "org:hardis:diagnose:unsecure-connected-apps",
6625
- "org:diagnose:hardis:unsecure-connected-apps",
6626
- "org:diagnose:unsecure-connected-apps:hardis",
6627
- "hardis:diagnose:org:unsecure-connected-apps",
6628
- "diagnose:hardis:org:unsecure-connected-apps",
6629
- "diagnose:org:hardis:unsecure-connected-apps",
6630
- "diagnose:org:unsecure-connected-apps:hardis",
6631
- "hardis:diagnose:unsecure-connected-apps:org",
6632
- "diagnose:hardis:unsecure-connected-apps:org",
6633
- "diagnose:unsecure-connected-apps:hardis:org",
6634
- "diagnose:unsecure-connected-apps:org:hardis",
6635
- "hardis:org:unsecure-connected-apps:diagnose",
6636
- "org:hardis:unsecure-connected-apps:diagnose",
6637
- "org:unsecure-connected-apps:hardis:diagnose",
6638
- "org:unsecure-connected-apps:diagnose:hardis",
6639
- "hardis:unsecure-connected-apps:org:diagnose",
6640
- "unsecure-connected-apps:hardis:org:diagnose",
6641
- "unsecure-connected-apps:org:hardis:diagnose",
6642
- "unsecure-connected-apps:org:diagnose:hardis",
6643
- "hardis:unsecure-connected-apps:diagnose:org",
6644
- "unsecure-connected-apps:hardis:diagnose:org",
6645
- "unsecure-connected-apps:diagnose:hardis:org",
6646
- "unsecure-connected-apps:diagnose:org:hardis"
6647
- ]
6648
- },
6649
- "hardis:org:diagnose:unused-apex-classes": {
6650
- "aliases": [],
6651
- "args": {},
6652
- "description": "List all async Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days.\n \nThe result class list probably can be removed from the project, and that will improve your test classes performances 😊\n\nThe number of unused day is overridable using --days option. \n\nThe command uses queries on AsyncApexJob and CronTrigger technical tables to build the result.\n\nApex Classes CreatedBy and CreatedOn fields are calculated from MIN(date from git, date from org)\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-apex-classes/) and can output Grafana, Slack and MsTeams Notifications.\n\n![](https://sfdx-hardis.cloudity.com/assets/images/screenshot-monitoring-unused-apex-grafana.jpg)\n",
6653
- "examples": [
6654
- "$ sf hardis:org:diagnose:unused-apex-classes",
6655
- "$ sf hardis:org:diagnose:unused-apex-classes --days 700"
6656
- ],
6657
- "flags": {
6658
- "json": {
6659
- "description": "Format output as json.",
6660
- "helpGroup": "GLOBAL",
6661
- "name": "json",
6662
- "allowNo": false,
6663
- "type": "boolean"
6664
- },
6665
- "flags-dir": {
6666
- "helpGroup": "GLOBAL",
6667
- "name": "flags-dir",
6668
- "summary": "Import flag values from a directory.",
6669
- "hasDynamicHelp": false,
6670
- "multiple": false,
6671
- "type": "option"
6672
- },
6673
- "outputfile": {
6674
- "char": "f",
6675
- "description": "Force the path and name of output report file. Must end with .csv",
6676
- "name": "outputfile",
6677
- "hasDynamicHelp": false,
6678
- "multiple": false,
6679
- "type": "option"
6680
- },
6681
- "days": {
6682
- "char": "t",
6683
- "description": "Extracts the users that have been inactive for the amount of days specified. In CI, default is 180 days",
6684
- "name": "days",
6685
- "hasDynamicHelp": false,
6686
- "multiple": false,
6687
- "type": "option"
6688
- },
6689
- "debug": {
6690
- "char": "d",
6691
- "description": "Activate debug mode (more logs)",
6692
- "name": "debug",
6693
- "allowNo": false,
6694
- "type": "boolean"
6695
- },
6696
- "websocket": {
6697
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
6698
- "name": "websocket",
6699
- "hasDynamicHelp": false,
6700
- "multiple": false,
6701
- "type": "option"
6702
- },
6703
- "skipauth": {
6704
- "description": "Skip authentication check when a default username is required",
6705
- "name": "skipauth",
6706
- "allowNo": false,
6707
- "type": "boolean"
6708
- },
6709
- "target-org": {
6710
- "aliases": [
6711
- "targetusername",
6712
- "u"
6713
- ],
6714
- "char": "o",
6715
- "deprecateAliases": true,
6716
- "name": "target-org",
6717
- "noCacheDefault": true,
6718
- "required": true,
6719
- "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
6720
- "hasDynamicHelp": true,
6721
- "multiple": false,
6722
- "type": "option"
6723
- }
6724
- },
6725
- "hasDynamicHelp": true,
6726
- "hiddenAliases": [],
6727
- "id": "hardis:org:diagnose:unused-apex-classes",
6728
- "pluginAlias": "sfdx-hardis",
6729
- "pluginName": "sfdx-hardis",
6730
- "pluginType": "core",
6731
- "strict": true,
6732
- "enableJsonFlag": true,
6733
- "title": "Detect unused Apex classes in an org",
6734
- "requiresProject": false,
6735
- "isESM": true,
6736
- "relativePath": [
6737
- "lib",
6738
- "commands",
6739
- "hardis",
6740
- "org",
6741
- "diagnose",
6742
- "unused-apex-classes.js"
6743
- ],
6744
- "aliasPermutations": [],
6745
- "permutations": [
6746
- "hardis:org:diagnose:unused-apex-classes",
6747
- "org:hardis:diagnose:unused-apex-classes",
6748
- "org:diagnose:hardis:unused-apex-classes",
6749
- "org:diagnose:unused-apex-classes:hardis",
6750
- "hardis:diagnose:org:unused-apex-classes",
6751
- "diagnose:hardis:org:unused-apex-classes",
6752
- "diagnose:org:hardis:unused-apex-classes",
6753
- "diagnose:org:unused-apex-classes:hardis",
6754
- "hardis:diagnose:unused-apex-classes:org",
6755
- "diagnose:hardis:unused-apex-classes:org",
6756
- "diagnose:unused-apex-classes:hardis:org",
6757
- "diagnose:unused-apex-classes:org:hardis",
6758
- "hardis:org:unused-apex-classes:diagnose",
6759
- "org:hardis:unused-apex-classes:diagnose",
6760
- "org:unused-apex-classes:hardis:diagnose",
6761
- "org:unused-apex-classes:diagnose:hardis",
6762
- "hardis:unused-apex-classes:org:diagnose",
6763
- "unused-apex-classes:hardis:org:diagnose",
6764
- "unused-apex-classes:org:hardis:diagnose",
6765
- "unused-apex-classes:org:diagnose:hardis",
6766
- "hardis:unused-apex-classes:diagnose:org",
6767
- "unused-apex-classes:hardis:diagnose:org",
6768
- "unused-apex-classes:diagnose:hardis:org",
6769
- "unused-apex-classes:diagnose:org:hardis"
7126
+ "org:releaseupdates:hardis:diagnose",
7127
+ "org:releaseupdates:diagnose:hardis",
7128
+ "hardis:releaseupdates:org:diagnose",
7129
+ "releaseupdates:hardis:org:diagnose",
7130
+ "releaseupdates:org:hardis:diagnose",
7131
+ "releaseupdates:org:diagnose:hardis",
7132
+ "hardis:releaseupdates:diagnose:org",
7133
+ "releaseupdates:hardis:diagnose:org",
7134
+ "releaseupdates:diagnose:hardis:org",
7135
+ "releaseupdates:diagnose:org:hardis"
6770
7136
  ]
6771
7137
  },
6772
- "hardis:org:diagnose:unused-connected-apps": {
7138
+ "hardis:org:diagnose:storage-stats": {
6773
7139
  "aliases": [],
6774
7140
  "args": {},
6775
- "description": "\n## Command Behavior\n\n**Identifies and reports on potentially unused Connected Apps in a Salesforce org, suggesting candidates for deletion or deactivation.**\n\nThis command helps improve org security and reduce technical debt by pinpointing Connected Apps that are no longer actively used. Connected Apps can pose security risks if left unmonitored, and cleaning them up contributes to a healthier Salesforce environment.\n\nKey functionalities:\n\n- **Connected App Data Collection:** Gathers information about all Connected Apps in the org, including creation and last modified dates, and associated users.\n- **Usage Analysis:** Analyzes `LoginHistory` and `OAuthToken` records to determine the last usage date of each Connected App.\n- **Inactivity Detection:** Flags Connected Apps as potentially unused if they have no recent login history or OAuth token usage.\n- **Accessibility Check:** Examines Connected App metadata to identify if they are accessible (e.g., if they require admin approval and have no profiles or permission sets assigned).\n- **Ignored Apps:** Automatically ignores a predefined list of common Salesforce Connected Apps (e.g., `Salesforce CLI`, `Salesforce Mobile Dashboards`). You can extend this list by defining the `ALLOWED_INACTIVE_CONNECTED_APPS` environment variable.\n- **CSV Report Generation:** Generates a CSV file containing details of all analyzed Connected Apps, including their usage status, last usage date, and reasons for being flagged as potentially unused.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of potentially unused Connected Apps.\n\n**Default Ignored Connected Apps:**\n\n- Ant Migration Tool\n- Chatter Desktop\n- Chatter Mobile for BlackBerry\n- Force.com IDE\n- OIQ_Integration\n- Salesforce CLI\n- Salesforce Files\n- Salesforce Mobile Dashboards\n- Salesforce Touch\n- Salesforce for Outlook\n- SalesforceA\n- SalesforceA for Android\n- SalesforceA for iOS\n- SalesforceDX Namespace Registry\n- SalesforceIQ\n\nYou can add more ignored apps by defining a comma-separated list of names in the `ALLOWED_INACTIVE_CONNECTED_APPS` environment variable.\n\n_Example: \nALLOWED_INACTIVE_CONNECTED_APPS=My App 1,My App 2, My App 3_\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-connected-apps/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce SOQL Queries:** It performs SOQL queries against `ConnectedApplication`, `LoginHistory`, and `OAuthToken` objects to gather comprehensive data about Connected Apps and their usage.\n- **Temporary SFDX Project:** It creates a temporary SFDX project to retrieve Connected App metadata, allowing for local parsing and analysis of their XML files.\n- **Metadata Parsing:** It parses the `connectedApp-meta.xml` files to check for `isAdminApproved` and the presence of `profileName` or `permissionsetName` to determine accessibility.\n- **Data Correlation:** It correlates data from various Salesforce objects to build a complete picture of each Connected App's usage and status.\n- **Date Calculation:** Uses `moment` to calculate the time since the last OAuth token usage.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of unused Connected Apps.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and metrics for monitoring dashboards.\n- **File System Operations:** Uses `fs-extra` for creating and removing temporary directories and files.\n- **Environment Variable Reading:** Reads the `ALLOWED_INACTIVE_CONNECTED_APPS` environment variable to customize the list of ignored Connected Apps.\n</details>\n",
7141
+ "description": "**Extracts and analyzes Data Storage usage for a Salesforce org, providing detailed per-object breakdowns with yearly trends.**\n\nThis command provides a comprehensive overview of your Salesforce data storage consumption. It's particularly useful for:\n\n- **Storage Management:** Understanding which SObjects consume the most storage and how usage has evolved over time.\n- **Cost Optimization:** Identifying storage-heavy objects that could be candidates for data archival or cleanup strategies.\n- **Capacity Planning:** Tracking storage trends to predict when additional capacity will be needed.\n- **Compliance & Governance:** Monitoring data growth patterns to ensure alignment with data retention policies.\n\nKey functionalities:\n\n- **Storage Limits Analysis:** Retrieves and displays org data storage limits, including total capacity, used storage, remaining storage, and percentage used. Detects and alerts on over-usage scenarios.\n- **SObject Discovery & Filtering:** Automatically discovers all SObjects in the org and filters them to focus on production/custom objects (excludes metadata types, platform-only objects, and cached empty objects).\n- **Interactive Selection:** Prompts the user to select which SObjects to analyze and choose between `CreatedDate` or `LastModifiedDate` for temporal breakdown.\n- **Yearly Storage Breakdown:** Executes grouped SOQL queries per object to calculate record counts by year, providing historical growth trends.\n- **Storage Estimation:** Estimates storage usage for each object using an average record size heuristic (2 KB per record) and calculates the percentage of org quota consumed.\n- **Dual CSV Reports:** Generates two CSV files: a detailed by-year breakdown and a totals-per-object summary, both suitable for spreadsheet analysis and reporting.\n- **Empty Objects Cache:** Maintains a per-user cache of objects detected with zero records to optimize subsequent runs by skipping empty tables.\n- **Progress Tracking:** Sends WebSocket progress messages for integration with external UIs and monitoring dashboards.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Limits Retrieval:** Calls `conn.limits()` to retrieve the `DataStorageMB` object containing `Max` and `Remaining` values. Handles negative `Remaining` values (over-usage scenarios) by calculating `overUsageMB` and adjusting display values.\n- **SObject Discovery:** Uses `conn.metadata.list([{ type: 'CustomObject' }])` to get custom objects and `conn.describeGlobal()` to get all SObjects. Filters by object capabilities (`layoutable`, `queryable`, `retrieveable`, `createable`, `updateable`, `deletable`) and excludes metadata types (`__mdt` suffix) and cached empty objects.\n- **User Interaction:** Uses `prompts` for interactive multi-select of SObjects and single-select for date field choice. All objects are pre-selected by default for user convenience.\n- **Yearly Aggregation Queries:** For each selected SObject, executes a grouped SOQL query: `SELECT CALENDAR_YEAR(<DateField>) year, COUNT(Id) total FROM <SObject> GROUP BY CALENDAR_YEAR(<DateField>) ORDER BY CALENDAR_YEAR(<DateField>) DESC`. Handles query errors gracefully (logs error and continues with next object).\n- **Storage Calculation:** Applies a conservative average record size of 2 KB (2048 bytes) to estimate storage consumption. Calculates both MB usage and percentage of org quota for each object and year.\n- **Report Generation:** Uses `generateCsvFile` and `generateReportPath` helpers to create two CSV files in the reports directory:\n - Detailed breakdown: includes all yearly statistics per object\n - Totals summary: includes only aggregate totals per object\n- **Caching Mechanism:** Writes a JSON cache file per authenticated username (sanitized) in the reports directory (`<username>_empty_tables_cache.json`) containing an array of empty object names. The cache is updated after each run with newly detected empty objects.\n- **Progress & UX:** Uses `WebSocketClient` to emit start/step/end progress messages for external monitoring. Outputs summary tables with `uxLogTable` and status messages with `uxLog`.\n- **Return Value:** Returns a JSON object containing `tableStorageInfos` (all rows), `tableStorageInfosTotals` (summary rows), `storageLimits` (org limits object), and `outputFiles` (paths to generated CSV/XLSX reports).\n</details>\n\n![](https://sfdx-hardis.cloudity.com/assets/images/storage-usage-year-breakdown.png)\n\n![](https://sfdx-hardis.cloudity.com/assets/images/storage-usage-total.png)\n",
6776
7142
  "examples": [
6777
- "$ sf hardis:org:diagnose:unused-connected-apps"
7143
+ "$ sf hardis:org:diagnose:storage-stats"
6778
7144
  ],
6779
7145
  "flags": {
6780
7146
  "json": {
@@ -6838,31 +7204,14 @@
6838
7204
  },
6839
7205
  "hasDynamicHelp": true,
6840
7206
  "hiddenAliases": [],
6841
- "id": "hardis:org:diagnose:unused-connected-apps",
7207
+ "id": "hardis:org:diagnose:storage-stats",
6842
7208
  "pluginAlias": "sfdx-hardis",
6843
7209
  "pluginName": "sfdx-hardis",
6844
7210
  "pluginType": "core",
6845
7211
  "strict": true,
6846
7212
  "enableJsonFlag": true,
6847
- "title": "Unused Connected Apps in an org",
6848
- "allowedInactiveConnectedApps": [
6849
- "Ant Migration Tool",
6850
- "Chatter Desktop",
6851
- "Chatter Mobile for BlackBerry",
6852
- "Force.com IDE",
6853
- "OIQ_Integration",
6854
- "Salesforce CLI",
6855
- "Salesforce Files",
6856
- "Salesforce Mobile Dashboards",
6857
- "Salesforce Touch",
6858
- "Salesforce for Outlook",
6859
- "SalesforceA",
6860
- "SalesforceA for Android",
6861
- "SalesforceA for iOS",
6862
- "SalesforceDX Namespace Registry",
6863
- "SalesforceIQ"
6864
- ],
6865
- "requiresProject": false,
7213
+ "title": "Extract Data Storage stats",
7214
+ "requiresProject": true,
6866
7215
  "isESM": true,
6867
7216
  "relativePath": [
6868
7217
  "lib",
@@ -6870,43 +7219,42 @@
6870
7219
  "hardis",
6871
7220
  "org",
6872
7221
  "diagnose",
6873
- "unused-connected-apps.js"
7222
+ "storage-stats.js"
6874
7223
  ],
6875
7224
  "aliasPermutations": [],
6876
7225
  "permutations": [
6877
- "hardis:org:diagnose:unused-connected-apps",
6878
- "org:hardis:diagnose:unused-connected-apps",
6879
- "org:diagnose:hardis:unused-connected-apps",
6880
- "org:diagnose:unused-connected-apps:hardis",
6881
- "hardis:diagnose:org:unused-connected-apps",
6882
- "diagnose:hardis:org:unused-connected-apps",
6883
- "diagnose:org:hardis:unused-connected-apps",
6884
- "diagnose:org:unused-connected-apps:hardis",
6885
- "hardis:diagnose:unused-connected-apps:org",
6886
- "diagnose:hardis:unused-connected-apps:org",
6887
- "diagnose:unused-connected-apps:hardis:org",
6888
- "diagnose:unused-connected-apps:org:hardis",
6889
- "hardis:org:unused-connected-apps:diagnose",
6890
- "org:hardis:unused-connected-apps:diagnose",
6891
- "org:unused-connected-apps:hardis:diagnose",
6892
- "org:unused-connected-apps:diagnose:hardis",
6893
- "hardis:unused-connected-apps:org:diagnose",
6894
- "unused-connected-apps:hardis:org:diagnose",
6895
- "unused-connected-apps:org:hardis:diagnose",
6896
- "unused-connected-apps:org:diagnose:hardis",
6897
- "hardis:unused-connected-apps:diagnose:org",
6898
- "unused-connected-apps:hardis:diagnose:org",
6899
- "unused-connected-apps:diagnose:hardis:org",
6900
- "unused-connected-apps:diagnose:org:hardis"
7226
+ "hardis:org:diagnose:storage-stats",
7227
+ "org:hardis:diagnose:storage-stats",
7228
+ "org:diagnose:hardis:storage-stats",
7229
+ "org:diagnose:storage-stats:hardis",
7230
+ "hardis:diagnose:org:storage-stats",
7231
+ "diagnose:hardis:org:storage-stats",
7232
+ "diagnose:org:hardis:storage-stats",
7233
+ "diagnose:org:storage-stats:hardis",
7234
+ "hardis:diagnose:storage-stats:org",
7235
+ "diagnose:hardis:storage-stats:org",
7236
+ "diagnose:storage-stats:hardis:org",
7237
+ "diagnose:storage-stats:org:hardis",
7238
+ "hardis:org:storage-stats:diagnose",
7239
+ "org:hardis:storage-stats:diagnose",
7240
+ "org:storage-stats:hardis:diagnose",
7241
+ "org:storage-stats:diagnose:hardis",
7242
+ "hardis:storage-stats:org:diagnose",
7243
+ "storage-stats:hardis:org:diagnose",
7244
+ "storage-stats:org:hardis:diagnose",
7245
+ "storage-stats:org:diagnose:hardis",
7246
+ "hardis:storage-stats:diagnose:org",
7247
+ "storage-stats:hardis:diagnose:org",
7248
+ "storage-stats:diagnose:hardis:org",
7249
+ "storage-stats:diagnose:org:hardis"
6901
7250
  ]
6902
7251
  },
6903
- "hardis:org:diagnose:unusedlicenses": {
7252
+ "hardis:org:diagnose:unsecure-connected-apps": {
6904
7253
  "aliases": [],
6905
7254
  "args": {},
6906
- "description": "\n## Command Behavior\n\n**Detects and suggests the deletion of unused Permission Set License Assignments in a Salesforce org.**\n\nWhen a Permission Set (PS) linked to a Permission Set License (PSL) is assigned to a user, a Permission Set License Assignment (PSLA) is automatically created. However, when that PS is unassigned from the user, the PSLA is *not* automatically deleted. This can lead to organizations being charged for unused PSLAs, representing a hidden cost and technical debt.\n\nThis command identifies such useless PSLAs and provides options to delete them, helping to optimize license usage and reduce unnecessary expenses.\n\nKey functionalities:\n\n- **PSLA Detection:** Queries the Salesforce org to find all active PSLAs.\n- **Usage Verification:** Correlates PSLAs with actual Permission Set Assignments and Permission Set Group Assignments to determine if the underlying Permission Sets are still assigned to the user.\n- **Special Case Handling:** Accounts for specific scenarios where profiles might implicitly assign PSLAs (e.g., `Salesforce API Only` profile assigning `SalesforceAPIIntegrationPsl`) and allows for always excluding certain PSLAs from the unused check.\n- **Reporting:** Generates a CSV report of all identified unused PSLAs, including the user and the associated Permission Set License.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of unused PSLAs.\n- **Interactive Deletion:** In non-CI environments, it offers an interactive prompt to bulk delete the identified unused PSLAs.\n\nMany thanks to [Vincent Finet](https://www.linkedin.com/in/vincentfinet/) for the inspiration during his great speaker session at [French Touch Dreamin '23](https://frenchtouchdreamin.com/), and his kind agreement for reusing such inspiration in this command 😊\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-licenses/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves extensive querying of Salesforce objects and data correlation:\n\n- **SOQL Queries (Bulk API):** It uses `bulkQuery` and `bulkQueryChunksIn` to efficiently retrieve large volumes of data from `PermissionSetLicenseAssign`, `PermissionSetLicense`, `PermissionSet`, `PermissionSetGroupComponent`, and `PermissionSetAssignment` objects.\n- **Data Correlation:** It meticulously correlates data across these objects to determine if a `PermissionSetLicenseAssign` record has a corresponding active assignment to a Permission Set or Permission Set Group for the same user.\n- **Filtering Logic:** It applies complex filtering logic to exclude PSLAs that are genuinely in use or are part of predefined exceptions (e.g., `alwaysExcludeForActiveUsersPermissionSetLicenses`).\n- **Bulk Deletion:** If the user opts to delete unused PSLAs, it uses `bulkUpdate` with the `delete` operation to efficiently remove multiple records.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of unused PSLAs.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and metrics for monitoring dashboards.\n- **User Interaction:** Uses `prompts` for interactive confirmation before performing deletion operations.\n</details>\n",
7255
+ "description": "\n## Command Behavior\n\n**Detects unsecured Connected Apps in a Salesforce org and generates detailed reports for security analysis.**\n\nThis command is a critical security diagnostic tool that helps administrators identify Connected Apps that may pose security risks due to improper configuration. It provides comprehensive analysis of OAuth tokens and Connected App security settings to ensure proper access control.\n\nKey functionalities:\n\n- **OAuth Token Analysis:** Queries all OAuth tokens in the org using SOQL to retrieve comprehensive token information including app names, users, authorization status, and usage statistics.\n- **Security Status Assessment:** Evaluates each Connected App's security configuration by checking the `IsUsingAdminAuthorization` flag to determine if admin pre-approval is required.\n- **Unsecured App Detection:** Identifies Connected Apps that allow users to authorize themselves without admin approval, which can pose security risks.\n- **Detailed Reporting:** Generates two comprehensive CSV reports:\n - **OAuth Tokens Report:** Lists all OAuth tokens with security status, user information, and usage data\n - **Connected Apps Summary:** Aggregates unsecured Connected Apps with counts of associated OAuth tokens\n- **Visual Indicators:** Uses status icons (❌ for unsecured, for secured) to provide immediate visual feedback on security status.\n- **Security Recommendations:** Provides actionable guidance on how to secure Connected Apps through proper configuration.\n- **Notifications:** Sends alerts to configured channels (Grafana, Slack, MS Teams) with security findings and attached reports.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-org-security/) and can output Grafana, Slack and MsTeams Notifications.\n\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/jHv8yrSK8Dg\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Query Execution:** Executes a comprehensive SOQL query on the `OauthToken` object, joining with `AppMenuItem` and `User` objects to gather complete security context.\n- **Security Analysis Logic:** Analyzes the `AppMenuItem.IsUsingAdminAuthorization` field to determine if a Connected App requires admin pre-approval for user authorization.\n- **Data Transformation:** Processes raw SOQL results to add security status indicators and reorganize data for optimal reporting and analysis.\n- **Aggregation Processing:** Groups OAuth tokens by Connected App name to provide summary statistics and identify the most problematic applications.\n- **Report Generation:** Uses `generateCsvFile` to create structured CSV reports with proper formatting and metadata for easy analysis and sharing.\n- **Notification Integration:** Integrates with the `NotifProvider` to send security alerts with detailed metrics, including the number of unsecured Connected Apps and associated OAuth tokens.\n- **File Management:** Generates multiple output formats (CSV, XLSX) and manages file paths using `generateReportPath` for consistent report organization.\n- **Connection Management:** Uses `setConnectionVariables` to ensure proper authentication context for notification providers that require org connection details.\n</details>\n",
6907
7256
  "examples": [
6908
- "$ sf hardis:org:diagnose:unusedlicenses",
6909
- "$ sf hardis:org:diagnose:unusedlicenses --fix"
7257
+ "$ sf hardis:org:diagnose:unsecure-connected-apps"
6910
7258
  ],
6911
7259
  "flags": {
6912
7260
  "json": {
@@ -6970,32 +7318,14 @@
6970
7318
  },
6971
7319
  "hasDynamicHelp": true,
6972
7320
  "hiddenAliases": [],
6973
- "id": "hardis:org:diagnose:unusedlicenses",
7321
+ "id": "hardis:org:diagnose:unsecure-connected-apps",
6974
7322
  "pluginAlias": "sfdx-hardis",
6975
7323
  "pluginName": "sfdx-hardis",
6976
7324
  "pluginType": "core",
6977
7325
  "strict": true,
6978
7326
  "enableJsonFlag": true,
6979
- "title": "Detect unused Permission Set Licenses (beta)",
7327
+ "title": "Detect Unsecured Connected Apps",
6980
7328
  "requiresProject": false,
6981
- "additionalPermissionSetsToAlwaysGet": [
6982
- "Sales_User"
6983
- ],
6984
- "permSetsPermSetLicenses": [
6985
- {
6986
- "permSet": "Sales_User",
6987
- "permSetLicense": "SalesUserPsl"
6988
- }
6989
- ],
6990
- "profilesPermissionSetLicenses": [
6991
- {
6992
- "profile": "Salesforce API Only",
6993
- "permSetLicense": "SalesforceAPIIntegrationPsl"
6994
- }
6995
- ],
6996
- "alwaysExcludeForActiveUsersPermissionSetLicenses": [
6997
- "IdentityConnect"
6998
- ],
6999
7329
  "isESM": true,
7000
7330
  "relativePath": [
7001
7331
  "lib",
@@ -7003,46 +7333,43 @@
7003
7333
  "hardis",
7004
7334
  "org",
7005
7335
  "diagnose",
7006
- "unusedlicenses.js"
7336
+ "unsecure-connected-apps.js"
7007
7337
  ],
7008
7338
  "aliasPermutations": [],
7009
7339
  "permutations": [
7010
- "hardis:org:diagnose:unusedlicenses",
7011
- "org:hardis:diagnose:unusedlicenses",
7012
- "org:diagnose:hardis:unusedlicenses",
7013
- "org:diagnose:unusedlicenses:hardis",
7014
- "hardis:diagnose:org:unusedlicenses",
7015
- "diagnose:hardis:org:unusedlicenses",
7016
- "diagnose:org:hardis:unusedlicenses",
7017
- "diagnose:org:unusedlicenses:hardis",
7018
- "hardis:diagnose:unusedlicenses:org",
7019
- "diagnose:hardis:unusedlicenses:org",
7020
- "diagnose:unusedlicenses:hardis:org",
7021
- "diagnose:unusedlicenses:org:hardis",
7022
- "hardis:org:unusedlicenses:diagnose",
7023
- "org:hardis:unusedlicenses:diagnose",
7024
- "org:unusedlicenses:hardis:diagnose",
7025
- "org:unusedlicenses:diagnose:hardis",
7026
- "hardis:unusedlicenses:org:diagnose",
7027
- "unusedlicenses:hardis:org:diagnose",
7028
- "unusedlicenses:org:hardis:diagnose",
7029
- "unusedlicenses:org:diagnose:hardis",
7030
- "hardis:unusedlicenses:diagnose:org",
7031
- "unusedlicenses:hardis:diagnose:org",
7032
- "unusedlicenses:diagnose:hardis:org",
7033
- "unusedlicenses:diagnose:org:hardis"
7340
+ "hardis:org:diagnose:unsecure-connected-apps",
7341
+ "org:hardis:diagnose:unsecure-connected-apps",
7342
+ "org:diagnose:hardis:unsecure-connected-apps",
7343
+ "org:diagnose:unsecure-connected-apps:hardis",
7344
+ "hardis:diagnose:org:unsecure-connected-apps",
7345
+ "diagnose:hardis:org:unsecure-connected-apps",
7346
+ "diagnose:org:hardis:unsecure-connected-apps",
7347
+ "diagnose:org:unsecure-connected-apps:hardis",
7348
+ "hardis:diagnose:unsecure-connected-apps:org",
7349
+ "diagnose:hardis:unsecure-connected-apps:org",
7350
+ "diagnose:unsecure-connected-apps:hardis:org",
7351
+ "diagnose:unsecure-connected-apps:org:hardis",
7352
+ "hardis:org:unsecure-connected-apps:diagnose",
7353
+ "org:hardis:unsecure-connected-apps:diagnose",
7354
+ "org:unsecure-connected-apps:hardis:diagnose",
7355
+ "org:unsecure-connected-apps:diagnose:hardis",
7356
+ "hardis:unsecure-connected-apps:org:diagnose",
7357
+ "unsecure-connected-apps:hardis:org:diagnose",
7358
+ "unsecure-connected-apps:org:hardis:diagnose",
7359
+ "unsecure-connected-apps:org:diagnose:hardis",
7360
+ "hardis:unsecure-connected-apps:diagnose:org",
7361
+ "unsecure-connected-apps:hardis:diagnose:org",
7362
+ "unsecure-connected-apps:diagnose:hardis:org",
7363
+ "unsecure-connected-apps:diagnose:org:hardis"
7034
7364
  ]
7035
7365
  },
7036
- "hardis:org:diagnose:unusedusers": {
7366
+ "hardis:org:diagnose:unused-apex-classes": {
7037
7367
  "aliases": [],
7038
7368
  "args": {},
7039
- "description": "\n## Command Behavior\n\n**Detects and reports on inactive or unused Salesforce user accounts, helping to optimize license usage and enhance security.**\n\nEfficient user management is vital in Salesforce to ensure resources are optimized and costs are controlled. However, inactive or unused user accounts can often go unnoticed, leading to wasted licenses and potential security risks. This tool addresses this challenge by enabling administrators to identify users who haven't logged in within a specified period.\n\nBy analyzing user login activity and last login timestamps, this feature highlights inactive user accounts, allowing administrators to take appropriate action. Whether it's deactivating dormant accounts, freeing up licenses, or ensuring compliance with security policies, this functionality empowers administrators to maintain a lean and secure Salesforce environment.\n\nKey functionalities:\n\n- **Inactivity Detection:** Identifies users who have not logged in for a specified number of days (`--days` flag, default 180 days in CI, 365 days otherwise).\n- **License Type Filtering:** Allows filtering users by license type using `--licensetypes` (e.g., `all-crm`, `all-paying`) or specific license identifiers using `--licenseidentifiers`.\n - `all-crm`: Includes `SFDC`, `AUL`, `AUL1`, `AULL_IGHT` licenses.\n - `all-paying`: Includes `SFDC`, `AUL`, `AUL1`, `AULL_IGHT`, `PID_Customer_Community`, `PID_Customer_Community_Login`, `PID_Partner_Community`, `PID_Partner_Community_Login` licenses.\n - Note: You can see the full list of available license identifiers in [Salesforce Documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/sfdx_cli_reference/sforce_api_objects_userlicense.htm).\n- **Active User Retrieval:** The `--returnactiveusers` flag inverts the command, allowing you to retrieve active users who *have* logged in during the specified period.\n- **CSV Report Generation:** Generates a CSV file containing details of all identified users (inactive or active), including their last login date, profile, and license information.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of inactive or active users.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-inactive-users/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Query (Bulk API):** It uses `bulkQuery` to efficiently retrieve user records from the Salesforce `User` object. The SOQL query dynamically constructs its WHERE clause based on the `--days`, `--licensetypes`, `--licenseidentifiers`, and `--returnactiveusers` flags.\n- **Interactive Prompts:** Uses `prompts` to interactively ask the user for the number of inactive days and license types if not provided via flags.\n- **License Mapping:** Internally maps common license type aliases (e.g., `all-crm`) to their corresponding Salesforce `LicenseDefinitionKey` values.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of users.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and metrics for monitoring dashboards.\n- **User Feedback:** Provides a summary of the findings in the console, indicating the number of inactive or active users found.\n</details>",
7369
+ "description": "List all async Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days.\n \nThe result class list probably can be removed from the project, and that will improve your test classes performances 😊\n\nThe number of unused day is overridable using --days option. \n\nThe command uses queries on AsyncApexJob and CronTrigger technical tables to build the result.\n\nApex Classes CreatedBy and CreatedOn fields are calculated from MIN(date from git, date from org)\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-apex-classes/) and can output Grafana, Slack and MsTeams Notifications.\n\n![](https://sfdx-hardis.cloudity.com/assets/images/screenshot-monitoring-unused-apex-grafana.jpg)\n",
7040
7370
  "examples": [
7041
- "$ sf hardis:org:diagnose:unusedusers",
7042
- "$ sf hardis:org:diagnose:unusedusers --days 365",
7043
- "$ sf hardis:org:diagnose:unusedusers --days 60 --licensetypes all-crm",
7044
- "$ sf hardis:org:diagnose:unusedusers --days 60 --licenseidentifiers SFDC,AUL,AUL1",
7045
- "$ sf hardis:org:diagnose:unusedusers --days 60 --licensetypes all-crm --returnactiveusers"
7371
+ "$ sf hardis:org:diagnose:unused-apex-classes",
7372
+ "$ sf hardis:org:diagnose:unused-apex-classes --days 700"
7046
7373
  ],
7047
7374
  "flags": {
7048
7375
  "json": {
@@ -7076,33 +7403,6 @@
7076
7403
  "multiple": false,
7077
7404
  "type": "option"
7078
7405
  },
7079
- "licensetypes": {
7080
- "char": "l",
7081
- "description": "Type of licenses to check. If set, do not use licenseidentifiers option. In CI, default is all-crm",
7082
- "name": "licensetypes",
7083
- "hasDynamicHelp": false,
7084
- "multiple": false,
7085
- "options": [
7086
- "all",
7087
- "all-crm",
7088
- "all-paying"
7089
- ],
7090
- "type": "option"
7091
- },
7092
- "licenseidentifiers": {
7093
- "char": "i",
7094
- "description": "Comma-separated list of license identifiers, in case licensetypes is not used.. Identifiers available at https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_userlicense.htm",
7095
- "name": "licenseidentifiers",
7096
- "hasDynamicHelp": false,
7097
- "multiple": false,
7098
- "type": "option"
7099
- },
7100
- "returnactiveusers": {
7101
- "description": "Inverts the command by returning the active users",
7102
- "name": "returnactiveusers",
7103
- "allowNo": false,
7104
- "type": "boolean"
7105
- },
7106
7406
  "debug": {
7107
7407
  "char": "d",
7108
7408
  "description": "Activate debug mode (more logs)",
@@ -7141,13 +7441,13 @@
7141
7441
  },
7142
7442
  "hasDynamicHelp": true,
7143
7443
  "hiddenAliases": [],
7144
- "id": "hardis:org:diagnose:unusedusers",
7444
+ "id": "hardis:org:diagnose:unused-apex-classes",
7145
7445
  "pluginAlias": "sfdx-hardis",
7146
7446
  "pluginName": "sfdx-hardis",
7147
7447
  "pluginType": "core",
7148
7448
  "strict": true,
7149
7449
  "enableJsonFlag": true,
7150
- "title": "Detect unused Users in Salesforce",
7450
+ "title": "Detect unused Apex classes in an org",
7151
7451
  "requiresProject": false,
7152
7452
  "isESM": true,
7153
7453
  "relativePath": [
@@ -7156,44 +7456,42 @@
7156
7456
  "hardis",
7157
7457
  "org",
7158
7458
  "diagnose",
7159
- "unusedusers.js"
7459
+ "unused-apex-classes.js"
7160
7460
  ],
7161
7461
  "aliasPermutations": [],
7162
7462
  "permutations": [
7163
- "hardis:org:diagnose:unusedusers",
7164
- "org:hardis:diagnose:unusedusers",
7165
- "org:diagnose:hardis:unusedusers",
7166
- "org:diagnose:unusedusers:hardis",
7167
- "hardis:diagnose:org:unusedusers",
7168
- "diagnose:hardis:org:unusedusers",
7169
- "diagnose:org:hardis:unusedusers",
7170
- "diagnose:org:unusedusers:hardis",
7171
- "hardis:diagnose:unusedusers:org",
7172
- "diagnose:hardis:unusedusers:org",
7173
- "diagnose:unusedusers:hardis:org",
7174
- "diagnose:unusedusers:org:hardis",
7175
- "hardis:org:unusedusers:diagnose",
7176
- "org:hardis:unusedusers:diagnose",
7177
- "org:unusedusers:hardis:diagnose",
7178
- "org:unusedusers:diagnose:hardis",
7179
- "hardis:unusedusers:org:diagnose",
7180
- "unusedusers:hardis:org:diagnose",
7181
- "unusedusers:org:hardis:diagnose",
7182
- "unusedusers:org:diagnose:hardis",
7183
- "hardis:unusedusers:diagnose:org",
7184
- "unusedusers:hardis:diagnose:org",
7185
- "unusedusers:diagnose:hardis:org",
7186
- "unusedusers:diagnose:org:hardis"
7463
+ "hardis:org:diagnose:unused-apex-classes",
7464
+ "org:hardis:diagnose:unused-apex-classes",
7465
+ "org:diagnose:hardis:unused-apex-classes",
7466
+ "org:diagnose:unused-apex-classes:hardis",
7467
+ "hardis:diagnose:org:unused-apex-classes",
7468
+ "diagnose:hardis:org:unused-apex-classes",
7469
+ "diagnose:org:hardis:unused-apex-classes",
7470
+ "diagnose:org:unused-apex-classes:hardis",
7471
+ "hardis:diagnose:unused-apex-classes:org",
7472
+ "diagnose:hardis:unused-apex-classes:org",
7473
+ "diagnose:unused-apex-classes:hardis:org",
7474
+ "diagnose:unused-apex-classes:org:hardis",
7475
+ "hardis:org:unused-apex-classes:diagnose",
7476
+ "org:hardis:unused-apex-classes:diagnose",
7477
+ "org:unused-apex-classes:hardis:diagnose",
7478
+ "org:unused-apex-classes:diagnose:hardis",
7479
+ "hardis:unused-apex-classes:org:diagnose",
7480
+ "unused-apex-classes:hardis:org:diagnose",
7481
+ "unused-apex-classes:org:hardis:diagnose",
7482
+ "unused-apex-classes:org:diagnose:hardis",
7483
+ "hardis:unused-apex-classes:diagnose:org",
7484
+ "unused-apex-classes:hardis:diagnose:org",
7485
+ "unused-apex-classes:diagnose:hardis:org",
7486
+ "unused-apex-classes:diagnose:org:hardis"
7187
7487
  ]
7188
7488
  },
7189
- "hardis:org:generate:packagexmlfull": {
7489
+ "hardis:org:diagnose:unused-connected-apps": {
7190
7490
  "aliases": [],
7191
7491
  "args": {},
7192
- "description": "\n## Command Behavior\n\n**Generates a comprehensive `package.xml` file for a Salesforce org, including all metadata components, even managed ones.**\n\nThis command is essential for various Salesforce development and administration tasks, especially when you need a complete snapshot of an org's metadata. It goes beyond typical source tracking by including managed package components, which is crucial for understanding the full metadata footprint of an org.\n\nKey functionalities:\n\n- **Full Org Metadata Retrieval:** Connects to a specified Salesforce org (or prompts for one if not provided) and retrieves a complete list of all metadata types and their members.\n- **Managed Package Inclusion:** Unlike standard source retrieval, this command explicitly includes metadata from managed packages, providing a truly comprehensive `package.xml`.\n- **Customizable Output:** Allows you to specify the output file path for the generated `package.xml`.\n- **Interactive Org Selection:** If no target org is specified, it interactively prompts the user to choose an org. (or use --no-prompt to skip this step)\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce Metadata API Interaction:** It leverages the Salesforce Metadata API to list all available metadata types and then retrieve all components for each type.\n- **`buildOrgManifest` Utility:** The core logic for querying the org's metadata and constructing the `package.xml` is encapsulated within the `buildOrgManifest` utility function.\n- **XML Generation:** It dynamically builds the XML structure of the `package.xml` file, including the `types` and `members` elements for all retrieved metadata.\n- **File System Operations:** It writes the generated `package.xml` file to the specified output path.\n- **Interactive Prompts:** Uses `promptOrgUsernameDefault` to guide the user in selecting the target Salesforce org.\n</details>\n",
7492
+ "description": "\n## Command Behavior\n\n**Identifies and reports on potentially unused Connected Apps in a Salesforce org, suggesting candidates for deletion or deactivation.**\n\nThis command helps improve org security and reduce technical debt by pinpointing Connected Apps that are no longer actively used. Connected Apps can pose security risks if left unmonitored, and cleaning them up contributes to a healthier Salesforce environment.\n\nKey functionalities:\n\n- **Connected App Data Collection:** Gathers information about all Connected Apps in the org, including creation and last modified dates, and associated users.\n- **Usage Analysis:** Analyzes `LoginHistory` and `OAuthToken` records to determine the last usage date of each Connected App.\n- **Inactivity Detection:** Flags Connected Apps as potentially unused if they have no recent login history or OAuth token usage.\n- **Accessibility Check:** Examines Connected App metadata to identify if they are accessible (e.g., if they require admin approval and have no profiles or permission sets assigned).\n- **Ignored Apps:** Automatically ignores a predefined list of common Salesforce Connected Apps (e.g., `Salesforce CLI`, `Salesforce Mobile Dashboards`). You can extend this list by defining the `ALLOWED_INACTIVE_CONNECTED_APPS` environment variable.\n- **CSV Report Generation:** Generates a CSV file containing details of all analyzed Connected Apps, including their usage status, last usage date, and reasons for being flagged as potentially unused.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of potentially unused Connected Apps.\n\n**Default Ignored Connected Apps:**\n\n- Ant Migration Tool\n- Chatter Desktop\n- Chatter Mobile for BlackBerry\n- Force.com IDE\n- OIQ_Integration\n- Salesforce CLI\n- Salesforce Files\n- Salesforce Mobile Dashboards\n- Salesforce Touch\n- Salesforce for Outlook\n- SalesforceA\n- SalesforceA for Android\n- SalesforceA for iOS\n- SalesforceDX Namespace Registry\n- SalesforceIQ\n\nYou can add more ignored apps by defining a comma-separated list of names in the `ALLOWED_INACTIVE_CONNECTED_APPS` environment variable.\n\n_Example: \nALLOWED_INACTIVE_CONNECTED_APPS=My App 1,My App 2, My App 3_\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-connected-apps/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce SOQL Queries:** It performs SOQL queries against `ConnectedApplication`, `LoginHistory`, and `OAuthToken` objects to gather comprehensive data about Connected Apps and their usage.\n- **Temporary SFDX Project:** It creates a temporary SFDX project to retrieve Connected App metadata, allowing for local parsing and analysis of their XML files.\n- **Metadata Parsing:** It parses the `connectedApp-meta.xml` files to check for `isAdminApproved` and the presence of `profileName` or `permissionsetName` to determine accessibility.\n- **Data Correlation:** It correlates data from various Salesforce objects to build a complete picture of each Connected App's usage and status.\n- **Date Calculation:** Uses `moment` to calculate the time since the last OAuth token usage.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of unused Connected Apps.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and metrics for monitoring dashboards.\n- **File System Operations:** Uses `fs-extra` for creating and removing temporary directories and files.\n- **Environment Variable Reading:** Reads the `ALLOWED_INACTIVE_CONNECTED_APPS` environment variable to customize the list of ignored Connected Apps.\n</details>\n",
7193
7493
  "examples": [
7194
- "$ sf hardis:org:generate:packagexmlfull",
7195
- "$ sf hardis:org:generate:packagexmlfull --outputfile /tmp/packagexmlfull.xml",
7196
- "$ sf hardis:org:generate:packagexmlfull --target-org nico@example.com"
7494
+ "$ sf hardis:org:diagnose:unused-connected-apps"
7197
7495
  ],
7198
7496
  "flags": {
7199
7497
  "json": {
@@ -7212,7 +7510,8 @@
7212
7510
  "type": "option"
7213
7511
  },
7214
7512
  "outputfile": {
7215
- "description": "Output package.xml file",
7513
+ "char": "f",
7514
+ "description": "Force the path and name of output report file. Must end with .csv",
7216
7515
  "name": "outputfile",
7217
7516
  "hasDynamicHelp": false,
7218
7517
  "multiple": false,
@@ -7225,13 +7524,6 @@
7225
7524
  "allowNo": false,
7226
7525
  "type": "boolean"
7227
7526
  },
7228
- "no-prompt": {
7229
- "char": "n",
7230
- "description": "Do not prompt for org username, use the default one",
7231
- "name": "no-prompt",
7232
- "allowNo": false,
7233
- "type": "boolean"
7234
- },
7235
7527
  "websocket": {
7236
7528
  "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
7237
7529
  "name": "websocket",
@@ -7263,13 +7555,30 @@
7263
7555
  },
7264
7556
  "hasDynamicHelp": true,
7265
7557
  "hiddenAliases": [],
7266
- "id": "hardis:org:generate:packagexmlfull",
7558
+ "id": "hardis:org:diagnose:unused-connected-apps",
7267
7559
  "pluginAlias": "sfdx-hardis",
7268
7560
  "pluginName": "sfdx-hardis",
7269
7561
  "pluginType": "core",
7270
7562
  "strict": true,
7271
7563
  "enableJsonFlag": true,
7272
- "title": "Generate Full Org package.xml",
7564
+ "title": "Unused Connected Apps in an org",
7565
+ "allowedInactiveConnectedApps": [
7566
+ "Ant Migration Tool",
7567
+ "Chatter Desktop",
7568
+ "Chatter Mobile for BlackBerry",
7569
+ "Force.com IDE",
7570
+ "OIQ_Integration",
7571
+ "Salesforce CLI",
7572
+ "Salesforce Files",
7573
+ "Salesforce Mobile Dashboards",
7574
+ "Salesforce Touch",
7575
+ "Salesforce for Outlook",
7576
+ "SalesforceA",
7577
+ "SalesforceA for Android",
7578
+ "SalesforceA for iOS",
7579
+ "SalesforceDX Namespace Registry",
7580
+ "SalesforceIQ"
7581
+ ],
7273
7582
  "requiresProject": false,
7274
7583
  "isESM": true,
7275
7584
  "relativePath": [
@@ -7277,43 +7586,44 @@
7277
7586
  "commands",
7278
7587
  "hardis",
7279
7588
  "org",
7280
- "generate",
7281
- "packagexmlfull.js"
7589
+ "diagnose",
7590
+ "unused-connected-apps.js"
7282
7591
  ],
7283
7592
  "aliasPermutations": [],
7284
7593
  "permutations": [
7285
- "hardis:org:generate:packagexmlfull",
7286
- "org:hardis:generate:packagexmlfull",
7287
- "org:generate:hardis:packagexmlfull",
7288
- "org:generate:packagexmlfull:hardis",
7289
- "hardis:generate:org:packagexmlfull",
7290
- "generate:hardis:org:packagexmlfull",
7291
- "generate:org:hardis:packagexmlfull",
7292
- "generate:org:packagexmlfull:hardis",
7293
- "hardis:generate:packagexmlfull:org",
7294
- "generate:hardis:packagexmlfull:org",
7295
- "generate:packagexmlfull:hardis:org",
7296
- "generate:packagexmlfull:org:hardis",
7297
- "hardis:org:packagexmlfull:generate",
7298
- "org:hardis:packagexmlfull:generate",
7299
- "org:packagexmlfull:hardis:generate",
7300
- "org:packagexmlfull:generate:hardis",
7301
- "hardis:packagexmlfull:org:generate",
7302
- "packagexmlfull:hardis:org:generate",
7303
- "packagexmlfull:org:hardis:generate",
7304
- "packagexmlfull:org:generate:hardis",
7305
- "hardis:packagexmlfull:generate:org",
7306
- "packagexmlfull:hardis:generate:org",
7307
- "packagexmlfull:generate:hardis:org",
7308
- "packagexmlfull:generate:org:hardis"
7594
+ "hardis:org:diagnose:unused-connected-apps",
7595
+ "org:hardis:diagnose:unused-connected-apps",
7596
+ "org:diagnose:hardis:unused-connected-apps",
7597
+ "org:diagnose:unused-connected-apps:hardis",
7598
+ "hardis:diagnose:org:unused-connected-apps",
7599
+ "diagnose:hardis:org:unused-connected-apps",
7600
+ "diagnose:org:hardis:unused-connected-apps",
7601
+ "diagnose:org:unused-connected-apps:hardis",
7602
+ "hardis:diagnose:unused-connected-apps:org",
7603
+ "diagnose:hardis:unused-connected-apps:org",
7604
+ "diagnose:unused-connected-apps:hardis:org",
7605
+ "diagnose:unused-connected-apps:org:hardis",
7606
+ "hardis:org:unused-connected-apps:diagnose",
7607
+ "org:hardis:unused-connected-apps:diagnose",
7608
+ "org:unused-connected-apps:hardis:diagnose",
7609
+ "org:unused-connected-apps:diagnose:hardis",
7610
+ "hardis:unused-connected-apps:org:diagnose",
7611
+ "unused-connected-apps:hardis:org:diagnose",
7612
+ "unused-connected-apps:org:hardis:diagnose",
7613
+ "unused-connected-apps:org:diagnose:hardis",
7614
+ "hardis:unused-connected-apps:diagnose:org",
7615
+ "unused-connected-apps:hardis:diagnose:org",
7616
+ "unused-connected-apps:diagnose:hardis:org",
7617
+ "unused-connected-apps:diagnose:org:hardis"
7309
7618
  ]
7310
7619
  },
7311
- "hardis:org:monitor:all": {
7620
+ "hardis:org:diagnose:unusedlicenses": {
7312
7621
  "aliases": [],
7313
7622
  "args": {},
7314
- "description": "Monitor org, generate reports and sends notifications\n\nYou can disable some commands defining either a **monitoringDisable** property in `.sfdx-hardis.yml`, or a comma separated list in env variable **MONITORING_DISABLE**\n\nExample in .sfdx-hardis.yml:\n \n```yaml\nmonitoringDisable:\n - METADATA_STATUS\n - MISSING_ATTRIBUTES\n - UNUSED_METADATAS\n```\n \nExample in env var:\n\n```sh\nMONITORING_DISABLE=METADATA_STATUS,MISSING_ATTRIBUTES,UNUSED_METADATAS\n```\n\nA [default list of monitoring commands](https://sfdx-hardis.cloudity.com/salesforce-monitoring-home/#monitoring-commands) is used, if you want to override it you can define property **monitoringCommands** in your .sfdx-hardis.yml file\n\nExample:\n\n```yaml\nmonitoringCommands:\n - title: My Custom command\n command: sf my:custom:command\n - title: My Custom command 2\n command: sf my:other:custom:command\n```\n\nYou can force the daily run of all commands by defining env var `MONITORING_IGNORE_FREQUENCY=true`\n\nThe default list of commands is the following:\n\n| Key | Description | Command | Frequency |\n| :---: | :---- | :---- | :-----: |\n| [AUDIT_TRAIL](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/audittrail) | Detect suspect setup actions in major org | [sf hardis:org:diagnose:audittrail](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/audittrail) | daily |\n| [LEGACY_API](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/legacyapi) | Detect calls to deprecated API versions | [sf hardis:org:diagnose:legacyapi](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/legacyapi) | daily |\n| [ORG_LIMITS](https://sfdx-hardis.cloudity.com/hardis/org/monitor/limits) | Detect if org limits are close to be reached | [sf hardis:org:monitor:limits](https://sfdx-hardis.cloudity.com/hardis/org/monitor/limits) | daily |\n| [UNSECURED_CONNECTED_APPS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unsecure-connected-apps) | Detect unsecured Connected Apps in an org | [sf hardis:org:diagnose:unsecure-connected-apps](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unsecure-connected-apps) | daily |\n| [LICENSES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/licenses) | Extract licenses information | [sf hardis:org:diagnose:licenses](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/licenses) | weekly |\n| [LINT_ACCESS](https://sfdx-hardis.cloudity.com/hardis/lint/access) | Detect custom elements with no access rights defined in permission sets | [sf hardis:lint:access](https://sfdx-hardis.cloudity.com/hardis/lint/access) | weekly |\n| [UNUSED_LICENSES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedlicenses) | Detect permission set licenses that are assigned to users that do not need them | [sf hardis:org:diagnose:unusedlicenses](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedlicenses) | weekly |\n| [UNUSED_USERS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | Detect active users without recent logins | [sf hardis:org:diagnose:unusedusers](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | weekly |\n| [ACTIVE_USERS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | Detect active users with recent logins | [sf hardis:org:diagnose:unusedusers --returnactiveusers](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers) | weekly |\n| [ORG_INFO](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/instanceupgrade) | Get org info + SF instance info + next major upgrade date | [sf hardis:org:diagnose:instanceupgrade](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/instanceupgrade) | weekly |\n| [RELEASE_UPDATES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/releaseupdates) | Gather warnings about incoming and overdue Release Updates | [sf hardis:org:diagnose:releaseupdates](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/releaseupdates) | weekly |\n| [UNUSED_METADATAS](https://sfdx-hardis.cloudity.com/hardis/lint/unusedmetadatas) | Detect custom labels and custom permissions that are not in use | [sf hardis:lint:unusedmetadatas](https://sfdx-hardis.cloudity.com/hardis/lint/unusedmetadatas) | weekly |\n| [UNUSED_APEX_CLASSES](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-apex-classes) | Detect unused Apex classes in an org | [sf hardis:org:diagnose:unused-apex-classes](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-apex-classes) | weekly |\n| [CONNECTED_APPS](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-connected-apps) | Detect unused Connected Apps in an org | [sf hardis:org:diagnose:unused-connected-apps](https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-connected-apps) | weekly |\n| [METADATA_STATUS](https://sfdx-hardis.cloudity.com/hardis/lint/metadatastatus) | Detect inactive metadata | [sf hardis:lint:metadatastatus](https://sfdx-hardis.cloudity.com/hardis/lint/metadatastatus) | weekly |\n| [MISSING_ATTRIBUTES](https://sfdx-hardis.cloudity.com/hardis/lint/missingattributes) | Detect missing description on custom field | [sf hardis:lint:missingattributes](https://sfdx-hardis.cloudity.com/hardis/lint/missingattributes) | weekly |\n\n",
7623
+ "description": "\n## Command Behavior\n\n**Detects and suggests the deletion of unused Permission Set License Assignments in a Salesforce org.**\n\nWhen a Permission Set (PS) linked to a Permission Set License (PSL) is assigned to a user, a Permission Set License Assignment (PSLA) is automatically created. However, when that PS is unassigned from the user, the PSLA is *not* automatically deleted. This can lead to organizations being charged for unused PSLAs, representing a hidden cost and technical debt.\n\nThis command identifies such useless PSLAs and provides options to delete them, helping to optimize license usage and reduce unnecessary expenses.\n\nKey functionalities:\n\n- **PSLA Detection:** Queries the Salesforce org to find all active PSLAs.\n- **Usage Verification:** Correlates PSLAs with actual Permission Set Assignments and Permission Set Group Assignments to determine if the underlying Permission Sets are still assigned to the user.\n- **Special Case Handling:** Accounts for specific scenarios where profiles might implicitly assign PSLAs (e.g., `Salesforce API Only` profile assigning `SalesforceAPIIntegrationPsl`) and allows for always excluding certain PSLAs from the unused check.\n- **Reporting:** Generates a CSV report of all identified unused PSLAs, including the user and the associated Permission Set License.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of unused PSLAs.\n- **Interactive Deletion:** In non-CI environments, it offers an interactive prompt to bulk delete the identified unused PSLAs.\n\nMany thanks to [Vincent Finet](https://www.linkedin.com/in/vincentfinet/) for the inspiration during his great speaker session at [French Touch Dreamin '23](https://frenchtouchdreamin.com/), and his kind agreement for reusing such inspiration in this command 😊\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-licenses/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves extensive querying of Salesforce objects and data correlation:\n\n- **SOQL Queries (Bulk API):** It uses `bulkQuery` and `bulkQueryChunksIn` to efficiently retrieve large volumes of data from `PermissionSetLicenseAssign`, `PermissionSetLicense`, `PermissionSet`, `PermissionSetGroupComponent`, and `PermissionSetAssignment` objects.\n- **Data Correlation:** It meticulously correlates data across these objects to determine if a `PermissionSetLicenseAssign` record has a corresponding active assignment to a Permission Set or Permission Set Group for the same user.\n- **Filtering Logic:** It applies complex filtering logic to exclude PSLAs that are genuinely in use or are part of predefined exceptions (e.g., `alwaysExcludeForActiveUsersPermissionSetLicenses`).\n- **Bulk Deletion:** If the user opts to delete unused PSLAs, it uses `bulkUpdate` with the `delete` operation to efficiently remove multiple records.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of unused PSLAs.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and metrics for monitoring dashboards.\n- **User Interaction:** Uses `prompts` for interactive confirmation before performing deletion operations.\n</details>\n",
7315
7624
  "examples": [
7316
- "$ sf hardis:org:monitor:all"
7625
+ "$ sf hardis:org:diagnose:unusedlicenses",
7626
+ "$ sf hardis:org:diagnose:unusedlicenses --fix"
7317
7627
  ],
7318
7628
  "flags": {
7319
7629
  "json": {
@@ -7331,6 +7641,14 @@
7331
7641
  "multiple": false,
7332
7642
  "type": "option"
7333
7643
  },
7644
+ "outputfile": {
7645
+ "char": "f",
7646
+ "description": "Force the path and name of output report file. Must end with .csv",
7647
+ "name": "outputfile",
7648
+ "hasDynamicHelp": false,
7649
+ "multiple": false,
7650
+ "type": "option"
7651
+ },
7334
7652
  "debug": {
7335
7653
  "char": "d",
7336
7654
  "description": "Activate debug mode (more logs)",
@@ -7369,159 +7687,79 @@
7369
7687
  },
7370
7688
  "hasDynamicHelp": true,
7371
7689
  "hiddenAliases": [],
7372
- "id": "hardis:org:monitor:all",
7690
+ "id": "hardis:org:diagnose:unusedlicenses",
7373
7691
  "pluginAlias": "sfdx-hardis",
7374
7692
  "pluginName": "sfdx-hardis",
7375
7693
  "pluginType": "core",
7376
7694
  "strict": true,
7377
7695
  "enableJsonFlag": true,
7378
- "title": "Monitor org",
7379
- "monitoringCommandsDefault": [
7380
- {
7381
- "key": "AUDIT_TRAIL",
7382
- "title": "Detect suspect setup actions in major org",
7383
- "command": "sf hardis:org:diagnose:audittrail",
7384
- "frequency": "daily"
7385
- },
7386
- {
7387
- "key": "LEGACY_API",
7388
- "title": "Detect calls to deprecated API versions",
7389
- "command": "sf hardis:org:diagnose:legacyapi",
7390
- "frequency": "daily"
7391
- },
7392
- {
7393
- "key": "ORG_LIMITS",
7394
- "title": "Detect if org limits are close to be reached",
7395
- "command": "sf hardis:org:monitor:limits",
7396
- "frequency": "daily"
7397
- },
7398
- {
7399
- "key": "UNSECURED_CONNECTED_APPS",
7400
- "title": "Detect unsecured Connected Apps in an org",
7401
- "command": "sf hardis:org:diagnose:unsecure-connected-apps",
7402
- "frequency": "daily"
7403
- },
7404
- {
7405
- "key": "LICENSES",
7406
- "title": "Extract licenses information",
7407
- "command": "sf hardis:org:diagnose:licenses",
7408
- "frequency": "weekly"
7409
- },
7410
- {
7411
- "key": "LINT_ACCESS",
7412
- "title": "Detect custom elements with no access rights defined in permission sets",
7413
- "command": "sf hardis:lint:access",
7414
- "frequency": "weekly"
7415
- },
7416
- {
7417
- "key": "UNUSED_LICENSES",
7418
- "title": "Detect permission set licenses that are assigned to users that do not need them",
7419
- "command": "sf hardis:org:diagnose:unusedlicenses",
7420
- "frequency": "weekly"
7421
- },
7422
- {
7423
- "key": "UNUSED_USERS",
7424
- "title": "Detect active users without recent logins",
7425
- "command": "sf hardis:org:diagnose:unusedusers",
7426
- "frequency": "weekly"
7427
- },
7428
- {
7429
- "key": "ACTIVE_USERS",
7430
- "title": "Detect active users with recent logins",
7431
- "command": "sf hardis:org:diagnose:unusedusers --returnactiveusers",
7432
- "frequency": "weekly"
7433
- },
7434
- {
7435
- "key": "ORG_INFO",
7436
- "title": "Get org info + SF instance info + next major upgrade date",
7437
- "command": "sf hardis:org:diagnose:instanceupgrade",
7438
- "frequency": "weekly"
7439
- },
7440
- {
7441
- "key": "RELEASE_UPDATES",
7442
- "title": "Gather warnings about incoming and overdue Release Updates",
7443
- "command": "sf hardis:org:diagnose:releaseupdates",
7444
- "frequency": "weekly"
7445
- },
7446
- {
7447
- "key": "UNUSED_METADATAS",
7448
- "title": "Detect custom labels and custom permissions that are not in use",
7449
- "command": "sf hardis:lint:unusedmetadatas",
7450
- "frequency": "weekly"
7451
- },
7452
- {
7453
- "key": "UNUSED_APEX_CLASSES",
7454
- "title": "Detect unused Apex classes in an org",
7455
- "command": "sf hardis:org:diagnose:unused-apex-classes",
7456
- "frequency": "weekly"
7457
- },
7458
- {
7459
- "key": "CONNECTED_APPS",
7460
- "title": "Detect unused Connected Apps in an org",
7461
- "command": "sf hardis:org:diagnose:unused-connected-apps",
7462
- "frequency": "weekly"
7463
- },
7696
+ "title": "Detect unused Permission Set Licenses (beta)",
7697
+ "requiresProject": false,
7698
+ "additionalPermissionSetsToAlwaysGet": [
7699
+ "Sales_User"
7700
+ ],
7701
+ "permSetsPermSetLicenses": [
7464
7702
  {
7465
- "key": "METADATA_STATUS",
7466
- "title": "Detect inactive metadata",
7467
- "command": "sf hardis:lint:metadatastatus",
7468
- "frequency": "weekly"
7469
- },
7703
+ "permSet": "Sales_User",
7704
+ "permSetLicense": "SalesUserPsl"
7705
+ }
7706
+ ],
7707
+ "profilesPermissionSetLicenses": [
7470
7708
  {
7471
- "key": "MISSING_ATTRIBUTES",
7472
- "title": "Detect missing description on custom field",
7473
- "command": "sf hardis:lint:missingattributes",
7474
- "frequency": "weekly"
7709
+ "profile": "Salesforce API Only",
7710
+ "permSetLicense": "SalesforceAPIIntegrationPsl"
7475
7711
  }
7476
7712
  ],
7477
- "requiresProject": true,
7478
- "triggerNotification": true,
7713
+ "alwaysExcludeForActiveUsersPermissionSetLicenses": [
7714
+ "IdentityConnect"
7715
+ ],
7479
7716
  "isESM": true,
7480
7717
  "relativePath": [
7481
7718
  "lib",
7482
7719
  "commands",
7483
7720
  "hardis",
7484
7721
  "org",
7485
- "monitor",
7486
- "all.js"
7722
+ "diagnose",
7723
+ "unusedlicenses.js"
7487
7724
  ],
7488
7725
  "aliasPermutations": [],
7489
7726
  "permutations": [
7490
- "hardis:org:monitor:all",
7491
- "org:hardis:monitor:all",
7492
- "org:monitor:hardis:all",
7493
- "org:monitor:all:hardis",
7494
- "hardis:monitor:org:all",
7495
- "monitor:hardis:org:all",
7496
- "monitor:org:hardis:all",
7497
- "monitor:org:all:hardis",
7498
- "hardis:monitor:all:org",
7499
- "monitor:hardis:all:org",
7500
- "monitor:all:hardis:org",
7501
- "monitor:all:org:hardis",
7502
- "hardis:org:all:monitor",
7503
- "org:hardis:all:monitor",
7504
- "org:all:hardis:monitor",
7505
- "org:all:monitor:hardis",
7506
- "hardis:all:org:monitor",
7507
- "all:hardis:org:monitor",
7508
- "all:org:hardis:monitor",
7509
- "all:org:monitor:hardis",
7510
- "hardis:all:monitor:org",
7511
- "all:hardis:monitor:org",
7512
- "all:monitor:hardis:org",
7513
- "all:monitor:org:hardis"
7727
+ "hardis:org:diagnose:unusedlicenses",
7728
+ "org:hardis:diagnose:unusedlicenses",
7729
+ "org:diagnose:hardis:unusedlicenses",
7730
+ "org:diagnose:unusedlicenses:hardis",
7731
+ "hardis:diagnose:org:unusedlicenses",
7732
+ "diagnose:hardis:org:unusedlicenses",
7733
+ "diagnose:org:hardis:unusedlicenses",
7734
+ "diagnose:org:unusedlicenses:hardis",
7735
+ "hardis:diagnose:unusedlicenses:org",
7736
+ "diagnose:hardis:unusedlicenses:org",
7737
+ "diagnose:unusedlicenses:hardis:org",
7738
+ "diagnose:unusedlicenses:org:hardis",
7739
+ "hardis:org:unusedlicenses:diagnose",
7740
+ "org:hardis:unusedlicenses:diagnose",
7741
+ "org:unusedlicenses:hardis:diagnose",
7742
+ "org:unusedlicenses:diagnose:hardis",
7743
+ "hardis:unusedlicenses:org:diagnose",
7744
+ "unusedlicenses:hardis:org:diagnose",
7745
+ "unusedlicenses:org:hardis:diagnose",
7746
+ "unusedlicenses:org:diagnose:hardis",
7747
+ "hardis:unusedlicenses:diagnose:org",
7748
+ "unusedlicenses:hardis:diagnose:org",
7749
+ "unusedlicenses:diagnose:hardis:org",
7750
+ "unusedlicenses:diagnose:org:hardis"
7514
7751
  ]
7515
7752
  },
7516
- "hardis:org:monitor:backup": {
7753
+ "hardis:org:diagnose:unusedusers": {
7517
7754
  "aliases": [],
7518
- "args": {},
7519
- "description": "Retrieve sfdx sources in the context of a monitoring backup\n\nThe command exists in 2 modes: filtered(default & recommended) and full.\n\n## Filtered mode (default, better performances)\n\nAutomatically skips metadatas from installed packages with namespace. \n\nYou can remove more metadata types from backup, especially in case you have too many metadatas and that provokes a crash, using:\n\n- Manual update of `manifest/package-skip-items.xml` config file (then commit & push in the same branch)\n\n - Works with full wildcard (`<members>*</members>`) , named metadata (`<members>Account.Name</members>`) or partial wildcards names (`<members>pi__*</members>` , `<members>*__dlm</members>` , or `<members>prefix*suffix</members>`)\n\n- Environment variable MONITORING_BACKUP_SKIP_METADATA_TYPES (example: `MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation`): that will be applied to all monitoring branches.\n\n## Full mode\n\nActivate it with **--full** parameter, or variable MONITORING_BACKUP_MODE_FULL=true\n\nIgnores filters (namespaces items & manifest/package-skip-items.xml) to retrieve ALL metadatas, including those you might not care about (reports, translations...)\n\nAs we can retrieve only 10000 files by call, the list of all metadatas will be chunked to make multiple calls (and take more time than filtered mode)\n\n- if you use `--full-apply-filters` , manifest/package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES filters will be applied anyway\n- if you use `--exclude-namespaces` , namespaced items will be ignored\n\n_With those both options, it's like if you are not using --full, but with chunked metadata download_\n\n## In CI/CD\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-metadata-backup/) and can output Grafana, Slack and MsTeams Notifications.\n\n## Troubleshooting\n\nIf you have unknown errors (it happens !), you can investigate using the full command with smaller chunks.\n\nExample: `sf hardis:org:monitor:backup --full --exclude-namespaces --full-apply-filters --max-by-chunk 500`\n\nIt will allow you the identify the responsible metadata and ignore it using package-skip-items.xml or MONITORING_BACKUP_SKIP_METADATA_TYPES env variable.\n\n## Documentation\n\n[Doc generation (including visual flows)](https://sfdx-hardis.cloudity.com/hardis/doc/project2markdown/) is triggered at the end of the command.\n\nIf you want to also upload HTML Documentation on your Salesforce Org as static resource, use variable **SFDX_HARDIS_DOC_DEPLOY_TO_ORG=\"true\"**\n\nIf you want to also upload HTML Documentation on Cloudflare, use variable **SFDX_HARDIS_DOC_DEPLOY_TO_CLOUDFLARE=\"true\"**\n\n- If you want to generate the documentation in multiple languages, define variable SFDX_DOC_LANGUAGES (ex: SFDX_DOC_LANGUAGES=en,fr,de)\n- You can define one Cloudflare site by language, for example with the following variables:\n - CLOUDFLARE_PROJECT_NAME_EN=cloudity-demo-english\n - CLOUDFLARE_PROJECT_NAME_FR=cloudity-demo-french\n - CLOUDFLARE_PROJECT_NAME_DE=cloudity-demo-german\n\nIf Flow history doc always display a single state, you probably need to update your workflow configuration:\n\n- on Gitlab: Env variable [`GIT_FETCH_EXTRA_FLAGS: --depth 10000`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/.gitlab-ci.yml#L11)\n- on GitHub: [`fetch-depth: 0`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/.github/workflows/org-monitoring.yml#L58)\n- on Azure: [`fetchDepth: \"0\"`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/azure-pipelines.yml#L39)\n- on Bitbucket: [`step: clone: depth: full`](https://github.com/hardisgroupcom/sfdx-hardis/blob/main/defaults/monitoring/bitbucket-pipelines.yml#L18)\n",
7520
- "examples": [
7521
- "$ sf hardis:org:monitor:backup",
7522
- "$ sf hardis:org:monitor:backup --full",
7523
- "$ sf hardis:org:monitor:backup --full --exclude-namespaces",
7524
- "$ sf hardis:org:monitor:backup --full --exclude-namespaces --full-apply-filters"
7755
+ "args": {},
7756
+ "description": "\n## Command Behavior\n\n**Detects and reports on inactive or unused Salesforce user accounts, helping to optimize license usage and enhance security.**\n\nEfficient user management is vital in Salesforce to ensure resources are optimized and costs are controlled. However, inactive or unused user accounts can often go unnoticed, leading to wasted licenses and potential security risks. This tool addresses this challenge by enabling administrators to identify users who haven't logged in within a specified period.\n\nBy analyzing user login activity and last login timestamps, this feature highlights inactive user accounts, allowing administrators to take appropriate action. Whether it's deactivating dormant accounts, freeing up licenses, or ensuring compliance with security policies, this functionality empowers administrators to maintain a lean and secure Salesforce environment.\n\nKey functionalities:\n\n- **Inactivity Detection:** Identifies users who have not logged in for a specified number of days (`--days` flag, default 180 days in CI, 365 days otherwise).\n- **License Type Filtering:** Allows filtering users by license type using `--licensetypes` (e.g., `all-crm`, `all-paying`) or specific license identifiers using `--licenseidentifiers`.\n - `all-crm`: Includes `SFDC`, `AUL`, `AUL1`, `AULL_IGHT` licenses.\n - `all-paying`: Includes `SFDC`, `AUL`, `AUL1`, `AULL_IGHT`, `PID_Customer_Community`, `PID_Customer_Community_Login`, `PID_Partner_Community`, `PID_Partner_Community_Login` licenses.\n - Note: You can see the full list of available license identifiers in [Salesforce Documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/sfdx_cli_reference/sforce_api_objects_userlicense.htm).\n- **Active User Retrieval:** The `--returnactiveusers` flag inverts the command, allowing you to retrieve active users who *have* logged in during the specified period.\n- **CSV Report Generation:** Generates a CSV file containing details of all identified users (inactive or active), including their last login date, profile, and license information.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of inactive or active users.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-inactive-users/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Query (Bulk API):** It uses `bulkQuery` to efficiently retrieve user records from the Salesforce `User` object. The SOQL query dynamically constructs its WHERE clause based on the `--days`, `--licensetypes`, `--licenseidentifiers`, and `--returnactiveusers` flags.\n- **Interactive Prompts:** Uses `prompts` to interactively ask the user for the number of inactive days and license types if not provided via flags.\n- **License Mapping:** Internally maps common license type aliases (e.g., `all-crm`) to their corresponding Salesforce `LicenseDefinitionKey` values.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of users.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and metrics for monitoring dashboards.\n- **User Feedback:** Provides a summary of the findings in the console, indicating the number of inactive or active users found.\n</details>",
7757
+ "examples": [
7758
+ "$ sf hardis:org:diagnose:unusedusers",
7759
+ "$ sf hardis:org:diagnose:unusedusers --days 365",
7760
+ "$ sf hardis:org:diagnose:unusedusers --days 60 --licensetypes all-crm",
7761
+ "$ sf hardis:org:diagnose:unusedusers --days 60 --licenseidentifiers SFDC,AUL,AUL1",
7762
+ "$ sf hardis:org:diagnose:unusedusers --days 60 --licensetypes all-crm --returnactiveusers"
7525
7763
  ],
7526
7764
  "flags": {
7527
7765
  "json": {
@@ -7539,57 +7777,163 @@
7539
7777
  "multiple": false,
7540
7778
  "type": "option"
7541
7779
  },
7542
- "full": {
7543
- "description": "Dot not take in account filtering using package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES. Efficient but much much slower !",
7544
- "name": "full",
7545
- "allowNo": false,
7546
- "type": "boolean"
7780
+ "outputfile": {
7781
+ "char": "f",
7782
+ "description": "Force the path and name of output report file. Must end with .csv",
7783
+ "name": "outputfile",
7784
+ "hasDynamicHelp": false,
7785
+ "multiple": false,
7786
+ "type": "option"
7547
7787
  },
7548
- "max-by-chunk": {
7549
- "char": "m",
7550
- "description": "If mode --full is activated, maximum number of metadatas in a package.xml chunk",
7551
- "name": "max-by-chunk",
7552
- "default": 3000,
7788
+ "days": {
7789
+ "char": "t",
7790
+ "description": "Extracts the users that have been inactive for the amount of days specified. In CI, default is 180 days",
7791
+ "name": "days",
7553
7792
  "hasDynamicHelp": false,
7554
7793
  "multiple": false,
7555
7794
  "type": "option"
7556
7795
  },
7557
- "exclude-namespaces": {
7558
- "char": "e",
7559
- "description": "If mode --full is activated, exclude namespaced metadatas",
7560
- "name": "exclude-namespaces",
7796
+ "licensetypes": {
7797
+ "char": "l",
7798
+ "description": "Type of licenses to check. If set, do not use licenseidentifiers option. In CI, default is all-crm",
7799
+ "name": "licensetypes",
7800
+ "hasDynamicHelp": false,
7801
+ "multiple": false,
7802
+ "options": [
7803
+ "all",
7804
+ "all-crm",
7805
+ "all-paying"
7806
+ ],
7807
+ "type": "option"
7808
+ },
7809
+ "licenseidentifiers": {
7810
+ "char": "i",
7811
+ "description": "Comma-separated list of license identifiers, in case licensetypes is not used.. Identifiers available at https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_userlicense.htm",
7812
+ "name": "licenseidentifiers",
7813
+ "hasDynamicHelp": false,
7814
+ "multiple": false,
7815
+ "type": "option"
7816
+ },
7817
+ "returnactiveusers": {
7818
+ "description": "Inverts the command by returning the active users",
7819
+ "name": "returnactiveusers",
7561
7820
  "allowNo": false,
7562
7821
  "type": "boolean"
7563
7822
  },
7564
- "full-apply-filters": {
7565
- "char": "z",
7566
- "description": "If mode --full is activated, apply filters of manifest/package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES anyway",
7567
- "name": "full-apply-filters",
7823
+ "debug": {
7824
+ "char": "d",
7825
+ "description": "Activate debug mode (more logs)",
7826
+ "name": "debug",
7568
7827
  "allowNo": false,
7569
7828
  "type": "boolean"
7570
7829
  },
7571
- "start-chunk": {
7572
- "description": "Use this parameter to troubleshoot a specific chunk. It will be used as the first chunk to retrieve",
7573
- "name": "start-chunk",
7574
- "default": 1,
7830
+ "websocket": {
7831
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
7832
+ "name": "websocket",
7575
7833
  "hasDynamicHelp": false,
7576
7834
  "multiple": false,
7577
7835
  "type": "option"
7578
7836
  },
7579
- "skip-doc": {
7580
- "description": "Skip the generation of project documentation at the end of the command",
7581
- "name": "skip-doc",
7837
+ "skipauth": {
7838
+ "description": "Skip authentication check when a default username is required",
7839
+ "name": "skipauth",
7582
7840
  "allowNo": false,
7583
7841
  "type": "boolean"
7584
7842
  },
7585
- "outputfile": {
7586
- "char": "f",
7587
- "description": "Force the path and name of output report file. Must end with .csv",
7588
- "name": "outputfile",
7843
+ "target-org": {
7844
+ "aliases": [
7845
+ "targetusername",
7846
+ "u"
7847
+ ],
7848
+ "char": "o",
7849
+ "deprecateAliases": true,
7850
+ "name": "target-org",
7851
+ "noCacheDefault": true,
7852
+ "required": true,
7853
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
7854
+ "hasDynamicHelp": true,
7855
+ "multiple": false,
7856
+ "type": "option"
7857
+ }
7858
+ },
7859
+ "hasDynamicHelp": true,
7860
+ "hiddenAliases": [],
7861
+ "id": "hardis:org:diagnose:unusedusers",
7862
+ "pluginAlias": "sfdx-hardis",
7863
+ "pluginName": "sfdx-hardis",
7864
+ "pluginType": "core",
7865
+ "strict": true,
7866
+ "enableJsonFlag": true,
7867
+ "title": "Detect unused Users in Salesforce",
7868
+ "requiresProject": false,
7869
+ "isESM": true,
7870
+ "relativePath": [
7871
+ "lib",
7872
+ "commands",
7873
+ "hardis",
7874
+ "org",
7875
+ "diagnose",
7876
+ "unusedusers.js"
7877
+ ],
7878
+ "aliasPermutations": [],
7879
+ "permutations": [
7880
+ "hardis:org:diagnose:unusedusers",
7881
+ "org:hardis:diagnose:unusedusers",
7882
+ "org:diagnose:hardis:unusedusers",
7883
+ "org:diagnose:unusedusers:hardis",
7884
+ "hardis:diagnose:org:unusedusers",
7885
+ "diagnose:hardis:org:unusedusers",
7886
+ "diagnose:org:hardis:unusedusers",
7887
+ "diagnose:org:unusedusers:hardis",
7888
+ "hardis:diagnose:unusedusers:org",
7889
+ "diagnose:hardis:unusedusers:org",
7890
+ "diagnose:unusedusers:hardis:org",
7891
+ "diagnose:unusedusers:org:hardis",
7892
+ "hardis:org:unusedusers:diagnose",
7893
+ "org:hardis:unusedusers:diagnose",
7894
+ "org:unusedusers:hardis:diagnose",
7895
+ "org:unusedusers:diagnose:hardis",
7896
+ "hardis:unusedusers:org:diagnose",
7897
+ "unusedusers:hardis:org:diagnose",
7898
+ "unusedusers:org:hardis:diagnose",
7899
+ "unusedusers:org:diagnose:hardis",
7900
+ "hardis:unusedusers:diagnose:org",
7901
+ "unusedusers:hardis:diagnose:org",
7902
+ "unusedusers:diagnose:hardis:org",
7903
+ "unusedusers:diagnose:org:hardis"
7904
+ ]
7905
+ },
7906
+ "hardis:org:purge:apexlog": {
7907
+ "aliases": [],
7908
+ "args": {},
7909
+ "description": "\n**Purges Apex debug logs from a Salesforce org.**\n\nThis command provides a quick and efficient way to clear out accumulated Apex debug logs from your Salesforce environment. This is particularly useful for:\n\n- **Storage Management:** Freeing up valuable data storage space in your Salesforce org.\n- **Performance Optimization:** Reducing the overhead associated with large volumes of debug logs.\n- **Troubleshooting:** Ensuring that new debug logs are generated cleanly without interference from old, irrelevant logs.\n\nKey functionalities:\n\n- **Log Identification:** Queries the `ApexLog` object to identify all existing debug logs.\n- **Confirmation Prompt:** Before deletion, it prompts for user confirmation, displaying the number of Apex logs that will be deleted.\n- **Bulk Deletion:** Uses the Salesforce Bulk API to efficiently delete a large number of Apex logs.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Query:** It executes a SOQL query (`SELECT Id FROM ApexLog LIMIT 50000`) to retrieve the IDs of Apex logs to be deleted. The limit is set to 50,000 to handle large volumes of logs.\n- **CSV Export:** The retrieved log IDs are temporarily exported to a CSV file (`ApexLogsToDelete_*.csv`) in the `./tmp` directory.\n- **User Confirmation:** It uses the `prompts` library to ask for user confirmation before proceeding with the deletion, displaying the count of logs to be purged.\n- **Bulk API Deletion:** It then uses the Salesforce CLI's `sf data delete bulk` command, pointing to the generated CSV file, to perform the mass deletion of Apex logs.\n- **File System Operations:** It uses `fs-extra` to create the temporary directory and manage the CSV file.\n- **Error Handling:** Includes error handling for the query and deletion operations.\n</details>\n",
7910
+ "examples": [
7911
+ "$ sf hardis:org:purge:apexlog",
7912
+ "$ sf hardis:org:purge:apexlog --target-org nicolas.vuillamy@gmail.com"
7913
+ ],
7914
+ "flags": {
7915
+ "json": {
7916
+ "description": "Format output as json.",
7917
+ "helpGroup": "GLOBAL",
7918
+ "name": "json",
7919
+ "allowNo": false,
7920
+ "type": "boolean"
7921
+ },
7922
+ "flags-dir": {
7923
+ "helpGroup": "GLOBAL",
7924
+ "name": "flags-dir",
7925
+ "summary": "Import flag values from a directory.",
7589
7926
  "hasDynamicHelp": false,
7590
7927
  "multiple": false,
7591
7928
  "type": "option"
7592
7929
  },
7930
+ "prompt": {
7931
+ "char": "z",
7932
+ "description": "Prompt for confirmation (true by default, use --no-prompt to skip)",
7933
+ "name": "prompt",
7934
+ "allowNo": true,
7935
+ "type": "boolean"
7936
+ },
7593
7937
  "debug": {
7594
7938
  "char": "d",
7595
7939
  "description": "Activate debug mode (more logs)",
@@ -7628,58 +7972,59 @@
7628
7972
  },
7629
7973
  "hasDynamicHelp": true,
7630
7974
  "hiddenAliases": [],
7631
- "id": "hardis:org:monitor:backup",
7975
+ "id": "hardis:org:purge:apexlog",
7632
7976
  "pluginAlias": "sfdx-hardis",
7633
7977
  "pluginName": "sfdx-hardis",
7634
7978
  "pluginType": "core",
7635
7979
  "strict": true,
7636
7980
  "enableJsonFlag": true,
7637
- "title": "Backup DX sources",
7638
- "requiresProject": true,
7639
- "triggerNotification": true,
7981
+ "title": "Purge Apex Logs",
7982
+ "requiresProject": false,
7640
7983
  "isESM": true,
7641
7984
  "relativePath": [
7642
7985
  "lib",
7643
7986
  "commands",
7644
7987
  "hardis",
7645
7988
  "org",
7646
- "monitor",
7647
- "backup.js"
7989
+ "purge",
7990
+ "apexlog.js"
7648
7991
  ],
7649
7992
  "aliasPermutations": [],
7650
7993
  "permutations": [
7651
- "hardis:org:monitor:backup",
7652
- "org:hardis:monitor:backup",
7653
- "org:monitor:hardis:backup",
7654
- "org:monitor:backup:hardis",
7655
- "hardis:monitor:org:backup",
7656
- "monitor:hardis:org:backup",
7657
- "monitor:org:hardis:backup",
7658
- "monitor:org:backup:hardis",
7659
- "hardis:monitor:backup:org",
7660
- "monitor:hardis:backup:org",
7661
- "monitor:backup:hardis:org",
7662
- "monitor:backup:org:hardis",
7663
- "hardis:org:backup:monitor",
7664
- "org:hardis:backup:monitor",
7665
- "org:backup:hardis:monitor",
7666
- "org:backup:monitor:hardis",
7667
- "hardis:backup:org:monitor",
7668
- "backup:hardis:org:monitor",
7669
- "backup:org:hardis:monitor",
7670
- "backup:org:monitor:hardis",
7671
- "hardis:backup:monitor:org",
7672
- "backup:hardis:monitor:org",
7673
- "backup:monitor:hardis:org",
7674
- "backup:monitor:org:hardis"
7994
+ "hardis:org:purge:apexlog",
7995
+ "org:hardis:purge:apexlog",
7996
+ "org:purge:hardis:apexlog",
7997
+ "org:purge:apexlog:hardis",
7998
+ "hardis:purge:org:apexlog",
7999
+ "purge:hardis:org:apexlog",
8000
+ "purge:org:hardis:apexlog",
8001
+ "purge:org:apexlog:hardis",
8002
+ "hardis:purge:apexlog:org",
8003
+ "purge:hardis:apexlog:org",
8004
+ "purge:apexlog:hardis:org",
8005
+ "purge:apexlog:org:hardis",
8006
+ "hardis:org:apexlog:purge",
8007
+ "org:hardis:apexlog:purge",
8008
+ "org:apexlog:hardis:purge",
8009
+ "org:apexlog:purge:hardis",
8010
+ "hardis:apexlog:org:purge",
8011
+ "apexlog:hardis:org:purge",
8012
+ "apexlog:org:hardis:purge",
8013
+ "apexlog:org:purge:hardis",
8014
+ "hardis:apexlog:purge:org",
8015
+ "apexlog:hardis:purge:org",
8016
+ "apexlog:purge:hardis:org",
8017
+ "apexlog:purge:org:hardis"
7675
8018
  ]
7676
8019
  },
7677
- "hardis:org:monitor:limits": {
8020
+ "hardis:org:purge:flow": {
7678
8021
  "aliases": [],
7679
8022
  "args": {},
7680
- "description": "\n## Command Behavior\n\n**Checks the current usage of various Salesforce org limits and sends notifications if thresholds are exceeded.**\n\nThis command is a critical component of proactive Salesforce org management, helping administrators and developers monitor resource consumption and prevent hitting critical limits that could impact performance or functionality. It provides early warnings when limits are approaching their capacity.\n\nKey functionalities:\n\n- **Limit Retrieval:** Fetches a comprehensive list of all Salesforce org limits using the Salesforce CLI.\n- **Usage Calculation:** Calculates the percentage of each limit that is currently being used.\n- **Threshold-Based Alerting:** Assigns a severity (success, warning, or error) to each limit based on configurable thresholds:\n - **Warning:** If usage exceeds 50% (configurable via `LIMIT_THRESHOLD_WARNING` environment variable).\n - **Error:** If usage exceeds 75% (configurable via `LIMIT_THRESHOLD_ERROR` environment variable).\n- **CSV Report Generation:** Generates a CSV file containing all org limits, their current usage, maximum allowed, and calculated percentage used, along with the assigned severity.\n- **Notifications:** Sends notifications to configured channels (Grafana, Slack, MS Teams) with a summary of limits that have exceeded the warning or error thresholds.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-org-limits/) and can output Grafana, Slack and MsTeams Notifications.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Salesforce CLI Integration:** It executes the `sf org limits list` command to retrieve the current org limits. It parses the JSON output of this command.\n- **Data Processing:** It iterates through the retrieved limits, calculates the `used` and `percentUsed` values, and assigns a `severity` (success, warning, error) based on the configured thresholds.\n- **Environment Variable Configuration:** Reads `LIMIT_THRESHOLD_WARNING` and `LIMIT_THRESHOLD_ERROR` environment variables to set the warning and error thresholds for limit usage.\n- **Report Generation:** It uses `generateCsvFile` to create the CSV report of org limits.\n- **Notification Integration:** It integrates with the `NotifProvider` to send notifications, including attachments of the generated CSV report and detailed metrics for each limit, which can be consumed by monitoring dashboards like Grafana.\n- **Exit Code Management:** Sets the process exit code to 1 if any limit is in an 'error' state, indicating a critical issue.\n</details>\n",
8023
+ "description": "\n**Purges old or unwanted Flow versions from a Salesforce org, with an option to delete related Flow Interviews.**\n\nThis command helps maintain a clean and performant Salesforce org by removing obsolete Flow versions. Over time, multiple versions of Flows can accumulate, consuming storage and potentially impacting performance. This tool provides a controlled way to clean up these versions.\n\nKey functionalities:\n\n- **Targeted Flow Selection:** Allows you to filter Flow versions to delete by name (`--name`) and status (`--status`, e.g., `Obsolete`, `Draft`, `Inactive`).\n- **Flow Interview Deletion:** If a Flow version cannot be deleted due to active Flow Interviews, the `--delete-flow-interviews` flag (or interactive prompt) allows you to delete these interviews first, then retry the Flow version deletion.\n- **Confirmation Prompt:** In interactive mode, it prompts for confirmation before proceeding with the deletion of Flow versions and Flow Interviews.\n- **Partial Success Handling:** The `--allowpurgefailure` flag (default `true`) allows the command to continue even if some deletions fail, reporting the errors.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Queries (Tooling API):** It queries the `Flow` object (using the Tooling API) to list Flow versions based on the provided filters (name, status, manageable state).\n- **Bulk Deletion (Tooling API):** It uses `bulkDeleteTooling` to perform mass deletions of Flow versions. If deletion fails due to active interviews, it extracts the interview IDs.\n- **Flow Interview Management:** If `delete-flow-interviews` is enabled, it queries `FlowInterview` objects, performs bulk deletion of the identified interviews using `bulkDelete`, and then retries the Flow version deletion.\n- **Interactive Prompts:** Uses the `prompts` library to interact with the user for selecting Flows, statuses, and confirming deletion actions.\n- **Error Reporting:** Logs detailed error messages for failed deletions, including the specific reasons.\n- **Command-Line Execution:** Uses `execSfdxJson` to execute Salesforce CLI commands for querying Flow data.\n</details>\n",
7681
8024
  "examples": [
7682
- "$ sf hardis:org:monitor:limits"
8025
+ "$ sf hardis:org:purge:flow",
8026
+ "$ sf hardis:org:purge:flow --target-org nicolas.vuillamy@gmail.com --no-prompt --delete-flow-interviews",
8027
+ "$ sf hardis:org:purge:flow --target-org nicolas.vuillamy@gmail.com --status \"Obsolete,Draft,InvalidDraft\" --name TestFlow"
7683
8028
  ],
7684
8029
  "flags": {
7685
8030
  "json": {
@@ -7697,10 +8042,48 @@
7697
8042
  "multiple": false,
7698
8043
  "type": "option"
7699
8044
  },
7700
- "outputfile": {
8045
+ "prompt": {
8046
+ "char": "z",
8047
+ "description": "Prompt for confirmation (true by default, use --no-prompt to skip)",
8048
+ "name": "prompt",
8049
+ "allowNo": true,
8050
+ "type": "boolean"
8051
+ },
8052
+ "name": {
8053
+ "char": "n",
8054
+ "description": "Filter according to Name criteria",
8055
+ "name": "name",
8056
+ "hasDynamicHelp": false,
8057
+ "multiple": false,
8058
+ "type": "option"
8059
+ },
8060
+ "status": {
8061
+ "char": "s",
8062
+ "description": "Filter according to Status criteria",
8063
+ "name": "status",
8064
+ "hasDynamicHelp": false,
8065
+ "multiple": false,
8066
+ "type": "option"
8067
+ },
8068
+ "delete-flow-interviews": {
8069
+ "char": "w",
8070
+ "description": "If the presence of Flow interviews prevent to delete flows versions, delete them before retrying to delete flow versions",
8071
+ "name": "delete-flow-interviews",
8072
+ "allowNo": false,
8073
+ "type": "boolean"
8074
+ },
8075
+ "allowpurgefailure": {
7701
8076
  "char": "f",
7702
- "description": "Force the path and name of output report file. Must end with .csv",
7703
- "name": "outputfile",
8077
+ "description": "Allows purges to fail without exiting with 1. Use --no-allowpurgefailure to disable",
8078
+ "name": "allowpurgefailure",
8079
+ "allowNo": true,
8080
+ "type": "boolean"
8081
+ },
8082
+ "instanceurl": {
8083
+ "char": "r",
8084
+ "description": "URL of org instance",
8085
+ "name": "instanceurl",
8086
+ "default": "https://login.salesforce.com",
7704
8087
  "hasDynamicHelp": false,
7705
8088
  "multiple": false,
7706
8089
  "type": "option"
@@ -7743,50 +8126,49 @@
7743
8126
  },
7744
8127
  "hasDynamicHelp": true,
7745
8128
  "hiddenAliases": [],
7746
- "id": "hardis:org:monitor:limits",
8129
+ "id": "hardis:org:purge:flow",
7747
8130
  "pluginAlias": "sfdx-hardis",
7748
8131
  "pluginName": "sfdx-hardis",
7749
8132
  "pluginType": "core",
7750
8133
  "strict": true,
7751
8134
  "enableJsonFlag": true,
7752
- "title": "Check org limits",
7753
- "requiresProject": true,
7754
- "triggerNotification": true,
8135
+ "title": "Purge Flow versions",
8136
+ "requiresProject": false,
7755
8137
  "isESM": true,
7756
8138
  "relativePath": [
7757
8139
  "lib",
7758
8140
  "commands",
7759
8141
  "hardis",
7760
8142
  "org",
7761
- "monitor",
7762
- "limits.js"
8143
+ "purge",
8144
+ "flow.js"
7763
8145
  ],
7764
8146
  "aliasPermutations": [],
7765
8147
  "permutations": [
7766
- "hardis:org:monitor:limits",
7767
- "org:hardis:monitor:limits",
7768
- "org:monitor:hardis:limits",
7769
- "org:monitor:limits:hardis",
7770
- "hardis:monitor:org:limits",
7771
- "monitor:hardis:org:limits",
7772
- "monitor:org:hardis:limits",
7773
- "monitor:org:limits:hardis",
7774
- "hardis:monitor:limits:org",
7775
- "monitor:hardis:limits:org",
7776
- "monitor:limits:hardis:org",
7777
- "monitor:limits:org:hardis",
7778
- "hardis:org:limits:monitor",
7779
- "org:hardis:limits:monitor",
7780
- "org:limits:hardis:monitor",
7781
- "org:limits:monitor:hardis",
7782
- "hardis:limits:org:monitor",
7783
- "limits:hardis:org:monitor",
7784
- "limits:org:hardis:monitor",
7785
- "limits:org:monitor:hardis",
7786
- "hardis:limits:monitor:org",
7787
- "limits:hardis:monitor:org",
7788
- "limits:monitor:hardis:org",
7789
- "limits:monitor:org:hardis"
8148
+ "hardis:org:purge:flow",
8149
+ "org:hardis:purge:flow",
8150
+ "org:purge:hardis:flow",
8151
+ "org:purge:flow:hardis",
8152
+ "hardis:purge:org:flow",
8153
+ "purge:hardis:org:flow",
8154
+ "purge:org:hardis:flow",
8155
+ "purge:org:flow:hardis",
8156
+ "hardis:purge:flow:org",
8157
+ "purge:hardis:flow:org",
8158
+ "purge:flow:hardis:org",
8159
+ "purge:flow:org:hardis",
8160
+ "hardis:org:flow:purge",
8161
+ "org:hardis:flow:purge",
8162
+ "org:flow:hardis:purge",
8163
+ "org:flow:purge:hardis",
8164
+ "hardis:flow:org:purge",
8165
+ "flow:hardis:org:purge",
8166
+ "flow:org:hardis:purge",
8167
+ "flow:org:purge:hardis",
8168
+ "hardis:flow:purge:org",
8169
+ "flow:hardis:purge:org",
8170
+ "flow:purge:hardis:org",
8171
+ "flow:purge:org:hardis"
7790
8172
  ]
7791
8173
  },
7792
8174
  "hardis:org:refresh:after-refresh": {
@@ -8028,128 +8410,13 @@
8028
8410
  "before-refresh:refresh:org:hardis"
8029
8411
  ]
8030
8412
  },
8031
- "hardis:org:purge:apexlog": {
8032
- "aliases": [],
8033
- "args": {},
8034
- "description": "\n**Purges Apex debug logs from a Salesforce org.**\n\nThis command provides a quick and efficient way to clear out accumulated Apex debug logs from your Salesforce environment. This is particularly useful for:\n\n- **Storage Management:** Freeing up valuable data storage space in your Salesforce org.\n- **Performance Optimization:** Reducing the overhead associated with large volumes of debug logs.\n- **Troubleshooting:** Ensuring that new debug logs are generated cleanly without interference from old, irrelevant logs.\n\nKey functionalities:\n\n- **Log Identification:** Queries the `ApexLog` object to identify all existing debug logs.\n- **Confirmation Prompt:** Before deletion, it prompts for user confirmation, displaying the number of Apex logs that will be deleted.\n- **Bulk Deletion:** Uses the Salesforce Bulk API to efficiently delete a large number of Apex logs.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Query:** It executes a SOQL query (`SELECT Id FROM ApexLog LIMIT 50000`) to retrieve the IDs of Apex logs to be deleted. The limit is set to 50,000 to handle large volumes of logs.\n- **CSV Export:** The retrieved log IDs are temporarily exported to a CSV file (`ApexLogsToDelete_*.csv`) in the `./tmp` directory.\n- **User Confirmation:** It uses the `prompts` library to ask for user confirmation before proceeding with the deletion, displaying the count of logs to be purged.\n- **Bulk API Deletion:** It then uses the Salesforce CLI's `sf data delete bulk` command, pointing to the generated CSV file, to perform the mass deletion of Apex logs.\n- **File System Operations:** It uses `fs-extra` to create the temporary directory and manage the CSV file.\n- **Error Handling:** Includes error handling for the query and deletion operations.\n</details>\n",
8035
- "examples": [
8036
- "$ sf hardis:org:purge:apexlog",
8037
- "$ sf hardis:org:purge:apexlog --target-org nicolas.vuillamy@gmail.com"
8038
- ],
8039
- "flags": {
8040
- "json": {
8041
- "description": "Format output as json.",
8042
- "helpGroup": "GLOBAL",
8043
- "name": "json",
8044
- "allowNo": false,
8045
- "type": "boolean"
8046
- },
8047
- "flags-dir": {
8048
- "helpGroup": "GLOBAL",
8049
- "name": "flags-dir",
8050
- "summary": "Import flag values from a directory.",
8051
- "hasDynamicHelp": false,
8052
- "multiple": false,
8053
- "type": "option"
8054
- },
8055
- "prompt": {
8056
- "char": "z",
8057
- "description": "Prompt for confirmation (true by default, use --no-prompt to skip)",
8058
- "name": "prompt",
8059
- "allowNo": true,
8060
- "type": "boolean"
8061
- },
8062
- "debug": {
8063
- "char": "d",
8064
- "description": "Activate debug mode (more logs)",
8065
- "name": "debug",
8066
- "allowNo": false,
8067
- "type": "boolean"
8068
- },
8069
- "websocket": {
8070
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
8071
- "name": "websocket",
8072
- "hasDynamicHelp": false,
8073
- "multiple": false,
8074
- "type": "option"
8075
- },
8076
- "skipauth": {
8077
- "description": "Skip authentication check when a default username is required",
8078
- "name": "skipauth",
8079
- "allowNo": false,
8080
- "type": "boolean"
8081
- },
8082
- "target-org": {
8083
- "aliases": [
8084
- "targetusername",
8085
- "u"
8086
- ],
8087
- "char": "o",
8088
- "deprecateAliases": true,
8089
- "name": "target-org",
8090
- "noCacheDefault": true,
8091
- "required": true,
8092
- "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
8093
- "hasDynamicHelp": true,
8094
- "multiple": false,
8095
- "type": "option"
8096
- }
8097
- },
8098
- "hasDynamicHelp": true,
8099
- "hiddenAliases": [],
8100
- "id": "hardis:org:purge:apexlog",
8101
- "pluginAlias": "sfdx-hardis",
8102
- "pluginName": "sfdx-hardis",
8103
- "pluginType": "core",
8104
- "strict": true,
8105
- "enableJsonFlag": true,
8106
- "title": "Purge Apex Logs",
8107
- "requiresProject": false,
8108
- "isESM": true,
8109
- "relativePath": [
8110
- "lib",
8111
- "commands",
8112
- "hardis",
8113
- "org",
8114
- "purge",
8115
- "apexlog.js"
8116
- ],
8117
- "aliasPermutations": [],
8118
- "permutations": [
8119
- "hardis:org:purge:apexlog",
8120
- "org:hardis:purge:apexlog",
8121
- "org:purge:hardis:apexlog",
8122
- "org:purge:apexlog:hardis",
8123
- "hardis:purge:org:apexlog",
8124
- "purge:hardis:org:apexlog",
8125
- "purge:org:hardis:apexlog",
8126
- "purge:org:apexlog:hardis",
8127
- "hardis:purge:apexlog:org",
8128
- "purge:hardis:apexlog:org",
8129
- "purge:apexlog:hardis:org",
8130
- "purge:apexlog:org:hardis",
8131
- "hardis:org:apexlog:purge",
8132
- "org:hardis:apexlog:purge",
8133
- "org:apexlog:hardis:purge",
8134
- "org:apexlog:purge:hardis",
8135
- "hardis:apexlog:org:purge",
8136
- "apexlog:hardis:org:purge",
8137
- "apexlog:org:hardis:purge",
8138
- "apexlog:org:purge:hardis",
8139
- "hardis:apexlog:purge:org",
8140
- "apexlog:hardis:purge:org",
8141
- "apexlog:purge:hardis:org",
8142
- "apexlog:purge:org:hardis"
8143
- ]
8144
- },
8145
- "hardis:org:purge:flow": {
8413
+ "hardis:org:retrieve:packageconfig": {
8146
8414
  "aliases": [],
8147
8415
  "args": {},
8148
- "description": "\n**Purges old or unwanted Flow versions from a Salesforce org, with an option to delete related Flow Interviews.**\n\nThis command helps maintain a clean and performant Salesforce org by removing obsolete Flow versions. Over time, multiple versions of Flows can accumulate, consuming storage and potentially impacting performance. This tool provides a controlled way to clean up these versions.\n\nKey functionalities:\n\n- **Targeted Flow Selection:** Allows you to filter Flow versions to delete by name (`--name`) and status (`--status`, e.g., `Obsolete`, `Draft`, `Inactive`).\n- **Flow Interview Deletion:** If a Flow version cannot be deleted due to active Flow Interviews, the `--delete-flow-interviews` flag (or interactive prompt) allows you to delete these interviews first, then retry the Flow version deletion.\n- **Confirmation Prompt:** In interactive mode, it prompts for confirmation before proceeding with the deletion of Flow versions and Flow Interviews.\n- **Partial Success Handling:** The `--allowpurgefailure` flag (default `true`) allows the command to continue even if some deletions fail, reporting the errors.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Queries (Tooling API):** It queries the `Flow` object (using the Tooling API) to list Flow versions based on the provided filters (name, status, manageable state).\n- **Bulk Deletion (Tooling API):** It uses `bulkDeleteTooling` to perform mass deletions of Flow versions. If deletion fails due to active interviews, it extracts the interview IDs.\n- **Flow Interview Management:** If `delete-flow-interviews` is enabled, it queries `FlowInterview` objects, performs bulk deletion of the identified interviews using `bulkDelete`, and then retries the Flow version deletion.\n- **Interactive Prompts:** Uses the `prompts` library to interact with the user for selecting Flows, statuses, and confirming deletion actions.\n- **Error Reporting:** Logs detailed error messages for failed deletions, including the specific reasons.\n- **Command-Line Execution:** Uses `execSfdxJson` to execute Salesforce CLI commands for querying Flow data.\n</details>\n",
8416
+ "description": "\n**Retrieves the installed package configuration from a Salesforce org and optionally updates the local project configuration.**\n\nThis command is useful for maintaining an accurate record of installed packages within your Salesforce project, which is crucial for managing dependencies and ensuring consistent deployments across environments.\n\nKey functionalities:\n\n- **Package Listing:** Connects to a specified Salesforce org (or prompts for one if not provided) and retrieves a list of all installed packages.\n- **Configuration Update:** Offers the option to update your local project's configuration with the retrieved list of installed packages. This can be beneficial for automating package installations during environment setup or CI/CD processes.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Org Connection:** It establishes a connection to the target Salesforce org using the provided or prompted username.\n- **Metadata Retrieval:** It utilizes `MetadataUtils.listInstalledPackages` to query the Salesforce org and obtain details about the installed packages.\n- **Interactive Prompt:** It uses the `prompts` library to ask the user whether they want to update their local project configuration with the retrieved package list.\n- **Configuration Management:** If the user confirms, it calls `managePackageConfig` to update the project's configuration file (likely `.sfdx-hardis.yml`) with the new package information.\n- **User Feedback:** Provides clear messages to the user about the success of the package retrieval and configuration update.\n</details>\n",
8149
8417
  "examples": [
8150
- "$ sf hardis:org:purge:flow",
8151
- "$ sf hardis:org:purge:flow --target-org nicolas.vuillamy@gmail.com --no-prompt --delete-flow-interviews",
8152
- "$ sf hardis:org:purge:flow --target-org nicolas.vuillamy@gmail.com --status \"Obsolete,Draft,InvalidDraft\" --name TestFlow"
8418
+ "$ sf hardis:org:retrieve:packageconfig",
8419
+ "sf hardis:org:retrieve:packageconfig -u myOrg"
8153
8420
  ],
8154
8421
  "flags": {
8155
8422
  "json": {
@@ -8162,53 +8429,7 @@
8162
8429
  "flags-dir": {
8163
8430
  "helpGroup": "GLOBAL",
8164
8431
  "name": "flags-dir",
8165
- "summary": "Import flag values from a directory.",
8166
- "hasDynamicHelp": false,
8167
- "multiple": false,
8168
- "type": "option"
8169
- },
8170
- "prompt": {
8171
- "char": "z",
8172
- "description": "Prompt for confirmation (true by default, use --no-prompt to skip)",
8173
- "name": "prompt",
8174
- "allowNo": true,
8175
- "type": "boolean"
8176
- },
8177
- "name": {
8178
- "char": "n",
8179
- "description": "Filter according to Name criteria",
8180
- "name": "name",
8181
- "hasDynamicHelp": false,
8182
- "multiple": false,
8183
- "type": "option"
8184
- },
8185
- "status": {
8186
- "char": "s",
8187
- "description": "Filter according to Status criteria",
8188
- "name": "status",
8189
- "hasDynamicHelp": false,
8190
- "multiple": false,
8191
- "type": "option"
8192
- },
8193
- "delete-flow-interviews": {
8194
- "char": "w",
8195
- "description": "If the presence of Flow interviews prevent to delete flows versions, delete them before retrying to delete flow versions",
8196
- "name": "delete-flow-interviews",
8197
- "allowNo": false,
8198
- "type": "boolean"
8199
- },
8200
- "allowpurgefailure": {
8201
- "char": "f",
8202
- "description": "Allows purges to fail without exiting with 1. Use --no-allowpurgefailure to disable",
8203
- "name": "allowpurgefailure",
8204
- "allowNo": true,
8205
- "type": "boolean"
8206
- },
8207
- "instanceurl": {
8208
- "char": "r",
8209
- "description": "URL of org instance",
8210
- "name": "instanceurl",
8211
- "default": "https://login.salesforce.com",
8432
+ "summary": "Import flag values from a directory.",
8212
8433
  "hasDynamicHelp": false,
8213
8434
  "multiple": false,
8214
8435
  "type": "option"
@@ -8251,13 +8472,13 @@
8251
8472
  },
8252
8473
  "hasDynamicHelp": true,
8253
8474
  "hiddenAliases": [],
8254
- "id": "hardis:org:purge:flow",
8475
+ "id": "hardis:org:retrieve:packageconfig",
8255
8476
  "pluginAlias": "sfdx-hardis",
8256
8477
  "pluginName": "sfdx-hardis",
8257
8478
  "pluginType": "core",
8258
8479
  "strict": true,
8259
8480
  "enableJsonFlag": true,
8260
- "title": "Purge Flow versions",
8481
+ "title": "Retrieve package configuration from an org",
8261
8482
  "requiresProject": false,
8262
8483
  "isESM": true,
8263
8484
  "relativePath": [
@@ -8265,44 +8486,43 @@
8265
8486
  "commands",
8266
8487
  "hardis",
8267
8488
  "org",
8268
- "purge",
8269
- "flow.js"
8489
+ "retrieve",
8490
+ "packageconfig.js"
8270
8491
  ],
8271
8492
  "aliasPermutations": [],
8272
8493
  "permutations": [
8273
- "hardis:org:purge:flow",
8274
- "org:hardis:purge:flow",
8275
- "org:purge:hardis:flow",
8276
- "org:purge:flow:hardis",
8277
- "hardis:purge:org:flow",
8278
- "purge:hardis:org:flow",
8279
- "purge:org:hardis:flow",
8280
- "purge:org:flow:hardis",
8281
- "hardis:purge:flow:org",
8282
- "purge:hardis:flow:org",
8283
- "purge:flow:hardis:org",
8284
- "purge:flow:org:hardis",
8285
- "hardis:org:flow:purge",
8286
- "org:hardis:flow:purge",
8287
- "org:flow:hardis:purge",
8288
- "org:flow:purge:hardis",
8289
- "hardis:flow:org:purge",
8290
- "flow:hardis:org:purge",
8291
- "flow:org:hardis:purge",
8292
- "flow:org:purge:hardis",
8293
- "hardis:flow:purge:org",
8294
- "flow:hardis:purge:org",
8295
- "flow:purge:hardis:org",
8296
- "flow:purge:org:hardis"
8494
+ "hardis:org:retrieve:packageconfig",
8495
+ "org:hardis:retrieve:packageconfig",
8496
+ "org:retrieve:hardis:packageconfig",
8497
+ "org:retrieve:packageconfig:hardis",
8498
+ "hardis:retrieve:org:packageconfig",
8499
+ "retrieve:hardis:org:packageconfig",
8500
+ "retrieve:org:hardis:packageconfig",
8501
+ "retrieve:org:packageconfig:hardis",
8502
+ "hardis:retrieve:packageconfig:org",
8503
+ "retrieve:hardis:packageconfig:org",
8504
+ "retrieve:packageconfig:hardis:org",
8505
+ "retrieve:packageconfig:org:hardis",
8506
+ "hardis:org:packageconfig:retrieve",
8507
+ "org:hardis:packageconfig:retrieve",
8508
+ "org:packageconfig:hardis:retrieve",
8509
+ "org:packageconfig:retrieve:hardis",
8510
+ "hardis:packageconfig:org:retrieve",
8511
+ "packageconfig:hardis:org:retrieve",
8512
+ "packageconfig:org:hardis:retrieve",
8513
+ "packageconfig:org:retrieve:hardis",
8514
+ "hardis:packageconfig:retrieve:org",
8515
+ "packageconfig:hardis:retrieve:org",
8516
+ "packageconfig:retrieve:hardis:org",
8517
+ "packageconfig:retrieve:org:hardis"
8297
8518
  ]
8298
8519
  },
8299
- "hardis:org:retrieve:packageconfig": {
8520
+ "hardis:org:test:apex": {
8300
8521
  "aliases": [],
8301
8522
  "args": {},
8302
- "description": "\n**Retrieves the installed package configuration from a Salesforce org and optionally updates the local project configuration.**\n\nThis command is useful for maintaining an accurate record of installed packages within your Salesforce project, which is crucial for managing dependencies and ensuring consistent deployments across environments.\n\nKey functionalities:\n\n- **Package Listing:** Connects to a specified Salesforce org (or prompts for one if not provided) and retrieves a list of all installed packages.\n- **Configuration Update:** Offers the option to update your local project's configuration with the retrieved list of installed packages. This can be beneficial for automating package installations during environment setup or CI/CD processes.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **Org Connection:** It establishes a connection to the target Salesforce org using the provided or prompted username.\n- **Metadata Retrieval:** It utilizes `MetadataUtils.listInstalledPackages` to query the Salesforce org and obtain details about the installed packages.\n- **Interactive Prompt:** It uses the `prompts` library to ask the user whether they want to update their local project configuration with the retrieved package list.\n- **Configuration Management:** If the user confirms, it calls `managePackageConfig` to update the project's configuration file (likely `.sfdx-hardis.yml`) with the new package information.\n- **User Feedback:** Provides clear messages to the user about the success of the package retrieval and configuration update.\n</details>\n",
8523
+ "description": "Run apex tests in Salesforce org\n\nIf following configuration is defined, it will fail if apex coverage target is not reached:\n\n- Env `APEX_TESTS_MIN_COVERAGE_ORG_WIDE` or `.sfdx-hardis` property `apexTestsMinCoverageOrgWide`\n- Env `APEX_TESTS_MIN_COVERAGE_ORG_WIDE` or `.sfdx-hardis` property `apexTestsMinCoverageOrgWide`\n\nYou can override env var SFDX_TEST_WAIT_MINUTES to wait more than 120 minutes.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-apex-tests/) and can output Grafana, Slack and MsTeams Notifications.\n",
8303
8524
  "examples": [
8304
- "$ sf hardis:org:retrieve:packageconfig",
8305
- "sf hardis:org:retrieve:packageconfig -u myOrg"
8525
+ "$ sf hardis:org:test:apex"
8306
8526
  ],
8307
8527
  "flags": {
8308
8528
  "json": {
@@ -8320,6 +8540,21 @@
8320
8540
  "multiple": false,
8321
8541
  "type": "option"
8322
8542
  },
8543
+ "testlevel": {
8544
+ "char": "l",
8545
+ "description": "Level of tests to apply to validate deployment",
8546
+ "name": "testlevel",
8547
+ "default": "RunLocalTests",
8548
+ "hasDynamicHelp": false,
8549
+ "multiple": false,
8550
+ "options": [
8551
+ "NoTestRun",
8552
+ "RunSpecifiedTests",
8553
+ "RunLocalTests",
8554
+ "RunAllTestsInOrg"
8555
+ ],
8556
+ "type": "option"
8557
+ },
8323
8558
  "debug": {
8324
8559
  "char": "d",
8325
8560
  "description": "Activate debug mode (more logs)",
@@ -8358,49 +8593,48 @@
8358
8593
  },
8359
8594
  "hasDynamicHelp": true,
8360
8595
  "hiddenAliases": [],
8361
- "id": "hardis:org:retrieve:packageconfig",
8596
+ "id": "hardis:org:test:apex",
8362
8597
  "pluginAlias": "sfdx-hardis",
8363
8598
  "pluginName": "sfdx-hardis",
8364
8599
  "pluginType": "core",
8365
8600
  "strict": true,
8366
8601
  "enableJsonFlag": true,
8367
- "title": "Retrieve package configuration from an org",
8368
- "requiresProject": false,
8602
+ "title": "Run apex tests",
8369
8603
  "isESM": true,
8370
8604
  "relativePath": [
8371
8605
  "lib",
8372
8606
  "commands",
8373
8607
  "hardis",
8374
8608
  "org",
8375
- "retrieve",
8376
- "packageconfig.js"
8609
+ "test",
8610
+ "apex.js"
8377
8611
  ],
8378
8612
  "aliasPermutations": [],
8379
8613
  "permutations": [
8380
- "hardis:org:retrieve:packageconfig",
8381
- "org:hardis:retrieve:packageconfig",
8382
- "org:retrieve:hardis:packageconfig",
8383
- "org:retrieve:packageconfig:hardis",
8384
- "hardis:retrieve:org:packageconfig",
8385
- "retrieve:hardis:org:packageconfig",
8386
- "retrieve:org:hardis:packageconfig",
8387
- "retrieve:org:packageconfig:hardis",
8388
- "hardis:retrieve:packageconfig:org",
8389
- "retrieve:hardis:packageconfig:org",
8390
- "retrieve:packageconfig:hardis:org",
8391
- "retrieve:packageconfig:org:hardis",
8392
- "hardis:org:packageconfig:retrieve",
8393
- "org:hardis:packageconfig:retrieve",
8394
- "org:packageconfig:hardis:retrieve",
8395
- "org:packageconfig:retrieve:hardis",
8396
- "hardis:packageconfig:org:retrieve",
8397
- "packageconfig:hardis:org:retrieve",
8398
- "packageconfig:org:hardis:retrieve",
8399
- "packageconfig:org:retrieve:hardis",
8400
- "hardis:packageconfig:retrieve:org",
8401
- "packageconfig:hardis:retrieve:org",
8402
- "packageconfig:retrieve:hardis:org",
8403
- "packageconfig:retrieve:org:hardis"
8614
+ "hardis:org:test:apex",
8615
+ "org:hardis:test:apex",
8616
+ "org:test:hardis:apex",
8617
+ "org:test:apex:hardis",
8618
+ "hardis:test:org:apex",
8619
+ "test:hardis:org:apex",
8620
+ "test:org:hardis:apex",
8621
+ "test:org:apex:hardis",
8622
+ "hardis:test:apex:org",
8623
+ "test:hardis:apex:org",
8624
+ "test:apex:hardis:org",
8625
+ "test:apex:org:hardis",
8626
+ "hardis:org:apex:test",
8627
+ "org:hardis:apex:test",
8628
+ "org:apex:hardis:test",
8629
+ "org:apex:test:hardis",
8630
+ "hardis:apex:org:test",
8631
+ "apex:hardis:org:test",
8632
+ "apex:org:hardis:test",
8633
+ "apex:org:test:hardis",
8634
+ "hardis:apex:test:org",
8635
+ "apex:hardis:test:org",
8636
+ "apex:test:hardis:org",
8637
+ "apex:test:org:hardis"
8404
8638
  ]
8405
8639
  },
8406
8640
  "hardis:org:user:activateinvalid": {
@@ -8803,126 +9037,6 @@
8803
9037
  "unfreeze:user:org:hardis"
8804
9038
  ]
8805
9039
  },
8806
- "hardis:org:test:apex": {
8807
- "aliases": [],
8808
- "args": {},
8809
- "description": "Run apex tests in Salesforce org\n\nIf following configuration is defined, it will fail if apex coverage target is not reached:\n\n- Env `APEX_TESTS_MIN_COVERAGE_ORG_WIDE` or `.sfdx-hardis` property `apexTestsMinCoverageOrgWide`\n- Env `APEX_TESTS_MIN_COVERAGE_ORG_WIDE` or `.sfdx-hardis` property `apexTestsMinCoverageOrgWide`\n\nYou can override env var SFDX_TEST_WAIT_MINUTES to wait more than 120 minutes.\n\nThis command is part of [sfdx-hardis Monitoring](https://sfdx-hardis.cloudity.com/salesforce-monitoring-apex-tests/) and can output Grafana, Slack and MsTeams Notifications.\n",
8810
- "examples": [
8811
- "$ sf hardis:org:test:apex"
8812
- ],
8813
- "flags": {
8814
- "json": {
8815
- "description": "Format output as json.",
8816
- "helpGroup": "GLOBAL",
8817
- "name": "json",
8818
- "allowNo": false,
8819
- "type": "boolean"
8820
- },
8821
- "flags-dir": {
8822
- "helpGroup": "GLOBAL",
8823
- "name": "flags-dir",
8824
- "summary": "Import flag values from a directory.",
8825
- "hasDynamicHelp": false,
8826
- "multiple": false,
8827
- "type": "option"
8828
- },
8829
- "testlevel": {
8830
- "char": "l",
8831
- "description": "Level of tests to apply to validate deployment",
8832
- "name": "testlevel",
8833
- "default": "RunLocalTests",
8834
- "hasDynamicHelp": false,
8835
- "multiple": false,
8836
- "options": [
8837
- "NoTestRun",
8838
- "RunSpecifiedTests",
8839
- "RunLocalTests",
8840
- "RunAllTestsInOrg"
8841
- ],
8842
- "type": "option"
8843
- },
8844
- "debug": {
8845
- "char": "d",
8846
- "description": "Activate debug mode (more logs)",
8847
- "name": "debug",
8848
- "allowNo": false,
8849
- "type": "boolean"
8850
- },
8851
- "websocket": {
8852
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
8853
- "name": "websocket",
8854
- "hasDynamicHelp": false,
8855
- "multiple": false,
8856
- "type": "option"
8857
- },
8858
- "skipauth": {
8859
- "description": "Skip authentication check when a default username is required",
8860
- "name": "skipauth",
8861
- "allowNo": false,
8862
- "type": "boolean"
8863
- },
8864
- "target-org": {
8865
- "aliases": [
8866
- "targetusername",
8867
- "u"
8868
- ],
8869
- "char": "o",
8870
- "deprecateAliases": true,
8871
- "name": "target-org",
8872
- "noCacheDefault": true,
8873
- "required": true,
8874
- "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
8875
- "hasDynamicHelp": true,
8876
- "multiple": false,
8877
- "type": "option"
8878
- }
8879
- },
8880
- "hasDynamicHelp": true,
8881
- "hiddenAliases": [],
8882
- "id": "hardis:org:test:apex",
8883
- "pluginAlias": "sfdx-hardis",
8884
- "pluginName": "sfdx-hardis",
8885
- "pluginType": "core",
8886
- "strict": true,
8887
- "enableJsonFlag": true,
8888
- "title": "Run apex tests",
8889
- "isESM": true,
8890
- "relativePath": [
8891
- "lib",
8892
- "commands",
8893
- "hardis",
8894
- "org",
8895
- "test",
8896
- "apex.js"
8897
- ],
8898
- "aliasPermutations": [],
8899
- "permutations": [
8900
- "hardis:org:test:apex",
8901
- "org:hardis:test:apex",
8902
- "org:test:hardis:apex",
8903
- "org:test:apex:hardis",
8904
- "hardis:test:org:apex",
8905
- "test:hardis:org:apex",
8906
- "test:org:hardis:apex",
8907
- "test:org:apex:hardis",
8908
- "hardis:test:apex:org",
8909
- "test:hardis:apex:org",
8910
- "test:apex:hardis:org",
8911
- "test:apex:org:hardis",
8912
- "hardis:org:apex:test",
8913
- "org:hardis:apex:test",
8914
- "org:apex:hardis:test",
8915
- "org:apex:test:hardis",
8916
- "hardis:apex:org:test",
8917
- "apex:hardis:org:test",
8918
- "apex:org:hardis:test",
8919
- "apex:org:test:hardis",
8920
- "hardis:apex:test:org",
8921
- "apex:hardis:test:org",
8922
- "apex:test:hardis:org",
8923
- "apex:test:org:hardis"
8924
- ]
8925
- },
8926
9040
  "hardis:package:version:create": {
8927
9041
  "aliases": [],
8928
9042
  "args": {},
@@ -12539,262 +12653,47 @@
12539
12653
  "enableJsonFlag": true,
12540
12654
  "requiresProject": true,
12541
12655
  "isESM": true,
12542
- "relativePath": [
12543
- "lib",
12544
- "commands",
12545
- "hardis",
12546
- "project",
12547
- "deploy",
12548
- "validate.js"
12549
- ],
12550
- "aliasPermutations": [
12551
- "hardis:deploy:validate",
12552
- "deploy:hardis:validate",
12553
- "deploy:validate:hardis",
12554
- "hardis:validate:deploy",
12555
- "validate:hardis:deploy",
12556
- "validate:deploy:hardis"
12557
- ],
12558
- "permutations": [
12559
- "hardis:project:deploy:validate",
12560
- "project:hardis:deploy:validate",
12561
- "project:deploy:hardis:validate",
12562
- "project:deploy:validate:hardis",
12563
- "hardis:deploy:project:validate",
12564
- "deploy:hardis:project:validate",
12565
- "deploy:project:hardis:validate",
12566
- "deploy:project:validate:hardis",
12567
- "hardis:deploy:validate:project",
12568
- "deploy:hardis:validate:project",
12569
- "deploy:validate:hardis:project",
12570
- "deploy:validate:project:hardis",
12571
- "hardis:project:validate:deploy",
12572
- "project:hardis:validate:deploy",
12573
- "project:validate:hardis:deploy",
12574
- "project:validate:deploy:hardis",
12575
- "hardis:validate:project:deploy",
12576
- "validate:hardis:project:deploy",
12577
- "validate:project:hardis:deploy",
12578
- "validate:project:deploy:hardis",
12579
- "hardis:validate:deploy:project",
12580
- "validate:hardis:deploy:project",
12581
- "validate:deploy:hardis:project",
12582
- "validate:deploy:project:hardis"
12583
- ]
12584
- },
12585
- "hardis:project:fix:profiletabs": {
12586
- "aliases": [],
12587
- "args": {},
12588
- "description": "\n## Command Behavior\n\n**Interactively updates tab visibility settings in Salesforce profiles, addressing a common issue where tab visibilities are not correctly retrieved by `sf project retrieve start`.**\n\nThis command provides a user-friendly interface to manage tab settings within your profile XML files, ensuring that your local project accurately reflects the intended tab configurations in your Salesforce org.\n\nKey functionalities:\n\n- **Interactive Tab Selection:** Displays a multi-select menu of all available tabs in your org, allowing you to choose which tabs to update.\n- **Visibility Control:** Lets you set the visibility for the selected tabs to either `DefaultOn` (Visible) or `Hidden`.\n- **Profile Selection:** Presents a multi-select menu of all .profile-meta.xml files in your project, allowing you to apply the tab visibility changes to specific profiles.\n- **XML Updates:** Modifies the <tabVisibilities> section of the selected profile XML files to reflect the chosen tab settings. If a tab visibility setting already exists for a selected tab, it will be updated; otherwise, a new one will be added.\n- **Sorted Output:** The <tabVisibilities> in the updated profile XML files are sorted alphabetically for consistency and readability.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Queries (Tooling API):** It queries the `TabDefinition` object using `soqlQueryTooling` to retrieve a list of all available tabs in the target org.\n- **File Discovery:** Uses `glob` to find all .profile-meta.xml files within the specified project path.\n- **Interactive Prompts:** Leverages the `prompts` library to create interactive menus for selecting tabs, visibility settings, and profiles.\n- **XML Parsing and Manipulation:** Uses `parseXmlFile` to read the content of profile XML files and `writeXmlFile` to write the modified content back. It manipulates the `tabVisibilities` array within the parsed XML to add or update tab settings.\n- **Array Sorting:** Employs the `sort-array` library to sort the `tabVisibilities` alphabetically by tab name.\n- **Logging:** Provides feedback to the user about which profiles have been updated and a summary of the changes.\n</details>\n",
12589
- "examples": [
12590
- "$ sf hardis:project:fix:profiletabs"
12591
- ],
12592
- "flags": {
12593
- "json": {
12594
- "description": "Format output as json.",
12595
- "helpGroup": "GLOBAL",
12596
- "name": "json",
12597
- "allowNo": false,
12598
- "type": "boolean"
12599
- },
12600
- "flags-dir": {
12601
- "helpGroup": "GLOBAL",
12602
- "name": "flags-dir",
12603
- "summary": "Import flag values from a directory.",
12604
- "hasDynamicHelp": false,
12605
- "multiple": false,
12606
- "type": "option"
12607
- },
12608
- "path": {
12609
- "char": "p",
12610
- "description": "Root folder",
12611
- "name": "path",
12612
- "default": "/home/runner/work/sfdx-hardis/sfdx-hardis",
12613
- "hasDynamicHelp": false,
12614
- "multiple": false,
12615
- "type": "option"
12616
- },
12617
- "debug": {
12618
- "char": "d",
12619
- "description": "Activate debug mode (more logs)",
12620
- "name": "debug",
12621
- "allowNo": false,
12622
- "type": "boolean"
12623
- },
12624
- "websocket": {
12625
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
12626
- "name": "websocket",
12627
- "hasDynamicHelp": false,
12628
- "multiple": false,
12629
- "type": "option"
12630
- },
12631
- "skipauth": {
12632
- "description": "Skip authentication check when a default username is required",
12633
- "name": "skipauth",
12634
- "allowNo": false,
12635
- "type": "boolean"
12636
- },
12637
- "target-org": {
12638
- "aliases": [
12639
- "targetusername",
12640
- "u"
12641
- ],
12642
- "char": "o",
12643
- "deprecateAliases": true,
12644
- "name": "target-org",
12645
- "noCacheDefault": true,
12646
- "required": true,
12647
- "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
12648
- "hasDynamicHelp": true,
12649
- "multiple": false,
12650
- "type": "option"
12651
- }
12652
- },
12653
- "hasDynamicHelp": true,
12654
- "hiddenAliases": [],
12655
- "id": "hardis:project:fix:profiletabs",
12656
- "pluginAlias": "sfdx-hardis",
12657
- "pluginName": "sfdx-hardis",
12658
- "pluginType": "core",
12659
- "strict": true,
12660
- "enableJsonFlag": true,
12661
- "title": "Fix profiles to add tabs that are not retrieved by SF CLI",
12662
- "requiresProject": true,
12663
- "isESM": true,
12664
- "relativePath": [
12665
- "lib",
12666
- "commands",
12667
- "hardis",
12668
- "project",
12669
- "fix",
12670
- "profiletabs.js"
12671
- ],
12672
- "aliasPermutations": [],
12673
- "permutations": [
12674
- "hardis:project:fix:profiletabs",
12675
- "project:hardis:fix:profiletabs",
12676
- "project:fix:hardis:profiletabs",
12677
- "project:fix:profiletabs:hardis",
12678
- "hardis:fix:project:profiletabs",
12679
- "fix:hardis:project:profiletabs",
12680
- "fix:project:hardis:profiletabs",
12681
- "fix:project:profiletabs:hardis",
12682
- "hardis:fix:profiletabs:project",
12683
- "fix:hardis:profiletabs:project",
12684
- "fix:profiletabs:hardis:project",
12685
- "fix:profiletabs:project:hardis",
12686
- "hardis:project:profiletabs:fix",
12687
- "project:hardis:profiletabs:fix",
12688
- "project:profiletabs:hardis:fix",
12689
- "project:profiletabs:fix:hardis",
12690
- "hardis:profiletabs:project:fix",
12691
- "profiletabs:hardis:project:fix",
12692
- "profiletabs:project:hardis:fix",
12693
- "profiletabs:project:fix:hardis",
12694
- "hardis:profiletabs:fix:project",
12695
- "profiletabs:hardis:fix:project",
12696
- "profiletabs:fix:hardis:project",
12697
- "profiletabs:fix:project:hardis"
12698
- ]
12699
- },
12700
- "hardis:project:fix:v53flexipages": {
12701
- "aliases": [],
12702
- "args": {},
12703
- "description": "\n## Command Behavior\n\n**Fixes Salesforce FlexiPages for compatibility with API Version 53.0 (Winter '22 release) by adding missing identifiers to component instances.**\n\nSalesforce introduced a change in API Version 53.0 that requires `identifier` tags within `componentInstance` and `fieldInstance` elements in FlexiPage metadata. If these identifiers are missing, deployments to orgs with API version 53.0 or higher will fail. This command automates the process of adding these missing identifiers, ensuring your FlexiPages remain deployable.\n\nKey functionalities:\n\n- **Targeted FlexiPage Processing:** Scans all .flexipage-meta.xml files within the specified root folder (defaults to current working directory).\n- **Identifier Injection:** Inserts a unique `identifier` tag (e.g., `SFDX_HARDIS_REPLACEMENT_ID`) into `componentInstance` and `fieldInstance` elements that lack one.\n\n**Important Note:** After running this command, ensure you update your `apiVersion` to `53.0` (or higher) in your `package.xml` and `sfdx-project.json` files.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **File Discovery:** Uses `glob` to find all .flexipage-meta.xml files.\n- **Content Reading:** Reads the XML content of each FlexiPage file.\n- **Regular Expression Replacement:** Employs a set of regular expressions to identify specific XML patterns (componentName.../componentName.../componentInstance, componentName.../componentName.../visibilityRule, fieldItem.../fieldItem.../fieldInstance) that are missing the `identifier` tag.\n- **Dynamic ID Generation:** For each match, it generates a unique identifier (e.g., `sfdxHardisIdX`) and injects it into the XML structure.\n- **File Writing:** If changes are made, the modified XML content is written back to the FlexiPage file using `fs.writeFile`.\n- **Logging:** Provides messages about which FlexiPages are being processed and a summary of the total number of identifiers added.\n</details>\n",
12704
- "examples": [
12705
- "$ sf hardis:project:fix:v53flexipages"
12706
- ],
12707
- "flags": {
12708
- "json": {
12709
- "description": "Format output as json.",
12710
- "helpGroup": "GLOBAL",
12711
- "name": "json",
12712
- "allowNo": false,
12713
- "type": "boolean"
12714
- },
12715
- "flags-dir": {
12716
- "helpGroup": "GLOBAL",
12717
- "name": "flags-dir",
12718
- "summary": "Import flag values from a directory.",
12719
- "hasDynamicHelp": false,
12720
- "multiple": false,
12721
- "type": "option"
12722
- },
12723
- "path": {
12724
- "char": "p",
12725
- "description": "Root folder",
12726
- "name": "path",
12727
- "default": "/home/runner/work/sfdx-hardis/sfdx-hardis",
12728
- "hasDynamicHelp": false,
12729
- "multiple": false,
12730
- "type": "option"
12731
- },
12732
- "debug": {
12733
- "char": "d",
12734
- "description": "Activate debug mode (more logs)",
12735
- "name": "debug",
12736
- "allowNo": false,
12737
- "type": "boolean"
12738
- },
12739
- "websocket": {
12740
- "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
12741
- "name": "websocket",
12742
- "hasDynamicHelp": false,
12743
- "multiple": false,
12744
- "type": "option"
12745
- },
12746
- "skipauth": {
12747
- "description": "Skip authentication check when a default username is required",
12748
- "name": "skipauth",
12749
- "allowNo": false,
12750
- "type": "boolean"
12751
- }
12752
- },
12753
- "hasDynamicHelp": false,
12754
- "hiddenAliases": [],
12755
- "id": "hardis:project:fix:v53flexipages",
12756
- "pluginAlias": "sfdx-hardis",
12757
- "pluginName": "sfdx-hardis",
12758
- "pluginType": "core",
12759
- "strict": true,
12760
- "enableJsonFlag": true,
12761
- "title": "Fix flexipages for v53",
12762
- "requiresProject": true,
12763
- "isESM": true,
12764
- "relativePath": [
12765
- "lib",
12766
- "commands",
12767
- "hardis",
12768
- "project",
12769
- "fix",
12770
- "v53flexipages.js"
12771
- ],
12772
- "aliasPermutations": [],
12773
- "permutations": [
12774
- "hardis:project:fix:v53flexipages",
12775
- "project:hardis:fix:v53flexipages",
12776
- "project:fix:hardis:v53flexipages",
12777
- "project:fix:v53flexipages:hardis",
12778
- "hardis:fix:project:v53flexipages",
12779
- "fix:hardis:project:v53flexipages",
12780
- "fix:project:hardis:v53flexipages",
12781
- "fix:project:v53flexipages:hardis",
12782
- "hardis:fix:v53flexipages:project",
12783
- "fix:hardis:v53flexipages:project",
12784
- "fix:v53flexipages:hardis:project",
12785
- "fix:v53flexipages:project:hardis",
12786
- "hardis:project:v53flexipages:fix",
12787
- "project:hardis:v53flexipages:fix",
12788
- "project:v53flexipages:hardis:fix",
12789
- "project:v53flexipages:fix:hardis",
12790
- "hardis:v53flexipages:project:fix",
12791
- "v53flexipages:hardis:project:fix",
12792
- "v53flexipages:project:hardis:fix",
12793
- "v53flexipages:project:fix:hardis",
12794
- "hardis:v53flexipages:fix:project",
12795
- "v53flexipages:hardis:fix:project",
12796
- "v53flexipages:fix:hardis:project",
12797
- "v53flexipages:fix:project:hardis"
12656
+ "relativePath": [
12657
+ "lib",
12658
+ "commands",
12659
+ "hardis",
12660
+ "project",
12661
+ "deploy",
12662
+ "validate.js"
12663
+ ],
12664
+ "aliasPermutations": [
12665
+ "hardis:deploy:validate",
12666
+ "deploy:hardis:validate",
12667
+ "deploy:validate:hardis",
12668
+ "hardis:validate:deploy",
12669
+ "validate:hardis:deploy",
12670
+ "validate:deploy:hardis"
12671
+ ],
12672
+ "permutations": [
12673
+ "hardis:project:deploy:validate",
12674
+ "project:hardis:deploy:validate",
12675
+ "project:deploy:hardis:validate",
12676
+ "project:deploy:validate:hardis",
12677
+ "hardis:deploy:project:validate",
12678
+ "deploy:hardis:project:validate",
12679
+ "deploy:project:hardis:validate",
12680
+ "deploy:project:validate:hardis",
12681
+ "hardis:deploy:validate:project",
12682
+ "deploy:hardis:validate:project",
12683
+ "deploy:validate:hardis:project",
12684
+ "deploy:validate:project:hardis",
12685
+ "hardis:project:validate:deploy",
12686
+ "project:hardis:validate:deploy",
12687
+ "project:validate:hardis:deploy",
12688
+ "project:validate:deploy:hardis",
12689
+ "hardis:validate:project:deploy",
12690
+ "validate:hardis:project:deploy",
12691
+ "validate:project:hardis:deploy",
12692
+ "validate:project:deploy:hardis",
12693
+ "hardis:validate:deploy:project",
12694
+ "validate:hardis:deploy:project",
12695
+ "validate:deploy:hardis:project",
12696
+ "validate:deploy:project:hardis"
12798
12697
  ]
12799
12698
  },
12800
12699
  "hardis:project:generate:bypass": {
@@ -13192,6 +13091,221 @@
13192
13091
  "gitdelta:generate:project:hardis"
13193
13092
  ]
13194
13093
  },
13094
+ "hardis:project:fix:profiletabs": {
13095
+ "aliases": [],
13096
+ "args": {},
13097
+ "description": "\n## Command Behavior\n\n**Interactively updates tab visibility settings in Salesforce profiles, addressing a common issue where tab visibilities are not correctly retrieved by `sf project retrieve start`.**\n\nThis command provides a user-friendly interface to manage tab settings within your profile XML files, ensuring that your local project accurately reflects the intended tab configurations in your Salesforce org.\n\nKey functionalities:\n\n- **Interactive Tab Selection:** Displays a multi-select menu of all available tabs in your org, allowing you to choose which tabs to update.\n- **Visibility Control:** Lets you set the visibility for the selected tabs to either `DefaultOn` (Visible) or `Hidden`.\n- **Profile Selection:** Presents a multi-select menu of all .profile-meta.xml files in your project, allowing you to apply the tab visibility changes to specific profiles.\n- **XML Updates:** Modifies the <tabVisibilities> section of the selected profile XML files to reflect the chosen tab settings. If a tab visibility setting already exists for a selected tab, it will be updated; otherwise, a new one will be added.\n- **Sorted Output:** The <tabVisibilities> in the updated profile XML files are sorted alphabetically for consistency and readability.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **SOQL Queries (Tooling API):** It queries the `TabDefinition` object using `soqlQueryTooling` to retrieve a list of all available tabs in the target org.\n- **File Discovery:** Uses `glob` to find all .profile-meta.xml files within the specified project path.\n- **Interactive Prompts:** Leverages the `prompts` library to create interactive menus for selecting tabs, visibility settings, and profiles.\n- **XML Parsing and Manipulation:** Uses `parseXmlFile` to read the content of profile XML files and `writeXmlFile` to write the modified content back. It manipulates the `tabVisibilities` array within the parsed XML to add or update tab settings.\n- **Array Sorting:** Employs the `sort-array` library to sort the `tabVisibilities` alphabetically by tab name.\n- **Logging:** Provides feedback to the user about which profiles have been updated and a summary of the changes.\n</details>\n",
13098
+ "examples": [
13099
+ "$ sf hardis:project:fix:profiletabs"
13100
+ ],
13101
+ "flags": {
13102
+ "json": {
13103
+ "description": "Format output as json.",
13104
+ "helpGroup": "GLOBAL",
13105
+ "name": "json",
13106
+ "allowNo": false,
13107
+ "type": "boolean"
13108
+ },
13109
+ "flags-dir": {
13110
+ "helpGroup": "GLOBAL",
13111
+ "name": "flags-dir",
13112
+ "summary": "Import flag values from a directory.",
13113
+ "hasDynamicHelp": false,
13114
+ "multiple": false,
13115
+ "type": "option"
13116
+ },
13117
+ "path": {
13118
+ "char": "p",
13119
+ "description": "Root folder",
13120
+ "name": "path",
13121
+ "default": "/home/runner/work/sfdx-hardis/sfdx-hardis",
13122
+ "hasDynamicHelp": false,
13123
+ "multiple": false,
13124
+ "type": "option"
13125
+ },
13126
+ "debug": {
13127
+ "char": "d",
13128
+ "description": "Activate debug mode (more logs)",
13129
+ "name": "debug",
13130
+ "allowNo": false,
13131
+ "type": "boolean"
13132
+ },
13133
+ "websocket": {
13134
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
13135
+ "name": "websocket",
13136
+ "hasDynamicHelp": false,
13137
+ "multiple": false,
13138
+ "type": "option"
13139
+ },
13140
+ "skipauth": {
13141
+ "description": "Skip authentication check when a default username is required",
13142
+ "name": "skipauth",
13143
+ "allowNo": false,
13144
+ "type": "boolean"
13145
+ },
13146
+ "target-org": {
13147
+ "aliases": [
13148
+ "targetusername",
13149
+ "u"
13150
+ ],
13151
+ "char": "o",
13152
+ "deprecateAliases": true,
13153
+ "name": "target-org",
13154
+ "noCacheDefault": true,
13155
+ "required": true,
13156
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
13157
+ "hasDynamicHelp": true,
13158
+ "multiple": false,
13159
+ "type": "option"
13160
+ }
13161
+ },
13162
+ "hasDynamicHelp": true,
13163
+ "hiddenAliases": [],
13164
+ "id": "hardis:project:fix:profiletabs",
13165
+ "pluginAlias": "sfdx-hardis",
13166
+ "pluginName": "sfdx-hardis",
13167
+ "pluginType": "core",
13168
+ "strict": true,
13169
+ "enableJsonFlag": true,
13170
+ "title": "Fix profiles to add tabs that are not retrieved by SF CLI",
13171
+ "requiresProject": true,
13172
+ "isESM": true,
13173
+ "relativePath": [
13174
+ "lib",
13175
+ "commands",
13176
+ "hardis",
13177
+ "project",
13178
+ "fix",
13179
+ "profiletabs.js"
13180
+ ],
13181
+ "aliasPermutations": [],
13182
+ "permutations": [
13183
+ "hardis:project:fix:profiletabs",
13184
+ "project:hardis:fix:profiletabs",
13185
+ "project:fix:hardis:profiletabs",
13186
+ "project:fix:profiletabs:hardis",
13187
+ "hardis:fix:project:profiletabs",
13188
+ "fix:hardis:project:profiletabs",
13189
+ "fix:project:hardis:profiletabs",
13190
+ "fix:project:profiletabs:hardis",
13191
+ "hardis:fix:profiletabs:project",
13192
+ "fix:hardis:profiletabs:project",
13193
+ "fix:profiletabs:hardis:project",
13194
+ "fix:profiletabs:project:hardis",
13195
+ "hardis:project:profiletabs:fix",
13196
+ "project:hardis:profiletabs:fix",
13197
+ "project:profiletabs:hardis:fix",
13198
+ "project:profiletabs:fix:hardis",
13199
+ "hardis:profiletabs:project:fix",
13200
+ "profiletabs:hardis:project:fix",
13201
+ "profiletabs:project:hardis:fix",
13202
+ "profiletabs:project:fix:hardis",
13203
+ "hardis:profiletabs:fix:project",
13204
+ "profiletabs:hardis:fix:project",
13205
+ "profiletabs:fix:hardis:project",
13206
+ "profiletabs:fix:project:hardis"
13207
+ ]
13208
+ },
13209
+ "hardis:project:fix:v53flexipages": {
13210
+ "aliases": [],
13211
+ "args": {},
13212
+ "description": "\n## Command Behavior\n\n**Fixes Salesforce FlexiPages for compatibility with API Version 53.0 (Winter '22 release) by adding missing identifiers to component instances.**\n\nSalesforce introduced a change in API Version 53.0 that requires `identifier` tags within `componentInstance` and `fieldInstance` elements in FlexiPage metadata. If these identifiers are missing, deployments to orgs with API version 53.0 or higher will fail. This command automates the process of adding these missing identifiers, ensuring your FlexiPages remain deployable.\n\nKey functionalities:\n\n- **Targeted FlexiPage Processing:** Scans all .flexipage-meta.xml files within the specified root folder (defaults to current working directory).\n- **Identifier Injection:** Inserts a unique `identifier` tag (e.g., `SFDX_HARDIS_REPLACEMENT_ID`) into `componentInstance` and `fieldInstance` elements that lack one.\n\n**Important Note:** After running this command, ensure you update your `apiVersion` to `53.0` (or higher) in your `package.xml` and `sfdx-project.json` files.\n\n<details markdown=\"1\">\n<summary>Technical explanations</summary>\n\nThe command's technical implementation involves:\n\n- **File Discovery:** Uses `glob` to find all .flexipage-meta.xml files.\n- **Content Reading:** Reads the XML content of each FlexiPage file.\n- **Regular Expression Replacement:** Employs a set of regular expressions to identify specific XML patterns (componentName.../componentName.../componentInstance, componentName.../componentName.../visibilityRule, fieldItem.../fieldItem.../fieldInstance) that are missing the `identifier` tag.\n- **Dynamic ID Generation:** For each match, it generates a unique identifier (e.g., `sfdxHardisIdX`) and injects it into the XML structure.\n- **File Writing:** If changes are made, the modified XML content is written back to the FlexiPage file using `fs.writeFile`.\n- **Logging:** Provides messages about which FlexiPages are being processed and a summary of the total number of identifiers added.\n</details>\n",
13213
+ "examples": [
13214
+ "$ sf hardis:project:fix:v53flexipages"
13215
+ ],
13216
+ "flags": {
13217
+ "json": {
13218
+ "description": "Format output as json.",
13219
+ "helpGroup": "GLOBAL",
13220
+ "name": "json",
13221
+ "allowNo": false,
13222
+ "type": "boolean"
13223
+ },
13224
+ "flags-dir": {
13225
+ "helpGroup": "GLOBAL",
13226
+ "name": "flags-dir",
13227
+ "summary": "Import flag values from a directory.",
13228
+ "hasDynamicHelp": false,
13229
+ "multiple": false,
13230
+ "type": "option"
13231
+ },
13232
+ "path": {
13233
+ "char": "p",
13234
+ "description": "Root folder",
13235
+ "name": "path",
13236
+ "default": "/home/runner/work/sfdx-hardis/sfdx-hardis",
13237
+ "hasDynamicHelp": false,
13238
+ "multiple": false,
13239
+ "type": "option"
13240
+ },
13241
+ "debug": {
13242
+ "char": "d",
13243
+ "description": "Activate debug mode (more logs)",
13244
+ "name": "debug",
13245
+ "allowNo": false,
13246
+ "type": "boolean"
13247
+ },
13248
+ "websocket": {
13249
+ "description": "Websocket host:port for VsCode SFDX Hardis UI integration",
13250
+ "name": "websocket",
13251
+ "hasDynamicHelp": false,
13252
+ "multiple": false,
13253
+ "type": "option"
13254
+ },
13255
+ "skipauth": {
13256
+ "description": "Skip authentication check when a default username is required",
13257
+ "name": "skipauth",
13258
+ "allowNo": false,
13259
+ "type": "boolean"
13260
+ }
13261
+ },
13262
+ "hasDynamicHelp": false,
13263
+ "hiddenAliases": [],
13264
+ "id": "hardis:project:fix:v53flexipages",
13265
+ "pluginAlias": "sfdx-hardis",
13266
+ "pluginName": "sfdx-hardis",
13267
+ "pluginType": "core",
13268
+ "strict": true,
13269
+ "enableJsonFlag": true,
13270
+ "title": "Fix flexipages for v53",
13271
+ "requiresProject": true,
13272
+ "isESM": true,
13273
+ "relativePath": [
13274
+ "lib",
13275
+ "commands",
13276
+ "hardis",
13277
+ "project",
13278
+ "fix",
13279
+ "v53flexipages.js"
13280
+ ],
13281
+ "aliasPermutations": [],
13282
+ "permutations": [
13283
+ "hardis:project:fix:v53flexipages",
13284
+ "project:hardis:fix:v53flexipages",
13285
+ "project:fix:hardis:v53flexipages",
13286
+ "project:fix:v53flexipages:hardis",
13287
+ "hardis:fix:project:v53flexipages",
13288
+ "fix:hardis:project:v53flexipages",
13289
+ "fix:project:hardis:v53flexipages",
13290
+ "fix:project:v53flexipages:hardis",
13291
+ "hardis:fix:v53flexipages:project",
13292
+ "fix:hardis:v53flexipages:project",
13293
+ "fix:v53flexipages:hardis:project",
13294
+ "fix:v53flexipages:project:hardis",
13295
+ "hardis:project:v53flexipages:fix",
13296
+ "project:hardis:v53flexipages:fix",
13297
+ "project:v53flexipages:hardis:fix",
13298
+ "project:v53flexipages:fix:hardis",
13299
+ "hardis:v53flexipages:project:fix",
13300
+ "v53flexipages:hardis:project:fix",
13301
+ "v53flexipages:project:hardis:fix",
13302
+ "v53flexipages:project:fix:hardis",
13303
+ "hardis:v53flexipages:fix:project",
13304
+ "v53flexipages:hardis:fix:project",
13305
+ "v53flexipages:fix:hardis:project",
13306
+ "v53flexipages:fix:project:hardis"
13307
+ ]
13308
+ },
13195
13309
  "hardis:project:metadata:activate-decomposed": {
13196
13310
  "aliases": [],
13197
13311
  "args": {},
@@ -15370,5 +15484,5 @@
15370
15484
  ]
15371
15485
  }
15372
15486
  },
15373
- "version": "6.9.1-alpha202510282151.0"
15487
+ "version": "6.10.1-alpha202511021043.0"
15374
15488
  }