Skip to content

Commit

Permalink
feat: deployer interface
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Jun 24, 2021
1 parent d837bc4 commit fbfee1e
Show file tree
Hide file tree
Showing 5 changed files with 479 additions and 14 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
"dependencies": {
"@salesforce/kit": "^1.5.8",
"@salesforce/ts-types": "^1.5.13",
"cli-ux": "^5.6.2",
"inquirer": "^8.1.1"
},
"devDependencies": {
"@salesforce/dev-config": "^2.0.0",
"@salesforce/dev-scripts": "^0.6.2",
"@salesforce/prettier-config": "^0.0.1",
"@salesforce/ts-sinon": "^1.2.3",
"@types/inquirer": "^7.3.2",
"@typescript-eslint/eslint-plugin": "^2.30.0",
"@typescript-eslint/parser": "^2.30.0",
"eslint": "^6.8.0",
Expand Down
55 changes: 55 additions & 0 deletions src/deployer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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 { EventEmitter } from 'events';
import { Dictionary, Nullable } from '@salesforce/ts-types';
import cli from 'cli-ux';

export interface Preferences {
interactive: boolean;
}

export interface Options {
deployers: Set<Deployer>;
username: string;
}

/**
* Deploy a piece of a project.
*/
export abstract class Deployer extends EventEmitter {
// Standard methods implemented in the base class methods
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
public progress(current: number, total: number, message: string): void {}

public log(msg: string | undefined, ...args: string[]): void {
cli.log(msg, ...args);
}

abstract getAppName(): string;
abstract getAppType(): string;
abstract getAppPath(): string;
abstract getEnvType(): Nullable<string>;

// These methods are only called if the CLI user decides to deploy that piece of the project.

/**
* Perform any initialization or setup. This is the time to prompt the
* user for any needed information. It should do so by respecting the user's
* preferences when possible (i.e. interactive mode or wait times).
*
* If options are passed it, it should use those instead of prompting the for the passed in information
*
* Uses the returned dictionary as the information to store in the project-deploy-options.json file.
*/
public abstract setup(preferences: Preferences, options?: Dictionary<string>): Promise<Dictionary<string>>;

/**
* Deploy the app.
*/
public abstract deploy(): Promise<void>;
}
3 changes: 3 additions & 0 deletions src/exported.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
* 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
*/

export { generateTableChoices } from './util';
export { Deployer, Options, Preferences } from './deployer';
43 changes: 43 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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 { Separator, ChoiceOptions, ChoiceBase } from 'inquirer';
import { Dictionary, Nullable, ensureString } from '@salesforce/ts-types';

export function generateTableChoices<T>(
columns: Dictionary<string>,
choices: Array<Dictionary<Nullable<string> | T>>,
padForCheckbox = true
): ChoiceBase[] {
const columnEntries = Object.entries(columns);
const columnLengths = columnEntries.map(
([key, value]) =>
Math.max(
ensureString(value).length,
...choices.map(
(option) =>
ensureString(option[key], `Type ${typeof option[key]} for ${key} in ${Object.keys(option).join(', ')}`)
.length
)
) + (padForCheckbox ? 3 : 0)
);

const choicesOptions: ChoiceBase[] = [
// Pad an extra 2 to account for checkbox
new Separator(columnEntries.map(([, value], index) => value?.padEnd(columnLengths[index] + 2, ' ')).join('')),
];

for (const meta of choices) {
const name = columnEntries
.map(([key], index) => ensureString(meta[key]).padEnd(columnLengths[index], ' '))
.join('');
const choice: ChoiceOptions = { name, value: meta.value, short: ensureString(meta.name) };
choicesOptions.push(choice);
}

return choicesOptions;
}
Loading

0 comments on commit fbfee1e

Please sign in to comment.