Skip to content

Commit

Permalink
feat(turbo/gen): update copy arg (#5040)
Browse files Browse the repository at this point in the history
  • Loading branch information
tknickman committed May 23, 2023
1 parent 49ac908 commit 306c210
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 46 deletions.
12 changes: 5 additions & 7 deletions crates/turborepo-lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,11 @@ pub struct GenerateWorkspaceArgs {
/// Generate an empty workspace
#[clap(short = 'b', long, conflicts_with = "copy", default_value_t = true)]
pub empty: bool,
/// Generate a workspace using an existing workspace as a template
#[clap(short = 'c', long, conflicts_with = "empty", default_value_t = false)]
pub copy: bool,
/// Generate a workspace using an existing workspace as a template. Can be
/// the name of a local workspace within your monorepo, or a fully
/// qualified GitHub URL with any branch and/or subdirectory
#[clap(short = 'c', long, conflicts_with = "empty", num_args = 0..=1, default_missing_value = "")]
pub copy: Option<String>,
/// Where the new workspace should be created
#[clap(short = 'd', long)]
pub destination: Option<String>,
Expand All @@ -343,10 +345,6 @@ pub struct GenerateWorkspaceArgs {
/// The root of your repository (default: directory with root turbo.json)
#[clap(short = 'r', long)]
pub root: Option<String>,
/// An example package to add. You can use a GitHub URL with any branch
/// and/or subdirectory.
#[clap(short = 'e', long)]
pub example: Option<String>,
/// In a rare case, your GitHub URL might contain a branch name with a slash
/// (e.g. bug/fix-1) and the path to the example (e.g. foo/bar). In this
/// case, you must specify the path to the example separately:
Expand Down
5 changes: 5 additions & 0 deletions crates/turborepo-lib/src/commands/generate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::process::{Command, Stdio};

use anyhow::Result;
use tracing::debug;

use crate::{
child::spawn_child,
Expand All @@ -23,6 +24,10 @@ fn verify_requirements() -> Result<()> {
}

fn call_turbo_gen(command: &str, tag: &String, raw_args: &str) -> Result<i32> {
debug!(
"Running @turbo/gen@{} with command `{}` and args {:?}",
tag, command, raw_args
);
let mut npx = Command::new("npx");
npx.arg("--yes")
.arg(format!("@turbo/gen@{}", tag))
Expand Down
34 changes: 30 additions & 4 deletions packages/turbo-gen/__tests__/raw.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,32 @@ describe("raw", () => {
command: "workspace",
options: {},
target: "workspace",
calledWith: {},
calledWith: {
empty: true,
copy: false,
},
},
{
command: "workspace",
options: {
copy: "",
},
target: "workspace",
calledWith: {
empty: false,
copy: true,
},
},
{
command: "workspace",
options: {
copy: "some-workspace",
},
target: "workspace",
calledWith: {
copy: "some-workspace",
empty: false,
},
},
{
command: "workspace",
Expand All @@ -56,6 +81,7 @@ describe("raw", () => {
type: "package",
name: "cool-name",
copy: true,
empty: false,
showAllDependencies: true,
},
},
Expand All @@ -65,19 +91,19 @@ describe("raw", () => {
type: "package",
name: "cool-name",
empty: true,
copy: "tailwind-css",
destination: "../../",
"show-all-dependencies": true,
example: "tailwind-css",
"example-path": "packages/cool-name",
},
target: "workspace",
calledWith: {
type: "package",
name: "cool-name",
empty: true,
empty: false,
copy: "tailwind-css",
destination: "../../",
showAllDependencies: true,
example: "tailwind-css",
examplePath: "packages/cool-name",
},
},
Expand Down
12 changes: 4 additions & 8 deletions packages/turbo-gen/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ turboGenCli
)
.addOption(
new Option(
"-c, --copy",
"Generate a workspace using an existing workspace as a template"
"-c, --copy [source]",
`Generate a workspace using an existing workspace as a template. Can be the name of a local workspace
within your monorepo, or a fully qualified GitHub URL with any branch and/or subdirectory.
`
).conflicts("empty")
)
.addOption(
Expand All @@ -81,12 +83,6 @@ turboGenCli
"The root of your repository (default: directory with root turbo.json)"
)
)
.addOption(
new Option(
"-e, --example [github-url]",
`An example package to add. You can use a GitHub URL with any branch and/or subdirectory.`
).implies({ copy: true })
)
.addOption(
new Option(
"-p, --example-path <path-to-example>",
Expand Down
27 changes: 22 additions & 5 deletions packages/turbo-gen/src/commands/raw/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { workspace, type TurboGeneratorOptions } from "../workspace";
import { run, type CustomGeneratorOptions } from "../run";
import { workspace, type TurboGeneratorCLIOptions } from "../workspace";
import { run, type CustomGeneratorCLIOptions } from "../run";
import { convertCase } from "@turbo/utils";

interface MinimalOptions {
Expand Down Expand Up @@ -27,15 +27,32 @@ export async function raw(command: string, options: { json: string }) {

switch (command) {
case "workspace":
await workspace(incomingOptions as TurboGeneratorOptions);
// copy and empty needs to get massaged a bit when coming from rust
let copy = false;
let empty = incomingOptions.empty || true;

// arg was passed with no value or as bool (explicitly)
if (incomingOptions.copy === "" || incomingOptions.copy === true) {
copy = true;
empty = false;
// arg was passed with a value
} else if (incomingOptions.copy && incomingOptions.copy.length > 0) {
copy = incomingOptions.copy;
empty = false;
}

// update options values
incomingOptions.copy = copy;
incomingOptions.empty = empty;
await workspace(incomingOptions as TurboGeneratorCLIOptions);
break;
case "run":
const { generatorName, ...options } = incomingOptions;
await run(generatorName, options as CustomGeneratorOptions);
await run(generatorName, options as CustomGeneratorCLIOptions);
break;
default:
console.error(
`Received unknown command - "${command}" (must be one of "add" | "generate")`
`Received unknown command - "${command}" (must be one of "workspace" | "run")`
);
process.exit(1);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/turbo-gen/src/commands/run/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { logger } from "@turbo/utils";
import { getProject } from "../../utils/getProject";
import { custom } from "../../generators";

export interface CustomGeneratorOptions {
export interface CustomGeneratorCLIOptions {
config?: string;
root?: string;
args?: Array<string>;
Expand All @@ -13,7 +13,7 @@ export interface CustomGeneratorOptions {
*/
export async function run(
generator: string | undefined,
opts: CustomGeneratorOptions
opts: CustomGeneratorCLIOptions
) {
const project = await getProject(opts);

Expand Down
42 changes: 33 additions & 9 deletions packages/turbo-gen/src/commands/workspace/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,57 @@
import { logger } from "@turbo/utils";
import { getProject } from "../../utils/getProject";
import { copy, empty } from "../../generators";
import { WorkspaceType } from "../../generators/types";
import { TurboGeneratorOptions, WorkspaceType } from "../../generators/types";

export interface TurboGeneratorOptions {
export interface TurboGeneratorCLIOptions {
name?: string;
// default to true
empty: boolean;
copy?: boolean;
copy?: string | boolean;
destination?: string;
type?: WorkspaceType;
root?: string;
example?: string;
examplePath?: string;
// defaults to false
showAllDependencies: boolean;
}

// convert CLI options to generator options
function parse(opts: TurboGeneratorCLIOptions): TurboGeneratorOptions {
const { empty, copy, ...rest } = opts;
const method = copy === true || typeof copy === "string" ? "copy" : "empty";
const source = typeof copy === "string" ? copy : "";
const sourceType =
typeof copy === "string" && copy.startsWith("https://")
? "external"
: "internal";

return {
method,
copy: {
type: sourceType,
source,
},
...rest,
};
}

/**
* Adds a new (blank, or copied) workspace to the project
*/
export async function workspace(opts: TurboGeneratorOptions) {
export async function workspace(opts: TurboGeneratorCLIOptions) {
const project = await getProject(opts);
const generatorOpts = parse(opts);

console.log();
const args = { project, opts };
if (opts.copy) {
if (opts.example) {
logger.info(`Copy a remote workspace from ${opts.example}`);
const args = {
project,
opts: generatorOpts,
};

if (generatorOpts.method === "copy") {
if (generatorOpts.copy.type === "external") {
logger.info(`Copy a remote workspace from ${generatorOpts.copy.source}`);
} else {
logger.info(`Copy an existing workspace from "${project.name}"`);
}
Expand Down
22 changes: 20 additions & 2 deletions packages/turbo-gen/src/commands/workspace/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import inquirer from "inquirer";
import { minimatch } from "minimatch";
import validName from "validate-npm-package-name";
import type { Project, Workspace } from "@turbo/workspaces";
import { validateDirectory } from "@turbo/utils";
import { validateDirectory, logger } from "@turbo/utils";
import { getWorkspaceStructure } from "../../utils/getWorkspaceStructure";
import type { WorkspaceType } from "../../generators/types";
import { getWorkspaceList } from "../../utils/getWorkspaceList";
Expand Down Expand Up @@ -37,8 +37,10 @@ export async function name({

export async function type({
override,
message,
}: {
override?: WorkspaceType;
message?: string;
}): Promise<{ answer: WorkspaceType }> {
if (override) {
return { answer: override };
Expand All @@ -47,7 +49,7 @@ export async function type({
return inquirer.prompt<{ answer: WorkspaceType }>({
type: "list",
name: "answer",
message: `What type of workspace should be added?`,
message: message ?? `What type of workspace should be added?`,
choices: [
{
name: "app",
Expand Down Expand Up @@ -131,12 +133,28 @@ export async function location({
}

export async function source({
override,
workspaces,
name,
}: {
override?: string;
workspaces: Array<Workspace | inquirer.Separator>;
name: string;
}) {
if (override) {
const source = workspaces.find((workspace) => {
if (workspace instanceof inquirer.Separator) {
return false;
}
return workspace.name === override;
}) as Workspace | undefined;
if (source) {
return { answer: source };
}
logger.warn(`Workspace "${override}" not found`);
console.log();
}

const sourceAnswer = await inquirer.prompt<{
answer: Workspace;
}>({
Expand Down
4 changes: 2 additions & 2 deletions packages/turbo-gen/src/generators/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ export async function generate({ project, opts }: TurboGeneratorArguments) {
const newPackageJsonPath = path.join(location.absolute, "package.json");

// copying from a remote example
if (opts.example) {
if (opts.copy.type === "external") {
console.log();
logger.warn("Some manual modifications may be required.");
logger.dimmed(
`This ${type} may require local dependencies or a different package manager than what is available in this repo`
);
await createProject({
appPath: location.absolute,
example: opts.example,
example: opts.copy.source,
examplePath: opts.examplePath,
});

Expand Down
18 changes: 15 additions & 3 deletions packages/turbo-gen/src/generators/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import type { Project } from "@turbo/workspaces";
import type { TurboGeneratorOptions } from "../commands/workspace";
import type { CustomGeneratorOptions } from "../commands/run";
import type { TurboGeneratorCLIOptions } from "../commands/workspace";
import type { CustomGeneratorCLIOptions } from "../commands/run";

export type WorkspaceType = "app" | "package";
export type CopyData = {
type: "internal" | "external";
source: string;
};

export type TurboGeneratorOptions = Omit<
TurboGeneratorCLIOptions,
"copy" | "empty"
> & {
copy: CopyData;
method: "copy" | "empty";
};

export interface TurboGeneratorArguments {
project: Project;
Expand All @@ -12,5 +24,5 @@ export interface TurboGeneratorArguments {
export interface CustomGeneratorArguments {
generator: string | undefined;
project: Project;
opts: CustomGeneratorOptions;
opts: CustomGeneratorCLIOptions;
}
Loading

1 comment on commit 306c210

@vercel
Copy link

@vercel vercel bot commented on 306c210 May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.