@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 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
+ [![NPM](https://img.shields.io/npm/v/@simplysf/simply-package?label=@simplysf/simply-package)](https://npmjs.com/package/@simplysf/simply-package) [![Downloads/week](https://img.shields.io/npm/dw/@simplysf/simply-package.svg)](https://npmjs.com/package/@simplysf/simply-package) [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD_3--Clause-yellow.svg)](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
@@ -0,0 +1,2 @@
1
+ declare const _default: {};
2
+ export default _default;
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
@@ -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.