@simplysf/simply-data 1.0.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.
- package/CHANGELOG.md +0 -0
- package/LICENSE.txt +12 -0
- package/README.md +138 -0
- package/lib/commands/simply/data/file/upload.d.ts +15 -0
- package/lib/commands/simply/data/file/upload.js +43 -0
- package/lib/commands/simply/data/file/upload.js.map +1 -0
- package/lib/commands/simply/data/files/upload.d.ts +13 -0
- package/lib/commands/simply/data/files/upload.js +90 -0
- package/lib/commands/simply/data/files/upload.js.map +1 -0
- package/lib/common/contentVersionTypes.d.ts +25 -0
- package/lib/common/contentVersionTypes.js +8 -0
- package/lib/common/contentVersionTypes.js.map +1 -0
- package/lib/common/contentVersionUtils.d.ts +3 -0
- package/lib/common/contentVersionUtils.js +34 -0
- package/lib/common/contentVersionUtils.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -0
- package/messages/simply.data.file.upload.md +29 -0
- package/messages/simply.data.files.upload.md +33 -0
- package/npm-shrinkwrap.json +17557 -0
- package/oclif.lock +9269 -0
- package/oclif.manifest.json +207 -0
- package/package.json +219 -0
package/CHANGELOG.md
ADDED
|
File without changes
|
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Copyright (c) 2024, Clay Chipps; Copyright (c) 2024, Salesforce.com, Inc.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
7
|
+
|
|
8
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
9
|
+
|
|
10
|
+
* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
11
|
+
|
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# @simplysf/simply-data
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/@simplysf/simply-package) [](https://npmjs.com/package/@simplysf/simply-package) [](https://raw.githubusercontent.com/SimplySF/simply-data/main/LICENSE.txt)
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
sf plugins install @simplysf/simply-data
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Issues
|
|
12
|
+
|
|
13
|
+
Please report any issues at https://github.com/SimplySF/simply-data/issues
|
|
14
|
+
|
|
15
|
+
## Contributing
|
|
16
|
+
|
|
17
|
+
1. Please read our [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
18
|
+
2. Create a new issue before starting your project so that we can keep track of
|
|
19
|
+
what you are trying to add/fix. That way, we can also offer suggestions or
|
|
20
|
+
let you know if there is already an effort in progress.
|
|
21
|
+
3. Fork this repository.
|
|
22
|
+
4. [Build the plugin locally](#build)
|
|
23
|
+
5. Create a _topic_ branch in your fork. Note, this step is recommended but technically not required if contributing using a fork.
|
|
24
|
+
6. Edit the code in your fork.
|
|
25
|
+
7. Write appropriate tests for your changes. Try to achieve at least 95% code coverage on any new code. No pull request will be accepted without unit tests.
|
|
26
|
+
8. Send us a pull request when you are done. We'll review your code, suggest any needed changes, and merge it in.
|
|
27
|
+
|
|
28
|
+
### Build
|
|
29
|
+
|
|
30
|
+
To build the plugin locally, make sure to have yarn installed and run the following commands:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Clone the repository
|
|
34
|
+
git clone git@github.com:SimplySF/simply-data
|
|
35
|
+
|
|
36
|
+
# Install the dependencies and compile
|
|
37
|
+
yarn && yarn build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
To use your plugin, run using the local `./bin/dev` or `./bin/dev.cmd` file.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Run using local run file.
|
|
44
|
+
./bin/dev.cmd simply data
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
There should be no differences when running via the Salesforce CLI or using the local run file. However, it can be useful to link the plugin to do some additional testing or run your commands from anywhere on your machine.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Link your plugin to the sf cli
|
|
51
|
+
sf plugins link .
|
|
52
|
+
# To verify
|
|
53
|
+
sf plugins
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
<!-- commands -->
|
|
59
|
+
* [`sf simply data file upload`](#sf-simply-data-file-upload)
|
|
60
|
+
* [`sf simply data files upload`](#sf-simply-data-files-upload)
|
|
61
|
+
|
|
62
|
+
## `sf simply data file upload`
|
|
63
|
+
|
|
64
|
+
Upload a file to a Salesforce org.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
USAGE
|
|
68
|
+
$ sf simply data file upload --file-path <value> -o <value> [--json] [--api-version <value>] [--first-publish-location-id
|
|
69
|
+
<value>] [--title <value>]
|
|
70
|
+
|
|
71
|
+
FLAGS
|
|
72
|
+
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the
|
|
73
|
+
`target-org` configuration variable is already set.
|
|
74
|
+
--api-version=<value> Override the api version used for api requests made by this command
|
|
75
|
+
--file-path=<value> (required) Path to the file to upload.
|
|
76
|
+
--first-publish-location-id=<value> Specify a record Id that the file should be linked to.
|
|
77
|
+
--title=<value> Specify the title for the file being uploaded.
|
|
78
|
+
|
|
79
|
+
GLOBAL FLAGS
|
|
80
|
+
--json Format output as json.
|
|
81
|
+
|
|
82
|
+
DESCRIPTION
|
|
83
|
+
Upload a file to a Salesforce org.
|
|
84
|
+
|
|
85
|
+
Uploads a file to a Salesforce org.
|
|
86
|
+
|
|
87
|
+
EXAMPLES
|
|
88
|
+
$ sf simply data file upload --file-path fileToUpload.txt --target-org myTargetOrg
|
|
89
|
+
|
|
90
|
+
$ sf simply data file upload --file-path fileToUpload.txt --first-publish-location-id 0019000000DmehK --target-org myTargetOrg
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
_See code: [src/commands/simply/data/file/upload.ts](https://github.com/SimplySF/simply-data/blob/1.0.0/src/commands/simply/data/file/upload.ts)_
|
|
94
|
+
|
|
95
|
+
## `sf simply data files upload`
|
|
96
|
+
|
|
97
|
+
Upload files to a Salesforce org.
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
USAGE
|
|
101
|
+
$ sf simply data files upload --file-path <value> -o <value> [--json] [--api-version <value>] [--max-parallel-jobs
|
|
102
|
+
<value>]
|
|
103
|
+
|
|
104
|
+
FLAGS
|
|
105
|
+
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the `target-org`
|
|
106
|
+
configuration variable is already set.
|
|
107
|
+
--api-version=<value> Override the api version used for api requests made by this command
|
|
108
|
+
--file-path=<value> (required) Path to the csv file that specifies the upload.
|
|
109
|
+
--max-parallel-jobs=<value> [default: 1] Maximum number of parallel jobs.
|
|
110
|
+
|
|
111
|
+
GLOBAL FLAGS
|
|
112
|
+
--json Format output as json.
|
|
113
|
+
|
|
114
|
+
DESCRIPTION
|
|
115
|
+
Upload files to a Salesforce org.
|
|
116
|
+
|
|
117
|
+
Uploads files specified by a csv to a Salesforce org. By default, the plugin uses the REST API for the upload as the
|
|
118
|
+
Bulk API is limited in its payload size. This means that each file will use one REST API request.
|
|
119
|
+
|
|
120
|
+
EXAMPLES
|
|
121
|
+
$ sf simply data files upload --file-path filesToUpload.csv --target-org myTargetOrg
|
|
122
|
+
|
|
123
|
+
$ sf simply data files upload --file-path filesToUpload.csv --max-parallel-jobs 5 --target-org myTargetOrg
|
|
124
|
+
|
|
125
|
+
FLAG DESCRIPTIONS
|
|
126
|
+
--file-path=<value> Path to the csv file that specifies the upload.
|
|
127
|
+
|
|
128
|
+
The csv file must specify the columns PathOnClient and Title. Optionally, a FirstPublishLocationId can be specified
|
|
129
|
+
to have it linked directly to a Salesforce record after upload.
|
|
130
|
+
|
|
131
|
+
--max-parallel-jobs=<value> Maximum number of parallel jobs.
|
|
132
|
+
|
|
133
|
+
By default the plugin will only process a single file upload at a time. You can increase this value to allow for
|
|
134
|
+
quasi concurrent uploads. Please note that setting this value too high can cause performance issues.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
_See code: [src/commands/simply/data/files/upload.ts](https://github.com/SimplySF/simply-data/blob/1.0.0/src/commands/simply/data/files/upload.ts)_
|
|
138
|
+
<!-- commandsstop -->
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
import { ContentVersion } from '../../../../common/contentVersionTypes.js';
|
|
3
|
+
export default class DataFileUpload extends SfCommand<ContentVersion> {
|
|
4
|
+
static readonly summary: string;
|
|
5
|
+
static readonly description: string;
|
|
6
|
+
static readonly examples: string[];
|
|
7
|
+
static readonly flags: {
|
|
8
|
+
'api-version': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
|
+
'file-path': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
+
'first-publish-location-id': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
'target-org': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
12
|
+
title: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<ContentVersion>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024, Clay Chipps; Copyright (c) 2024, Salesforce.com, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
import { Messages } from '@salesforce/core';
|
|
8
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
9
|
+
import { uploadContentVersion } from '../../../../common/contentVersionUtils.js';
|
|
10
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
11
|
+
const messages = Messages.loadMessages('@simplysf/simply-data', 'simply.data.file.upload');
|
|
12
|
+
export default class DataFileUpload extends SfCommand {
|
|
13
|
+
static summary = messages.getMessage('summary');
|
|
14
|
+
static description = messages.getMessage('description');
|
|
15
|
+
static examples = messages.getMessages('examples');
|
|
16
|
+
static flags = {
|
|
17
|
+
'api-version': Flags.orgApiVersion(),
|
|
18
|
+
'file-path': Flags.directory({
|
|
19
|
+
summary: messages.getMessage('flags.file-path.summary'),
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
'first-publish-location-id': Flags.string({
|
|
23
|
+
summary: messages.getMessage('flags.first-publish-location-id.summary'),
|
|
24
|
+
}),
|
|
25
|
+
'target-org': Flags.requiredOrg(),
|
|
26
|
+
title: Flags.string({
|
|
27
|
+
summary: messages.getMessage('flags.title.summary'),
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
async run() {
|
|
31
|
+
const { flags } = await this.parse(DataFileUpload);
|
|
32
|
+
// Authorize to the target org
|
|
33
|
+
const targetOrgConnection = flags['target-org']?.getConnection(flags['api-version']);
|
|
34
|
+
if (!targetOrgConnection) {
|
|
35
|
+
throw messages.createError('error.targetOrgConnectionFailed');
|
|
36
|
+
}
|
|
37
|
+
this.spinner.start('Uploading file', '', { stdout: true });
|
|
38
|
+
const contentVersion = await uploadContentVersion(targetOrgConnection, flags['file-path'], flags['title'], flags['first-publish-location-id']);
|
|
39
|
+
this.spinner.stop();
|
|
40
|
+
return contentVersion;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../../../src/commands/simply/data/file/upload.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAGjF,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,uBAAuB,EAAE,yBAAyB,CAAC,CAAC;AAE3F,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAyB;IAC5D,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC7B,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE;QACpC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,yBAAyB,CAAC;YACvD,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,2BAA2B,EAAE,KAAK,CAAC,MAAM,CAAC;YACxC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,yCAAyC,CAAC;SACxE,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE;QACjC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;SACpD,CAAC;KACH,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAEnD,8BAA8B;QAC9B,MAAM,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;QAErF,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,MAAM,QAAQ,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3D,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAC/C,mBAAmB,EACnB,KAAK,CAAC,WAAW,CAAC,EAClB,KAAK,CAAC,OAAO,CAAC,EACd,KAAK,CAAC,2BAA2B,CAAC,CACnC,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAEpB,OAAO,cAAc,CAAC;IACxB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export default class DataFilesUpload extends SfCommand<void> {
|
|
3
|
+
static readonly summary: string;
|
|
4
|
+
static readonly description: string;
|
|
5
|
+
static readonly examples: string[];
|
|
6
|
+
static readonly flags: {
|
|
7
|
+
'api-version': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
'file-path': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
|
+
'max-parallel-jobs': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
+
'target-org': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024, Clay Chipps; Copyright (c) 2024, Salesforce.com, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import { parse } from 'csv-parse';
|
|
9
|
+
import { createObjectCsvWriter } from 'csv-writer';
|
|
10
|
+
import PQueue from 'p-queue';
|
|
11
|
+
import { Messages } from '@salesforce/core';
|
|
12
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
13
|
+
import { uploadContentVersion } from '../../../../common/contentVersionUtils.js';
|
|
14
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
15
|
+
const messages = Messages.loadMessages('@simplysf/simply-data', 'simply.data.files.upload');
|
|
16
|
+
export default class DataFilesUpload extends SfCommand {
|
|
17
|
+
static summary = messages.getMessage('summary');
|
|
18
|
+
static description = messages.getMessage('description');
|
|
19
|
+
static examples = messages.getMessages('examples');
|
|
20
|
+
static flags = {
|
|
21
|
+
'api-version': Flags.orgApiVersion(),
|
|
22
|
+
'file-path': Flags.directory({
|
|
23
|
+
summary: messages.getMessage('flags.file-path.summary'),
|
|
24
|
+
description: messages.getMessage('flags.file-path.description'),
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
'max-parallel-jobs': Flags.integer({
|
|
28
|
+
summary: messages.getMessage('flags.max-parallel-jobs.summary'),
|
|
29
|
+
description: messages.getMessage('flags.max-parallel-jobs.description'),
|
|
30
|
+
default: 1,
|
|
31
|
+
}),
|
|
32
|
+
'target-org': Flags.requiredOrg(),
|
|
33
|
+
};
|
|
34
|
+
async run() {
|
|
35
|
+
const { flags } = await this.parse(DataFilesUpload);
|
|
36
|
+
// Authorize to the target org
|
|
37
|
+
const targetOrgConnection = flags['target-org']?.getConnection(flags['api-version']);
|
|
38
|
+
if (!targetOrgConnection) {
|
|
39
|
+
throw messages.createError('error.targetOrgConnectionFailed');
|
|
40
|
+
}
|
|
41
|
+
this.spinner.start('Initializing file upload', '\n', { stdout: true });
|
|
42
|
+
const successWriter = createObjectCsvWriter({
|
|
43
|
+
path: 'success.csv',
|
|
44
|
+
header: [
|
|
45
|
+
{ id: 'PathOnClient', title: 'PathOnClient' },
|
|
46
|
+
{ id: 'Title', title: 'Title' },
|
|
47
|
+
{ id: 'FirstPublishLocationId', title: 'FirstPublishLocationId' },
|
|
48
|
+
{ id: 'ContentDocumentId', title: 'ContentDocumentId' },
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
const errorWriter = createObjectCsvWriter({
|
|
52
|
+
path: 'error.csv',
|
|
53
|
+
header: [
|
|
54
|
+
{ id: 'PathOnClient', title: 'PathOnClient' },
|
|
55
|
+
{ id: 'Title', title: 'Title' },
|
|
56
|
+
{ id: 'FirstPublishLocationId', title: 'FirstPublishLocationId' },
|
|
57
|
+
{ id: 'Error', title: 'Error' },
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
this.spinner.stop();
|
|
61
|
+
const fileQueue = new PQueue({ concurrency: flags['max-parallel-jobs'] });
|
|
62
|
+
const parser = fs.createReadStream(flags['file-path']).pipe(parse({ bom: true, columns: true }));
|
|
63
|
+
this.spinner.start('Uploading files', 'Initializing\n', { stdout: true });
|
|
64
|
+
let count = 0;
|
|
65
|
+
fileQueue.on('add', () => {
|
|
66
|
+
this.spinner.status = `Completed: ${count}. Size: ${fileQueue.size} Pending: ${fileQueue.pending}\n`;
|
|
67
|
+
});
|
|
68
|
+
fileQueue.on('completed', () => {
|
|
69
|
+
count++;
|
|
70
|
+
this.spinner.status = `Completed: ${count}. Size: ${fileQueue.size} Pending: ${fileQueue.pending}\n`;
|
|
71
|
+
});
|
|
72
|
+
for await (const record of parser) {
|
|
73
|
+
void fileQueue.add(async () => {
|
|
74
|
+
const contentVersionToUpload = record;
|
|
75
|
+
try {
|
|
76
|
+
const contentVersion = await uploadContentVersion(targetOrgConnection, contentVersionToUpload.PathOnClient, contentVersionToUpload.Title, contentVersionToUpload.FirstPublishLocationId);
|
|
77
|
+
contentVersionToUpload.ContentDocumentId = contentVersion.ContentDocumentId;
|
|
78
|
+
await successWriter.writeRecords([contentVersionToUpload]);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
contentVersionToUpload.Error = error;
|
|
82
|
+
await errorWriter.writeRecords([contentVersionToUpload]);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
await fileQueue.onIdle();
|
|
87
|
+
this.spinner.stop();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../../../src/commands/simply/data/files/upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ContentVersion {
|
|
2
|
+
ContentDocumentId?: string;
|
|
3
|
+
FileExtension: string;
|
|
4
|
+
Id: string;
|
|
5
|
+
Title: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ContentVersionCreateRequest {
|
|
8
|
+
FirstPublishLocationId?: string;
|
|
9
|
+
PathOnClient: string;
|
|
10
|
+
Title?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ContentVersionCreateResult {
|
|
13
|
+
id: string;
|
|
14
|
+
success: boolean;
|
|
15
|
+
errors: string[];
|
|
16
|
+
name: string;
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
export type ContentVersionToUpload = {
|
|
20
|
+
ContentDocumentId?: string;
|
|
21
|
+
Error?: string;
|
|
22
|
+
FirstPublishLocationId?: string;
|
|
23
|
+
PathOnClient: string;
|
|
24
|
+
Title: string;
|
|
25
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024, Clay Chipps; Copyright (c) 2024, Salesforce.com, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=contentVersionTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentVersionTypes.js","sourceRoot":"","sources":["../../src/common/contentVersionTypes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
import { ContentVersion } from './contentVersionTypes.js';
|
|
3
|
+
export declare function uploadContentVersion(targetOrgConnection: Connection, pathOnClient: string, title?: string, firstPublishLocationId?: string): Promise<ContentVersion>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024, Clay Chipps; Copyright (c) 2024, Salesforce.com, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import FormData from 'form-data';
|
|
10
|
+
import got from 'got';
|
|
11
|
+
export async function uploadContentVersion(targetOrgConnection, pathOnClient, title, firstPublishLocationId) {
|
|
12
|
+
// Check that we have access to the file
|
|
13
|
+
await fs.promises.access(pathOnClient, fs.constants.F_OK);
|
|
14
|
+
const contentVersionCreateRequest = {
|
|
15
|
+
FirstPublishLocationId: firstPublishLocationId,
|
|
16
|
+
PathOnClient: pathOnClient,
|
|
17
|
+
Title: title ?? path.basename(pathOnClient),
|
|
18
|
+
};
|
|
19
|
+
const form = new FormData();
|
|
20
|
+
form.append('entity_content', JSON.stringify(contentVersionCreateRequest), { contentType: 'application/json' });
|
|
21
|
+
form.append('VersionData', fs.createReadStream(pathOnClient), { filename: path.basename(pathOnClient) });
|
|
22
|
+
const data = await got.post(`${targetOrgConnection.baseUrl()}/sobjects/ContentVersion`, {
|
|
23
|
+
body: form,
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${targetOrgConnection.accessToken}`,
|
|
26
|
+
'Content-Type': `multipart/form-data; boundary="${form.getBoundary()}"`,
|
|
27
|
+
},
|
|
28
|
+
resolveBodyOnly: true,
|
|
29
|
+
responseType: 'json',
|
|
30
|
+
});
|
|
31
|
+
const queryResult = await targetOrgConnection.singleRecordQuery(`SELECT ContentDocumentId, FileExtension, Id, Title FROM ContentVersion WHERE Id='${data.id}'`);
|
|
32
|
+
return queryResult;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=contentVersionUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentVersionUtils.js","sourceRoot":"","sources":["../../src/common/contentVersionUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,GAAG,MAAM,KAAK,CAAC;AAItB,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,mBAA+B,EAC/B,YAAoB,EACpB,KAAc,EACd,sBAA+B;IAE/B,wCAAwC;IACxC,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAE1D,MAAM,2BAA2B,GAAgC;QAC/D,sBAAsB,EAAE,sBAAsB;QAC9C,YAAY,EAAE,YAAY;QAC1B,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;KAC5C,CAAC;IAEF,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,2BAA2B,CAAC,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAChH,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAEzG,MAAM,IAAI,GAA+B,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,EAAE;QAClH,IAAI,EAAE,IAAI;QACV,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,mBAAmB,CAAC,WAAW,EAAE;YAC1D,cAAc,EAAE,kCAAkC,IAAI,CAAC,WAAW,EAAE,GAAG;SACxE;QACD,eAAe,EAAE,IAAI;QACrB,YAAY,EAAE,MAAM;KACrB,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAC7D,oFAAoF,IAAI,CAAC,EAAE,GAAG,CAC/F,CAAC;IAEF,OAAO,WAA6B,CAAC;AACvC,CAAC"}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024, Clay Chipps; Copyright (c) 2024, Salesforce.com, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
export default {};
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# summary
|
|
2
|
+
|
|
3
|
+
Upload a file to a Salesforce org.
|
|
4
|
+
|
|
5
|
+
# description
|
|
6
|
+
|
|
7
|
+
Uploads a file to a Salesforce org.
|
|
8
|
+
|
|
9
|
+
# flags.file-path.summary
|
|
10
|
+
|
|
11
|
+
Path to the file to upload.
|
|
12
|
+
|
|
13
|
+
# flags.first-publish-location-id.summary
|
|
14
|
+
|
|
15
|
+
Specify a record Id that the file should be linked to.
|
|
16
|
+
|
|
17
|
+
# flags.title.summary
|
|
18
|
+
|
|
19
|
+
Specify the title for the file being uploaded.
|
|
20
|
+
|
|
21
|
+
# examples
|
|
22
|
+
|
|
23
|
+
- <%= config.bin %> <%= command.id %> --file-path fileToUpload.txt --target-org myTargetOrg
|
|
24
|
+
|
|
25
|
+
- <%= config.bin %> <%= command.id %> --file-path fileToUpload.txt --first-publish-location-id 0019000000DmehK --target-org myTargetOrg
|
|
26
|
+
|
|
27
|
+
# error.targetOrgConnectionFailed
|
|
28
|
+
|
|
29
|
+
Unable to establish connection to the org.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# summary
|
|
2
|
+
|
|
3
|
+
Upload files to a Salesforce org.
|
|
4
|
+
|
|
5
|
+
# description
|
|
6
|
+
|
|
7
|
+
Uploads files specified by a csv to a Salesforce org. By default, the plugin uses the REST API for the upload as the Bulk API is limited in its payload size. This means that each file will use one REST API request.
|
|
8
|
+
|
|
9
|
+
# flags.file-path.summary
|
|
10
|
+
|
|
11
|
+
Path to the csv file that specifies the upload.
|
|
12
|
+
|
|
13
|
+
# flags.file-path.description
|
|
14
|
+
|
|
15
|
+
The csv file must specify the columns PathOnClient and Title. Optionally, a FirstPublishLocationId can be specified to have it linked directly to a Salesforce record after upload.
|
|
16
|
+
|
|
17
|
+
# flags.max-parallel-jobs.summary
|
|
18
|
+
|
|
19
|
+
Maximum number of parallel jobs.
|
|
20
|
+
|
|
21
|
+
# flags.max-parallel-jobs.description
|
|
22
|
+
|
|
23
|
+
By default the plugin will only process a single file upload at a time. You can increase this value to allow for quasi concurrent uploads. Please note that setting this value too high can cause performance issues.
|
|
24
|
+
|
|
25
|
+
# examples
|
|
26
|
+
|
|
27
|
+
- <%= config.bin %> <%= command.id %> --file-path filesToUpload.csv --target-org myTargetOrg
|
|
28
|
+
|
|
29
|
+
- <%= config.bin %> <%= command.id %> --file-path filesToUpload.csv --max-parallel-jobs 5 --target-org myTargetOrg
|
|
30
|
+
|
|
31
|
+
# error.targetOrgConnectionFailed
|
|
32
|
+
|
|
33
|
+
Unable to establish connection to the org.
|