Skip to content

Commit

Permalink
feat: lots of stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Jan 8, 2022
1 parent 861f516 commit 5ffba41
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 116 deletions.
4 changes: 2 additions & 2 deletions messages/dev.generate.command.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Generate a NUT test file for the command.

Generate a unit test file for the command.

# args.name.description
# flags.name.description

Name of the new command. Must be separated by colons.

# examples

- <%= config.bin %> <%= command.id %> my:command
- <%= config.bin %> <%= command.id %> --name my:command
2 changes: 1 addition & 1 deletion messages/dev.generate.hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ Event to run hook on.

# examples

- <%= config.bin %> <%= command.id %> my:command
- <%= config.bin %> <%= command.id %> --event sf:env:display
10 changes: 1 addition & 9 deletions messages/dev.generate.plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ Generate a new sf plugin.

This will clone the template repo 'salesforcecli/plugin-template-sf' and update package properties

# args.name.description

Directory name of new plugin. Must begin with "plugin-"

# examples

- <%= config.bin %> <%= command.id %> plugin-awesome

# error.InvalidPluginName

%s must begin with "plugin-"
- <%= config.bin %> <%= command.id %>
18 changes: 11 additions & 7 deletions src/commands/dev/generate/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@
*/
import { Flags } from '@oclif/core';
import { Messages } from '@salesforce/core';
import { GeneratorCommand } from '../../../generatorCommand';
import { SfCommand } from '@salesforce/sf-plugins-core';
import { generate } from '../../../util';

Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/plugin-dev', 'dev.generate.command');

export default class GenerateCommand extends GeneratorCommand {
export default class GenerateCommand extends SfCommand<void> {
public static enableJsonFlag = false;
public static summary = messages.getMessage('summary');
public static description = messages.getMessage('description');
public static examples = messages.getMessages('examples');

public static flags = {
name: Flags.string({
required: true,
description: messages.getMessage('flags.name.description'),
}),
force: Flags.boolean({
description: messages.getMessage('flags.force.description'),
}),
Expand All @@ -32,12 +38,10 @@ export default class GenerateCommand extends GeneratorCommand {
}),
};

public static args = [{ name: 'name', required: true, description: messages.getMessage('args.name.description') }];

public async run(): Promise<void> {
const { args, flags } = await this.parse(GenerateCommand);
await super.generate('command', {
name: args.name,
const { flags } = await this.parse(GenerateCommand);
generate('command', {
name: flags.name,
force: flags.force,
nuts: flags.nuts,
unit: flags.unit,
Expand Down
11 changes: 7 additions & 4 deletions src/commands/dev/generate/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
*/
import { Flags } from '@oclif/core';
import { Messages } from '@salesforce/core';
import { GeneratorCommand } from '../../../generatorCommand';
import { SfCommand } from '@salesforce/sf-plugins-core';
import { generate } from '../../../util';
import { Hook } from '../../../types';

Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/plugin-dev', 'dev.generate.hook');

export default class GenerateHook extends GeneratorCommand {
export default class GenerateHook extends SfCommand<void> {
public static enableJsonFlag = false;
public static summary = messages.getMessage('summary');
public static description = messages.getMessage('description');
public static examples = messages.getMessages('examples');
Expand All @@ -22,14 +25,14 @@ export default class GenerateHook extends GeneratorCommand {
}),
event: Flags.string({
description: messages.getMessage('flags.event.description'),
options: ['sf:env:display', 'sf:env:list', 'sf:deploy', 'sf:logout'],
options: Object.keys(Hook),
required: true,
}),
};

public async run(): Promise<void> {
const { flags } = await this.parse(GenerateHook);
await super.generate('hook', {
generate('hook', {
force: flags.force,
event: flags.event,
});
Expand Down
21 changes: 6 additions & 15 deletions src/commands/dev/generate/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,22 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { Messages } from '@salesforce/core';
import { GeneratorCommand } from '../../../generatorCommand';
import { SfCommand } from '@salesforce/sf-plugins-core';
import { generate } from '../../../util';

Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/plugin-dev', 'dev.generate.plugin');

export default class GeneratePlugin extends GeneratorCommand {
export default class GeneratePlugin extends SfCommand<void> {
public static enableJsonFlag = false;
public static summary = messages.getMessage('summary');
public static description = messages.getMessage('description');
public static examples = messages.getMessages('examples');

public static flags = {};

public static args = [{ name: 'name', required: true, description: messages.getMessage('args.name.description') }];

// eslint-disable-next-line @typescript-eslint/require-await
public async run(): Promise<void> {
const { args } = await this.parse(GeneratePlugin);
const pluginName = args.name as string;

if (!pluginName.startsWith('plugin-')) {
throw messages.createError('error.InvalidPluginName', [pluginName]);
}

await super.generate('plugin', {
name: pluginName,
force: true,
});
generate('plugin', { force: true });
}
}
22 changes: 0 additions & 22 deletions src/generatorCommand.ts

This file was deleted.

34 changes: 8 additions & 26 deletions src/generators/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,28 @@ import * as path from 'path';
import { camelCase } from 'change-case';
import * as Generator from 'yeoman-generator';
import yosay = require('yosay');
import { PackageJson } from '../types';
import { Hook, PackageJson } from '../types';
import { addHookToPackageJson, readJson } from '../util';

// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
const { version } = require('../../package.json');

export interface CommandGeneratorOptions extends Generator.GeneratorOptions {
export interface HookGeneratorOptions extends Generator.GeneratorOptions {
name: string;
event: string;
}

function toArray(item: string | string[]): string[] {
return Array.isArray(item) ? item : [item];
}

export default class Command extends Generator {
public options: CommandGeneratorOptions;
export default class HookGenerator extends Generator {
public options: HookGeneratorOptions;
public pjson!: PackageJson;

public constructor(args: string | string[], opts: CommandGeneratorOptions) {
public constructor(args: string | string[], opts: HookGeneratorOptions) {
super(args, opts);
}

// eslint-disable-next-line @typescript-eslint/require-await
public async prompting(): Promise<void> {
this.pjson = this.fs.readJSON('package.json') as unknown as PackageJson;
this.pjson = readJson<PackageJson>(path.join(this.env.cwd, 'package.json'));
this.log(yosay(`Adding a ${this.options.event} hook to ${this.pjson.name} Version: ${version as string}`));
}

Expand All @@ -46,22 +43,7 @@ export default class Command extends Generator {
{ year: new Date().getFullYear() }
);

// TODO
// this.fs.copyTpl(
// this.templatePath('test/hook.test.ts.ejs'),
// this.destinationPath(`test/hooks/${this.options.event}/${this.options.name}.test.ts`),
// this
// );

this.pjson.oclif.hooks = this.pjson.oclif.hooks || {};
const hooks = this.pjson.oclif.hooks;
const p = `./lib/hooks/${filename}`;
if (hooks[this.options.event]) {
hooks[this.options.event] = [...toArray(hooks[this.options.event]), p];
} else {
this.pjson.oclif.hooks[this.options.event] = p;
}

this.pjson = addHookToPackageJson(this.options.event as Hook, filename, this.pjson);
this.fs.writeJSON(this.destinationPath('./package.json'), this.pjson);
}
}
70 changes: 49 additions & 21 deletions src/generators/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,77 @@ import * as Generator from 'yeoman-generator';
import yosay = require('yosay');
import { exec } from 'shelljs';
import replace = require('replace-in-file');
import { PackageJson } from '../types';
import { camelCase } from 'change-case';
import { Hook, PackageJson } from '../types';
import { addHookToPackageJson, readJson } from '../util';

// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
const { version } = require('../../package.json');

export interface PluginGeneratorOptions extends Generator.GeneratorOptions {
name: string;
}

export default class Plugin extends Generator {
private name: string;
private answers!: {
name: string;
description: string;
hooks: Hook[];
};

public constructor(args: string | string[], opts: PluginGeneratorOptions) {
public constructor(args: string | string[], opts: Generator.GeneratorOptions) {
super(args, opts);
this.name = opts.name;
this.env.options.nodePackageManager = 'yarn';
}

public async prompting(): Promise<void> {
const msg = 'Time to build an sf plugin!';
const directory = path.resolve(this.name);

this.log(yosay(`${msg} Version: ${version as string}`));
exec(`git clone [email protected]:salesforcecli/plugin-template-sf.git ${directory}`);
fs.rmSync(`${path.resolve(this.name, '.git')}`, { recursive: true });

this.destinationRoot(directory);
this.env.cwd = this.destinationPath();
this.answers = await this.prompt<{ description: string }>([
this.answers = await this.prompt<{ name: string; description: string; hooks: Hook[] }>([
{
type: 'input',
name: 'name',
message: 'Name (must start with plugin-)',
validate: (input: string): boolean => /plugin-[a-z]+$/.test(input),
},
{
type: 'input',
name: 'description',
message: 'description',
message: 'Description',
},
{
type: 'checkbox',
name: 'hooks',
message: 'Which commands do you plan to extend',
choices: Object.values(Hook),
},
]);

const directory = path.resolve(this.answers.name);
exec(`git clone [email protected]:salesforcecli/plugin-template-sf.git ${directory}`);
fs.rmSync(`${path.resolve(this.answers.name, '.git')}`, { recursive: true });
this.destinationRoot(directory);
this.env.cwd = this.destinationPath();
}

public writing(): void {
const pjsonRaw = fs.readFileSync(path.join(this.env.cwd, 'package.json'), 'utf-8');
const pjson = JSON.parse(pjsonRaw) as PackageJson;
let pjson = readJson<PackageJson>(path.join(this.env.cwd, 'package.json'));

this.sourceRoot(path.join(__dirname, '../../templates'));
const hooks = this.answers.hooks.map((h) => h.split(' ').join(':')) as Hook[];
for (const hook of hooks) {
const filename = camelCase(hook.replace('sf:', ''));
this.fs.copyTpl(
this.templatePath(`src/hooks/${hook.replace(/:/g, '.')}.ts.ejs`),
this.destinationPath(`src/hooks/${filename}.ts`),
{ year: new Date().getFullYear() }
);

pjson = addHookToPackageJson(hook, filename, pjson);
}

const updated = {
name: `@salesforce/${this.name}`,
repository: `salesforcecli/${this.name}`,
homepage: `https://github.com/salesforcecli/${this.name}`,
name: `@salesforce/${this.answers.name}`,
repository: `salesforcecli/${this.answers.name}`,
homepage: `https://github.com/salesforcecli/${this.answers.name}`,
description: this.answers.description,
};
const final = Object.assign({}, pjson, updated);
Expand All @@ -66,7 +90,11 @@ export default class Plugin extends Generator {
replace.sync({
files: `${this.env.cwd}/**/*`,
from: /plugin-template-sf/g,
to: this.name,
to: this.answers.name,
});
}

public end(): void {
exec(`${path.join(path.resolve(this.env.cwd), 'bin', 'dev')} schema generate`, { cwd: this.env.cwd });
}
}
7 changes: 7 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@ export interface PackageJson {
repository: string;
homepage: string;
}

export enum Hook {
'sf:env:list' = 'sf env list',
'sf:env:display' = 'sf env display',
'sf:deploy' = 'sf deploy',
'sf:logout' = 'sf logout',
}
38 changes: 38 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2022, 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 fs from 'fs';
import { createEnv } from 'yeoman-environment';
import { Hook, PackageJson } from './types';

/* eslint-disable @typescript-eslint/ban-ts-comment */

export function generate(type: string, generatorOptions: Record<string, unknown> = {}): void {
const env = createEnv();
env.register(require.resolve(`./generators/${type}`), `sf:${type}`);
// @ts-ignore
env.run(`sf:${type}`, generatorOptions);
}

export function readJson<T>(filePath: string): T {
const pjsonRaw = fs.readFileSync(filePath, 'utf-8');
return JSON.parse(pjsonRaw) as T;
}

export function toArray(item: string | string[]): string[] {
return Array.isArray(item) ? item : [item];
}

export function addHookToPackageJson(hook: Hook, filename: string, pjson: PackageJson): PackageJson {
pjson.oclif.hooks = pjson.oclif.hooks || {};
const p = `./lib/hooks/${filename}`;
if (pjson.oclif.hooks[hook]) {
pjson.oclif.hooks[hook] = [...toArray(pjson.oclif.hooks[hook]), p];
} else {
pjson.oclif.hooks[hook] = p;
}
return pjson;
}
Loading

0 comments on commit 5ffba41

Please sign in to comment.