fix(core): Remove nameAndDirectoryFormat option from generators (#28110)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

Currently, when we use generator's via the CLI passing the `name` arg
has more than one responsibility:
1.  it can be used as a path
2. it can be used as the generator's name (e.g. Component name)

This is not intuitive as if we use via Nx Console because it creates
some ambiguity around the `--name` property which is normally described
as only 2.

![image](https://github.com/user-attachments/assets/b05fa2a7-36e7-44a1-af82-6f55f53d6c43)

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

What is expected is that the `name` property should only have the
responsibility of determining the name of the generated module
(Component, Directive etc...).

The new property `path` replaces the `directory` property but fulfils
the same purpose as determining where the module should be created.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #

---------

Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
This commit is contained in:
Nicholas Cunningham 2024-10-01 06:26:27 -06:00 committed by GitHub
parent e802d2c872
commit bc8b71ac6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
187 changed files with 1162 additions and 1815 deletions

View File

@ -10,23 +10,17 @@
"description": "Creates a new Angular component.",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the component file, relative to the workspace root. By default, it is set to the root of the project.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where to create the component?"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"prefix": {
"type": "string",
"description": "The prefix to apply to the generated component selector.",
@ -118,7 +112,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nCreate a component named `my-component`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component\n```\n\n{% /tab %}\n\n{% tab label=\"Single File Component\" %}\n\nCreate a component named `my-component` with inline styles and inline template:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --inlineStyle --inlineTemplate\n```\n\n{% /tab %}\n\n{% tab label=\"Component with OnPush Change Detection Strategy\" %}\n\nCreate a component named `my-component` with OnPush Change Detection Strategy:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --changeDetection=OnPush\n```\n\n{% /tab %}\n",
"presets": []
},

View File

@ -10,23 +10,17 @@
"description": "Creates a new Angular directive.",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the directive file.",
"x-prompt": "Where to put the directive?",
"$default": { "$source": "argv", "index": 0 }
},
"name": {
"type": "string",
"description": "The name of the new directive.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the directive?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the directive file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the directive in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"prefix": {
"type": "string",
"description": "A prefix to apply to generated selectors.",
@ -72,7 +66,7 @@
"description": "Skip formatting of files."
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"aliases": ["d"],

View File

@ -10,30 +10,17 @@
"additionalProperties": false,
"description": "Creates an Angular pipe.",
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the pipe file, relative to the workspace root.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the new pipe?"
},
"name": {
"type": "string",
"description": "The name of the pipe.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the pipe?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the pipe file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the pipe in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": { "$source": "projectName" },
"x-dropdown": "projects",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"skipTests": {
"type": "boolean",
"description": "Do not create \"spec.ts\" test files for the new pipe.",
@ -65,7 +52,7 @@
"description": "Skip formatting of files."
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Generate an Angular Pipe",

View File

@ -16,10 +16,15 @@
"description": "Creates a new, generic Angular directive definition in the given or default project.",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the SCAM Directive files, relative to the workspace root.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the new directive?"
},
"name": {
"type": "string",
"description": "The name of the directive.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the directive?",
"x-priority": "important"
},
@ -85,7 +90,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Generate a directive with an accompanying Single Component Angular Module (SCAM).",

View File

@ -9,38 +9,25 @@
"type": "object",
"examples": [
{
"command": "nx g @nx/angular:scam-pipe --project=my-lib --flat=false my-transformation",
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/my-transformation/my-transformation",
"description": "Generates a `MyTransformationPipe` in a `my-transformation` folder in the `my-lib` project"
}
],
"description": "Creates a new, generic Angular pipe definition in the given or default project.",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the pipe file, relative to the workspace root.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the new pipe?"
},
"name": {
"type": "string",
"description": "The name of the pipe.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the pipe?",
"x-priority": "important"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": { "$source": "projectName" },
"x-dropdown": "projects",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"skipTests": {
"type": "boolean",
"description": "Do not create `spec.ts` test files for the new pipe.",
@ -71,7 +58,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Generate a pipe with an accompanying Single Component Angular Module (SCAM).",

View File

@ -9,37 +9,24 @@
"type": "object",
"examples": [
{
"command": "nx g @nx/angular:scam my-sample --directory=my-lib/src/lib/my-sample",
"command": "nx g @nx/angular:scam my-lib/src/lib/my-sample/my-sample",
"description": "Generate a `MySampleComponent` component in the `my-lib` library."
}
],
"description": "Creates a new Angular SCAM.",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the SCAM file, relative to the workspace root.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the new SCAM?"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the SCAM files. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the SCAM in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": { "$source": "projectName" },
"x-dropdown": "projects",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"displayBlock": {
"description": "Specifies if the style will contain `:host { display: block; }`.",
"type": "boolean",
@ -125,7 +112,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Generate a component with an accompanying Single Component Angular Module (SCAM).",

View File

@ -9,19 +9,25 @@
"type": "object",
"examples": [
{
"command": "g @nx/expo:component my-component --directory=mylib/my-component",
"command": "g @nx/expo:component mylib/my-component --name my-component",
"description": "Generate a component in the mylib library"
},
{
"command": "g @nx/expo:component my-component --directory=mylib/my-component --classComponent",
"command": "g @nx/expo:component mylib/my-component --name my-component --classComponent",
"description": "Generate a class component in the mylib library"
}
],
"properties": {
"path": {
"type": "string",
"description": "Path where the component will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the component be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?"
},
"js": {
@ -40,16 +46,6 @@
"description": "When true, does not create \"spec.ts\" test files for the new component.",
"default": false
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"export": {
"type": "boolean",
"description": "When true, the component is exported from the project index.ts (if it exists).",
@ -64,7 +60,7 @@
"default": false
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Create a component",

View File

@ -9,29 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the class will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the class be generated?"
},
"name": {
"description": "The name of the class.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"description": "The Nest project to target.",
"type": "string",
"$default": { "$source": "projectName" },
"alias": "p",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -57,7 +45,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `class` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the controller will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the controller be generated?"
},
"name": {
"description": "The name of the controller.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -53,7 +48,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `controller` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the decorator will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the decorator be generated?"
},
"name": {
"description": "The name of the decorator.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -38,7 +33,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `decorator` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the filter will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the filter be generated?"
},
"name": {
"description": "The name of the filter.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"type": "boolean",
"description": "Skip formatting files.",
@ -44,7 +39,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `filter` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the gateway will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the gateway be generated?"
},
"name": {
"description": "The name of the gateway.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -44,7 +39,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `gateway` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the guard will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the guard be generated?"
},
"name": {
"description": "The name of the guard.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the interceptor will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the interceptor be generated?"
},
"name": {
"description": "The name of the interceptor.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",

View File

@ -9,29 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the interface will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the interface be generated?"
},
"name": {
"description": "The name of the interface.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"description": "The Nest project to target.",
"type": "string",
"$default": { "$source": "projectName" },
"alias": "p",
"x-deprecated": "Provide The `directory` option instead and use the `as-provided` format. the project will be determined from the directory provided. It will be removed in Nx v20."
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -46,7 +34,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `interface` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the middleware will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the middleware be generated?"
},
"name": {
"description": "The name of the middleware.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -44,7 +39,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `middleware` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the module will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the module be generated?"
},
"name": {
"description": "The name of the module.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -48,7 +43,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `module` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the pipe will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the pipe be generated?"
},
"name": {
"description": "The name of the pipe.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -44,7 +39,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `pipe` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the provider will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the provider be generated?"
},
"name": {
"description": "The name of the provider.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -44,7 +39,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `provider` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"description": "Path where the resolver will be generated.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the resolver be generated?"
},
"name": {
"description": "The name of the resolver.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -44,7 +39,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `resolver` NestJS generator with Nx project support.",

View File

@ -9,22 +9,17 @@
"cli": "nx",
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path where the resource will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the resource be generated?"
},
"name": {
"type": "string",
"description": "The name of the resource.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for this resource (plural, e.g., `users`)?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -84,7 +79,7 @@
}
},
"additionalProperties": false,
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Run the `resource` NestJS generator with Nx project support.",

View File

@ -15,16 +15,6 @@
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",

View File

@ -9,10 +9,16 @@
"description": "Create a React Component for Next.",
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path where the component will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the component be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?",
"x-priority": "important"
},
@ -56,17 +62,6 @@
"default": false,
"x-priority": "internal"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"alias": "dir",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"export": {
"type": "boolean",
"description": "When true, the component is exported from the project index.ts (if it exists).",
@ -85,7 +80,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Create an app component\" %}\n\n```shell\nnx g component apps/my-app/src/lib/my-cmp/my-cmp\n```\n\n{% /tab %}\n{% tab label=\"Create a component without its own folder\" %}\n\nRunning the following will create a component under `apps/my-app/components/my-cmp.tsx` rather than `apps/my-app/components/my-cmp/my-cmp.tsx`.\n\n```shell\nnx g component apps/my-app/src/lib/my-cmp\n```\n\n{% /tab %}\n{% tab label=\"Create component in a custom directory\" %}\n\nRunning the following will create a component under `apps/my-app/foo/my-cmp.tsx` rather than `apps/my-app/my-cmp/my-cmp.tsx`.\n\n```shell\nnx g component apps/my-app/foo/my-cmp\n```\n\n{% /tab %}\n{% /tabs %}\n",
"presets": []
},

View File

@ -9,31 +9,19 @@
"description": "Create a Page for Next.",
"type": "object",
"properties": {
"project": {
"path": {
"type": "string",
"description": "The name of the project.",
"alias": "p",
"$default": { "$source": "projectName" },
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
"description": "Path where the page will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the page be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?",
"description": "The name of the page.",
"x-prompt": "What name would you like to use for the page?",
"x-priority": "important"
},
"directory": {
"type": "string",
"description": "The directory at which to create the page file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"alias": "dir",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"style": {
"description": "The file extension to be used for style files.",
"type": "string",
@ -98,7 +86,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Create static page in an app\" %}\n\n```shell\nnx g page apps/my-app/pages/my-page\n```\n\n{% /tab %}\n{% tab label=\"Create dynamic page in an app\" %}\n\nThe following creates a page under `apps/my-app/pages/products/[id].tsx`.\n\n```shell\nnx g page \"apps/my-app/pages/products/[id]\"\n```\n\n{% /tab %}\n\n{% /tabs %}\n",
"presets": []
},

View File

@ -16,19 +16,19 @@
}
],
"properties": {
"path": {
"type": "string",
"description": "Path at which to generate the executor file.",
"x-prompt": "What path would you like to use for the executor?",
"$default": { "$source": "argv", "index": 0 },
"x-priority": "important"
},
"name": {
"type": "string",
"description": "Executor name.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the executor?",
"x-priority": "important"
},
"directory": {
"type": "string",
"description": "The directory at which to create the executor file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir"],
"x-priority": "important"
},
"description": {
"type": "string",
"description": "Executor description.",
@ -50,11 +50,6 @@
"default": false,
"description": "Do not add an eslint configuration for plugin json files."
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the executor in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"skipFormat": {
"type": "boolean",
"description": "Skip formatting files.",
@ -62,7 +57,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"additionalProperties": false,
"presets": []
},

View File

@ -10,24 +10,24 @@
"type": "object",
"examples": [
{
"command": "nx g generator my-generator --project=my-plugin",
"command": "nx g generator libs/my-plugin/src/generators//my-generator",
"description": "Generate `libs/my-plugin/src/generators/my-generator`"
}
],
"properties": {
"path": {
"type": "string",
"description": "Path where the generator will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the generator be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "Generator name.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the generator?",
"x-priority": "important"
},
"directory": {
"type": "string",
"description": "The directory at which to create the generator file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir"],
"x-priority": "important"
},
"description": {
"type": "string",
"description": "Generator description.",
@ -49,14 +49,9 @@
"default": false,
"description": "Do not format files with prettier.",
"x-priority": "internal"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the generator in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
}
},
"required": ["name"],
"required": ["path"],
"additionalProperties": false,
"presets": []
},

View File

@ -10,22 +10,23 @@
"type": "object",
"examples": [
{
"command": "nx g migration my-migration --project=my-plugin --version=1.0.0",
"description": "Adds a new migration to the project `my-plugin`, which will be triggered when migrating to version 1.0.0 or above from a previous version."
"command": "nx g migration my-plugin/my-migration --version=1.0.0",
"description": "Adds a new migration inside `my-plugin`, which will be triggered when migrating to version 1.0.0 or above from a previous version."
}
],
"properties": {
"path": {
"type": "string",
"description": "Path where the migration will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the migration be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "Migration name.",
"$default": { "$source": "argv", "index": 0 },
"x-priority": "important"
},
"directory": {
"type": "string",
"description": "The directory at which to create the migration file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir"]
},
"description": {
"type": "string",
"description": "Migration description."
@ -47,14 +48,9 @@
"type": "boolean",
"default": false,
"description": "Do not eslint configuration for plugin json files."
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the migration in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
}
},
"required": ["packageVersion"],
"required": ["packageVersion", "path"],
"additionalProperties": false,
"presets": []
},

View File

@ -10,19 +10,24 @@
"type": "object",
"examples": [
{
"command": "nx g @nx/react-native:component my-component --directory=mylib/src/lib/my-component",
"command": "nx g @nx/react-native:component mylib/src/lib/my-component/my-component ",
"description": "Generate a component in the `mylib` library"
},
{
"command": "nx g @nx/react-native:component my-component --directory=mylib/src/lib/my-component --classComponent",
"command": "nx g @nx/react-native:component mylib/src/lib/my-component/my-component --classComponent",
"description": "Generate a class component in the `mylib` library"
}
],
"properties": {
"path": {
"type": "string",
"description": "The path at which to create the component file.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What path would you like to use for the component?"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?"
},
"js": {
@ -35,16 +40,6 @@
"description": "When true, does not create `spec.ts` test files for the new component.",
"default": false
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"export": {
"type": "boolean",
"description": "When true, the component is exported from the project `index.ts` (if it exists).",
@ -59,7 +54,7 @@
"default": false
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Create a React Native component.",

View File

@ -9,10 +9,16 @@
"description": "Create a React Component for Nx.",
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path where the component will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the component be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?",
"x-priority": "important"
},
@ -61,17 +67,6 @@
"default": false,
"x-priority": "internal"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"alias": "dir",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"export": {
"type": "boolean",
"description": "When true, the component is exported from the project `index.ts` (if it exists).",
@ -110,7 +105,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nCreate a component named `my-component` under the `libs/ui` project:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component\n```\n\n{% /tab %}\n\n{% tab label=\"Standalone Component\" %}\n\nCreate a class component named `my-component` under the `libs/ui` project:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component --classComponent\n```\n\n{% /tab %}\n",
"presets": []
},

View File

@ -10,15 +10,21 @@
"type": "object",
"examples": [
{
"command": "nx g hook my-hook --project=mylib",
"description": "Generate a hook in the `mylib` library"
"command": "nx g hook mylib/my-hook",
"description": "Generate a hook `my-hook` in the `mylib` library"
}
],
"properties": {
"path": {
"type": "string",
"description": "Path where the hook will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the hook be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the hook.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the hook?",
"x-priority": "important"
},

View File

@ -9,24 +9,18 @@
"description": "Create a Redux state slice for a React project.",
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path where the Redux slice will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the Redux slice be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "Redux slice name.",
"$default": { "$source": "argv", "index": 0 },
"x-priority": "important"
},
"directory": {
"type": "string",
"alias": "dir",
"default": "",
"description": "The directory at which to create the Redux files. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"appProject": {
"type": "string",
"description": "The application project to add the slice to.",
@ -38,7 +32,7 @@
"default": false
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"description": "Create a Redux slice for a project.",

View File

@ -20,11 +20,6 @@
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the route? (e.g. 'apps/demo/app/routes/foo/bar')"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the styles in the path as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"action": {
"type": "boolean",
"description": "Generate an action function",

View File

@ -16,15 +16,10 @@
"properties": {
"path": {
"type": "string",
"description": "The route path or path to the filename of the route. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"description": "The route path or path to the filename of the route.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the route? (e.g. 'apps/demo/app/routes/foo/bar')"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the route in the path as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and path relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"style": {
"type": "string",
"description": "Generate a stylesheet",

View File

@ -19,11 +19,6 @@
"description": "Route path",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What is the path of the route? (e.g. 'apps/demo/app/routes/foo/bar.tsx')"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the styles in the path as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
}
},
"required": ["path"],

View File

@ -10,22 +10,26 @@
"type": "object",
"examples": [
{
"command": "nx g @nx/vue:component --directory=my-app/src/app/one --name=one --nameAndDirectoryFormat=as-provided --unitTestRunner=vitest",
"description": "Generate a component in the `my-app` application"
"command": "nx g @nx/vue:component my-app/src/app/one --name=one --unitTestRunner=vitest",
"description": "Generate a component `one` in the `my-app` application at my-app/src/app/one"
},
{
"command": "nx g @nx/vue:component my-app/src/app/one",
"description": "Generate a component `one` in the `my-app` application at my-app/src/app/one"
}
],
"properties": {
"path": {
"type": "string",
"description": "Path where the component will be generated.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "Where should the component be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the component.",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the component?",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
"x-prompt": "What name would you like to use for the component?"
},
"js": {
"type": "boolean",
@ -38,12 +42,6 @@
"default": false,
"x-priority": "internal"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"alias": "dir",
"x-priority": "important"
},
"export": {
"type": "boolean",
"description": "When true, the component is exported from the project `index.ts` (if it exists).",
@ -71,7 +69,7 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"presets": []
},
"aliases": ["c"],

View File

@ -136,7 +136,7 @@ function createApp(appName: string) {
`generate @nx/angular:app ${appName} --bundler=webpack --project-name-and-root-format=as-provided --no-interactive`
);
runCLI(
`generate @nx/angular:component fancy-component --directory=${appName}/src/lib/fancy-component --no-interactive`
`generate @nx/angular:component ${appName}/src/lib/fancy-component/fancy-component --no-interactive`
);
}
@ -145,10 +145,10 @@ function createLib(projectName: string, appName: string, libName: string) {
`generate @nx/angular:lib ${libName} --project-name-and-root-format=as-provided --no-interactive`
);
runCLI(
`generate @nx/angular:component btn --directory=${libName}/src/lib/btn --inlineTemplate --inlineStyle --export --no-interactive`
`generate @nx/angular:component ${libName}/src/lib/btn/btn --inlineTemplate --inlineStyle --export --no-interactive`
);
runCLI(
`generate @nx/angular:component btn-standalone --directory=${libName}/src/lib/btn-standalone --inlineTemplate --inlineStyle --export --standalone --no-interactive`
`generate @nx/angular:component ${libName}/src/lib/btn-standalone/btn-standalone --inlineTemplate --inlineStyle --export --standalone --no-interactive`
);
updateFile(
`${libName}/src/lib/btn/btn.component.ts`,
@ -191,11 +191,11 @@ function createBuildableLib(projectName: string, libName: string) {
);
// create cmp for lib
runCLI(
`generate @nx/angular:component input --directory=${libName}/src/lib/input --inlineTemplate --inlineStyle --export --no-interactive`
`generate @nx/angular:component ${libName}/src/lib/input/input --inlineTemplate --inlineStyle --export --no-interactive`
);
// create standlone cmp for lib
runCLI(
`generate @nx/angular:component input-standalone --directory=${libName}/src/lib/input-standalone --inlineTemplate --inlineStyle --export --standalone --no-interactive`
`generate @nx/angular:component ${libName}/src/lib/input-standalone/input-standalone --inlineTemplate --inlineStyle --export --standalone --no-interactive`
);
// update cmp implmentation to use tailwind clasasserting in tests
updateFile(

View File

@ -49,7 +49,7 @@ describe('Cypress E2E Test runner (legacy)', () => {
{ env: { NX_ADD_PLUGINS: 'false' } }
);
runCLI(
`generate @nx/react:component btn --directory=${appName}/src/app/btn --no-interactive`,
`generate @nx/react:component ${appName}/src/app/btn/btn --no-interactive`,
{ env: { NX_ADD_PLUGINS: 'false' } }
);
runCLI(

View File

@ -158,7 +158,7 @@ export default defineConfig({
`generate @nx/next:app ${appName} --directory=apps/${appName} --e2eTestRunner=none --no-interactive --projectNameAndRootFormat=as-provided`
);
runCLI(
`generate @nx/next:component btn --project=${appName} --directory=apps/${appName}/components --nameAndDirectoryFormat=as-provided --no-interactive`
`generate @nx/next:component apps/${appName}/components/btn --no-interactive`
);
runCLI(
`generate @nx/next:cypress-component-configuration --project=${appName} --generate-tests --no-interactive`
@ -186,7 +186,7 @@ export default defineConfig({
`generate @nx/angular:app ${appName} --directory=apps/${appName} --e2eTestRunner=none --no-interactive --bundler=webpack`
);
runCLI(
`generate @nx/angular:component btn --directory=apps/${appName}/src/app/btn --no-interactive`
`generate @nx/angular:component apps/${appName}/src/app/btn/btn --no-interactive`
);
runCLI(
`generate @nx/angular:cypress-component-configuration --project=${appName} --generate-tests --no-interactive`

View File

@ -55,7 +55,7 @@ describe('@nx/expo (legacy)', () => {
const componentName = uniq('Component');
runCLI(
`generate @nx/expo:component ${componentName} --directory=libs/${libName}/src/${componentName} --export --no-interactive`
`generate @nx/expo:component libs/${libName}/src/${componentName} --name ${componentName} --export --no-interactive`
);
updateFile(`apps/${appName}/src/app/App.tsx`, (content) => {

View File

@ -121,7 +121,7 @@ function createAppWithCt(appName: string) {
`generate @nx/next:app ${appName} --directory=apps/${appName} --no-interactive --appDir=false --src=false --projectNameAndRootFormat=as-provided`
);
runCLI(
`generate @nx/next:component button --project=${appName} --directory=apps/${appName}/components --nameAndDirectoryFormat=as-provided --no-interactive`
`generate @nx/next:component apps/${appName}/components/button --no-interactive`
);
createFile(
`apps/${appName}/public/data.json`,
@ -191,7 +191,7 @@ function createLibWithCt(libName: string, buildable: boolean) {
);
runCLI(
`generate @nx/next:component button --directory=libs/${libName}/src/lib --export --no-interactive`
`generate @nx/next:component libs/${libName}/src/lib/button --export --no-interactive`
);
updateFile(`libs/${libName}/src/lib/button.tsx`, (content) => {
return `import { useEffect, useState } from 'react';

View File

@ -18,7 +18,7 @@ describe('Next.js Storybook', () => {
`generate @nx/next:app ${appName} --e2eTestRunner=none --project-name-and-root-format=as-provided --no-interactive`
);
runCLI(
`generate @nx/next:component foo --directory=${appName}/components/foo --nameAndDirectoryFormat=as-provided --no-interactive`
`generate @nx/next:component ${appName}/components/foo/foo --no-interactive`
);
});

View File

@ -20,7 +20,7 @@ describe('Nuxt Plugin', () => {
`generate @nx/nuxt:app ${app} --unitTestRunner=vitest --projectNameAndRootFormat=as-provided --e2eTestRunner=cypress`
);
runCLI(
`generate @nx/nuxt:component --directory=${app}/src/components/one --name=one --nameAndDirectoryFormat=as-provided --unitTestRunner=vitest`
`generate @nx/nuxt:component ${app}/src/components/one/one --name=one --unitTestRunner=vitest`
);
});

View File

@ -60,7 +60,7 @@ describe('Nx Plugin', () => {
runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
runCLI(
`generate @nx/plugin:migration --directory=${plugin}/src/migrations/update-${version} --packageVersion=${version} --packageJsonUpdates=false`
`generate @nx/plugin:migration --path=${plugin}/src/migrations/update-${version} --packageVersion=${version} --packageJsonUpdates=false`
);
const lintResults = runCLI(`lint ${plugin}`);
@ -92,7 +92,7 @@ describe('Nx Plugin', () => {
runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
runCLI(
`generate @nx/plugin:generator ${generator} --directory=${plugin}/src/generators/${generator}`
`generate @nx/plugin:generator ${plugin}/src/generators/${generator} --name ${generator}`
);
const lintResults = runCLI(`lint ${plugin}`);
@ -129,7 +129,7 @@ describe('Nx Plugin', () => {
runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
runCLI(
`generate @nx/plugin:executor ${executor} --directory=${plugin}/src/executors/${executor} --includeHasher`
`generate @nx/plugin:executor --name ${executor} --path=${plugin}/src/executors/${executor} --includeHasher`
);
const lintResults = runCLI(`lint ${plugin}`);
@ -178,31 +178,31 @@ describe('Nx Plugin', () => {
runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
runCLI(
`generate @nx/plugin:generator ${goodGenerator} --directory=${plugin}/src/generators/${goodGenerator}`
`generate @nx/plugin:generator --name=${goodGenerator} --path=${plugin}/src/generators/${goodGenerator}`
);
runCLI(
`generate @nx/plugin:generator ${badFactoryPath} --directory=${plugin}/src/generators/${badFactoryPath}`
`generate @nx/plugin:generator --name=${badFactoryPath} --path=${plugin}/src/generators/${badFactoryPath}`
);
runCLI(
`generate @nx/plugin:executor ${goodExecutor} --directory=${plugin}/src/executors/${goodExecutor}`
`generate @nx/plugin:executor --name=${goodExecutor} --path=${plugin}/src/executors/${goodExecutor}`
);
runCLI(
`generate @nx/plugin:executor ${badExecutorBadImplPath} --directory=${plugin}/src/executors/${badExecutorBadImplPath}`
`generate @nx/plugin:executor --name=${badExecutorBadImplPath} --path=${plugin}/src/executors/${badExecutorBadImplPath}`
);
runCLI(
`generate @nx/plugin:migration ${badMigrationVersion} --directory=${plugin} --packageVersion="invalid"`
`generate @nx/plugin:migration --name=${badMigrationVersion} --path=${plugin}/src/migrations --packageVersion="invalid"`
);
runCLI(
`generate @nx/plugin:migration ${missingMigrationVersion} --directory=${plugin}/migrations/0.1.0 --packageVersion="0.1.0"`
`generate @nx/plugin:migration --name=${missingMigrationVersion} --path=${plugin}/migrations/0.1.0 --packageVersion="0.1.0"`
);
runCLI(
`generate @nx/plugin:migration ${goodMigration} --directory=${plugin}/migrations/0.1.0 --packageVersion="0.1.0"`
`generate @nx/plugin:migration --name=${goodMigration} --path=${plugin}/migrations/0.1.0 --packageVersion="0.1.0"`
);
updateFile(`${plugin}/generators.json`, (f) => {
@ -348,11 +348,11 @@ describe('Nx Plugin', () => {
const generatedProject = uniq('project');
runCLI(
`generate @nx/plugin:generator ${generator} --directory=${plugin}/src/generators/${generator}`
`generate @nx/plugin:generator --name ${generator} --path ${plugin}/src/generators/${generator}`
);
runCLI(
`generate @nx/plugin:executor ${executor} --directory=${plugin}/src/executors/${executor}`
`generate @nx/plugin:executor --name ${executor} --path ${plugin}/src/executors/${executor}`
);
updateFile(
@ -389,7 +389,7 @@ describe('Nx Plugin', () => {
expect(() => {
runCLI(
`generate @nx/plugin:generator ${generator} --directory=${plugin}/src/generators/${generator}`
`generate @nx/plugin:generator ${plugin}/src/generators/${generator} --name ${generator}`
);
runCLI(

View File

@ -57,7 +57,7 @@ describe('@nx/react-native (legacy)', () => {
it('should test and lint', async () => {
const componentName = uniq('Component');
runCLI(
`generate @nx/react-native:component ${componentName} --directory=libs/${libName}/src/lib/${componentName} --export --no-interactive`
`generate @nx/react-native:component libs/${libName}/src/lib/${componentName}/${componentName} --export --no-interactive`
);
updateFile(`apps/${appName}/src/app/App.tsx`, (content) => {
@ -189,7 +189,7 @@ describe('@nx/react-native (legacy)', () => {
const componentName = uniq('Component');
runCLI(
`generate @nx/react-native:component ${componentName} --directory=libs/${libName}/src/lib/${componentName} --export`
`generate @nx/react-native:component libs/${libName}/src/lib/${componentName}/${componentName} --export`
);
expect(() => {
runCLI(`build ${libName}`);

View File

@ -43,13 +43,13 @@ describe('React Cypress Component Tests', () => {
}));
runCLI(
`generate @nx/react:component fancy-cmp --directory=apps/${appName}/src/app/fancy-cmp --no-interactive`
`generate @nx/react:component apps/${appName}/src/app/fancy-cmp/fancy-cmp --no-interactive`
);
runCLI(
`generate @nx/react:lib ${usedInAppLibName} --directory=libs/${usedInAppLibName} --no-interactive --unitTestRunner=jest`
);
runCLI(
`generate @nx/react:component btn --directory=libs/${usedInAppLibName}/src/lib/btn --export --no-interactive`
`generate @nx/react:component libs/${usedInAppLibName}/src/lib/btn/btn --export --no-interactive`
);
// makes sure custom webpack is loading
createFile(
@ -111,7 +111,7 @@ export default App;`
`generate @nx/react:lib ${buildableLibName} --directory=libs/${buildableLibName} --buildable --no-interactive --unitTestRunner=jest`
);
runCLI(
`generate @nx/react:component input --directory=libs/${buildableLibName}/src/lib/input --export --no-interactive`
`generate @nx/react:component libs/${buildableLibName}/src/lib/input/input --export --no-interactive`
);
checkFilesExist(`libs/${buildableLibName}/src/lib/input/input.tsx`);

View File

@ -92,14 +92,14 @@ describe('Build React applications and libraries with Vite', () => {
}).toThrow();
runCLI(
`generate @nx/react:component comp1 --inSourceTests --export --directory=libs/${viteLib}/src/lib/comp1 --no-interactive`
`generate @nx/react:component libs/${viteLib}/src/lib/comp1/comp1 --inSourceTests --export --no-interactive`
);
expect(() => {
checkFilesExist(`libs/${viteLib}/src/lib/comp1/comp1.spec.tsx`);
}).toThrow();
runCLI(
`generate @nx/react:component comp2 --export --directory=libs/${viteLib}/src/lib/comp2 --no-interactive`
`generate @nx/react:component libs/${viteLib}/src/lib/comp2/comp2 --export --no-interactive`
);
checkFilesExist(`libs/${viteLib}/src/lib/comp2/comp2.spec.tsx`);

View File

@ -113,7 +113,7 @@ describe('React Applications', () => {
`generate @nx/react:lib ${libName} --directory=libs${libName} --style=css --no-interactive --unit-test-runner=jest --skipFormat`
);
runCLI(
`generate @nx/react:lib ${libWithNoComponents} --directory=libs${libWithNoComponents} --no-interactive --no-component --unit-test-runner=jest --skipFormat`
`generate @nx/react:lib ${libWithNoComponents} --directory=libs/${libWithNoComponents} --no-interactive --no-component --unit-test-runner=jest --skipFormat`
);
// Libs should not include package.json by default
@ -219,13 +219,13 @@ describe('React Applications', () => {
`g @nx/react:app ${appName} --directory=apps/${appName} --bundler=webpack --no-interactive --skipFormat`
);
runCLI(
`g @nx/react:redux lemon --directory=apps/${appName}/src/app/lemon --skipFormat`
`g @nx/react:redux apps/${appName}/src/app/lemon/lemon --skipFormat`
);
runCLI(
`g @nx/react:lib ${libName} --directory=libs/${libName} --unit-test-runner=jest --no-interactive --skipFormat`
);
runCLI(
`g @nx/react:redux orange --directory=libs/${libName}/src/lib/orange --skipFormat`
`g @nx/react:redux libs/${libName}/src/lib/orange/orange --skipFormat`
);
let lintResults = runCLI(`lint ${appName}`);

View File

@ -37,10 +37,10 @@ describe('create-nx-plugin', () => {
);
runCLI(
`generate @nx/plugin:generator ${generatorName} --directory=${pluginName}/src/generators/${generatorName}`
`generate @nx/plugin:generator ${pluginName}/src/generators/${generatorName} --name ${generatorName}`
);
runCLI(
`generate @nx/plugin:executor ${executorName} --directory=${pluginName}/src/executors/${executorName}`
`generate @nx/plugin:executor ${pluginName}/src/executors/${executorName} --name ${executorName}`
);
runCLI(`build ${pluginName}`);

View File

@ -19,7 +19,7 @@ describe('componentStory generator', () => {
await generateTestLibrary(tree, { name: libName, skipFormat: true });
await componentGenerator(tree, {
name: 'test-button',
directory: `${libName}/src/lib/test-button`,
path: `${libName}/src/lib/test-button`,
skipFormat: true,
});

View File

@ -31,7 +31,7 @@ describe('Angular Cypress Component Test Generator', () => {
skipFormat: true,
});
await componentGenerator(tree, {
directory: 'my-lib/src/lib/my-lib',
path: 'my-lib/src/lib/my-lib/my-lib',
name: 'my-lib',
skipFormat: true,
});
@ -55,7 +55,7 @@ describe('Angular Cypress Component Test Generator', () => {
skipFormat: true,
});
await componentGenerator(tree, {
directory: 'my-lib/src/lib/my-lib',
path: 'my-lib/src/lib/my-lib/',
name: 'my-lib',
skipFormat: true,
});
@ -109,7 +109,7 @@ export class MyLibComponent implements OnInit {
skipFormat: true,
});
await componentGenerator(tree, {
directory: 'my-lib/src/lib/my-lib',
path: 'my-lib/src/lib/my-lib',
name: 'my-lib',
standalone: true,
skipFormat: true,
@ -164,7 +164,7 @@ export class MyLibComponent implements OnInit {
await componentGenerator(tree, {
name: 'my-lib',
directory: 'my-lib/src/lib/my-lib',
path: 'my-lib/src/lib/my-lib',
skipFormat: true,
});
tree.write(
@ -195,7 +195,7 @@ export class MyLibComponent implements OnInit {
await componentGenerator(tree, {
name: 'my-lib',
directory: 'my-lib/src/lib/my-lib',
path: 'my-lib/src/lib/my-lib/my-lib',
skipFormat: true,
});

View File

@ -33,8 +33,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
standalone: false,
});
@ -79,8 +78,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
skipTests: true,
standalone: false,
skipFormat: true,
@ -115,8 +113,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
inlineTemplate: true,
standalone: false,
skipFormat: true,
@ -154,8 +151,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
inlineStyle: true,
standalone: false,
skipFormat: true,
@ -193,8 +189,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
style: 'none',
standalone: false,
skipFormat: true,
@ -240,8 +235,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
export: true,
standalone: false,
skipFormat: true,
@ -281,8 +275,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
export: true,
skipFormat: true,
});
@ -323,8 +316,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
export: false,
standalone: false,
skipFormat: true,
@ -366,8 +358,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
export: false,
skipFormat: true,
});
@ -408,8 +399,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
skipImport: true,
standalone: false,
skipFormat: true,
@ -450,8 +440,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
export: true,
standalone: false,
skipFormat: true,
@ -491,8 +480,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
export: true,
standalone: false,
skipFormat: true,
@ -539,8 +527,7 @@ describe('component Generator', () => {
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
module,
export: true,
standalone: false,
@ -582,8 +569,7 @@ export class LibModule {}
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/shared/ui/src/lib/example',
path: 'libs/shared/ui/src/lib/example/example',
export: true,
standalone: false,
skipFormat: true,
@ -631,8 +617,7 @@ export class LibModule {}
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
module: 'not-exported',
export: true,
standalone: false,
@ -669,8 +654,7 @@ export class LibModule {}
// ACT & ASSERT
await expect(
componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
module: 'not-found',
standalone: false,
skipFormat: true,
@ -712,8 +696,7 @@ export class LibModule {}
// ACT & ASSERT
await expect(
componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
standalone: false,
skipFormat: true,
})
@ -734,9 +717,8 @@ export class LibModule {}
it('should use the prefix', async () => {
await componentGenerator(tree, {
name: 'lib1/src/lib/example/example',
path: 'lib1/src/lib/example/example',
prefix: 'foo',
nameAndDirectoryFormat: 'as-provided',
});
const content = tree.read(
@ -749,18 +731,16 @@ export class LibModule {}
it('should error when name starts with a digit', async () => {
await expect(
componentGenerator(tree, {
name: 'lib1/src/lib/1-one/1-one',
path: 'lib1/src/lib/1-one/1-one',
prefix: 'foo',
nameAndDirectoryFormat: 'as-provided',
})
).rejects.toThrow('The selector "foo-1-one" is invalid.');
});
it('should allow dash in selector before a number', async () => {
await componentGenerator(tree, {
name: 'lib1/src/lib/one-1/one-1',
path: 'lib1/src/lib/one-1/one-1',
prefix: 'foo',
nameAndDirectoryFormat: 'as-provided',
});
const content = tree.read(
@ -772,9 +752,8 @@ export class LibModule {}
it('should allow dash in selector before a number and without a prefix', async () => {
await componentGenerator(tree, {
name: 'lib1/src/lib/example/example',
path: 'lib1/src/lib/example/example',
selector: 'one-1',
nameAndDirectoryFormat: 'as-provided',
});
const content = tree.read(
@ -792,8 +771,7 @@ export class LibModule {}
} as AngularProjectConfiguration);
await componentGenerator(tree, {
name: 'lib1/src/lib/example/example',
nameAndDirectoryFormat: 'as-provided',
path: 'lib1/src/lib/example/example',
});
const content = tree.read(
@ -811,8 +789,7 @@ export class LibModule {}
} as AngularProjectConfiguration);
await componentGenerator(tree, {
name: 'lib1/src/lib/example/example',
nameAndDirectoryFormat: 'as-provided',
path: 'lib1/src/lib/example/example',
});
const content = tree.read(
@ -867,8 +844,7 @@ export class LibModule {}
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/secondary/src/lib/example',
path: 'libs/lib1/secondary/src/lib/example/example',
export: true,
standalone: false,
skipFormat: true,
@ -928,8 +904,7 @@ export class LibModule {}
// ACT
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/secondary/src/lib/example',
path: 'libs/lib1/secondary/src/lib/example',
export: true,
standalone: false,
skipFormat: true,
@ -966,8 +941,7 @@ export class LibModule {}
tree.write('libs/lib1/src/index.ts', '');
await componentGenerator(tree, {
name: 'example',
directory: 'libs/lib1/src/lib/example',
path: 'libs/lib1/src/lib/example/example',
inlineStyle: true,
standalone: false,
skipFormat: true,

View File

@ -18,8 +18,7 @@ export async function normalizeOptions(
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(tree, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
suffix: options.type ?? 'component',
});

View File

@ -1,9 +1,6 @@
import type { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface Schema {
name: string;
directory?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
path: string;
name?: string;
displayBlock?: boolean;
inlineStyle?: boolean;
inlineTemplate?: boolean;

View File

@ -7,26 +7,20 @@
"description": "Creates a new Angular component.",
"additionalProperties": false,
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the component.",
"description": "The path at which to create the component file, relative to the workspace root. By default, it is set to the root of the project.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Where to create the component?"
},
"name": {
"type": "string",
"description": "The name of the component.",
"x-prompt": "What name would you like to use for the component?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"prefix": {
"type": "string",
"description": "The prefix to apply to the generated component selector.",
@ -118,6 +112,6 @@
"x-priority": "internal"
}
},
"required": ["name"],
"required": ["path"],
"examplesFile": "../../../docs/component-examples.md"
}

View File

@ -64,7 +64,7 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-cmp',
directory: 'fancy-lib/src/lib/fancy-cmp',
path: 'fancy-lib/src/lib/fancy-cmp/fancy-cmp',
export: true,
skipFormat: true,
});
@ -130,7 +130,7 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-cmp',
directory: 'fancy-lib/src/lib/fancy-cmp/',
path: 'fancy-lib/src/lib/fancy-cmp/fancy-cmp',
export: true,
skipFormat: true,
});
@ -196,7 +196,7 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-cmp',
directory: 'fancy-lib/src/lib/fancy-cmp/',
path: 'fancy-lib/src/lib/fancy-cmp/fancy-cmp/',
export: true,
skipFormat: true,
});
@ -252,7 +252,7 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-cmp',
directory: 'fancy-app/src/lib/fancy-cmp',
path: 'fancy-app/src/lib/fancy-cmp/fancy-cmp',
export: true,
skipFormat: true,
});
@ -300,7 +300,7 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-cmp',
directory: 'fancy-app/src/app/fancy-lib',
path: 'fancy-app/src/app/fancy-lib/fancy-lib',
export: true,
skipFormat: true,
});
@ -424,7 +424,7 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-cmp',
directory: 'fancy-app/src/app/fancy-cmp',
path: 'fancy-app/src/app/fancy-cmp/fancy-cmp',
export: true,
skipFormat: true,
});
@ -695,12 +695,12 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'fancy-button',
directory: 'secondary/src/lib/button/',
path: 'secondary/src/lib/button/fancy-button',
skipFormat: true,
});
await componentGenerator(tree, {
name: 'standalone-fancy-button',
directory: 'secondary/src/lib/button',
path: 'secondary/src/lib/button/standalone-fancy-button',
standalone: true,
skipFormat: true,
});
@ -815,12 +815,12 @@ describe('Cypress Component Testing Configuration', () => {
});
await componentGenerator(tree, {
name: 'cmp-one',
directory: 'multiple-components/src/lib',
path: 'multiple-components/src/lib/cmp-one',
skipFormat: true,
});
await componentGenerator(tree, {
name: 'cmp-two',
directory: 'multiple-components/src/lib',
path: 'multiple-components/src/lib/cmp-two',
skipFormat: true,
});
tree.write(
@ -908,7 +908,7 @@ async function setup(
`${options.name}-three`,
]) {
await componentGenerator(tree, {
directory: `${options.project}/src/lib/${name}`,
path: `${options.project}/src/lib/${name}/${name}`,
name,
skipFormat: true,
});

View File

@ -53,7 +53,7 @@ describe('directive generator', () => {
// ACT
await generateDirectiveWithDefaultOptions(tree, {
directory: 'test/src/app/my-directives/test',
path: 'test/src/app/my-directives/test',
skipTests: true,
});
@ -114,7 +114,7 @@ describe('directive generator', () => {
// ACT
await generateDirectiveWithDefaultOptions(tree, {
directory: 'test/src/app/my-directives/test',
path: 'test/src/app/my-directives/test/test',
standalone: false,
});
@ -138,7 +138,7 @@ describe('directive generator', () => {
// ACT
await generateDirectiveWithDefaultOptions(tree, {
directory: 'test/src/app/my-directives/test',
path: 'test/src/app/my-directives/test/test',
export: true,
standalone: false,
});
@ -154,7 +154,7 @@ describe('directive generator', () => {
// ACT
await generateDirectiveWithDefaultOptions(tree, {
directory: 'test/src/app/my-directives',
path: 'test/src/app/my-directives',
skipImport: true,
standalone: false,
});
@ -169,9 +169,9 @@ describe('directive generator', () => {
describe('prefix & selector', () => {
it('should use the prefix', async () => {
await directiveGenerator(tree, {
name: 'test/src/app/example/example',
path: 'test/src/app/example/example',
name: 'example',
prefix: 'foo',
nameAndDirectoryFormat: 'as-provided',
});
const content = tree.read(
@ -189,8 +189,8 @@ describe('directive generator', () => {
} as AngularProjectConfiguration);
await directiveGenerator(tree, {
name: 'test/src/app/example/example',
nameAndDirectoryFormat: 'as-provided',
path: 'test/src/app/example/example',
name: 'example',
});
const content = tree.read(
@ -208,8 +208,8 @@ describe('directive generator', () => {
} as AngularProjectConfiguration);
await directiveGenerator(tree, {
name: 'test/src/app/example/example',
nameAndDirectoryFormat: 'as-provided',
path: 'test/src/app/example/example',
name: 'example',
});
const content = tree.read(
@ -221,9 +221,9 @@ describe('directive generator', () => {
it('should use provided selector as is', async () => {
await directiveGenerator(tree, {
name: 'test/src/app/example/example',
path: 'test/src/app/example/example',
name: 'example',
selector: 'mySelector',
nameAndDirectoryFormat: 'as-provided',
});
const content = tree.read(
@ -255,7 +255,7 @@ async function generateDirectiveWithDefaultOptions(
) {
await directiveGenerator(tree, {
name: 'test',
directory: 'test/src/app',
path: 'test/src/app/test',
skipFormat: true,
...overrides,
});

View File

@ -17,8 +17,7 @@ export async function normalizeOptions(
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(tree, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
suffix: 'directive',
});

View File

@ -1,9 +1,8 @@
import { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface Schema {
name: string;
directory?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
path: string;
name?: string;
prefix?: string;
skipTests?: boolean;
skipImport?: boolean;

View File

@ -7,26 +7,20 @@
"description": "Creates a new Angular directive.",
"additionalProperties": false,
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the new directive.",
"description": "The path at which to create the directive file.",
"x-prompt": "Where to put the directive?",
"$default": {
"$source": "argv",
"index": 0
},
}
},
"name": {
"type": "string",
"description": "The name of the new directive.",
"x-prompt": "What name would you like to use for the directive?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the directive file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the directive in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"prefix": {
"type": "string",
"description": "A prefix to apply to generated selectors.",
@ -77,5 +71,5 @@
"description": "Skip formatting of files."
}
},
"required": ["name"]
"required": ["path"]
}

View File

@ -11,13 +11,14 @@ export async function addStandaloneComponent(
await componentGenerator(tree, {
...componentOptions,
name: componentOptions.name,
directory: joinPathFragments(
path: joinPathFragments(
libraryOptions.projectRoot,
'src',
'lib',
componentOptions.flat ? '' : componentOptions.name
componentOptions.flat
? `${componentOptions.name}`
: `${componentOptions.name}/${componentOptions.name}`
),
nameAndDirectoryFormat: 'as-provided',
standalone: true,
export: true,
skipFormat: true,

View File

@ -15,8 +15,7 @@ export async function normalizeOptions(
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(tree, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
suffix: 'pipe',
});

View File

@ -43,7 +43,7 @@ describe('pipe generator', () => {
it('should not generate test file when skipTests=true', async () => {
// ACT
await generatePipeWithDefaultOptions(tree, {
directory: 'test/src/app/my-pipes/test',
path: 'test/src/app/my-pipes/test',
skipTests: true,
});
@ -82,7 +82,7 @@ describe('pipe generator', () => {
// ACT
await generatePipeWithDefaultOptions(tree, {
directory: 'test/src/app/test',
path: 'test/src/app/test/test',
standalone: false,
});
@ -103,7 +103,7 @@ describe('pipe generator', () => {
// ACT
await generatePipeWithDefaultOptions(tree, {
directory: 'test/src/app/my-pipes/test',
path: 'test/src/app/my-pipes/test/test',
standalone: false,
});
@ -124,7 +124,7 @@ describe('pipe generator', () => {
// ACT
await generatePipeWithDefaultOptions(tree, {
directory: 'test/src/app/my-pipes/test',
path: 'test/src/app/my-pipes/test/test',
export: true,
standalone: false,
});
@ -140,7 +140,7 @@ describe('pipe generator', () => {
// ACT
await generatePipeWithDefaultOptions(tree, {
directory: 'test/src/app/my-pipes/test',
path: 'test/src/app/my-pipes/test/test',
skipImport: true,
standalone: false,
});
@ -173,7 +173,7 @@ async function generatePipeWithDefaultOptions(
) {
await pipeGenerator(tree, {
name: 'test',
directory: 'test/src/app',
path: 'test/src/app/test',
skipFormat: true,
...overrides,
});

View File

@ -1,9 +1,8 @@
import { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface Schema {
name: string;
directory?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
path: string;
name?: string;
skipTests?: boolean;
skipImport?: boolean;
standalone?: boolean;

View File

@ -7,35 +7,20 @@
"additionalProperties": false,
"description": "Creates an Angular pipe.",
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the pipe.",
"description": "The path at which to create the pipe file, relative to the workspace root.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "What is the path of the new pipe?"
},
"name": {
"type": "string",
"description": "The name of the pipe.",
"x-prompt": "What name would you like to use for the pipe?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the pipe file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the pipe in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": {
"$source": "projectName"
},
"x-dropdown": "projects",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"skipTests": {
"type": "boolean",
"description": "Do not create \"spec.ts\" test files for the new pipe.",
@ -67,5 +52,5 @@
"description": "Skip formatting of files."
}
},
"required": ["name"]
"required": ["path"]
}

View File

@ -15,7 +15,7 @@ describe('convertDirectiveToScam', () => {
await directiveGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
skipImport: true,
export: false,
standalone: false,
@ -24,6 +24,7 @@ describe('convertDirectiveToScam', () => {
// ACT
convertDirectiveToScam(tree, {
path: 'apps/app1/src/app/example/example',
directory: 'apps/app1/src/app/example',
fileName: 'example.directive',
filePath: 'apps/app1/src/app/example/example.directive.ts',
@ -71,7 +72,7 @@ describe('convertDirectiveToScam', () => {
await directiveGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
skipImport: true,
export: false,
standalone: false,
@ -80,6 +81,7 @@ describe('convertDirectiveToScam', () => {
// ACT
convertDirectiveToScam(tree, {
path: 'apps/app1/src/app/example/example',
directory: 'apps/app1/src/app/example',
fileName: 'example.directive',
filePath: 'apps/app1/src/app/example/example.directive.ts',

View File

@ -15,8 +15,7 @@ export async function normalizeOptions(
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(tree, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
suffix: 'directive',
});

View File

@ -15,7 +15,7 @@ describe('SCAM Directive Generator', () => {
// ACT
await scamDirectiveGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app',
path: 'apps/app1/src/app/example',
inlineScam: true,
skipFormat: true,
});
@ -58,7 +58,7 @@ describe('SCAM Directive Generator', () => {
// ACT
await scamDirectiveGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app',
path: 'apps/app1/src/app/example',
inlineScam: false,
skipFormat: true,
});
@ -99,7 +99,7 @@ describe('SCAM Directive Generator', () => {
// ACT
await scamDirectiveGenerator(tree, {
name: 'example',
directory: 'libs/lib1/feature/src/lib/example',
path: 'libs/lib1/feature/src/lib/example/example',
inlineScam: false,
export: true,
skipFormat: true,
@ -146,7 +146,7 @@ describe('SCAM Directive Generator', () => {
// ACT
await scamDirectiveGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/random/example',
path: 'apps/app1/src/app/random/example/example',
inlineScam: true,
skipFormat: true,
});
@ -189,7 +189,7 @@ describe('SCAM Directive Generator', () => {
// ACT
await scamDirectiveGenerator(tree, {
name: 'example',
directory: '/apps/app1/src/app/random/example',
path: '/apps/app1/src/app/random/example/example',
inlineScam: true,
skipFormat: true,
});
@ -233,7 +233,7 @@ describe('SCAM Directive Generator', () => {
expect(
scamDirectiveGenerator(tree, {
name: 'example',
directory: 'libs/proj/src/lib/random/example',
path: 'libs/proj/src/lib/random/example/example',
inlineScam: true,
skipFormat: true,
})

View File

@ -13,8 +13,6 @@ export async function scamDirectiveGenerator(tree: Tree, rawOptions: Schema) {
export: false,
standalone: false,
skipFormat: true,
// options are already normalize, use them as is
nameAndDirectoryFormat: 'as-provided',
});
convertDirectiveToScam(tree, options);

View File

@ -1,9 +1,8 @@
import { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface Schema {
name: string;
directory?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
path: string;
name?: string;
skipTests?: boolean;
inlineScam?: boolean;
prefix?: string;
@ -13,6 +12,7 @@ export interface Schema {
}
export interface NormalizedSchema extends Schema {
name: string;
directory: string;
export: boolean;
fileName: string;

View File

@ -13,13 +13,18 @@
"description": "Creates a new, generic Angular directive definition in the given or default project.",
"additionalProperties": false,
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the directive.",
"description": "The path at which to create the SCAM Directive files, relative to the workspace root.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "What is the path of the new directive?"
},
"name": {
"type": "string",
"description": "The name of the directive.",
"x-prompt": "What name would you like to use for the directive?",
"x-priority": "important"
},
@ -92,5 +97,5 @@
"x-priority": "internal"
}
},
"required": ["name"]
"required": ["path"]
}

View File

@ -15,7 +15,7 @@ describe('convertPipeToScam', () => {
await pipeGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
skipImport: true,
export: false,
standalone: false,
@ -24,6 +24,7 @@ describe('convertPipeToScam', () => {
// ACT
convertPipeToScam(tree, {
path: 'apps/app1/src/app/example/example',
directory: 'apps/app1/src/app/example',
fileName: 'example.pipe',
filePath: 'apps/app1/src/app/example/example.pipe.ts',
@ -73,7 +74,7 @@ describe('convertPipeToScam', () => {
await pipeGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
skipImport: true,
export: false,
skipFormat: true,
@ -81,6 +82,7 @@ describe('convertPipeToScam', () => {
// ACT
convertPipeToScam(tree, {
path: 'apps/app1/src/app/example/example',
directory: 'apps/app1/src/app/example',
fileName: 'example.pipe',
filePath: 'apps/app1/src/app/example/example.pipe.ts',

View File

@ -15,8 +15,7 @@ export async function normalizeOptions(
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(tree, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
suffix: 'pipe',
});

View File

@ -15,7 +15,7 @@ describe('SCAM Pipe Generator', () => {
// ACT
await scamPipeGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
inlineScam: true,
skipFormat: true,
});
@ -60,7 +60,7 @@ describe('SCAM Pipe Generator', () => {
// ACT
await scamPipeGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
inlineScam: false,
skipFormat: true,
});
@ -101,7 +101,7 @@ describe('SCAM Pipe Generator', () => {
// ACT
await scamPipeGenerator(tree, {
name: 'example',
directory: 'libs/lib1/feature/src/lib/example',
path: 'libs/lib1/feature/src/lib/example/example',
inlineScam: false,
export: true,
skipFormat: true,
@ -148,7 +148,7 @@ describe('SCAM Pipe Generator', () => {
// ACT
await scamPipeGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/random/example',
path: 'apps/app1/src/app/random/example/example',
inlineScam: true,
skipFormat: true,
});
@ -193,7 +193,7 @@ describe('SCAM Pipe Generator', () => {
// ACT
await scamPipeGenerator(tree, {
name: 'example',
directory: '/apps/app1/src/app/random/example',
path: '/apps/app1/src/app/random/example/example',
inlineScam: true,
skipFormat: true,
});
@ -239,7 +239,7 @@ describe('SCAM Pipe Generator', () => {
expect(
scamPipeGenerator(tree, {
name: 'example',
directory: 'libs/proj/src/lib/random/example',
path: 'libs/proj/src/lib/random/example/example',
inlineScam: true,
skipFormat: true,
})

View File

@ -13,8 +13,6 @@ export async function scamPipeGenerator(tree: Tree, rawOptions: Schema) {
export: false,
standalone: false,
skipFormat: true,
// options are already normalize, use them as is
nameAndDirectoryFormat: 'as-provided',
});
convertPipeToScam(tree, options);

View File

@ -1,9 +1,8 @@
import { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface Schema {
name: string;
directory?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
path: string;
name?: string;
skipTests?: boolean;
inlineScam?: boolean;
export?: boolean;
@ -11,6 +10,7 @@ export interface Schema {
}
export interface NormalizedSchema extends Schema {
name: string;
directory: string;
export: boolean;
fileName: string;

View File

@ -6,43 +6,28 @@
"type": "object",
"examples": [
{
"command": "nx g @nx/angular:scam-pipe --project=my-lib --flat=false my-transformation",
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/my-transformation/my-transformation",
"description": "Generates a `MyTransformationPipe` in a `my-transformation` folder in the `my-lib` project"
}
],
"description": "Creates a new, generic Angular pipe definition in the given or default project.",
"additionalProperties": false,
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the pipe.",
"description": "The path at which to create the pipe file, relative to the workspace root.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "What is the path of the new pipe?"
},
"name": {
"type": "string",
"description": "The name of the pipe.",
"x-prompt": "What name would you like to use for the pipe?",
"x-priority": "important"
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": {
"$source": "projectName"
},
"x-dropdown": "projects",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"skipTests": {
"type": "boolean",
"description": "Do not create `spec.ts` test files for the new pipe.",
@ -73,5 +58,5 @@
"x-priority": "internal"
}
},
"required": ["name"]
"required": ["path"]
}

View File

@ -11,7 +11,7 @@ describe('scam-to-standalone', () => {
await generateTestApplication(tree, { name: 'foo', skipFormat: true });
await scamGenerator(tree, {
name: 'bar',
directory: 'foo/src/app/bar',
path: 'foo/src/app/bar/bar',
skipFormat: true,
});

View File

@ -15,7 +15,7 @@ describe('convertComponentToScam', () => {
await componentGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
skipImport: true,
export: false,
standalone: false,
@ -24,6 +24,7 @@ describe('convertComponentToScam', () => {
// ACT
convertComponentToScam(tree, {
path: 'apps/app1/src/app/example/example',
directory: 'apps/app1/src/app/example',
fileName: 'example.component',
filePath: 'apps/app1/src/app/example/example.component.ts',
@ -71,7 +72,7 @@ describe('convertComponentToScam', () => {
await componentGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
skipImport: true,
export: false,
standalone: false,
@ -80,6 +81,7 @@ describe('convertComponentToScam', () => {
// ACT
convertComponentToScam(tree, {
path: 'apps/app1/src/app/example/example',
directory: 'apps/app1/src/app/example',
fileName: 'example.component',
filePath: 'apps/app1/src/app/example/example.component.ts',
@ -121,7 +123,7 @@ describe('convertComponentToScam', () => {
await componentGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app',
path: 'apps/app1/src/app/example',
skipImport: true,
export: false,
type: 'random',
@ -131,6 +133,7 @@ describe('convertComponentToScam', () => {
// ACT
convertComponentToScam(tree, {
path: 'apps/app1/src/app/example',
directory: 'apps/app1/src/app',
fileName: 'example.random',
filePath: 'apps/app1/src/app/example.random.ts',
@ -179,7 +182,7 @@ describe('convertComponentToScam', () => {
await componentGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app',
path: 'apps/app1/src/app/example',
skipImport: true,
export: false,
type: 'random',
@ -189,6 +192,7 @@ describe('convertComponentToScam', () => {
// ACT
convertComponentToScam(tree, {
path: 'apps/app1/src/app/example',
directory: 'apps/app1/src/app',
fileName: 'example.random',
filePath: 'apps/app1/src/app/example.random.ts',

View File

@ -16,8 +16,7 @@ export async function normalizeOptions(
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(tree, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
suffix: options.type ?? 'component',
});

View File

@ -15,7 +15,7 @@ describe('SCAM Generator', () => {
// ACT
await scamGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
inlineScam: true,
skipFormat: true,
});
@ -58,7 +58,7 @@ describe('SCAM Generator', () => {
// ACT
await scamGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/example',
path: 'apps/app1/src/app/example/example',
inlineScam: false,
skipFormat: true,
});
@ -99,7 +99,7 @@ describe('SCAM Generator', () => {
// ACT
await scamGenerator(tree, {
name: 'example',
directory: 'libs/lib1/feature/src/lib/example',
path: 'libs/lib1/feature/src/lib/example/example',
inlineScam: false,
export: true,
skipFormat: true,
@ -146,7 +146,7 @@ describe('SCAM Generator', () => {
// ACT
await scamGenerator(tree, {
name: 'example',
directory: 'apps/app1/src/app/random/example',
path: 'apps/app1/src/app/random/example/example',
inlineScam: true,
skipFormat: true,
});
@ -189,7 +189,7 @@ describe('SCAM Generator', () => {
// ACT
await scamGenerator(tree, {
name: 'example',
directory: '/apps/app1/src/app/random/example',
path: '/apps/app1/src/app/random/example/example',
inlineScam: true,
skipFormat: true,
});
@ -233,7 +233,7 @@ describe('SCAM Generator', () => {
expect(
scamGenerator(tree, {
name: 'example',
directory: 'libs/proj/src/lib/random/example',
path: 'libs/proj/src/lib/random/example/example',
inlineScam: true,
skipFormat: true,
})

View File

@ -13,8 +13,6 @@ export async function scamGenerator(tree: Tree, rawOptions: Schema) {
export: false,
standalone: false,
skipFormat: true,
// options are already normalize, use them as is
nameAndDirectoryFormat: 'as-provided',
});
convertComponentToScam(tree, options);

View File

@ -1,9 +1,8 @@
import { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface Schema {
name: string;
directory?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
path: string;
name?: string;
displayBlock?: boolean;
inlineStyle?: boolean;
inlineTemplate?: boolean;
@ -21,6 +20,7 @@ export interface Schema {
}
export interface NormalizedSchema extends Schema {
name: string;
directory: string;
projectName: string;
fileName: string;

View File

@ -6,42 +6,27 @@
"type": "object",
"examples": [
{
"command": "nx g @nx/angular:scam my-sample --directory=my-lib/src/lib/my-sample",
"command": "nx g @nx/angular:scam my-lib/src/lib/my-sample/my-sample",
"description": "Generate a `MySampleComponent` component in the `my-lib` library."
}
],
"description": "Creates a new Angular SCAM.",
"additionalProperties": false,
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the component.",
"description": "The path at which to create the SCAM file, relative to the workspace root.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "What is the path of the new SCAM?"
},
"name": {
"type": "string",
"description": "The name of the component.",
"x-prompt": "What name would you like to use for the component?"
},
"directory": {
"type": "string",
"description": "The directory at which to create the SCAM files. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.",
"aliases": ["dir", "path"],
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the SCAM in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": {
"$source": "projectName"
},
"x-dropdown": "projects",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"displayBlock": {
"description": "Specifies if the style will contain `:host { display: block; }`.",
"type": "boolean",
@ -132,5 +117,5 @@
"x-priority": "internal"
}
},
"required": ["name"]
"required": ["path"]
}

View File

@ -31,7 +31,7 @@ describe('angularStories generator: applications', () => {
it('should generate stories file for scam component', async () => {
await scamGenerator(tree, {
name: 'my-scam',
directory: `${appName}/src/app/my-scam`,
path: `${appName}/src/app/my-scam/my-scam`,
skipFormat: true,
});
@ -45,7 +45,7 @@ describe('angularStories generator: applications', () => {
it('should ignore paths', async () => {
await scamGenerator(tree, {
name: 'my-scam',
directory: `${appName}/src/app/my-scam`,
path: `${appName}/src/app/my-scam/my-scam`,
skipFormat: true,
});
@ -63,7 +63,7 @@ describe('angularStories generator: applications', () => {
it('should ignore paths when full path to component is provided', async () => {
await scamGenerator(tree, {
name: 'my-scam',
directory: `${appName}/src/app/my-scam`,
path: `${appName}/src/app/my-scam/my-scam`,
skipFormat: true,
});
@ -81,12 +81,12 @@ describe('angularStories generator: applications', () => {
it('should ignore a path that has a nested component, but still generate nested component stories', async () => {
await componentGenerator(tree, {
name: 'component-a',
directory: `${appName}/src/app/component-a`,
path: `${appName}/src/app/component-a/component-a`,
skipFormat: true,
});
await componentGenerator(tree, {
name: 'component-b',
directory: `${appName}/src/app/component-a/component-b`,
path: `${appName}/src/app/component-a/component-b/component-b`,
skipFormat: true,
});
@ -136,7 +136,7 @@ describe('angularStories generator: applications', () => {
);
await componentGenerator(tree, {
name: 'component',
directory: `${appName}/src/app/component`,
path: `${appName}/src/app/component/component`,
skipFormat: true,
});
@ -160,7 +160,7 @@ describe('angularStories generator: applications', () => {
it('should generate stories file for inline scam component', async () => {
await scamGenerator(tree, {
name: 'my-scam',
directory: `${appName}/src/app/my-scam`,
path: `${appName}/src/app/my-scam/my-scam`,
inlineScam: true,
skipFormat: true,
});

View File

@ -51,7 +51,7 @@ describe('angularStories generator: libraries', () => {
// add a standalone component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-button',
directory: `${libName}/secondary-entry-point/src/lib/secondary-button`,
path: `${libName}/secondary-entry-point/src/lib/secondary-button/secondary-button`,
skipFormat: true,
});
@ -167,7 +167,7 @@ describe('angularStories generator: libraries', () => {
it('should generate stories file for scam component', async () => {
await scamGenerator(tree, {
name: 'my-scam',
directory: `${libName}/src/lib/my-scam`,
path: `${libName}/src/lib/my-scam/my-scam`,
skipFormat: true,
});
@ -181,7 +181,7 @@ describe('angularStories generator: libraries', () => {
it('should generate stories file for inline scam component', async () => {
await scamGenerator(tree, {
name: 'my-scam',
directory: `${libName}/src/lib/my-scam`,
path: `${libName}/src/lib/my-scam/my-scam`,
inlineScam: true,
skipFormat: true,
});
@ -197,7 +197,7 @@ describe('angularStories generator: libraries', () => {
// add standalone component
await componentGenerator(tree, {
name: 'standalone',
directory: `${libName}/src/lib/standalone`,
path: `${libName}/src/lib/standalone/standalone`,
standalone: true,
skipFormat: true,
});
@ -211,7 +211,7 @@ describe('angularStories generator: libraries', () => {
// add a standalone component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-standalone',
directory: `${libName}/secondary-entry-point/src/lib/secondary-standalone`,
path: `${libName}/secondary-entry-point/src/lib/secondary-standalone/secondary-standalone`,
standalone: true,
skipFormat: true,
});
@ -253,7 +253,7 @@ describe('angularStories generator: libraries', () => {
// add a standalone component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-button',
directory: `${libName}/secondary-entry-point/src/lib/secondary-button`,
path: `${libName}/secondary-entry-point/src/lib/secondary-button/seconday-button`,
skipFormat: true,
});

View File

@ -109,7 +109,7 @@ describe('StorybookConfiguration generator', () => {
// add standalone component
await componentGenerator(tree, {
name: 'standalone',
directory: `${libName}/src/lib/standalone`,
path: `${libName}/src/lib/standalone/standalone`,
standalone: true,
skipFormat: true,
});
@ -123,14 +123,14 @@ describe('StorybookConfiguration generator', () => {
// add a regular component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-button',
directory: `${libName}/secondary-entry-point/src/lib/secondary-button`,
path: `${libName}/secondary-entry-point/src/lib/secondary-button/secondary-button`,
export: true,
skipFormat: true,
});
// add a standalone component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-standalone',
directory: `${libName}/secondary-entry-point/src/lib/secondary-standalone`,
path: `${libName}/secondary-entry-point/src/lib/secondary-standalone/secondary-standalone`,
standalone: true,
export: true,
skipFormat: true,
@ -149,7 +149,7 @@ describe('StorybookConfiguration generator', () => {
// add standalone component
await componentGenerator(tree, {
name: 'standalone',
directory: `${libName}/src/lib/standalone`,
path: `${libName}/src/lib/standalone/standalone`,
standalone: true,
skipFormat: true,
});
@ -163,14 +163,14 @@ describe('StorybookConfiguration generator', () => {
// add a regular component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-button',
directory: `${libName}/secondary-entry-point/src/lib/secondary-button`,
path: `${libName}/secondary-entry-point/src/lib/secondary-button/secondary-button`,
export: true,
skipFormat: true,
});
// add a standalone component to the secondary entrypoint
await componentGenerator(tree, {
name: 'secondary-standalone',
directory: `${libName}/secondary-entry-point/src/lib/secondary-standalone`,
path: `${libName}/secondary-entry-point/src/lib/secondary-standalone/secondary-standalone`,
standalone: true,
export: true,
skipFormat: true,

View File

@ -71,7 +71,7 @@ export async function createStorybookTestWorkspaceForLib(
await componentGenerator(tree, {
name: 'test-button',
directory: `${libName}/src/lib/test-button`,
path: `${libName}/src/lib/test-button/test-button`,
standalone: false,
skipFormat: true,
});
@ -115,7 +115,7 @@ export class TestButtonComponent {
await componentGenerator(tree, {
name: 'barrel-button',
directory: `${libName}/src/lib/barrel/barrel-button`,
path: `${libName}/src/lib/barrel/barrel-button/barrel-button`,
module: 'barrel',
standalone: false,
skipFormat: true,
@ -147,7 +147,7 @@ export class BarrelModule {}`
await componentGenerator(tree, {
name: 'variable-declare-button',
directory: `${libName}/src/lib/variable-declare/variable-declare-button`,
path: `${libName}/src/lib/variable-declare/variable-declare-button/variable-declare-button`,
module: 'variable-declare',
standalone: false,
skipFormat: true,
@ -155,7 +155,7 @@ export class BarrelModule {}`
await componentGenerator(tree, {
name: 'variable-declare-view',
directory: `${libName}/src/lib/variable-declare/variable-declare-view`,
path: `${libName}/src/lib/variable-declare/variable-declare-view/variable-declare-view`,
module: 'variable-declare',
standalone: false,
skipFormat: true,
@ -189,7 +189,7 @@ export class VariableDeclareModule {}`
await componentGenerator(tree, {
name: 'variable-spread-declare-button',
directory: `${libName}/src/lib/variable-spread-declare/variable-spread-declare-button`,
path: `${libName}/src/lib/variable-spread-declare/variable-spread-declare-button/variable-spread-declare-button`,
module: 'variable-spread-declare',
standalone: false,
skipFormat: true,
@ -197,7 +197,7 @@ export class VariableDeclareModule {}`
await componentGenerator(tree, {
name: 'variable-spread-declare-view',
directory: `${libName}/src/lib/variable-spread-declare/variable-spread-declare-view`,
path: `${libName}/src/lib/variable-spread-declare/variable-spread-declare-view/variable-spread-declare-view`,
module: 'variable-spread-declare',
standalone: false,
skipFormat: true,
@ -205,7 +205,7 @@ export class VariableDeclareModule {}`
await componentGenerator(tree, {
name: 'variable-spread-declare-anotherview',
directory: `${libName}/src/lib/variable-spread-declare/variable-spread-declare-anotherview`,
path: `${libName}/src/lib/variable-spread-declare/variable-spread-declare-anotherview/variable-spread-declare-anotherview`,
module: 'variable-spread-declare',
standalone: false,
skipFormat: true,
@ -239,7 +239,7 @@ export class VariableSpreadDeclareModule {}`
await componentGenerator(tree, {
name: 'cmp1',
directory: `${libName}/src/lib/static-member-declarations/cmp1`,
path: `${libName}/src/lib/static-member-declarations/cmp1/cmp1`,
module: 'static-member-declarations',
standalone: false,
skipFormat: true,
@ -247,7 +247,7 @@ export class VariableSpreadDeclareModule {}`
await componentGenerator(tree, {
name: 'cmp2',
directory: `${libName}/src/lib/static-member-declarations/cmp2`,
path: `${libName}/src/lib/static-member-declarations/cmp2/cmp2`,
module: 'static-member-declarations',
standalone: false,
skipFormat: true,
@ -280,14 +280,14 @@ export class StaticMemberDeclarationsModule {
await componentGenerator(tree, {
name: 'nested-button',
module: 'nested',
directory: `${libName}/src/lib/nested/nested-button`,
path: `${libName}/src/lib/nested/nested-button/nested-button`,
standalone: false,
skipFormat: true,
});
await componentGenerator(tree, {
name: 'test-other',
directory: `${libName}/src/lib/test-other`,
path: `${libName}/src/lib/test-other/test-other`,
standalone: false,
skipFormat: true,
});

View File

@ -35,213 +35,173 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
await expect(
determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
path: 'myComponent',
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"The current working directory "some/path" does not exist under any project root. Please make sure to navigate to a location or provide a directory that exists under a project root."`
`"The provided directory resolved relative to the current working directory "some/path" does not exist under any project root. Please make sure to navigate to a location or provide a directory that exists under a project root."`
);
restoreCwd();
});
it('should throw when receiving a path as the name and a directory', async () => {
it('should return options as provided when there is a project at the cwd', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
setCwd('apps/app1');
const result = await determineArtifactNameAndDirectoryOptions(tree, {
path: 'apps/app1/myComponent',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
});
restoreCwd();
});
it('should not duplicate the cwd when the provided directory starts with the cwd and format is "as-provided"', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
setCwd('apps/app1');
const result = await determineArtifactNameAndDirectoryOptions(tree, {
path: 'apps/app1/myComponent',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
});
restoreCwd();
});
it('should return the options as provided when directory is provided', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
await expect(
determineArtifactNameAndDirectoryOptions(tree, {
name: 'apps/app1/foo/bar/myComponent',
directory: 'foo/bar',
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"You can't specify both a directory (foo/bar) and a name with a directory path (apps/app1/foo/bar/myComponent). Please specify either a directory or a name with a directory path."`
);
const result = await determineArtifactNameAndDirectoryOptions(tree, {
path: 'apps/app1/myComponent',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
});
});
describe('as-provided', () => {
it('should return options as provided when there is a project at the cwd', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
setCwd('apps/app1');
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
restoreCwd();
it(`should handle window's style paths correctly`, async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
it('should not duplicate the cwd when the provided directory starts with the cwd and format is "as-provided"', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
setCwd('apps/app1');
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
directory: 'apps/app1',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
restoreCwd();
const result = await determineArtifactNameAndDirectoryOptions(tree, {
path: 'apps\\app1\\myComponent',
});
it('should return the options as provided when directory is provided', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
});
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
directory: 'apps/app1',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
it('should support receiving a path as the name', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
it(`should handle window's style paths correctly`, async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
directory: 'apps\\app1',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
path: 'apps/app1/foo/bar/myComponent',
});
it('should support receiving a path as the name', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1/foo/bar',
fileName: 'myComponent',
filePath: 'apps/app1/foo/bar/myComponent.ts',
project: 'app1',
});
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'apps/app1/foo/bar/myComponent',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1/foo/bar',
fileName: 'myComponent',
filePath: 'apps/app1/foo/bar/myComponent.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
it('should support receiving a suffix', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
it('should support receiving a suffix', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
suffix: 'component',
directory: 'apps/app1',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent.component',
filePath: 'apps/app1/myComponent.component.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
suffix: 'component',
path: 'apps/app1/myComponent',
});
it('should support receiving a fileName', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent.component',
filePath: 'apps/app1/myComponent.component.ts',
project: 'app1',
});
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
fileName: 'myComponent.component',
directory: 'apps/app1',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent.component',
filePath: 'apps/app1/myComponent.component.ts',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
it('should support receiving a fileName', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
it('should support receiving a different file extension', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
fileName: 'myComponent.component',
path: 'apps/app1/myComponent',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
name: 'myComponent',
fileExtension: 'tsx',
directory: 'apps/app1',
nameAndDirectoryFormat: 'as-provided',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent.component',
filePath: 'apps/app1/myComponent.component.ts',
project: 'app1',
});
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.tsx',
project: 'app1',
nameAndDirectoryFormat: 'as-provided',
});
it('should support receiving a different file extension', async () => {
addProjectConfiguration(tree, 'app1', {
root: 'apps/app1',
projectType: 'application',
});
const result = await determineArtifactNameAndDirectoryOptions(tree, {
fileExtension: 'tsx',
path: 'apps/app1/myComponent',
});
expect(result).toStrictEqual({
artifactName: 'myComponent',
directory: 'apps/app1',
fileName: 'myComponent',
filePath: 'apps/app1/myComponent.tsx',
project: 'app1',
});
});
});

View File

@ -12,15 +12,11 @@ import {
} from 'nx/src/devkit-internals';
import { join, relative } from 'path';
// TODO(leo): remove in a follow up
export type NameAndDirectoryFormat = 'as-provided';
export type ArtifactGenerationOptions = {
name: string;
directory?: string;
path: string;
name?: string;
fileExtension?: 'js' | 'jsx' | 'ts' | 'tsx' | 'vue';
fileName?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
suffix?: string;
};
@ -50,115 +46,59 @@ export type NameAndDirectoryOptions = {
export async function determineArtifactNameAndDirectoryOptions(
tree: Tree,
options: ArtifactGenerationOptions
): Promise<
NameAndDirectoryOptions & {
// TODO(leo): remove in a follow up
nameAndDirectoryFormat: NameAndDirectoryFormat;
}
> {
const nameAndDirectoryOptions = getNameAndDirectoryOptions(tree, options);
): Promise<NameAndDirectoryOptions> {
const normalizedOptions = getNameAndDirectoryOptions(tree, options);
validateResolvedProject(
tree,
nameAndDirectoryOptions.project,
options,
nameAndDirectoryOptions.directory
normalizedOptions.project,
normalizedOptions.directory
);
return {
...nameAndDirectoryOptions,
nameAndDirectoryFormat: 'as-provided',
};
return normalizedOptions;
}
function getNameAndDirectoryOptions(
tree: Tree,
options: ArtifactGenerationOptions
): NameAndDirectoryOptions {
const directory = options.directory
? normalizePath(options.directory.replace(/^\.?\//, ''))
) {
const path = options.path
? normalizePath(options.path.replace(/^\.?\//, ''))
: undefined;
const fileExtension = options.fileExtension ?? 'ts';
const { name: extractedName, directory: extractedDirectory } =
extractNameAndDirectoryFromName(options.name);
if (extractedDirectory && directory) {
throw new Error(
`You can't specify both a directory (${options.directory}) and a name with a directory path (${options.name}). ` +
`Please specify either a directory or a name with a directory path.`
);
}
const asProvidedOptions = getAsProvidedOptions(tree, {
...options,
directory: directory ?? extractedDirectory,
fileExtension,
name: extractedName,
});
return asProvidedOptions;
}
function getAsProvidedOptions(
tree: Tree,
options: ArtifactGenerationOptions
): NameAndDirectoryOptions {
let { name: extractedName, directory } =
extractNameAndDirectoryFromPath(path);
const relativeCwd = getRelativeCwd();
let asProvidedDirectory: string;
if (options.directory) {
// append the directory to the current working directory if it doesn't start with it
if (
options.directory === relativeCwd ||
options.directory.startsWith(`${relativeCwd}/`)
) {
asProvidedDirectory = options.directory;
} else {
asProvidedDirectory = joinPathFragments(relativeCwd, options.directory);
}
} else {
asProvidedDirectory = relativeCwd;
// append the directory to the current working directory if it doesn't start with it
if (directory !== relativeCwd && !directory.startsWith(`${relativeCwd}/`)) {
directory = joinPathFragments(relativeCwd, directory);
}
const asProvidedProject = findProjectFromPath(tree, asProvidedDirectory);
const asProvidedFileName =
const project = findProjectFromPath(tree, directory);
const name =
options.fileName ??
(options.suffix ? `${options.name}.${options.suffix}` : options.name);
const asProvidedFilePath = joinPathFragments(
asProvidedDirectory,
`${asProvidedFileName}.${options.fileExtension}`
);
(options.suffix ? `${extractedName}.${options.suffix}` : extractedName);
const filePath = joinPathFragments(directory, `${name}.${fileExtension}`);
return {
artifactName: options.name,
directory: asProvidedDirectory,
fileName: asProvidedFileName,
filePath: asProvidedFilePath,
project: asProvidedProject,
artifactName: options.name ?? extractedName,
directory: directory,
fileName: name,
filePath: filePath,
project: project,
};
}
function validateResolvedProject(
tree: Tree,
project: string | undefined,
options: ArtifactGenerationOptions,
normalizedDirectory: string
): void {
if (project) {
return;
}
if (options.directory) {
throw new Error(
`The provided directory resolved relative to the current working directory "${normalizedDirectory}" does not exist under any project root. ` +
`Please make sure to navigate to a location or provide a directory that exists under a project root.`
);
}
throw new Error(
`The current working directory "${
getRelativeCwd() || '.'
}" does not exist under any project root. ` +
`The provided directory resolved relative to the current working directory "${normalizedDirectory}" does not exist under any project root. ` +
`Please make sure to navigate to a location or provide a directory that exists under a project root.`
);
}
@ -192,13 +132,16 @@ function getCwd(): string {
: process.cwd();
}
function extractNameAndDirectoryFromName(rawName: string): {
function extractNameAndDirectoryFromPath(path: string): {
name: string;
directory: string | undefined;
directory: string;
} {
const parsedName = normalizePath(rawName).split('/');
const name = parsedName.pop();
const directory = parsedName.length ? parsedName.join('/') : undefined;
// Remove trailing slash
path = path.replace(/\/$/, '');
const parsedPath = normalizePath(path).split('/');
const name = parsedPath.pop();
const directory = parsedPath.join('/');
return { name, directory };
}

View File

@ -20,7 +20,7 @@ describe('component', () => {
appTree.write('.gitignore', '');
defaultSchema = {
name: 'hello',
directory: 'my-lib/src/lib/hello',
path: 'my-lib/src/lib/hello/hello',
skipTests: false,
export: false,
classComponent: false,
@ -35,7 +35,6 @@ describe('component', () => {
skipFormat: false,
js: true,
unitTestRunner: 'jest',
projectNameAndRootFormat: 'as-provided',
});
await expoLibraryGenerator(appTree, {
name: projectName,
@ -45,7 +44,6 @@ describe('component', () => {
unitTestRunner: 'jest',
strict: true,
js: false,
projectNameAndRootFormat: 'as-provided',
});
jest.spyOn(logger, 'warn').mockImplementation(() => {});
jest.spyOn(logger, 'debug').mockImplementation(() => {});
@ -65,7 +63,7 @@ describe('component', () => {
it('should generate files for an app', async () => {
await expoComponentGenerator(appTree, {
...defaultSchema,
directory: 'my-app/src/app/hello',
path: 'my-app/src/app/hello/hello',
});
expect(appTree.exists('my-app/src/app/hello/hello.tsx')).toBeTruthy();
@ -87,7 +85,7 @@ describe('component', () => {
it('should not export from an app', async () => {
await expoComponentGenerator(appTree, {
...defaultSchema,
directory: 'my-lib/src/app/my-app',
path: 'my-lib/src/app/my-app',
export: true,
});
@ -101,7 +99,7 @@ describe('component', () => {
it('should create component under the directory', async () => {
await expoComponentGenerator(appTree, {
...defaultSchema,
directory: 'my-lib/src/components/hello',
path: 'my-lib/src/components/hello',
});
expect(appTree.exists('my-lib/src/components/hello/hello.tsx'));
@ -111,7 +109,7 @@ describe('component', () => {
await expoComponentGenerator(appTree, {
...defaultSchema,
name: 'helloWorld',
directory: 'my-lib/src/lib/foo/hello-world',
path: 'my-lib/src/lib/foo/hello-world',
});
expect(appTree.exists('my-lib/src/lib/foo/hello-world/hello-world.tsx'));

View File

@ -3,6 +3,7 @@ import { Schema } from '../schema';
import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
export interface NormalizedSchema extends Schema {
directory: string;
projectSourceRoot: string;
fileName: string;
className: string;
@ -18,14 +19,13 @@ export async function normalizeOptions(
const {
artifactName: name,
directory,
fileName,
filePath,
directory,
project: projectName,
} = await determineArtifactNameAndDirectoryOptions(host, {
name: options.name,
directory: options.directory,
nameAndDirectoryFormat: options.nameAndDirectoryFormat,
path: options.path,
fileExtension: 'tsx',
});
@ -60,8 +60,8 @@ function assertValidOptions(options: Schema) {
if (options.name.indexOf(s) !== -1) {
const [name, ...rest] = options.name.split(s).reverse();
let suggestion = rest.map((x) => x.toLowerCase()).join(s);
if (options.directory) {
suggestion = `${options.directory}${s}${suggestion}`;
if (options.path) {
suggestion = `${options.path}${s}${suggestion}`;
}
throw new Error(
`Found "${s}" in the component name. Did you mean to use the --directory option (e.g. \`nx g c ${name} --directory ${suggestion}\`)?`

View File

@ -1,11 +1,9 @@
import type { NameAndDirectoryFormat } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
/**
* Same as the @nx/react library schema, except it removes keys: style, routing, globalCss
*/
export interface Schema {
name: string;
directory?: string;
path: string;
name?: string;
skipFormat: boolean; // default is false
skipTests: boolean; // default is false
export: boolean; // default is false

View File

@ -6,22 +6,28 @@
"type": "object",
"examples": [
{
"command": "g @nx/expo:component my-component --directory=mylib/my-component",
"command": "g @nx/expo:component mylib/my-component --name my-component",
"description": "Generate a component in the mylib library"
},
{
"command": "g @nx/expo:component my-component --directory=mylib/my-component --classComponent",
"command": "g @nx/expo:component mylib/my-component --name my-component --classComponent",
"description": "Generate a class component in the mylib library"
}
],
"properties": {
"name": {
"path": {
"type": "string",
"description": "The name of the component.",
"description": "Path where the component will be generated.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Where should the component be generated?",
"x-priority": "important"
},
"name": {
"type": "string",
"description": "The name of the component.",
"x-prompt": "What name would you like to use for the component?"
},
"js": {
@ -40,16 +46,6 @@
"description": "When true, does not create \"spec.ts\" test files for the new component.",
"default": false
},
"directory": {
"type": "string",
"description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the project root.",
"x-priority": "important"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"export": {
"type": "boolean",
"description": "When true, the component is exported from the project index.ts (if it exists).",
@ -64,5 +60,5 @@
"default": false
}
},
"required": ["name"]
"required": ["path"]
}

View File

@ -5,19 +5,21 @@ import { classGenerator } from './class';
describe('class generator', () => {
let tree: Tree;
const project = 'api';
const path = 'api';
const options: ClassGeneratorOptions = {
name: 'test',
directory: project,
path,
unitTestRunner: 'jest',
};
beforeEach(() => {
tree = createTreeWithNestApplication(project);
tree = createTreeWithNestApplication(path);
jest.clearAllMocks();
});
it('should run successfully', async () => {
await expect(classGenerator(tree, options)).resolves.not.toThrow();
await expect(
classGenerator(tree, { ...options, path: 'api/test' })
).resolves.not.toThrow();
});
});

View File

@ -6,34 +6,20 @@
"cli": "nx",
"type": "object",
"properties": {
"name": {
"description": "The name of the class.",
"path": {
"description": "Path where the class will be generated.",
"type": "string",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Where should the class be generated?"
},
"name": {
"description": "The name of the class.",
"type": "string",
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"project": {
"description": "The Nest project to target.",
"type": "string",
"$default": {
"$source": "projectName"
},
"alias": "p",
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -59,5 +45,5 @@
}
},
"additionalProperties": false,
"required": ["name"]
"required": ["path"]
}

View File

@ -5,19 +5,21 @@ import { controllerGenerator } from './controller';
describe('controller generator', () => {
let tree: Tree;
const directory = 'api';
const path = 'api';
const options: ControllerGeneratorOptions = {
name: 'test',
directory,
path,
unitTestRunner: 'jest',
};
beforeEach(() => {
tree = createTreeWithNestApplication(directory);
tree = createTreeWithNestApplication(path);
jest.clearAllMocks();
});
it('should run successfully', async () => {
await expect(controllerGenerator(tree, options)).resolves.not.toThrow();
await expect(
controllerGenerator(tree, { ...options, path: 'api/test' })
).resolves.not.toThrow();
});
});

View File

@ -6,25 +6,20 @@
"cli": "nx",
"type": "object",
"properties": {
"name": {
"description": "The name of the controller.",
"path": {
"description": "Path where the controller will be generated.",
"type": "string",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Where should the controller be generated?"
},
"name": {
"description": "The name of the controller.",
"type": "string",
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -53,5 +48,5 @@
}
},
"additionalProperties": false,
"required": ["name"]
"required": ["path"]
}

View File

@ -5,18 +5,20 @@ import { decoratorGenerator } from './decorator';
describe('decorator generator', () => {
let tree: Tree;
const directory = 'api';
const path = 'api';
const options: DecoratorGeneratorOptions = {
name: 'test',
directory,
path,
};
beforeEach(() => {
tree = createTreeWithNestApplication(directory);
tree = createTreeWithNestApplication(path);
jest.clearAllMocks();
});
it('should run successfully', async () => {
await expect(decoratorGenerator(tree, options)).resolves.not.toThrow();
await expect(
decoratorGenerator(tree, { ...options, path: 'api/test' })
).resolves.not.toThrow();
});
});

View File

@ -6,25 +6,20 @@
"cli": "nx",
"type": "object",
"properties": {
"name": {
"description": "The name of the decorator.",
"path": {
"description": "Path where the decorator will be generated.",
"type": "string",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Where should the decorator be generated?"
},
"name": {
"description": "The name of the decorator.",
"type": "string",
"x-prompt": "What name would you like to use?"
},
"nameAndDirectoryFormat": {
"description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"directory": {
"description": "Directory where the generated files are placed. when `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. otherwise, it will be relative to the workspace root.",
"type": "string",
"aliases": ["dir", "path"]
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
@ -38,5 +33,5 @@
}
},
"additionalProperties": false,
"required": ["name"]
"required": ["path"]
}

View File

@ -5,19 +5,21 @@ import { filterGenerator } from './filter';
describe('filter generator', () => {
let tree: Tree;
const directory = 'api';
const path = 'api';
const options: FilterGeneratorOptions = {
name: 'test',
directory,
path,
unitTestRunner: 'jest',
};
beforeEach(() => {
tree = createTreeWithNestApplication(directory);
tree = createTreeWithNestApplication(path);
jest.clearAllMocks();
});
it('should run successfully', async () => {
await expect(filterGenerator(tree, options)).resolves.not.toThrow();
await expect(
filterGenerator(tree, { ...options, path: 'api/test' })
).resolves.not.toThrow();
});
});

Some files were not shown because too many files have changed in this diff Show More