Skip to content

Commit fbfee1e

Browse files
committed
feat: deployer interface
1 parent d837bc4 commit fbfee1e

File tree

5 files changed

+479
-14
lines changed

5 files changed

+479
-14
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@
4242
"dependencies": {
4343
"@salesforce/kit": "^1.5.8",
4444
"@salesforce/ts-types": "^1.5.13",
45+
"cli-ux": "^5.6.2",
4546
"inquirer": "^8.1.1"
4647
},
4748
"devDependencies": {
4849
"@salesforce/dev-config": "^2.0.0",
4950
"@salesforce/dev-scripts": "^0.6.2",
5051
"@salesforce/prettier-config": "^0.0.1",
5152
"@salesforce/ts-sinon": "^1.2.3",
53+
"@types/inquirer": "^7.3.2",
5254
"@typescript-eslint/eslint-plugin": "^2.30.0",
5355
"@typescript-eslint/parser": "^2.30.0",
5456
"eslint": "^6.8.0",

src/deployer.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2021, 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+
8+
import { EventEmitter } from 'events';
9+
import { Dictionary, Nullable } from '@salesforce/ts-types';
10+
import cli from 'cli-ux';
11+
12+
export interface Preferences {
13+
interactive: boolean;
14+
}
15+
16+
export interface Options {
17+
deployers: Set<Deployer>;
18+
username: string;
19+
}
20+
21+
/**
22+
* Deploy a piece of a project.
23+
*/
24+
export abstract class Deployer extends EventEmitter {
25+
// Standard methods implemented in the base class methods
26+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
27+
public progress(current: number, total: number, message: string): void {}
28+
29+
public log(msg: string | undefined, ...args: string[]): void {
30+
cli.log(msg, ...args);
31+
}
32+
33+
abstract getAppName(): string;
34+
abstract getAppType(): string;
35+
abstract getAppPath(): string;
36+
abstract getEnvType(): Nullable<string>;
37+
38+
// These methods are only called if the CLI user decides to deploy that piece of the project.
39+
40+
/**
41+
* Perform any initialization or setup. This is the time to prompt the
42+
* user for any needed information. It should do so by respecting the user's
43+
* preferences when possible (i.e. interactive mode or wait times).
44+
*
45+
* If options are passed it, it should use those instead of prompting the for the passed in information
46+
*
47+
* Uses the returned dictionary as the information to store in the project-deploy-options.json file.
48+
*/
49+
public abstract setup(preferences: Preferences, options?: Dictionary<string>): Promise<Dictionary<string>>;
50+
51+
/**
52+
* Deploy the app.
53+
*/
54+
public abstract deploy(): Promise<void>;
55+
}

src/exported.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
* Licensed under the BSD 3-Clause license.
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
7+
8+
export { generateTableChoices } from './util';
9+
export { Deployer, Options, Preferences } from './deployer';

src/util.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021, 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+
8+
import { Separator, ChoiceOptions, ChoiceBase } from 'inquirer';
9+
import { Dictionary, Nullable, ensureString } from '@salesforce/ts-types';
10+
11+
export function generateTableChoices<T>(
12+
columns: Dictionary<string>,
13+
choices: Array<Dictionary<Nullable<string> | T>>,
14+
padForCheckbox = true
15+
): ChoiceBase[] {
16+
const columnEntries = Object.entries(columns);
17+
const columnLengths = columnEntries.map(
18+
([key, value]) =>
19+
Math.max(
20+
ensureString(value).length,
21+
...choices.map(
22+
(option) =>
23+
ensureString(option[key], `Type ${typeof option[key]} for ${key} in ${Object.keys(option).join(', ')}`)
24+
.length
25+
)
26+
) + (padForCheckbox ? 3 : 0)
27+
);
28+
29+
const choicesOptions: ChoiceBase[] = [
30+
// Pad an extra 2 to account for checkbox
31+
new Separator(columnEntries.map(([, value], index) => value?.padEnd(columnLengths[index] + 2, ' ')).join('')),
32+
];
33+
34+
for (const meta of choices) {
35+
const name = columnEntries
36+
.map(([key], index) => ensureString(meta[key]).padEnd(columnLengths[index], ' '))
37+
.join('');
38+
const choice: ChoiceOptions = { name, value: meta.value, short: ensureString(meta.name) };
39+
choicesOptions.push(choice);
40+
}
41+
42+
return choicesOptions;
43+
}

0 commit comments

Comments
 (0)