Skip to content

Commit

Permalink
feat!: ga new tree commands (#975)
Browse files Browse the repository at this point in the history
* feat!: ga the new data tree commands

* test: fix relative path references

* test: nuts for new commands use their permanent name

* test: don't use the old weird files format for importing

* test: works ok without existing save/resolve refs

* fix: prevent undefined in template literal

* docs: fix aliases, message from old command

* chore: correct snapshots for alias fix

* fix: update messages (#976)

* fix: deprecation shows on legacy tree commands

---------

Co-authored-by: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com>
  • Loading branch information
mshanemc and jshackell-sfdc authored Jul 1, 2024
1 parent c809b66 commit cb49efc
Show file tree
Hide file tree
Showing 22 changed files with 358 additions and 259 deletions.
6 changes: 3 additions & 3 deletions NewTreeCommandsPlan.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

We're improving the `data export tree` and `data import tree` commands, but doing it in phases.

## Phase 1: Beta the new commands. [Now]
## Phase 1: Beta the new commands. [Completed]

Our plan:

Expand All @@ -29,7 +29,7 @@ Other differences:
- `data import beta tree --files` (and not `--plan`) imports the files in parallel. Files can only reference each other if you specify `--plan`.
- `data import tree` outputs deprecation warnings for both `--content-type` and `--config-help` flags.

## Phase 2: GA the new commands, put the old ones under the `legacy` sub-topic. [July 10, 2024]
## Phase 2: GA the new commands, put the old ones under the `legacy` sub-topic. [Now]

Our plan:

Expand All @@ -43,7 +43,7 @@ Our plan:

Our plan:

1. Update `data export tree --plan` to stop writing the unused `saveRefs` and `resolveRefs` properties on plan files, and stop returning them in JSON output.
1. Update `data export tree --plan` to stop writing the unused `saveRefs` and `resolveRefs` properties on plan files, and stop returning them in JSON output, and remove the warning about that change.
1. Tighten the schema to remove the `object` part of `files`, and remove `saveRefs` and `resolveRefs`.
1. Check messages for any that aren't being used, then remove them.
1. Remove the `beta` alias from `data import tree` and `data export tree`.
Expand Down
22 changes: 11 additions & 11 deletions command-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@
},
{
"alias": [],
"command": "data:export:beta:tree",
"command": "data:export:legacy:tree",
"flagAliases": ["apiversion", "outputdir", "targetusername", "u"],
"flagChars": ["d", "o", "p", "q", "x"],
"flags": ["api-version", "flags-dir", "json", "loglevel", "output-dir", "plan", "prefix", "query", "target-org"],
"plugin": "@salesforce/plugin-data"
},
{
"alias": ["force:data:tree:export"],
"alias": ["force:data:tree:export", "data:export:beta:tree"],
"command": "data:export:tree",
"flagAliases": ["apiversion", "outputdir", "targetusername", "u"],
"flagChars": ["d", "o", "p", "q", "x"],
Expand Down Expand Up @@ -109,15 +109,7 @@
},
{
"alias": [],
"command": "data:import:beta:tree",
"flagAliases": ["apiversion", "sobjecttreefiles", "targetusername", "u"],
"flagChars": ["f", "o", "p"],
"flags": ["api-version", "files", "flags-dir", "json", "loglevel", "plan", "target-org"],
"plugin": "@salesforce/plugin-data"
},
{
"alias": ["force:data:tree:import"],
"command": "data:import:tree",
"command": "data:import:legacy:tree",
"flagAliases": ["apiversion", "confighelp", "contenttype", "sobjecttreefiles", "targetusername", "u"],
"flagChars": ["c", "f", "o", "p"],
"flags": [
Expand All @@ -133,6 +125,14 @@
],
"plugin": "@salesforce/plugin-data"
},
{
"alias": ["force:data:tree:import", "data:import:beta:tree"],
"command": "data:import:tree",
"flagAliases": ["apiversion", "sobjecttreefiles", "targetusername", "u"],
"flagChars": ["f", "o", "p"],
"flags": ["api-version", "files", "flags-dir", "json", "loglevel", "plan", "target-org"],
"plugin": "@salesforce/plugin-data"
},
{
"alias": ["force:data:soql:query"],
"command": "data:query",
Expand Down
10 changes: 9 additions & 1 deletion messages/tree.export.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Directory in which to generate the JSON files; default is current directory.

- Export records retrieved with the specified SOQL query into a single JSON file in the current directory; the command uses your default org:

<%= config.bin %> <%= command.id %> --query "SELECT Id, Name, (SELECT Name, Address__c FROM Properties__r) FROM Broker__c"
<%= config.bin %> <%= command.id %> --query "SELECT Id, Name, (SELECT Name, Address**c FROM Properties**r) FROM Broker\_\_c"

- Export data using a SOQL query in the "query.txt" file and generate JSON files for each object and a plan that aggregates them:

Expand All @@ -43,3 +43,11 @@ Directory in which to generate the JSON files; default is current directory.
# PrefixSlashError

`--prefix` cannot contain a forward slash or backslash.

# PlanJsonWarning

Starting on Nov 10, 2024, the JSON output for `--plan` will no longer include the `saveRefs` and `resolveRefs` properties.

# LegacyDeprecation

Starting on Nov 10, 2024, this command will no longer be available. Use `data export tree` instead.
43 changes: 0 additions & 43 deletions messages/tree.import.beta.md

This file was deleted.

60 changes: 60 additions & 0 deletions messages/tree.import.legacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# summary

Import data from one or more JSON files into an org.

# description

The JSON files that contain the data are in sObject tree format, which is a collection of nested, parent-child records with a single root record. Use the "<%= config.bin %> data export tree" command to generate these JSON files.

If you used the --plan flag when exporting the data to generate a plan definition file, use the --plan flag to reference the file when you import. If you're not using a plan, use the --files flag to list the files. If you specify multiple JSON files that depend on each other in a parent-child relationship, be sure you list them in the correct order.

The sObject Tree API supports requests that contain up to 200 records. For more information, see the REST API Developer Guide. (https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_sobject_tree.htm)

# flags.files.summary

Comma-separated and in-order JSON files that contain the records, in sObject tree format, that you want to insert.

# flags.plan.summary

Plan definition file to insert multiple data files.

# flags.content-type.summary

Content type of import files if their extention is not .json.

# flags.content-type.deprecation

The `config-type` flag is deprecated and will be moved to a `legacy` command after July 10, 2024. It will be completely removed after Nov 10, 2024. Use the new `data tree beta import` command.

# flags.config-help.summary

Display schema information for the --plan configuration file to stdout; if you specify this flag, all other flags except --json are ignored.

# flags.config-help.deprecation

The `config-help` flag is deprecated and will be moved to a `legacy` command after July 10, 2024. It will be completely removed after Nov 10, 2024. Use the new `data tree beta import` command.

# examples

- Import the records contained in two JSON files into the org with alias "my-scratch":

<%= config.bin %> <%= command.id %> --files Contact.json,Account.json --target-org my-scratch

- Import records using a plan definition file into your default org:

<%= config.bin %> <%= command.id %> --plan Account-Contact-plan.json

# schema-help

schema(array) - Data Import Plan: Schema for SFDX Toolbelt's data import plan JSON.

- items(object) - SObject Type: Definition of records to be insert per SObject Type
- sobject(string) - Name of SObject: Child file references must have SObject roots of this type
- saveRefs(boolean) - Save References: Post-save, save references (Name/ID) to be used for reference replacement in subsequent saves. Applies to all data files for this SObject type.
- resolveRefs(boolean) - Resolve References: Pre-save, replace @<reference> with ID from previous save. Applies to all data files for this SObject type.
- files(array) - Files: An array of files paths to load
- items(string|object) - Filepath: Filepath string or object to point to a JSON or XML file having data defined in SObject Tree format.

# deprecation

After Nov 10, 2024, this command will no longer be available. Use `data export tree`.
35 changes: 11 additions & 24 deletions messages/tree.import.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,29 @@ The JSON files that contain the data are in sObject tree format, which is a coll

If you used the --plan flag when exporting the data to generate a plan definition file, use the --plan flag to reference the file when you import. If you're not using a plan, use the --files flag to list the files. If you specify multiple JSON files that depend on each other in a parent-child relationship, be sure you list them in the correct order.

The sObject Tree API supports requests that contain up to 200 records. For more information, see the REST API Developer Guide. (https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_sobject_tree.htm)

# flags.files.summary

Comma-separated and in-order JSON files that contain the records, in sObject tree format, that you want to insert.

# flags.plan.summary

Plan definition file to insert multiple data files.
# flag.files.description

# flags.content-type.summary
Each file can contain up to 200 total records. For more information, see the REST API Developer Guide. (https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_sobject_tree.htm)

Content type of import files if their extention is not .json.
# flags.plan.summary

# flags.content-type.deprecation
Plan definition file to insert multiple data files.

The `config-type` flag is deprecated and will be moved to a `legacy` command after July 10, 2024. It will be completely removed after Nov 10, 2024. Use the new `data tree beta import` command.
# flags.plan.description

# flags.config-help.summary
Unlike when you use the `--files` flag, the files listed in the plan definition file **can** contain more then 200 records. When the CLI executes the import, it automatically batches the records to comply with the 200 record limit set by the API.

Display schema information for the --plan configuration file to stdout; if you specify this flag, all other flags except --json are ignored.
The order in which you list the files in the plan definition file matters. Specifically, records with lookups to records in another file should be listed AFTER that file. For example, let's say you're loading Account and Contact records, and the contacts have references to those accounts. Be sure you list the Accounts file before the Contacts file.

# flags.config-help.deprecation
The plan definition file has the following schema:

The `config-help` flag is deprecated and will be moved to a `legacy` command after July 10, 2024. It will be completely removed after Nov 10, 2024. Use the new `data tree beta import` command.
- items(object) - SObject Type: Definition of records to be insert per SObject Type
- sobject(string) - Name of SObject: Child file references must have SObject roots of this type
- files(array) - Files: An array of files paths to load

# examples

Expand All @@ -43,14 +41,3 @@ The `config-help` flag is deprecated and will be moved to a `legacy` command aft
- Import records using a plan definition file into your default org:

<%= config.bin %> <%= command.id %> --plan Account-Contact-plan.json

# schema-help

schema(array) - Data Import Plan: Schema for SFDX Toolbelt's data import plan JSON.

- items(object) - SObject Type: Definition of records to be insert per SObject Type
- sobject(string) - Name of SObject: Child file references must have SObject roots of this type
- saveRefs(boolean) - Save References: Post-save, save references (Name/ID) to be used for reference replacement in subsequent saves. Applies to all data files for this SObject type.
- resolveRefs(boolean) - Resolve References: Pre-save, replace @<reference> with ID from previous save. Applies to all data files for this SObject type.
- files(array) - Files: An array of files paths to load
- items(string|object) - Filepath: Filepath string or object to point to a JSON or XML file having data defined in SObject Tree format.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import { Messages } from '@salesforce/core';
import { SfCommand, Flags, Ux } from '@salesforce/sf-plugins-core';
import { orgFlags, prefixValidation } from '../../../../flags.js';
import { ExportConfig, runExport } from '../../../../export.js';
import { orgFlags } from '../../../../flags.js';
import { ExportApi, ExportConfig } from '../../../../api/data/tree/exportApi.js';
import type { DataPlanPart, SObjectTreeFileContents } from '../../../../types.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
Expand All @@ -18,9 +18,12 @@ export default class Export extends SfCommand<DataPlanPart[] | SObjectTreeFileCo
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');
// TODO: when you remove the beta state, put the force: aliases back in
public static readonly state = 'beta';

public static readonly hidden = true;
public static readonly state = 'deprecated';
public static readonly deprecationOptions = {
to: 'data tree export',
message: messages.getMessage('LegacyDeprecation'),
};
public static readonly flags = {
...orgFlags,
query: Flags.string({
Expand All @@ -35,7 +38,6 @@ export default class Export extends SfCommand<DataPlanPart[] | SObjectTreeFileCo
prefix: Flags.string({
char: 'x',
summary: messages.getMessage('flags.prefix.summary'),
parse: prefixValidation,
}),
'output-dir': Flags.directory({
char: 'd',
Expand All @@ -47,14 +49,14 @@ export default class Export extends SfCommand<DataPlanPart[] | SObjectTreeFileCo

public async run(): Promise<DataPlanPart[] | SObjectTreeFileContents> {
const { flags } = await this.parse(Export);
const ux = new Ux({ jsonEnabled: this.jsonEnabled() });
const exportApi = new ExportApi(flags['target-org'], ux);
const exportConfig: ExportConfig = {
outputDir: flags['output-dir'],
plan: flags.plan,
prefix: flags.prefix,
query: flags.query,
conn: flags['target-org'].getConnection(flags['api-version']),
ux: new Ux({ jsonEnabled: this.jsonEnabled() }),
};
return runExport(exportConfig);
return exportApi.export(exportConfig);
}
}
20 changes: 10 additions & 10 deletions src/commands/data/export/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import { Messages } from '@salesforce/core';
import { SfCommand, Flags, Ux } from '@salesforce/sf-plugins-core';
import { orgFlags } from '../../../flags.js';
import { ExportApi, ExportConfig } from '../../../api/data/tree/exportApi.js';
import { orgFlags, prefixValidation } from '../../../flags.js';
import { ExportConfig, runExport } from '../../../export.js';
import type { DataPlanPart, SObjectTreeFileContents } from '../../../types.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
Expand All @@ -18,7 +18,7 @@ export default class Export extends SfCommand<DataPlanPart[] | SObjectTreeFileCo
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');
public static readonly aliases = ['force:data:tree:export'];
public static readonly aliases = ['force:data:tree:export', 'data:export:beta:tree'];
public static readonly deprecateAliases = true;

public static readonly flags = {
Expand All @@ -35,6 +35,7 @@ export default class Export extends SfCommand<DataPlanPart[] | SObjectTreeFileCo
prefix: Flags.string({
char: 'x',
summary: messages.getMessage('flags.prefix.summary'),
parse: prefixValidation,
}),
'output-dir': Flags.directory({
char: 'd',
Expand All @@ -45,19 +46,18 @@ export default class Export extends SfCommand<DataPlanPart[] | SObjectTreeFileCo
};

public async run(): Promise<DataPlanPart[] | SObjectTreeFileContents> {
this.info(
'Try the the new "sf data export beta tree" command. It support SOQL queries with up to 5 levels of objects!'
);

const { flags } = await this.parse(Export);
const ux = new Ux({ jsonEnabled: this.jsonEnabled() });
const exportApi = new ExportApi(flags['target-org'], ux);
if (flags.plan) {
this.warn(messages.getMessage('PlanJsonWarning'));
}
const exportConfig: ExportConfig = {
outputDir: flags['output-dir'],
plan: flags.plan,
prefix: flags.prefix,
query: flags.query,
conn: flags['target-org'].getConnection(flags['api-version']),
ux: new Ux({ jsonEnabled: this.jsonEnabled() }),
};
return exportApi.export(exportConfig);
return runExport(exportConfig);
}
}
Loading

0 comments on commit cb49efc

Please sign in to comment.