Skip to content
This repository was archived by the owner on Nov 5, 2023. It is now read-only.

Commit e22083b

Browse files
author
Mohith Shrivastava
committed
support static resource file save via tooling api
1 parent b9d4895 commit e22083b

File tree

5 files changed

+162
-18
lines changed

5 files changed

+162
-18
lines changed

README.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ If you are Visual Studio Code user then recommend installing the extension along
3434
* [`sfdx deploy:vfcomponent`](#sfdx-deployvfcomponent)
3535
* [`sfdx deploy:aura`](#sfdx-deployaura)
3636
* [`sfdx deploy:lwc`](#sfdx-deploylwc)
37+
* [`sfdx deploy:staticresource`](#sfdx-deploystaticresource)
3738

3839
## `sfdx retrieve:dxsource`
3940

@@ -96,7 +97,7 @@ OPTIONS
9697
--p, --pathname=pathname (required) the file path of the apex class you want to save to salesforce. Note you can run pwd command on terminal to obtain the path easily.
9798
9899
EXAMPLES
99-
$ sfdx deploy:apex -p pathname // Default authorized org is used for the deploy .The pathname parameter must be enclosed in double quotes. Example if your path is /Users/mohith/Desktop/ForceProjects/TestApp/force-app/main/default/classes/Constants.cls then the command to save this class will be sfdx deploy:apex -p "/Users/mohith/Desktop/ForceProjects/TestApp/force-app/main/default/classes/Constants.cls"
100+
$ sfdx deploy:apex -p <pathname> // Default authorized org is used for the deploy .The pathname parameter must be enclosed in double quotes. Example if your path is /Users/mohith/Desktop/ForceProjects/TestApp/force-app/main/default/classes/Constants.cls then the command to save this class will be sfdx deploy:apex -p "/Users/mohith/Desktop/ForceProjects/TestApp/force-app/main/default/classes/Constants.cls"
100101
```
101102

102103
_See code: [src/commands/deploy/apex.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/apex.ts)_
@@ -113,7 +114,7 @@ OPTIONS
113114
--p, --pathname=pathname (required) the file path of the apex trigger you want to save to salesforce. Note you can run pwd command on terminal to obtain the path easily
114115
115116
EXAMPLES
116-
$ sfdx deploy:trigger -p pathname // Default authorized org is used for the deploy
117+
$ sfdx deploy:trigger -p <pathname> // Default authorized org is used for the deploy
117118
```
118119

119120
_See code: [src/commands/deploy/trigger.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/trigger.ts)_
@@ -130,7 +131,7 @@ OPTIONS
130131
--p, --pathname=pathname (required) the file path of the vf page you want to save to salesforce . Note you can run pwd command on terminal to obtain the path.
131132
132133
EXAMPLES
133-
$ sfdx deploy:vf -p pathname // Default authorized org is used for the deploy
134+
$ sfdx deploy:vf -p <pathname> // Default authorized org is used for the deploy
134135
```
135136

136137
_See code: [src/commands/deploy/vf.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/vf.ts)_
@@ -147,7 +148,7 @@ OPTIONS
147148
--p, --pathname=pathname (required) the file path of the vf component you want to save
148149
149150
EXAMPLES
150-
$ sfdx deploy:vfcomponent -p pathname // file path used to save the component to Salesforce.
151+
$ sfdx deploy:vfcomponent -p <pathname> // file path used to save the component to Salesforce.
151152
```
152153

153154
_See code: [src/commands/deploy/vfcomponent.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/vfcomponent.ts)_
@@ -166,7 +167,7 @@ OPTIONS
166167
--p, --pathname=pathname (required) the file path of the aura bundle you want to save to Salesforce.
167168
168169
EXAMPLES
169-
$ sfdx deploy:aura -p pathname // Default authorized org is used for the deploy
170+
$ sfdx deploy:aura -p <pathname> // Default authorized org is used for the deploy
170171
```
171172

172173
_See code: [src/commands/deploy/aura.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/aura.ts)_
@@ -185,11 +186,34 @@ OPTIONS
185186
--p, --pathname=pathname (required) the file path of the lightning web components bundle you want to save to Salesforce.
186187
187188
EXAMPLES
188-
$ sfdx deploy:lwc -p pathname // Default authorized org is used for the deploy
189+
$ sfdx deploy:lwc -p <pathname> // Default authorized org is used for the deploy
189190
```
190191

191192
_See code: [src/commands/deploy/lwc.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/lwc.ts)_
192193

194+
## `sfdx deploy:staticresource`
195+
196+
Deploys Static Resources to the Salesforce Org using Tooling API.
197+
198+
Supports deploying sttaic resource folder (It zips it up) as well individual files in static resource folder.
199+
200+
```
201+
USAGE
202+
$ sfdx deploy:staticresource
203+
204+
OPTIONS
205+
--p, --pathname=pathname (required) the file path of the lightning web components bundle you want to save to Salesforce.
206+
207+
EXAMPLES
208+
$ sfdx deploy:staticresource -p <pathname> // Default authorized org is used for the deploy
209+
$ sfdx deploy:staticresource -p <pathname> --resourcepath <name of the folder where you have app>' // Default authorized org is used for the deploy
210+
$ sfdx deploy:staticresource -p <pathname> --resourcepath <name of the folder where you have app>' --cachecontrol public //makes the cache control of static resource public
211+
```
212+
213+
_See code: [src/commands/deploy/staticresource.ts](https://github.com/msrivastav13/mo-dx-plugin/blob/master/src/commands/deploy/staticresource.ts)_
214+
215+
216+
193217
### Important Note When Using these Commands With Non-Scratch Org
194218

195219
**These commands do not maintain history and files are overriden on server .Make sure you have source control for the project setup so you do not loose anything**

messages/org.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
"triggerDeploy": "Deploy apex triggers using tooling api",
77
"lwcDeploy": "Deploy lwc wusing tooling api",
88
"retrieveDxSource": "Retrieves Source is DX format from Unmanaged/Managed package",
9-
"retrieveSource": "Retrieves Source from Unmanaged/Managed package in Metadata API format"
9+
"retrieveSource": "Retrieves Source from Unmanaged/Managed package in Metadata API format",
10+
"staticresourceDeploy" : "Deploy static resource using tooling api"
1011
}

package.json

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
{
22
"name": "mo-dx-plugin",
3-
"version": "0.2.12",
3+
"version": "0.2.3",
44
"author": "Mohith Shrivastava",
55
"bugs": "https://github.com/ForceProjects/mo-dx-plugin/issues",
66
"dependencies": {
77
"@oclif/command": "^1",
8-
"@oclif/plugin-help": "^2",
98
"@oclif/config": "^1",
109
"@oclif/errors": "^1",
10+
"@oclif/plugin-help": "^2",
1111
"@salesforce/command": "^1.4.1",
12+
"@salesforce/core": "^1.3.2",
1213
"@salesforce/ts-types": "^1.0.1",
13-
"tslib": "^1",
1414
"adm-zip": "^0.4.13",
15+
"chalk": "^2.4.1",
1516
"fs-extra": "^8.1.0",
1617
"lodash": "^4.17.13",
17-
"chalk": "^2.4.1",
18-
"@salesforce/core": "^1.3.2"
18+
"mime-types": "^2.1.24",
19+
"tslib": "^1"
1920
},
2021
"devDependencies": {
21-
"@types/adm-zip": "^0.4.31",
2222
"@oclif/dev-cli": "^1",
2323
"@oclif/plugin-help": "^2",
2424
"@oclif/test": "^1",
2525
"@salesforce/dev-config": "1.1.4",
26+
"@types/adm-zip": "^0.4.31",
2627
"@types/chai": "^4",
28+
"@types/fs-extra": "^5.0.3",
2729
"@types/jsforce": "1.9.8",
30+
"@types/lodash": "^4.14.13",
31+
"@types/mime-types": "^2.1.0",
2832
"@types/mocha": "^5",
2933
"@types/node": "^10",
30-
"@types/lodash": "^4.14.13",
3134
"chai": "^4",
3235
"globby": "8",
3336
"mocha": "^5",
3437
"nyc": "^12",
3538
"sinon": "5",
3639
"ts-node": "^7",
37-
"typescript": "~3.3",
38-
"@types/fs-extra": "^5.0.3"
40+
"typescript": "~3.3"
3941
},
4042
"engines": {
4143
"node": ">=8.0.0"
@@ -57,7 +59,7 @@
5759
"deploy": {
5860
"description": "Commands to deploy apex,vf,trigger and aura bundle."
5961
},
60-
"retrieve":{
62+
"retrieve": {
6163
"description": "Commands to get DX formatted code or metadata from the unmanaged package/managed package or changeset."
6264
}
6365
},
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import {core, flags, SfdxCommand} from '@salesforce/command';
2+
import {AnyJson} from '@salesforce/ts-types';
3+
import * as AdmZip from 'adm-zip';
4+
import chalk from 'chalk';
5+
import fs = require('fs-extra');
6+
import * as Mime from 'mime-types';
7+
import {displaylog} from '../../service/displayError';
8+
import {getNameSpacePrefix} from '../../service/getNamespacePrefix';
9+
10+
// Initialize Messages with the current plugin directory
11+
core.Messages.importMessagesDirectory(__dirname);
12+
13+
// Load the specific messages for this file. Messages from @salesforce/command, @salesforce/core,
14+
// or any library that is using the messages framework can also be loaded this way.
15+
const messages = core.Messages.loadMessages('mo-dx-plugin', 'org');
16+
17+
export default class StaticResourceDeploy extends SfdxCommand {
18+
19+
public static description = messages.getMessage('staticresourceDeploy');
20+
21+
public static examples = [
22+
'$ sfdx deploy:staticresource -p <filepath>',
23+
'$ sfdx deploy:staticresource -p <filepath> --cachecontrol public',
24+
'$ sfdx deploy:staticresource -p <filepath> --cachecontrol public --resourcepath <name of the folder where you have single page app>'
25+
];
26+
27+
protected static flagsConfig = {
28+
// flag with a value (-n, --name=VALUE)
29+
filepath: flags.string({char: 'p', description: 'file path' }),
30+
resourcepath : flags.string({char: 'r', description: 'resource path, This defaults to staticresources', default: 'staticresources' }),
31+
cachecontrol : flags.string({char: 'c', description: 'cache control, defaults to public', default: 'private'})
32+
};
33+
34+
// Comment this out if your command does not require an org username
35+
protected static requiresUsername = true;
36+
37+
// Set this to true if your command requires a project workspace; 'requiresProject' is false by default
38+
protected static requiresProject = true;
39+
40+
public async run(): Promise<AnyJson> {
41+
42+
this.ux.startSpinner(chalk.bold.yellowBright('Saving'));
43+
44+
const conn = this.org.getConnection();
45+
46+
const namespacePrefix = await getNameSpacePrefix(conn);
47+
48+
interface StaticResource {
49+
Body: string;
50+
Id: string;
51+
ContentType: string;
52+
CacheControl: string;
53+
Name: string;
54+
}
55+
56+
try {
57+
// find the depth of the file from static Resource folder
58+
const resourcepath = this.flags.filepath.split(this.flags.resourcepath + '/').pop();
59+
const folderorfilename = resourcepath.split('/')[0];
60+
let staticResourceName: string;
61+
let contentType: string | boolean;
62+
let body: string;
63+
64+
staticResourceName = folderorfilename.split('.')[0];
65+
// check if resource is bundled or individual file with extension
66+
if (folderorfilename === staticResourceName) {
67+
// zip the resource and get the body as archive
68+
const resourcebundlepath = this.flags.filepath.slice(0, this.flags.filepath.indexOf(this.flags.resourcepath));
69+
const zipper = new AdmZip();
70+
zipper.addLocalFolder(resourcebundlepath + '/' + this.flags.resourcepath + '/' + staticResourceName);
71+
body = zipper.toBuffer().toString('base64');
72+
contentType = 'application/zip';
73+
} else {
74+
body = await fs.readFile(this.flags.filepath, 'utf8');
75+
const buff = Buffer.alloc(body.length, body);
76+
body = buff.toString('base64');
77+
contentType = Mime.lookup(folderorfilename.split('.')[1]);
78+
if (contentType === false) {
79+
contentType = 'application/octet-stream';
80+
}
81+
}
82+
83+
// check if static resource already exists
84+
const staticResources = await conn.tooling.sobject('StaticResource').find({
85+
Name: staticResourceName,
86+
NameSpacePrefix : namespacePrefix
87+
}) as StaticResource[];
88+
89+
if (staticResources.length > 0) {
90+
const staticresourceToUpdate = {} as StaticResource;
91+
staticresourceToUpdate.Id = staticResources[0].Id;
92+
staticresourceToUpdate.Body = body;
93+
await conn.tooling.sobject('StaticResource').update(staticresourceToUpdate);
94+
} else {
95+
// Create a new Static Resource
96+
const staticresource = {} as StaticResource;
97+
staticresource.Body = body;
98+
staticresource.ContentType = contentType;
99+
staticresource.CacheControl = this.flags.cachecontrol;
100+
staticresource.Name = staticResourceName;
101+
await conn.tooling.sobject('StaticResource').create(staticresource);
102+
}
103+
this.ux.stopSpinner(chalk.bold.greenBright('StaticResource Deployed SuccessFully ✔'));
104+
} catch (e) {
105+
this.ux.stopSpinner(chalk.bold.redBright('Static Resource Save Failed ✖'));
106+
displaylog(e, this.ux);
107+
}
108+
109+
return '{}';
110+
}
111+
112+
}

yarn.lock

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,11 @@
381381
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.136.tgz#413e85089046b865d960c9ff1d400e04c31ab60f"
382382
integrity sha512-0GJhzBdvsW2RUccNHOBkabI8HZVdOXmXbXhuKlDEd5Vv12P7oAVGfomGp3Ne21o5D/qu1WmthlNKFaoZJJeErA==
383383

384+
"@types/mime-types@^2.1.0":
385+
version "2.1.0"
386+
resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73"
387+
integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=
388+
384389
"@types/minimatch@*":
385390
version "3.0.3"
386391
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -2545,7 +2550,7 @@ mime-db@1.40.0:
25452550
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
25462551
integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
25472552

2548-
mime-types@^2.1.12, mime-types@~2.1.19:
2553+
mime-types@^2.1.12, mime-types@^2.1.24, mime-types@~2.1.19:
25492554
version "2.1.24"
25502555
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
25512556
integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==

0 commit comments

Comments
 (0)