generated from salesforcecli/plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 13
/
sandboxRequest.ts
153 lines (138 loc) · 5.97 KB
/
sandboxRequest.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* Copyright (c) 2020, 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 fs from 'node:fs';
import { Logger, SandboxInfo, SandboxRequest, Messages, SfError, Lifecycle, Connection } from '@salesforce/core';
import { lowerToUpper } from './utils.js';
import { SandboxLicenseType } from './orgTypes.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const cloneMessages = Messages.loadMessages('@salesforce/plugin-org', 'clone');
export const generateSboxName = async (): Promise<string> => {
// sandbox names are 10 chars or less, a radix of 36 = [a-z][0-9]
// technically without querying the production org, the generated name could already exist, but the chances of that are lower than the perf penalty of querying and verifying
const generated = `sbx${Date.now().toString(36).slice(-7)}`;
await Lifecycle.getInstance().emitWarning(`No SandboxName defined, generating new SandboxName: ${generated}`);
return generated;
};
// Reads the sandbox definition file and converts properties to CapCase.
export function readSandboxDefFile(
defFile: string
): Partial<SandboxInfo & { ApexClassName?: string; ActivationUserGroupName?: string; SourceSandboxName?: string }> {
const fileContent = fs.readFileSync(defFile, 'utf-8');
const parsedContent = lowerToUpper(JSON.parse(fileContent) as Record<string, unknown>);
// validate input
if (parsedContent.ApexClassName && parsedContent.ApexClassId) {
throw cloneMessages.createError('error.bothApexClassIdAndNameProvided');
}
if (parsedContent.ActivationUserGroupId && parsedContent.ActivationUserGroupName) {
throw cloneMessages.createError('error.bothUserGroupIdAndNameProvided');
}
if (parsedContent.SourceId && parsedContent.SourceSandboxName) {
throw cloneMessages.createError('error.bothSourceIdAndNameProvided');
}
if (parsedContent.SourceId && parsedContent.LicenseType) {
throw cloneMessages.createError('error.bothSourceIdAndLicenseTypeProvided');
}
if (parsedContent.LicenseType && parsedContent.SourceSandboxName) {
throw cloneMessages.createError('error.bothSourceSandboxNameAndLicenseTypeProvided');
}
return parsedContent as Partial<SandboxInfo>;
}
export async function createSandboxRequest(
definitionFile: string | undefined,
logger?: Logger | undefined,
properties?: Record<string, string | undefined>
): Promise<{
sandboxReq: SandboxRequest & {
ApexClassName: string | undefined;
ActivationUserGroupName: string | undefined;
};
srcSandboxName: string;
srcId: string;
}>;
export async function createSandboxRequest(
definitionFile: string | undefined,
logger?: Logger | undefined,
properties?: Record<string, string | undefined>
): Promise<{
sandboxReq: SandboxRequest & {
ApexClassName: string | undefined;
ActivationUserGroupName: string | undefined;
};
}>;
export async function createSandboxRequest(
definitionFile: string | undefined,
logger?: Logger | undefined,
properties?: Record<string, string | undefined>
): Promise<{ sandboxReq: SandboxRequest; srcSandboxName?: string; srcId?: string }> {
if (!logger) {
logger = await Logger.child('createSandboxRequest');
}
logger.debug('Varargs: %s ', properties);
const sandboxDefFileContents = definitionFile ? readSandboxDefFile(definitionFile) : {};
const capitalizedVarArgs = properties ? lowerToUpper(properties) : {};
// varargs override file input
const sandboxReqWithName: SandboxRequest & { SourceSandboxName?: string; SourceId?: string } = {
...(sandboxDefFileContents as Record<string, unknown>),
...capitalizedVarArgs,
SandboxName:
(capitalizedVarArgs.SandboxName as string) ??
(sandboxDefFileContents.SandboxName as string) ??
(await generateSboxName()),
};
const isClone = sandboxReqWithName.SourceSandboxName ?? sandboxReqWithName.SourceId;
const { SourceSandboxName, SourceId, ...sandboxReq } = sandboxReqWithName;
logger.debug('SandboxRequest after merging DefFile and Varargs: %s ', sandboxReq);
if (isClone) {
if (!sandboxReqWithName.SourceSandboxName && !sandboxReqWithName.SourceId) {
// error - we need SourceSandboxName or SourceID to know which sandbox to clone from
throw new SfError(
cloneMessages.getMessage('missingSourceSandboxNameORSourceId'),
cloneMessages.getMessage('missingSourceSandboxNameORSourceIdAction')
);
}
return { sandboxReq, srcSandboxName: SourceSandboxName, srcId: SourceId };
} else {
if (!sandboxReq.LicenseType) {
return { sandboxReq: { ...sandboxReq, LicenseType: SandboxLicenseType.developer } };
}
return { sandboxReq };
}
}
export async function getApexClassIdByName(conn: Connection, className: string): Promise<string | undefined> {
try {
const result = (await conn.singleRecordQuery(`SELECT Id FROM ApexClass WHERE Name = '${className}'`)).Id;
return result;
} catch (err) {
throw cloneMessages.createError('error.apexClassQueryFailed', [className], [], err as Error);
}
}
export async function getUserGroupIdByName(conn: Connection, groupName: string): Promise<string | undefined> {
try {
const result = (await conn.singleRecordQuery(`SELECT id FROM Group WHERE NAME = '${groupName}'`)).Id;
return result;
} catch (err) {
throw cloneMessages.createError('error.userGroupQueryFailed', [groupName], [], err as Error);
}
}
export async function getSrcIdByName(conn: Connection, sandboxName: string): Promise<string | undefined> {
try {
const result = (
await conn.singleRecordQuery(`SELECT id FROM SandboxInfo WHERE SandboxName = '${sandboxName}'`, { tooling: true })
).Id;
return result;
} catch (err) {
throw cloneMessages.createError('error.sandboxNameQueryFailed', [sandboxName], [], err as Error);
}
}
export default {
createSandboxRequest,
generateSboxName,
readSandboxDefFile,
getApexClassIdByName,
getUserGroupIdByName,
getSrcIdByName,
};