Skip to content

feat: add generate command #3870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 15, 2018
Merged
29 changes: 29 additions & 0 deletions docs/man_pages/project/configuration/generate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<% if (isJekyll) { %>---
title: tns generate
position: 9
---<% } %>
# tns generate


Usage | Synopsis
------|-------
General | `$ tns generate <Schematic Name> [--collection <Collection>] [option=value]`

Modifies the project by executing a specified schematic to it.

### Options
* `--collection` - specifies the node package to be used as schematics collection. If it's not specified, `@nativescript/schematics` will be used.

### Attributes
* `<Schematic Name>` - name of the schematic to be executed. The schematic should be specified in the used collection.
* `<option=value>` - options for executed schematic.

<% if(isHtml) { %>
### Related Commands

Command | Description
----------|----------
[update](update.md) | Updates a NativeScript project to the latest (or specified) version.
[resources generate icons](resources-generate-icons.md) | Generates icons for Android and iOS.
[resources generate splashes](resources-generate-splashes.md) | Generates splashscreens for Android and iOS.
<% } %>
1 change: 1 addition & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ $injector.require("emulatorSettingsService", "./services/emulator-settings-servi

$injector.require("platformCommandParameter", "./platform-command-param");
$injector.requireCommand("create", "./commands/create-project");
$injector.requireCommand("generate", "./commands/generate");
$injector.requireCommand("platform|*list", "./commands/list-platforms");
$injector.requireCommand("platform|add", "./commands/add-platform");
$injector.requireCommand("platform|remove", "./commands/remove-platform");
Expand Down
84 changes: 84 additions & 0 deletions lib/commands/generate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { run, ExecutionOptions } from '@nativescript/schematics-executor';

export class GenerateCommand implements ICommand {
public allowedParameters: ICommandParameter[] = [];
private executionOptions: ExecutionOptions;

constructor(private $logger: ILogger,
private $options: IOptions,
private $errors: IErrors) { }

public async execute(_rawArgs: string[]): Promise<void> {
try {
await run(this.executionOptions);
} catch (error) {
this.$errors.failWithoutHelp(error.message);
}
}

public async canExecute(rawArgs: string[]): Promise<boolean> {
this.setExecutionOptions(rawArgs);
this.validateExecutionOptions();

return true;
}

private validateExecutionOptions() {
if (!this.executionOptions.schematic) {
this.$errors.fail(`The generate command requires a schematic name to be specified.`);
}
}

private setExecutionOptions(rawArgs: string[]) {
const options = this.parseRawArgs(rawArgs);

this.executionOptions = {
...options,
logger: this.$logger,
directory: process.cwd(),
};
}

private parseRawArgs(rawArgs: string[]) {
const collection = this.$options.collection;
const schematic = rawArgs.shift();
const { options, args } = parseSchematicSettings(rawArgs);

return {
collection,
schematic,
schematicOptions: options,
schematicArgs: args,
};
}
}

/**
* Converts an array of command line arguments to options for the executed schematic.
* @param rawArgs The command line arguments. They should be in the format 'key=value' for strings or 'key' for booleans.
*/
function parseSchematicSettings(rawArgs: string[]) {
const [optionStrings, args] = partition<string>(rawArgs, item => item.includes('='));
const options = optionStrings
.map(o => o.split("=")) // split to key and value pairs
.map(([key, ...value]) => [key, value.join("=")]) // concat the value arrays if there are multiple = signs
.reduce((obj, [key, value]) => {
return { ...obj, [key]: value };
}, {});

return { options, args };
}
/**
* Splits an array into two groups based on a predicate.
* @param array The array to split.
* @param predicate The condition to be used for splitting.
*/
function partition<T>(array: T[], predicate: (item: T) => boolean): T[][] {
return array.reduce(([pass, fail], item) => {
return predicate(item) ?
[[...pass, item], fail] :
[pass, [...fail, item]];
}, [[], []]);
}

$injector.registerCommand("generate", GenerateCommand);
6 changes: 5 additions & 1 deletion lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ interface ICreateProjectOptions extends INpmInstallConfigurationOptionsBase {
pathToTemplate?: string;
}

interface IGenerateOptions {
collection?: string;
}

interface IDebugInformation extends IPort, Mobile.IDeviceIdentifier {
url: string;
}
Expand All @@ -451,7 +455,7 @@ interface IPluginSeedOptions {
pluginName: string;
}

interface IOptions extends ICommonOptions, IBundleString, IPlatformTemplate, IHasEmulatorOption, IClean, IProvision, ITeamIdentifier, IAndroidReleaseOptions, INpmInstallConfigurationOptions, IPort, IEnvOptions, IPluginSeedOptions {
interface IOptions extends ICommonOptions, IBundleString, IPlatformTemplate, IHasEmulatorOption, IClean, IProvision, ITeamIdentifier, IAndroidReleaseOptions, INpmInstallConfigurationOptions, IPort, IEnvOptions, IPluginSeedOptions, IGenerateOptions {
all: boolean;
client: boolean;
compileSdk: number;
Expand Down
3 changes: 2 additions & 1 deletion lib/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export class Options extends commonOptionsLibPath.OptionsBase {
background: { type: OptionType.String },
username: { type: OptionType.String },
pluginName: { type: OptionType.String },
hmr: {type: OptionType.Boolean}
hmr: { type: OptionType.Boolean },
collection: { type: OptionType.String, alias: "c" },
},
$errors, $staticConfig, $settingsService);

Expand Down
5 changes: 5 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"mobile"
],
"dependencies": {
"@nativescript/schematics-executor": "0.0.2",
"byline": "4.2.1",
"chalk": "1.1.0",
"chokidar": "1.7.0",
Expand Down