generated from salesforcecli/plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathopen.ts
138 lines (122 loc) · 4.61 KB
/
open.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';
import * as open from 'open';
import { getString } from '@salesforce/ts-types';
import { flags, FlagsConfig } from '@salesforce/command';
import { AuthInfo, Messages, sfdc, SfdcUrl, SfError } from '@salesforce/core';
import { MetadataResolver, SourceComponent } from '@salesforce/source-deploy-retrieve';
import { OpenCommandResult, OpenResultFormatter } from '../../../formatters/source/openResultFormatter';
import { SourceCommand } from '../../../sourceCommand';
Messages.importMessagesDirectory(__dirname);
const messages = Messages.load('@salesforce/plugin-source', 'open', [
'description',
'examples',
'SourceOpenFileDescription',
'SourceOpenPathDescription',
]);
export class Open extends SourceCommand {
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessage('examples').split(os.EOL);
public static readonly requiresProject = true;
public static readonly requiresUsername = true;
public static readonly flagsConfig: FlagsConfig = {
sourcefile: flags.filepath({
char: 'f',
required: true,
description: messages.getMessage('SourceOpenFileDescription'),
}),
urlonly: flags.boolean({
char: 'r',
description: messages.getMessage('SourceOpenPathDescription'),
}),
};
protected openResult: OpenCommandResult;
public async run(): Promise<OpenCommandResult> {
await this.doOpen();
this.resolveSuccess();
return this.formatResult();
}
protected resolveSuccess(): void {
if (!getString(this.openResult, 'url')) {
process.exitCode = 1;
}
}
protected formatResult(): OpenCommandResult {
const formatter = new OpenResultFormatter(this.logger, this.ux, this.openResult);
if (!this.isJsonOutput()) {
formatter.display();
}
return formatter.getJson();
}
private async doOpen(): Promise<void> {
const typeName = this.getTypeNameDefinitionByFileName(path.resolve(this.flags.sourcefile as string));
const openPath = ['FlexiPage', 'ApexPage'].includes(typeName)
? await this.setUpOpenPath(typeName)
: await this.buildFrontdoorUrl();
this.openResult = await this.open(openPath);
}
private getTypeNameDefinitionByFileName(fsPath: string): string | undefined {
if (fs.existsSync(fsPath)) {
const metadataResolver = new MetadataResolver();
const components: SourceComponent[] = metadataResolver.getComponentsFromPath(fsPath);
return components[0].type.name;
}
throw new SfError(`File not found: ${fsPath}`, 'FileNotFound');
}
private async buildFrontdoorUrl(): Promise<string> {
const authInfo = await AuthInfo.create({ username: this.org.getUsername() });
return authInfo.getOrgFrontDoorUrl();
}
private async open(src: string): Promise<OpenCommandResult> {
const url = `${await this.buildFrontdoorUrl()}&retURL=${encodeURIComponent(decodeURIComponent(src))}`;
const result: OpenCommandResult = {
url,
username: this.org.getUsername(),
orgId: this.org.getOrgId(),
};
if (!sfdc.isInternalUrl(url)) {
try {
await new SfdcUrl(url).checkLightningDomain();
} catch (error) {
throw new SfError('SourceOpenCommandTimeoutError', 'SourceOpenCommandTimeoutError');
}
}
return this.flags.urlonly ? result : this.openBrowser(url, result);
}
private async setUpOpenPath(pageType: string): Promise<string> {
try {
if (pageType === 'FlexiPage') {
const flexipage = await this.org
.getConnection()
.singleRecordQuery<{ Id: string }>(
`SELECT id FROM flexipage WHERE DeveloperName='${path.basename(
this.flags.sourcefile as string,
'.flexipage-meta.xml'
)}'`,
{ tooling: true }
);
return `/visualEditor/appBuilder.app?pageId=${flexipage.Id}`;
} else if (pageType === 'ApexPage') {
return `/apex/${path
.basename(this.flags.sourcefile as string)
.replace('.page-meta.xml', '')
.replace('.page', '')}`;
} else {
return '_ui/flexipage/ui/FlexiPageFilterListPage';
}
} catch (error) {
return '_ui/flexipage/ui/FlexiPageFilterListPage';
}
}
private openBrowser(url: string, options: OpenCommandResult): OpenCommandResult {
void open(url);
return options;
}
}