feat(misc): handle artifact generators' path options including file extensions (#29111)
<!-- 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 --> Artifact generators don't handle consistently receiving a file extension in the `path` option. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> Artifact generators should handle receiving a file extension in the `path` option. If the file extension is passed, the file path will be treated as "complete" and used fully as provided. If the `path` provided doesn't contain a file extension, the default extension will be appended to it (or the one provided in a related option, e.g. `--language`, `--js`, etc) together with the suffix for generators that use it. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
3474d7c607
commit
28c53f942b
@ -12,7 +12,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the component file path?"
|
"x-prompt": "What is the component file path?"
|
||||||
},
|
},
|
||||||
@ -117,7 +117,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["path"],
|
"required": ["path"],
|
||||||
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\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=\"With Different Symbol Name\" %}\n\nGenerate a component named `CustomComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --name=custom\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",
|
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component.ts\n```\n\n{% /tab %}\n\n{% tab label=\"Without Providing the File Extension\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\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=\"With Different Symbol Name\" %}\n\nGenerate a component named `CustomComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --name=custom\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": []
|
"presets": []
|
||||||
},
|
},
|
||||||
"aliases": ["c"],
|
"aliases": ["c"],
|
||||||
|
|||||||
@ -12,6 +12,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
|
"command": "nx g @nx/angular:directive mylib/src/lib/foo.directive.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a directive without providing the file extension. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
"command": "nx g @nx/angular:directive mylib/src/lib/foo"
|
"command": "nx g @nx/angular:directive mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -22,7 +26,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the directive without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the directive. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the directive file path?"
|
"x-prompt": "What is the directive file path?"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,6 +12,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
|
"command": "nx g @nx/angular:pipe mylib/src/lib/foo.pipe.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a pipe without providing the file extension. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
"command": "nx g @nx/angular:pipe mylib/src/lib/foo"
|
"command": "nx g @nx/angular:pipe mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -22,7 +26,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the pipe without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the pipe. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the pipe file path?"
|
"x-prompt": "What is the pipe file path?"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
|
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo.directive.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a directive without providing the file extension. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo"
|
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -22,7 +26,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the SCAM directive without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the SCAM directive. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the SCAM directive file path?"
|
"x-prompt": "What is the SCAM directive file path?"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
|
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/foo.pipe.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a pipe without providing the file extension. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/foo"
|
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -22,7 +26,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the SCAM pipe without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the SCAM pipe. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the SCAM pipe file path?"
|
"x-prompt": "What is the SCAM pipe file path?"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol matching the file name. It results in the component `FooComponent` at `mylib/src/lib/foo.component.ts`",
|
"description": "Generate a component with the exported symbol matching the file name. It results in the component `FooComponent` at `mylib/src/lib/foo.component.ts`",
|
||||||
|
"command": "nx g @nx/angular:scam mylib/src/lib/foo.component.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a component without providing the file extension. It results in the component `FooComponent` at `mylib/src/lib/foo.component.ts`",
|
||||||
"command": "nx g @nx/angular:scam mylib/src/lib/foo"
|
"command": "nx g @nx/angular:scam mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -22,7 +26,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the SCAM without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the SCAM. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the SCAM file path?"
|
"x-prompt": "What is the SCAM file path?"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,11 +10,15 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol matching the file name. It results in the component `Foo` at `mylib/src/foo.tsx`",
|
"description": "Generate a component with the exported symbol matching the file name. It results in the component `Foo` at `mylib/src/foo.tsx`",
|
||||||
"command": "nx g @nx/expo:component mylib/src/foo"
|
"command": "nx g @nx/expo:component mylib/src/foo.tsx"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol different from the file name. It results in the component `Custom` at `mylib/src/foo.tsx`",
|
"description": "Generate a component with the exported symbol different from the file name. It results in the component `Custom` at `mylib/src/foo.tsx`",
|
||||||
"command": "nx g @nx/expo:component mylib/src/foo --name=custom"
|
"command": "nx g @nx/expo:component mylib/src/foo.tsx --name=custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a component without the providing the file extension. It results in the component `Foo` at `mylib/src/foo.tsx`",
|
||||||
|
"command": "nx g @nx/expo:component mylib/src/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a class component at `mylib/src/foo.tsx`",
|
"description": "Generate a class component at `mylib/src/foo.tsx`",
|
||||||
@ -24,7 +28,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the component file path?"
|
"x-prompt": "What is the component file path?"
|
||||||
},
|
},
|
||||||
@ -35,7 +39,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
"description": "Skip formatting files.",
|
"description": "Skip formatting files.",
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the class `Foo` at `myapp/src/app/foo.ts`",
|
"description": "Generate the class `Foo` at `myapp/src/app/foo.ts`",
|
||||||
|
"command": "nx g @nx/nest:class myapp/src/app/foo.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the class without providing the file extension. It results in the class `Foo` at `myapp/src/app/foo.ts`",
|
||||||
"command": "nx g @nx/nest:class myapp/src/app/foo"
|
"command": "nx g @nx/nest:class myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the class without the file extension. Relative to the current working directory.",
|
"description": "The file path to the class. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the class file path?"
|
"x-prompt": "What is the class file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the controller `FooController` at `myapp/src/app/foo.controller.ts`",
|
"description": "Generate the controller `FooController` at `myapp/src/app/foo.controller.ts`",
|
||||||
|
"command": "nx g @nx/nest:controller myapp/src/app/foo.controller.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the controller without providing the file extension. It results in the controller `FooController` at `myapp/src/app/foo.controller.ts`",
|
||||||
"command": "nx g @nx/nest:controller myapp/src/app/foo"
|
"command": "nx g @nx/nest:controller myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the controller without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the controller. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the controller file path?"
|
"x-prompt": "What is the controller file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the decorator `Foo` at `myapp/src/app/foo.decorator.ts`",
|
"description": "Generate the decorator `Foo` at `myapp/src/app/foo.decorator.ts`",
|
||||||
|
"command": "nx g @nx/nest:decorator myapp/src/app/foo.decorator.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the decorator without providing the file extension. It results in the decorator `Foo` at `myapp/src/app/foo.decorator.ts`",
|
||||||
"command": "nx g @nx/nest:decorator myapp/src/app/foo"
|
"command": "nx g @nx/nest:decorator myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the decorator without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the decorator. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the decorator file path?"
|
"x-prompt": "What is the decorator file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the filter `FooFilter` at `myapp/src/app/foo.filter.ts`",
|
"description": "Generate the filter `FooFilter` at `myapp/src/app/foo.filter.ts`",
|
||||||
|
"command": "nx g @nx/nest:filter myapp/src/app/foo.filter.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the filter without providing the file extension. It results in the filter `FooFilter` at `myapp/src/app/foo.filter.ts`",
|
||||||
"command": "nx g @nx/nest:filter myapp/src/app/foo"
|
"command": "nx g @nx/nest:filter myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the filter without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the filter. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the filter file path?"
|
"x-prompt": "What is the filter file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the gateway `FooGateway` at `myapp/src/app/foo.gateway.ts`",
|
"description": "Generate the gateway `FooGateway` at `myapp/src/app/foo.gateway.ts`",
|
||||||
|
"command": "nx g @nx/nest:gateway myapp/src/app/foo.gateway.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the gateway without providing the file extension. It results in the gateway `FooGateway` at `myapp/src/app/foo.gateway.ts`",
|
||||||
"command": "nx g @nx/nest:gateway myapp/src/app/foo"
|
"command": "nx g @nx/nest:gateway myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the gateway without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the gateway. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the gateway file path?"
|
"x-prompt": "What is the gateway file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the guard `FooGuard` at `myapp/src/app/foo.guard.ts`",
|
"description": "Generate the guard `FooGuard` at `myapp/src/app/foo.guard.ts`",
|
||||||
|
"command": "nx g @nx/nest:guard myapp/src/app/foo.guard.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the guard without providing the file extension. It results in the guard `FooGuard` at `myapp/src/app/foo.guard.ts`",
|
||||||
"command": "nx g @nx/nest:guard myapp/src/app/foo"
|
"command": "nx g @nx/nest:guard myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the guard without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the guard. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the guard file path?"
|
"x-prompt": "What is the guard file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the interceptor `FooInterceptor` at `myapp/src/app/foo.interceptor.ts`",
|
"description": "Generate the interceptor `FooInterceptor` at `myapp/src/app/foo.interceptor.ts`",
|
||||||
|
"command": "nx g @nx/nest:interceptor myapp/src/app/foo.interceptor.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the interceptor without providing the file extension. It results in the interceptor `FooInterceptor` at `myapp/src/app/foo.interceptor.ts`",
|
||||||
"command": "nx g @nx/nest:interceptor myapp/src/app/foo"
|
"command": "nx g @nx/nest:interceptor myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the interceptor without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the interceptor. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the interceptor file path?"
|
"x-prompt": "What is the interceptor file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the interface `Foo` at `myapp/src/app/foo.interface.ts`",
|
"description": "Generate the interface `Foo` at `myapp/src/app/foo.interface.ts`",
|
||||||
|
"command": "nx g @nx/nest:interface myapp/src/app/foo.interface.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the interface without providing the file extension. It results in the interface `Foo` at `myapp/src/app/foo.interface.ts`",
|
||||||
"command": "nx g @nx/nest:interface myapp/src/app/foo"
|
"command": "nx g @nx/nest:interface myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the interface without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the interface. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the interface file path?"
|
"x-prompt": "What is the interface file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the middleware `FooMiddleware` at `myapp/src/app/foo.middleware.ts`",
|
"description": "Generate the middleware `FooMiddleware` at `myapp/src/app/foo.middleware.ts`",
|
||||||
|
"command": "nx g @nx/nest:middleware myapp/src/app/foo.middleware.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the middleware without providing the file extension. It results in the middleware `FooMiddleware` at `myapp/src/app/foo.middleware.ts`",
|
||||||
"command": "nx g @nx/nest:middleware myapp/src/app/foo"
|
"command": "nx g @nx/nest:middleware myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the middleware without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the middleware. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the middleware file path?"
|
"x-prompt": "What is the middleware file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the module `FooModule` at `myapp/src/app/foo.module.ts`",
|
"description": "Generate the module `FooModule` at `myapp/src/app/foo.module.ts`",
|
||||||
|
"command": "nx g @nx/nest:module myapp/src/app/foo.module.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the module without providing the file extension. It results in the module `FooModule` at `myapp/src/app/foo.module.ts`",
|
||||||
"command": "nx g @nx/nest:module myapp/src/app/foo"
|
"command": "nx g @nx/nest:module myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the module without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the module. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the module file path?"
|
"x-prompt": "What is the module file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the pipe `FooPipe` at `myapp/src/app/foo.pipe.ts`",
|
"description": "Generate the pipe `FooPipe` at `myapp/src/app/foo.pipe.ts`",
|
||||||
|
"command": "nx g @nx/nest:pipe myapp/src/app/foo.pipe.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the pipe without providing the file extension. It results in the pipe `FooPipe` at `myapp/src/app/foo.pipe.ts`",
|
||||||
"command": "nx g @nx/nest:pipe myapp/src/app/foo"
|
"command": "nx g @nx/nest:pipe myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the pipe without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the pipe. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the pipe file path?"
|
"x-prompt": "What is the pipe file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the provider `Foo` at `myapp/src/app/foo.ts`",
|
"description": "Generate the provider `Foo` at `myapp/src/app/foo.ts`",
|
||||||
|
"command": "nx g @nx/nest:provider myapp/src/app/foo.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the provider without providing the file extension. It results in the provider `Foo` at `myapp/src/app/foo.ts`",
|
||||||
"command": "nx g @nx/nest:provider myapp/src/app/foo"
|
"command": "nx g @nx/nest:provider myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the provider without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the provider. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the provider file path?"
|
"x-prompt": "What is the provider file path?"
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the resolver `FooResolver` at `myapp/src/app/foo.resolver.ts`",
|
"description": "Generate the resolver `FooResolver` at `myapp/src/app/foo.resolver.ts`",
|
||||||
|
"command": "nx g @nx/nest:resolver myapp/src/app/foo.resolver.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the resolver without providing the file extension. It results in the resolver `FooResolver` at `myapp/src/app/foo.resolver.ts`",
|
||||||
"command": "nx g @nx/nest:resolver myapp/src/app/foo"
|
"command": "nx g @nx/nest:resolver myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the resolver without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the resolver. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the resolver file path?"
|
"x-prompt": "What is the resolver file path?"
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the resource without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the resource. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the resource file path?"
|
"x-prompt": "What is the resource file path?"
|
||||||
},
|
},
|
||||||
@ -33,11 +33,6 @@
|
|||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "none"],
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"language": {
|
|
||||||
"description": "Nest class language.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["js", "ts"]
|
|
||||||
},
|
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The transport layer.",
|
"description": "The transport layer.",
|
||||||
|
|||||||
@ -11,12 +11,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the service `FooService` at `myapp/src/app/foo.service.ts`",
|
"description": "Generate the service `FooService` at `myapp/src/app/foo.service.ts`",
|
||||||
|
"command": "nx g @nx/nest:service myapp/src/app/foo.service.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the service without providing the file extension. It results in the service `FooService` at `myapp/src/app/foo.service.ts`",
|
||||||
"command": "nx g @nx/nest:service myapp/src/app/foo"
|
"command": "nx g @nx/nest:service myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the service without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the service. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the service file path?"
|
"x-prompt": "What is the service file path?"
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the component file path?",
|
"x-prompt": "What is the component file path?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
@ -69,7 +69,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
"description": "Skip formatting files.",
|
"description": "Skip formatting files.",
|
||||||
@ -79,7 +79,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["path"],
|
"required": ["path"],
|
||||||
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Create a Component\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/app/my-component/my-component.tsx`:\n\n```shell\nnx g component apps/my-app/src/app/my-component/my-component\n```\n\n{% /tab %}\n{% tab label=\"Create a Component with a Different Symbol Name\" %}\n\nGenerate a component named `Custom` at `apps/my-app/src/app/my-component/my-component.tsx`:\n\n```shell\nnx g component apps/my-app/src/app/my-component/my-component --name=custom\n```\n\n{% /tab %}\n{% /tabs %}\n",
|
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Create a Component\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/app/my-component/my-component.tsx`:\n\n```shell\nnx g component apps/my-app/src/app/my-component/my-component.tsx\n```\n\n{% /tab %}\n{% tab label=\"Create a Component with a Different Symbol Name\" %}\n\nGenerate a component named `Custom` at `apps/my-app/src/app/my-component/my-component.tsx`:\n\n```shell\nnx g component apps/my-app/src/app/my-component/my-component.tsx --name=custom\n```\n\n{% /tab %}\n{% tab label=\"Create a Component Omitting the File Extension\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/app/my-component/my-component.tsx` without specifying the file extension:\n\n```shell\nnx g component apps/my-app/src/app/my-component/my-component\n```\n\n{% /tab %}\n{% /tabs %}\n",
|
||||||
"presets": []
|
"presets": []
|
||||||
},
|
},
|
||||||
"description": "Create a component.",
|
"description": "Create a component.",
|
||||||
|
|||||||
@ -7,12 +7,12 @@
|
|||||||
"$id": "NxPluginExecutor",
|
"$id": "NxPluginExecutor",
|
||||||
"title": "Create an Executor for an Nx Plugin",
|
"title": "Create an Executor for an Nx Plugin",
|
||||||
"description": "Create an Executor for an Nx Plugin.",
|
"description": "Create an Executor for an Nx Plugin.",
|
||||||
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Basic executor\" %}\n\nCreate a new executor called `build` at `tools/my-plugin/src/executors/build.ts`:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build\n```\n\n{% /tab %}\n{% tab label=\"With different exported name\" %}\n\nCreate a new executor called `custom` at `tools/my-plugin/src/executors/build.ts`:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build --name=custom\n```\n\n{% /tab %}\n{% tab label=\"With custom hashing\" %}\n\nCreate a new executor called `build` at `tools/my-plugin/src/executors/build.ts`, that uses a custom hashing function:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build --includeHasher\n```\n\n{% /tab %}\n{% /tabs %}\n",
|
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Basic executor\" %}\n\nCreate a new executor called `build` at `tools/my-plugin/src/executors/build.ts`:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build.ts\n```\n\n{% /tab %}\n{% tab label=\"Without providing the file extension\" %}\n\nCreate a new executor called `build` at `tools/my-plugin/src/executors/build.ts`:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build\n```\n\n{% /tab %}\n{% tab label=\"With different exported name\" %}\n\nCreate a new executor called `custom` at `tools/my-plugin/src/executors/build.ts`:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build.ts --name=custom\n```\n\n{% /tab %}\n{% tab label=\"With custom hashing\" %}\n\nCreate a new executor called `build` at `tools/my-plugin/src/executors/build.ts`, that uses a custom hashing function:\n\n```bash\nnx g @nx/plugin:executor tools/my-plugin/src/executors/build --includeHasher\n```\n\n{% /tab %}\n{% /tabs %}\n",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the executor without the file extension. Relative to the current working directory.",
|
"description": "The file path to the executor. Relative to the current working directory.",
|
||||||
"x-prompt": "What is the executor file path?",
|
"x-prompt": "What is the executor file path?",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a generator exported with the name matching the file name. It results in the generator `foo` at `mylib/src/generators/foo.ts`",
|
"description": "Generate a generator exported with the name matching the file name. It results in the generator `foo` at `mylib/src/generators/foo.ts`",
|
||||||
|
"command": "nx g @nx/plugin:generator mylib/src/generators/foo.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a generator without providing the file extension. It results in the generator `foo` at `mylib/src/generators/foo.ts`",
|
||||||
"command": "nx g @nx/plugin:generator mylib/src/generators/foo"
|
"command": "nx g @nx/plugin:generator mylib/src/generators/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -21,7 +25,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the generator without the file extension. Relative to the current working directory.",
|
"description": "The file path to the generator. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the generator file path?",
|
"x-prompt": "What is the generator file path?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a migration exported with the name matching the file name, which will be triggered when migrating to version 1.0.0 or above from a previous version. It results in the migration `foo` at `mylib/src/migrations/foo.ts`",
|
"description": "Generate a migration exported with the name matching the file name, which will be triggered when migrating to version 1.0.0 or above from a previous version. It results in the migration `foo` at `mylib/src/migrations/foo.ts`",
|
||||||
|
"command": "nx g @nx/plugin:migration mylib/src/migrations/foo.ts -v=1.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a migration without providing the file extension, which will be triggered when migrating to version 1.0.0 or above from a previous version. It results in the migration `foo` at `mylib/src/migrations/foo.ts`",
|
||||||
"command": "nx g @nx/plugin:migration mylib/src/migrations/foo -v=1.0.0"
|
"command": "nx g @nx/plugin:migration mylib/src/migrations/foo -v=1.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -11,11 +11,15 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol matching the file name. It results in the component `Foo` at `mylib/src/lib/foo.tsx`",
|
"description": "Generate a component with the exported symbol matching the file name. It results in the component `Foo` at `mylib/src/lib/foo.tsx`",
|
||||||
"command": "nx g @nx/react-native:component mylib/src/lib/foo"
|
"command": "nx g @nx/react-native:component mylib/src/lib/foo.tsx"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol different from the file name. It results in the component `Custom` at `mylib/src/lib/foo.tsx`",
|
"description": "Generate a component with the exported symbol different from the file name. It results in the component `Custom` at `mylib/src/lib/foo.tsx`",
|
||||||
"command": "nx g @nx/react-native:component mylib/src/lib/foo --name=custom"
|
"command": "nx g @nx/react-native:component mylib/src/lib/foo.tsx --name=custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a component without providing the file extension. It results in the component `Foo` at `mylib/src/lib/foo.tsx`",
|
||||||
|
"command": "nx g @nx/react-native:component mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a class component at `mylib/src/lib/foo.tsx`",
|
"description": "Generate a class component at `mylib/src/lib/foo.tsx`",
|
||||||
@ -25,7 +29,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the component file path?"
|
"x-prompt": "What is the component file path?"
|
||||||
},
|
},
|
||||||
@ -36,7 +40,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipTests": {
|
"skipTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the component file path?",
|
"x-prompt": "What is the component file path?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
@ -57,7 +57,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipTests": {
|
"skipTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@ -87,10 +87,6 @@
|
|||||||
"description": "Default is `false`. When `true`, the component is generated with `*.css`/`*.scss` instead of `*.module.css`/`*.module.scss`.",
|
"description": "Default is `false`. When `true`, the component is generated with `*.css`/`*.scss` instead of `*.module.css`/`*.module.scss`.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"fileName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Create a component with this file name."
|
|
||||||
},
|
|
||||||
"inSourceTests": {
|
"inSourceTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
@ -104,7 +100,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["path"],
|
"required": ["path"],
|
||||||
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nCreate a component named `MyComponent` at `libs/ui/src/my-component.tsx`:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component\n```\n\n{% /tab %}\n\n{% tab label=\"With a Different Symbol Name\" %}\n\nCreate a component named `Custom` at `libs/ui/src/my-component.tsx`:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component --name=custom\n```\n\n{% /tab %}\n\n{% tab label=\"Class Component\" %}\n\nCreate a class component named `MyComponent` at `libs/ui/src/my-component.tsx`:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component --classComponent\n```\n\n{% /tab %}\n",
|
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nCreate a component named `MyComponent` at `libs/ui/src/my-component.tsx`:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component.tsx\n```\n\n{% /tab %}\n\n{% tab label=\"With a Different Symbol Name\" %}\n\nCreate a component named `Custom` at `libs/ui/src/my-component.tsx`:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component.tsx --name=custom\n```\n\n{% /tab %}\n\n{% tab label=\"Omitting the File Extension\" %}\n\nCreate a component named `MyComponent` at `libs/ui/src/my-component.tsx` without specifying the file extension:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component\n```\n\n{% /tab %}\n\n{% tab label=\"Class Component\" %}\n\nCreate a class component named `MyComponent` at `libs/ui/src/my-component.tsx`:\n\n```shell\nnx g @nx/react:component libs/ui/src/my-component --classComponent\n```\n\n{% /tab %}\n",
|
||||||
"presets": []
|
"presets": []
|
||||||
},
|
},
|
||||||
"description": "Create a React component.",
|
"description": "Create a React component.",
|
||||||
|
|||||||
@ -11,17 +11,21 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a hook with the exported symbol matching the file name. It results in the hook `useFoo` at `mylib/src/lib/foo.ts`",
|
"description": "Generate a hook with the exported symbol matching the file name. It results in the hook `useFoo` at `mylib/src/lib/foo.ts`",
|
||||||
"command": "nx g @nx/react:hook mylib/src/lib/foo"
|
"command": "nx g @nx/react:hook mylib/src/lib/foo.ts"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a hook with the exported symbol different from the file name. It results in the hook `useCustom` at `mylib/src/lib/foo.ts`",
|
"description": "Generate a hook with the exported symbol different from the file name. It results in the hook `useCustom` at `mylib/src/lib/foo.ts`",
|
||||||
"command": "nx g @nx/react:hook mylib/src/lib/foo --name=useCustom"
|
"command": "nx g @nx/react:hook mylib/src/lib/foo.ts --name=useCustom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a hook without providing the file extension. It results in the hook `useFoo` at `mylib/src/lib/foo.ts`",
|
||||||
|
"command": "nx g @nx/react:hook mylib/src/lib/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the hook without the file extension. Relative to the current working directory.",
|
"description": "The file path to the hook. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the hook file path?",
|
"x-prompt": "What is the hook file path?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
@ -33,7 +37,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipTests": {
|
"skipTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -11,17 +11,21 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a Redux state slice with the exported symbol matching the file name. It results in the slice `fooSlice` at `mylib/src/lib/foo.slice.ts`",
|
"description": "Generate a Redux state slice with the exported symbol matching the file name. It results in the slice `fooSlice` at `mylib/src/lib/foo.slice.ts`",
|
||||||
"command": "nx g @nx/react:redux mylib/src/lib/foo"
|
"command": "nx g @nx/react:redux mylib/src/lib/foo.slice.ts"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a Redux state slice with the exported symbol different from the file name. It results in the slice `customSlice` at `mylib/src/lib/foo.slice.ts`",
|
"description": "Generate a Redux state slice with the exported symbol different from the file name. It results in the slice `customSlice` at `mylib/src/lib/foo.slice.ts`",
|
||||||
"command": "nx g @nx/react:redux mylib/src/lib/foo --name=custom"
|
"command": "nx g @nx/react:redux mylib/src/lib/foo.slice.ts --name=custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a Redux state slice without providing the \"slice\" suffix and the file extension. It results in the slice `fooSlice` at `mylib/src/lib/foo.slice.ts`",
|
||||||
|
"command": "nx g @nx/react:redux mylib/src/lib/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the Redux state slice without the file extension. Relative to the current working directory.",
|
"description": "The file path to the Redux state slice. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the Redux stateslice file path?",
|
"x-prompt": "What is the Redux stateslice file path?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
@ -38,7 +42,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["path"],
|
"required": ["path"],
|
||||||
|
|||||||
@ -9,16 +9,20 @@
|
|||||||
"description": "Generate a resource route.",
|
"description": "Generate a resource route.",
|
||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"command": "g resource-route 'path/to/page'",
|
"description": "Generate a resource route at `myapp/app/routes/foo.ts`",
|
||||||
"description": "Generate resource route at /path/to/page"
|
"command": "nx g resource-route myapp/app/routes/foo.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a resource route without providing the file extension at `myapp/app/routes/foo.tsx`",
|
||||||
|
"command": "nx g resource-route myapp/app/routes/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The route path or path to the filename of the route.",
|
"description": "The file path to the route. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the path of the route? (e.g. 'apps/demo/app/routes/foo/bar')"
|
"x-prompt": "What is the route file path?"
|
||||||
},
|
},
|
||||||
"action": {
|
"action": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -9,16 +9,20 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"command": "g route 'path/to/page'",
|
"description": "Generate a route at `myapp/app/routes/foo.tsx`",
|
||||||
"description": "Generate route at /path/to/page"
|
"command": "nx g resource-route myapp/app/routes/foo.tsx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a route without providing the file extension at `myapp/app/routes/foo.tsx`",
|
||||||
|
"command": "nx g resource-route myapp/app/routes/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The route path or path to the filename of the route.",
|
"description": "The file path to the route. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the path of the route? (e.g. 'apps/demo/app/routes/foo/bar')"
|
"x-prompt": "What is the route file path?"
|
||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -9,16 +9,16 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"command": "g style --path='apps/demo/app/routes/path/to/page.tsx'",
|
"description": "Generate a stylesheet at `myapp/app/styles/foo.css`",
|
||||||
"description": "Generate route at apps/demo/app/routes/path/to/page.tsx"
|
"command": "nx g style myapp/app/routes/foo.tsx"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Route path",
|
"description": "The file path to the route. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the path of the route? (e.g. 'apps/demo/app/routes/foo/bar.tsx')"
|
"x-prompt": "What is the route file path?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["path"],
|
"required": ["path"],
|
||||||
|
|||||||
@ -9,6 +9,14 @@
|
|||||||
"description": "Create a Vue Component for Nx.",
|
"description": "Create a Vue Component for Nx.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"examples": [
|
"examples": [
|
||||||
|
{
|
||||||
|
"description": "Generate a component at `mylib/src/lib/foo.vue`",
|
||||||
|
"command": "nx g @nx/vue:component mylib/src/lib/foo.vue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a component without providing the file extension at `mylib/src/lib/foo.vue`",
|
||||||
|
"command": "nx g @nx/vue:component mylib/src/lib/foo"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a component at `mylib/src/lib/foo.vue` with `vitest` as the unit test runner",
|
"description": "Generate a component at `mylib/src/lib/foo.vue` with `vitest` as the unit test runner",
|
||||||
"command": "nx g @nx/vue:component mylib/src/lib/foo --unitTestRunner=vitest"
|
"command": "nx g @nx/vue:component mylib/src/lib/foo --unitTestRunner=vitest"
|
||||||
@ -17,7 +25,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": { "$source": "argv", "index": 0 },
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
"x-prompt": "What is the component file path?"
|
"x-prompt": "What is the component file path?"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,6 +5,16 @@
|
|||||||
|
|
||||||
Generate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:
|
Generate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Without Providing the File Extension" %}
|
||||||
|
|
||||||
|
Generate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component
|
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component
|
||||||
```
|
```
|
||||||
|
|||||||
@ -179,6 +179,54 @@ export class ExampleComponent {}
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`component Generator should handle path with file extension: component 1`] = `
|
||||||
|
"import { Component } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'example.component',
|
||||||
|
imports: [CommonModule],
|
||||||
|
templateUrl: './example.component.html',
|
||||||
|
styleUrl: './example.component.css',
|
||||||
|
})
|
||||||
|
export class ExampleComponentComponent {}
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`component Generator should handle path with file extension: component test file 1`] = `
|
||||||
|
"import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { ExampleComponentComponent } from './example.component';
|
||||||
|
|
||||||
|
describe('ExampleComponentComponent', () => {
|
||||||
|
let component: ExampleComponentComponent;
|
||||||
|
let fixture: ComponentFixture<ExampleComponentComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ExampleComponentComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ExampleComponentComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`component Generator should handle path with file extension: entry point file 1`] = `null`;
|
||||||
|
|
||||||
|
exports[`component Generator should handle path with file extension: stylesheet 1`] = `""`;
|
||||||
|
|
||||||
|
exports[`component Generator should handle path with file extension: template 1`] = `
|
||||||
|
"<p>example.component works!</p>
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`component Generator should inline styles when --inline-style=true 1`] = `
|
exports[`component Generator should inline styles when --inline-style=true 1`] = `
|
||||||
"import { Component } from '@angular/core';
|
"import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
|||||||
@ -77,6 +77,35 @@ describe('component Generator', () => {
|
|||||||
).toContain(`import ExampleComponent from './example.component';`);
|
).toContain(`import ExampleComponent from './example.component';`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
const tree = createTreeWithEmptyWorkspace();
|
||||||
|
addProjectConfiguration(tree, 'lib1', {
|
||||||
|
projectType: 'library',
|
||||||
|
sourceRoot: 'lib1/src',
|
||||||
|
root: 'lib1',
|
||||||
|
});
|
||||||
|
|
||||||
|
await componentGenerator(tree, {
|
||||||
|
path: 'lib1/src/lib/example/example.component.ts',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tree.read('lib1/src/lib/example/example.component.ts', 'utf-8')
|
||||||
|
).toMatchSnapshot('component');
|
||||||
|
expect(
|
||||||
|
tree.read('lib1/src/lib/example/example.component.html', 'utf-8')
|
||||||
|
).toMatchSnapshot('template');
|
||||||
|
expect(
|
||||||
|
tree.read('lib1/src/lib/example/example.component.css', 'utf-8')
|
||||||
|
).toMatchSnapshot('stylesheet');
|
||||||
|
expect(
|
||||||
|
tree.read('lib1/src/lib/example/example.component.spec.ts', 'utf-8')
|
||||||
|
).toMatchSnapshot('component test file');
|
||||||
|
expect(tree.read('lib1/src/index.ts', 'utf-8')).toMatchSnapshot(
|
||||||
|
'entry point file'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not generate test file when --skip-tests=true', async () => {
|
it('should not generate test file when --skip-tests=true', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
|||||||
@ -21,6 +21,8 @@ export async function normalizeOptions(
|
|||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
suffix: options.type ?? 'component',
|
suffix: options.type ?? 'component',
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
fileExtension: 'ts',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
|
|||||||
@ -125,3 +125,27 @@ describe('TestDirective', () => {
|
|||||||
});
|
});
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`directive generator should handle path with file extension 1`] = `
|
||||||
|
"import { Directive } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[test]',
|
||||||
|
})
|
||||||
|
export class TestDirective {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`directive generator should handle path with file extension 2`] = `
|
||||||
|
"import { TestDirective } from './test.directive';
|
||||||
|
|
||||||
|
describe('TestDirective', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
const directive = new TestDirective();
|
||||||
|
expect(directive).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|||||||
@ -35,6 +35,20 @@ describe('directive generator', () => {
|
|||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
await generateDirectiveWithDefaultOptions(tree, {
|
||||||
|
path: 'test/src/app/test.directive.ts',
|
||||||
|
skipFormat: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tree.read('test/src/app/test.directive.ts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
expect(
|
||||||
|
tree.read('test/src/app/test.directive.spec.ts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not import the directive into an existing module', async () => {
|
it('should not import the directive into an existing module', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
addModule(tree);
|
addModule(tree);
|
||||||
|
|||||||
@ -20,6 +20,8 @@ export async function normalizeOptions(
|
|||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
suffix: 'directive',
|
suffix: 'directive',
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
fileExtension: 'ts',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
|||||||
@ -9,6 +9,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
|
"command": "nx g @nx/angular:directive mylib/src/lib/foo.directive.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a directive without providing the file extension. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
"command": "nx g @nx/angular:directive mylib/src/lib/foo"
|
"command": "nx g @nx/angular:directive mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -19,7 +23,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the directive without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the directive. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
|
|||||||
@ -154,3 +154,29 @@ describe('TestPipe', () => {
|
|||||||
});
|
});
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`pipe generator should handle path with file extension 1`] = `
|
||||||
|
"import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'test',
|
||||||
|
})
|
||||||
|
export class TestPipe implements PipeTransform {
|
||||||
|
transform(value: unknown, ...args: unknown[]): unknown {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`pipe generator should handle path with file extension 2`] = `
|
||||||
|
"import { TestPipe } from './test.pipe';
|
||||||
|
|
||||||
|
describe('TestPipe', () => {
|
||||||
|
it('create an instance', () => {
|
||||||
|
const pipe = new TestPipe();
|
||||||
|
expect(pipe).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|||||||
@ -18,6 +18,8 @@ export async function normalizeOptions(
|
|||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
suffix: 'pipe',
|
suffix: 'pipe',
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
fileExtension: 'ts',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
|||||||
@ -27,6 +27,18 @@ describe('pipe generator', () => {
|
|||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
await generatePipeWithDefaultOptions(tree, {
|
||||||
|
path: 'test/src/app/test.pipe.ts',
|
||||||
|
skipFormat: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot();
|
||||||
|
expect(
|
||||||
|
tree.read('test/src/app/test.pipe.spec.ts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not import the pipe into an existing module', async () => {
|
it('should not import the pipe into an existing module', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
addModule(tree);
|
addModule(tree);
|
||||||
|
|||||||
@ -9,6 +9,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
|
"command": "nx g @nx/angular:pipe mylib/src/lib/foo.pipe.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a pipe without providing the file extension. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
"command": "nx g @nx/angular:pipe mylib/src/lib/foo"
|
"command": "nx g @nx/angular:pipe mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -19,7 +23,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the pipe without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the pipe. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
|
|||||||
@ -18,6 +18,8 @@ export async function normalizeOptions(
|
|||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
suffix: 'directive',
|
suffix: 'directive',
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
fileExtension: 'ts',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
|||||||
@ -84,6 +84,47 @@ describe('SCAM Directive Generator', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
projectType: 'application',
|
||||||
|
sourceRoot: 'apps/app1/src',
|
||||||
|
root: 'apps/app1',
|
||||||
|
});
|
||||||
|
|
||||||
|
await scamDirectiveGenerator(tree, {
|
||||||
|
name: 'example',
|
||||||
|
path: 'apps/app1/src/app/example.directive.ts',
|
||||||
|
inlineScam: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const directiveSource = tree.read(
|
||||||
|
'apps/app1/src/app/example.directive.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(directiveSource).toMatchInlineSnapshot(`
|
||||||
|
"import { Directive, NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[example]',
|
||||||
|
standalone: false
|
||||||
|
})
|
||||||
|
export class ExampleDirective {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule],
|
||||||
|
declarations: [ExampleDirective],
|
||||||
|
exports: [ExampleDirective],
|
||||||
|
})
|
||||||
|
export class ExampleDirectiveModule {}
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should create the scam directive correctly and export it for a secondary entrypoint', async () => {
|
it('should create the scam directive correctly and export it for a secondary entrypoint', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
|||||||
@ -7,6 +7,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
"description": "Generate a directive with the exported symbol matching the file name. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
|
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo.directive.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a directive without providing the file extension. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||||
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo"
|
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -19,7 +23,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the SCAM directive without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the SCAM directive. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
|
|||||||
@ -18,6 +18,8 @@ export async function normalizeOptions(
|
|||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
suffix: 'pipe',
|
suffix: 'pipe',
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
fileExtension: 'ts',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
|||||||
@ -86,6 +86,49 @@ describe('SCAM Pipe Generator', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
projectType: 'application',
|
||||||
|
sourceRoot: 'apps/app1/src',
|
||||||
|
root: 'apps/app1',
|
||||||
|
});
|
||||||
|
|
||||||
|
await scamPipeGenerator(tree, {
|
||||||
|
name: 'example',
|
||||||
|
path: 'apps/app1/src/app/example/example.pipe.ts',
|
||||||
|
inlineScam: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const pipeSource = tree.read(
|
||||||
|
'apps/app1/src/app/example/example.pipe.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(pipeSource).toMatchInlineSnapshot(`
|
||||||
|
"import { Pipe, PipeTransform, NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'example',
|
||||||
|
standalone: false
|
||||||
|
})
|
||||||
|
export class ExamplePipe implements PipeTransform {
|
||||||
|
transform(value: unknown, ...args: unknown[]): unknown {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule],
|
||||||
|
declarations: [ExamplePipe],
|
||||||
|
exports: [ExamplePipe],
|
||||||
|
})
|
||||||
|
export class ExamplePipeModule {}
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should create the scam pipe correctly and export it for a secondary entrypoint', async () => {
|
it('should create the scam pipe correctly and export it for a secondary entrypoint', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
|||||||
@ -7,6 +7,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
"description": "Generate a pipe with the exported symbol matching the file name. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
|
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/foo.pipe.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a pipe without providing the file extension. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||||
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/foo"
|
"command": "nx g @nx/angular:scam-pipe mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -19,7 +23,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the SCAM pipe without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the SCAM pipe. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
|
|||||||
@ -19,6 +19,8 @@ export async function normalizeOptions(
|
|||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
suffix: options.type ?? 'component',
|
suffix: options.type ?? 'component',
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
fileExtension: 'ts',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
|||||||
@ -84,6 +84,47 @@ describe('SCAM Generator', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
projectType: 'application',
|
||||||
|
sourceRoot: 'apps/app1/src',
|
||||||
|
root: 'apps/app1',
|
||||||
|
});
|
||||||
|
|
||||||
|
await scamGenerator(tree, {
|
||||||
|
name: 'example',
|
||||||
|
path: 'apps/app1/src/app/example/example.component.ts',
|
||||||
|
inlineScam: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const componentSource = tree.read(
|
||||||
|
'apps/app1/src/app/example/example.component.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(componentSource).toMatchInlineSnapshot(`
|
||||||
|
"import { Component, NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'example',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './example.component.html',
|
||||||
|
styleUrl: './example.component.css'
|
||||||
|
})
|
||||||
|
export class ExampleComponent {}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CommonModule],
|
||||||
|
declarations: [ExampleComponent],
|
||||||
|
exports: [ExampleComponent],
|
||||||
|
})
|
||||||
|
export class ExampleComponentModule {}
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should create the scam correctly and export it for a secondary entrypoint', async () => {
|
it('should create the scam correctly and export it for a secondary entrypoint', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
|||||||
@ -7,6 +7,10 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol matching the file name. It results in the component `FooComponent` at `mylib/src/lib/foo.component.ts`",
|
"description": "Generate a component with the exported symbol matching the file name. It results in the component `FooComponent` at `mylib/src/lib/foo.component.ts`",
|
||||||
|
"command": "nx g @nx/angular:scam mylib/src/lib/foo.component.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a component without providing the file extension. It results in the component `FooComponent` at `mylib/src/lib/foo.component.ts`",
|
||||||
"command": "nx g @nx/angular:scam mylib/src/lib/foo"
|
"command": "nx g @nx/angular:scam mylib/src/lib/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -19,7 +23,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the SCAM without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the SCAM. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
|
|||||||
@ -26,7 +26,7 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
|
|||||||
originalInitCwd = process.env.INIT_CWD;
|
originalInitCwd = process.env.INIT_CWD;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the resolver directory is not under any project root', async () => {
|
it('should throw an error when the resolved directory is not under any project root', async () => {
|
||||||
addProjectConfiguration(tree, 'app1', {
|
addProjectConfiguration(tree, 'app1', {
|
||||||
root: 'apps/app1',
|
root: 'apps/app1',
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -44,7 +44,31 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
|
|||||||
restoreCwd();
|
restoreCwd();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return options as provided when there is a project at the cwd', async () => {
|
it('should return the normalized options 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: 'myComponent',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toStrictEqual({
|
||||||
|
artifactName: 'myComponent',
|
||||||
|
directory: 'apps/app1',
|
||||||
|
fileName: 'myComponent',
|
||||||
|
filePath: 'apps/app1/myComponent.ts',
|
||||||
|
fileExtension: 'ts',
|
||||||
|
fileExtensionType: 'ts',
|
||||||
|
project: 'app1',
|
||||||
|
});
|
||||||
|
|
||||||
|
restoreCwd();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not duplicate the cwd when the provided directory starts with the cwd', async () => {
|
||||||
addProjectConfiguration(tree, 'app1', {
|
addProjectConfiguration(tree, 'app1', {
|
||||||
root: 'apps/app1',
|
root: 'apps/app1',
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -60,53 +84,14 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
|
|||||||
directory: 'apps/app1',
|
directory: 'apps/app1',
|
||||||
fileName: 'myComponent',
|
fileName: 'myComponent',
|
||||||
filePath: 'apps/app1/myComponent.ts',
|
filePath: 'apps/app1/myComponent.ts',
|
||||||
|
fileExtension: 'ts',
|
||||||
|
fileExtensionType: 'ts',
|
||||||
project: 'app1',
|
project: 'app1',
|
||||||
});
|
});
|
||||||
|
|
||||||
restoreCwd();
|
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',
|
|
||||||
});
|
|
||||||
|
|
||||||
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',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should handle window's style paths correctly`, async () => {
|
it(`should handle window's style paths correctly`, async () => {
|
||||||
addProjectConfiguration(tree, 'app1', {
|
addProjectConfiguration(tree, 'app1', {
|
||||||
root: 'apps/app1',
|
root: 'apps/app1',
|
||||||
@ -122,25 +107,8 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
|
|||||||
directory: 'apps/app1',
|
directory: 'apps/app1',
|
||||||
fileName: 'myComponent',
|
fileName: 'myComponent',
|
||||||
filePath: 'apps/app1/myComponent.ts',
|
filePath: 'apps/app1/myComponent.ts',
|
||||||
project: 'app1',
|
fileExtension: 'ts',
|
||||||
});
|
fileExtensionType: 'ts',
|
||||||
});
|
|
||||||
|
|
||||||
it('should support receiving a path as the name', async () => {
|
|
||||||
addProjectConfiguration(tree, 'app1', {
|
|
||||||
root: 'apps/app1',
|
|
||||||
projectType: 'application',
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await determineArtifactNameAndDirectoryOptions(tree, {
|
|
||||||
path: 'apps/app1/foo/bar/myComponent',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toStrictEqual({
|
|
||||||
artifactName: 'myComponent',
|
|
||||||
directory: 'apps/app1/foo/bar',
|
|
||||||
fileName: 'myComponent',
|
|
||||||
filePath: 'apps/app1/foo/bar/myComponent.ts',
|
|
||||||
project: 'app1',
|
project: 'app1',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -161,26 +129,51 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
|
|||||||
directory: 'apps/app1',
|
directory: 'apps/app1',
|
||||||
fileName: 'myComponent.component',
|
fileName: 'myComponent.component',
|
||||||
filePath: 'apps/app1/myComponent.component.ts',
|
filePath: 'apps/app1/myComponent.component.ts',
|
||||||
|
fileExtension: 'ts',
|
||||||
|
fileExtensionType: 'ts',
|
||||||
project: 'app1',
|
project: 'app1',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support receiving a fileName', async () => {
|
it('should support receiving the full file path including the file extension', async () => {
|
||||||
addProjectConfiguration(tree, 'app1', {
|
addProjectConfiguration(tree, 'app1', {
|
||||||
root: 'apps/app1',
|
root: 'apps/app1',
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await determineArtifactNameAndDirectoryOptions(tree, {
|
const result = await determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
fileName: 'myComponent.component',
|
path: 'apps/app1/myComponent.ts',
|
||||||
path: 'apps/app1/myComponent',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toStrictEqual({
|
expect(result).toStrictEqual({
|
||||||
artifactName: 'myComponent',
|
artifactName: 'myComponent',
|
||||||
directory: 'apps/app1',
|
directory: 'apps/app1',
|
||||||
fileName: 'myComponent.component',
|
fileName: 'myComponent',
|
||||||
filePath: 'apps/app1/myComponent.component.ts',
|
filePath: 'apps/app1/myComponent.ts',
|
||||||
|
fileExtension: 'ts',
|
||||||
|
fileExtensionType: 'ts',
|
||||||
|
project: 'app1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore specified suffix when receiving the full file path including the file extension', async () => {
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
root: 'apps/app1',
|
||||||
|
projectType: 'application',
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
|
path: 'apps/app1/myComponent.ts',
|
||||||
|
suffix: 'component',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toStrictEqual({
|
||||||
|
artifactName: 'myComponent',
|
||||||
|
directory: 'apps/app1',
|
||||||
|
fileName: 'myComponent',
|
||||||
|
filePath: 'apps/app1/myComponent.ts',
|
||||||
|
fileExtension: 'ts',
|
||||||
|
fileExtensionType: 'ts',
|
||||||
project: 'app1',
|
project: 'app1',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -201,7 +194,97 @@ describe('determineArtifactNameAndDirectoryOptions', () => {
|
|||||||
directory: 'apps/app1',
|
directory: 'apps/app1',
|
||||||
fileName: 'myComponent',
|
fileName: 'myComponent',
|
||||||
filePath: 'apps/app1/myComponent.tsx',
|
filePath: 'apps/app1/myComponent.tsx',
|
||||||
|
fileExtension: 'tsx',
|
||||||
|
fileExtensionType: 'ts',
|
||||||
project: 'app1',
|
project: 'app1',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support receiving a file path with a non-default file extension', async () => {
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
root: 'apps/app1',
|
||||||
|
projectType: 'application',
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
|
path: 'apps/app1/myComponent.astro',
|
||||||
|
allowedFileExtensions: ['astro'],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toStrictEqual({
|
||||||
|
artifactName: 'myComponent',
|
||||||
|
directory: 'apps/app1',
|
||||||
|
fileName: 'myComponent',
|
||||||
|
filePath: 'apps/app1/myComponent.astro',
|
||||||
|
fileExtension: 'astro',
|
||||||
|
fileExtensionType: 'other',
|
||||||
|
project: 'app1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when the file extension is not supported', async () => {
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
root: 'apps/app1',
|
||||||
|
projectType: 'application',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
|
path: 'apps/app1/myComponent.ts',
|
||||||
|
allowedFileExtensions: ['jsx', 'tsx'],
|
||||||
|
})
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
"The provided file path has an extension (.ts) that is not supported by this generator.
|
||||||
|
The supported extensions are: .jsx, .tsx."
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when having a TypeScript file extension and the --js option is used', async () => {
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
root: 'apps/app1',
|
||||||
|
projectType: 'application',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
|
path: 'apps/app1/myComponent.tsx',
|
||||||
|
js: true,
|
||||||
|
})
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"The provided file path has an extension (.tsx) that conflicts with the provided "--js" option."`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when having a JavaScript file extension and the --js=false option is used', async () => {
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
root: 'apps/app1',
|
||||||
|
projectType: 'application',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
|
path: 'apps/app1/myComponent.jsx',
|
||||||
|
js: false,
|
||||||
|
})
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"The provided file path has an extension (.jsx) that conflicts with the provided "--js" option."`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support customizing the --js option name', async () => {
|
||||||
|
addProjectConfiguration(tree, 'app1', {
|
||||||
|
root: 'apps/app1',
|
||||||
|
projectType: 'application',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
|
path: 'apps/app1/myComponent.tsx',
|
||||||
|
js: true,
|
||||||
|
jsOptionName: 'language',
|
||||||
|
})
|
||||||
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"The provided file path has an extension (.tsx) that conflicts with the provided "--language" option."`
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -12,14 +12,32 @@ import {
|
|||||||
} from 'nx/src/devkit-internals';
|
} from 'nx/src/devkit-internals';
|
||||||
import { join, relative } from 'path';
|
import { join, relative } from 'path';
|
||||||
|
|
||||||
|
const DEFAULT_ALLOWED_JS_FILE_EXTENSIONS = ['js', 'cjs', 'mjs', 'jsx'];
|
||||||
|
const DEFAULT_ALLOWED_TS_FILE_EXTENSIONS = ['ts', 'cts', 'mts', 'tsx'];
|
||||||
|
const DEFAULT_ALLOWED_FILE_EXTENSIONS = [
|
||||||
|
...DEFAULT_ALLOWED_JS_FILE_EXTENSIONS,
|
||||||
|
...DEFAULT_ALLOWED_TS_FILE_EXTENSIONS,
|
||||||
|
'vue',
|
||||||
|
];
|
||||||
|
|
||||||
export type ArtifactGenerationOptions = {
|
export type ArtifactGenerationOptions = {
|
||||||
path: string;
|
path: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
fileExtension?: 'js' | 'jsx' | 'ts' | 'tsx' | 'vue';
|
fileExtension?: string;
|
||||||
fileName?: string;
|
|
||||||
suffix?: string;
|
suffix?: string;
|
||||||
|
allowedFileExtensions?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21.
|
||||||
|
*/
|
||||||
|
js?: boolean;
|
||||||
|
/**
|
||||||
|
* @deprecated Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21.
|
||||||
|
*/
|
||||||
|
jsOptionName?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FileExtensionType = 'js' | 'ts' | 'other';
|
||||||
export type NameAndDirectoryOptions = {
|
export type NameAndDirectoryOptions = {
|
||||||
/**
|
/**
|
||||||
* Normalized artifact name.
|
* Normalized artifact name.
|
||||||
@ -33,6 +51,14 @@ export type NameAndDirectoryOptions = {
|
|||||||
* Normalized file name of the artifact without the extension.
|
* Normalized file name of the artifact without the extension.
|
||||||
*/
|
*/
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
/**
|
||||||
|
* Normalized file extension.
|
||||||
|
*/
|
||||||
|
fileExtension: string;
|
||||||
|
/**
|
||||||
|
* Normalized file extension type.
|
||||||
|
*/
|
||||||
|
fileExtensionType: FileExtensionType;
|
||||||
/**
|
/**
|
||||||
* Normalized full file path of the artifact.
|
* Normalized full file path of the artifact.
|
||||||
*/
|
*/
|
||||||
@ -60,11 +86,10 @@ export async function determineArtifactNameAndDirectoryOptions(
|
|||||||
function getNameAndDirectoryOptions(
|
function getNameAndDirectoryOptions(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ArtifactGenerationOptions
|
options: ArtifactGenerationOptions
|
||||||
) {
|
): NameAndDirectoryOptions {
|
||||||
const path = options.path
|
const path = options.path
|
||||||
? normalizePath(options.path.replace(/^\.?\//, ''))
|
? normalizePath(options.path.replace(/^\.?\//, ''))
|
||||||
: undefined;
|
: undefined;
|
||||||
const fileExtension = options.fileExtension ?? 'ts';
|
|
||||||
let { name: extractedName, directory } =
|
let { name: extractedName, directory } =
|
||||||
extractNameAndDirectoryFromPath(path);
|
extractNameAndDirectoryFromPath(path);
|
||||||
const relativeCwd = getRelativeCwd();
|
const relativeCwd = getRelativeCwd();
|
||||||
@ -75,17 +100,43 @@ function getNameAndDirectoryOptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const project = findProjectFromPath(tree, directory);
|
const project = findProjectFromPath(tree, directory);
|
||||||
const name =
|
|
||||||
options.fileName ??
|
let fileName = extractedName;
|
||||||
(options.suffix ? `${extractedName}.${options.suffix}` : extractedName);
|
let fileExtension: string = options.fileExtension ?? 'ts';
|
||||||
const filePath = joinPathFragments(directory, `${name}.${fileExtension}`);
|
|
||||||
|
const allowedFileExtensions =
|
||||||
|
options.allowedFileExtensions ?? DEFAULT_ALLOWED_FILE_EXTENSIONS;
|
||||||
|
const fileExtensionRegex = new RegExp(
|
||||||
|
`\\.(${allowedFileExtensions.join('|')})$`
|
||||||
|
);
|
||||||
|
const fileExtensionMatch = fileName.match(fileExtensionRegex);
|
||||||
|
|
||||||
|
if (fileExtensionMatch) {
|
||||||
|
fileExtension = fileExtensionMatch[1];
|
||||||
|
fileName = fileName.replace(fileExtensionRegex, '');
|
||||||
|
extractedName = fileName;
|
||||||
|
} else if (options.suffix) {
|
||||||
|
fileName = `${fileName}.${options.suffix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = joinPathFragments(directory, `${fileName}.${fileExtension}`);
|
||||||
|
const fileExtensionType = getFileExtensionType(fileExtension);
|
||||||
|
|
||||||
|
validateFileExtension(
|
||||||
|
fileExtension,
|
||||||
|
allowedFileExtensions,
|
||||||
|
options.js,
|
||||||
|
options.jsOptionName
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
artifactName: options.name ?? extractedName,
|
artifactName: options.name ?? extractedName,
|
||||||
directory: directory,
|
directory,
|
||||||
fileName: name,
|
fileName,
|
||||||
filePath: filePath,
|
fileExtension,
|
||||||
project: project,
|
fileExtensionType,
|
||||||
|
filePath,
|
||||||
|
project,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,3 +196,50 @@ function extractNameAndDirectoryFromPath(path: string): {
|
|||||||
|
|
||||||
return { name, directory };
|
return { name, directory };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFileExtensionType(fileExtension: string): FileExtensionType {
|
||||||
|
if (DEFAULT_ALLOWED_JS_FILE_EXTENSIONS.includes(fileExtension)) {
|
||||||
|
return 'js';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEFAULT_ALLOWED_TS_FILE_EXTENSIONS.includes(fileExtension)) {
|
||||||
|
return 'ts';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'other';
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateFileExtension(
|
||||||
|
fileExtension: string,
|
||||||
|
allowedFileExtensions: string[],
|
||||||
|
js: boolean | undefined,
|
||||||
|
jsOptionName: string | undefined
|
||||||
|
): FileExtensionType {
|
||||||
|
const fileExtensionType = getFileExtensionType(fileExtension);
|
||||||
|
|
||||||
|
if (!allowedFileExtensions.includes(fileExtension)) {
|
||||||
|
throw new Error(
|
||||||
|
`The provided file path has an extension (.${fileExtension}) that is not supported by this generator.
|
||||||
|
The supported extensions are: ${allowedFileExtensions
|
||||||
|
.map((ext) => `.${ext}`)
|
||||||
|
.join(', ')}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (js !== undefined) {
|
||||||
|
jsOptionName = jsOptionName ?? 'js';
|
||||||
|
|
||||||
|
if (js && fileExtensionType === 'ts') {
|
||||||
|
throw new Error(
|
||||||
|
`The provided file path has an extension (.${fileExtension}) that conflicts with the provided "--${jsOptionName}" option.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!js && fileExtensionType === 'js') {
|
||||||
|
throw new Error(
|
||||||
|
`The provided file path has an extension (.${fileExtension}) that conflicts with the provided "--${jsOptionName}" option.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileExtensionType;
|
||||||
|
}
|
||||||
|
|||||||
@ -59,6 +59,16 @@ describe('component', () => {
|
|||||||
expect(appTree.exists('my-lib/src/lib/hello/hello.spec.tsx')).toBeTruthy();
|
expect(appTree.exists('my-lib/src/lib/hello/hello.spec.tsx')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
await expoComponentGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
path: 'my-lib/src/lib/hello/hello.tsx',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(appTree.exists('my-lib/src/lib/hello/hello.tsx')).toBeTruthy();
|
||||||
|
expect(appTree.exists('my-lib/src/lib/hello/hello.spec.tsx')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should generate files for an app', async () => {
|
it('should generate files for an app', async () => {
|
||||||
await expoComponentGenerator(appTree, {
|
await expoComponentGenerator(appTree, {
|
||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import {
|
|||||||
generateFiles,
|
generateFiles,
|
||||||
getProjects,
|
getProjects,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
toJS,
|
|
||||||
Tree,
|
Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { NormalizedSchema, normalizeOptions } from './lib/normalize-options';
|
import { NormalizedSchema, normalizeOptions } from './lib/normalize-options';
|
||||||
@ -25,25 +24,23 @@ export async function expoComponentGenerator(host: Tree, schema: Schema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createComponentFiles(host: Tree, options: NormalizedSchema) {
|
function createComponentFiles(host: Tree, options: NormalizedSchema) {
|
||||||
generateFiles(host, join(__dirname, './files'), options.directory, {
|
generateFiles(
|
||||||
|
host,
|
||||||
|
join(__dirname, './files', options.fileExtensionType),
|
||||||
|
options.directory,
|
||||||
|
{
|
||||||
...options,
|
...options,
|
||||||
tmpl: '',
|
ext: options.fileExtension,
|
||||||
});
|
|
||||||
|
|
||||||
for (const c of host.listChanges()) {
|
|
||||||
let deleteFile = false;
|
|
||||||
|
|
||||||
if (options.skipTests && /.*spec.tsx/.test(c.path)) {
|
|
||||||
deleteFile = true;
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (deleteFile) {
|
if (options.skipTests) {
|
||||||
host.delete(c.path);
|
host.delete(
|
||||||
}
|
joinPathFragments(
|
||||||
}
|
options.directory,
|
||||||
|
`${options.fileName}.spec.${options.fileExtension}`
|
||||||
if (options.js) {
|
)
|
||||||
toJS(host);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +52,14 @@ function addExportsToBarrel(host: Tree, options: NormalizedSchema) {
|
|||||||
if (options.export && !isApp) {
|
if (options.export && !isApp) {
|
||||||
const indexFilePath = joinPathFragments(
|
const indexFilePath = joinPathFragments(
|
||||||
options.projectSourceRoot,
|
options.projectSourceRoot,
|
||||||
options.js ? 'index.js' : 'index.ts'
|
options.fileExtensionType === 'js' ? 'index.js' : 'index.ts'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!host.exists(indexFilePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const indexSource = host.read(indexFilePath, 'utf-8');
|
const indexSource = host.read(indexFilePath, 'utf-8');
|
||||||
if (indexSource !== null) {
|
|
||||||
const indexSourceFile = ts.createSourceFile(
|
const indexSourceFile = ts.createSourceFile(
|
||||||
indexFilePath,
|
indexFilePath,
|
||||||
indexSource,
|
indexSource,
|
||||||
@ -75,7 +76,6 @@ function addExportsToBarrel(host: Tree, options: NormalizedSchema) {
|
|||||||
);
|
);
|
||||||
host.write(indexFilePath, changes);
|
host.write(indexFilePath, changes);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRelativeImportToFile(indexPath: string, filePath: string) {
|
function getRelativeImportToFile(indexPath: string, filePath: string) {
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
<%_ if (classComponent) { _%>
|
||||||
|
import { Component } from 'react';
|
||||||
|
<%_ } else { _%>
|
||||||
|
import React from 'react';
|
||||||
|
<%_ } _%>
|
||||||
|
import { View, Text } from 'react-native';
|
||||||
|
|
||||||
|
<%_ if (classComponent) { _%>
|
||||||
|
export class <%= className %> extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>Welcome to <%= name %>!</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<%_ } else { _%>
|
||||||
|
export function <%= className %>(props) {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>Welcome to <%= name %>!</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
<%_ } _%>
|
||||||
|
|
||||||
|
export default <%= className %>;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react-native';
|
||||||
|
import <%= className %> from './<%= fileName %>';
|
||||||
|
|
||||||
|
describe('<%= className %>', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { root } = render(< <%= className %> />);
|
||||||
|
expect(root).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,15 +1,15 @@
|
|||||||
<% if (classComponent) { %>
|
<%_ if (classComponent) { _%>
|
||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
<% } else { %>
|
<%_ } else { _%>
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
<% } %>
|
<%_ } _%>
|
||||||
import { View, Text } from 'react-native';
|
import { View, Text } from 'react-native';
|
||||||
|
|
||||||
/* eslint-disable-next-line */
|
/* eslint-disable-next-line */
|
||||||
export interface <%= className %>Props {
|
export interface <%= className %>Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
<% if (classComponent) { %>
|
<%_ if (classComponent) { _%>
|
||||||
export class <%= className %> extends Component<<%= className %>Props> {
|
export class <%= className %> extends Component<<%= className %>Props> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@ -19,7 +19,7 @@ export class <%= className %> extends Component<<%= className %>Props> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<% } else { %>
|
<%_ } else { _%>
|
||||||
export function <%= className %>(props: <%= className %>Props) {
|
export function <%= className %>(props: <%= className %>Props) {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
@ -27,6 +27,6 @@ export function <%= className %>(props: <%= className %>Props) {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
<% } %>
|
<%_ } _%>
|
||||||
|
|
||||||
export default <%= className %>;
|
export default <%= className %>;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react-native';
|
||||||
|
import <%= className %> from './<%= fileName %>';
|
||||||
|
|
||||||
|
describe('<%= className %>', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { root } = render(< <%= className %> />);
|
||||||
|
expect(root).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,11 +1,16 @@
|
|||||||
import { getProjects, logger, names, Tree } from '@nx/devkit';
|
import { getProjects, logger, names, Tree } from '@nx/devkit';
|
||||||
|
import {
|
||||||
|
determineArtifactNameAndDirectoryOptions,
|
||||||
|
type FileExtensionType,
|
||||||
|
} from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Omit<Schema, 'js'> {
|
||||||
directory: string;
|
directory: string;
|
||||||
projectSourceRoot: string;
|
projectSourceRoot: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
fileExtension: string;
|
||||||
|
fileExtensionType: FileExtensionType;
|
||||||
className: string;
|
className: string;
|
||||||
filePath: string;
|
filePath: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
@ -18,19 +23,21 @@ export async function normalizeOptions(
|
|||||||
const {
|
const {
|
||||||
artifactName: name,
|
artifactName: name,
|
||||||
fileName,
|
fileName,
|
||||||
|
fileExtension,
|
||||||
|
fileExtensionType,
|
||||||
filePath,
|
filePath,
|
||||||
directory,
|
directory,
|
||||||
project: projectName,
|
project: projectName,
|
||||||
} = await determineArtifactNameAndDirectoryOptions(host, {
|
} = await determineArtifactNameAndDirectoryOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
path: options.path,
|
path: options.path,
|
||||||
fileExtension: 'tsx',
|
allowedFileExtensions: ['js', 'jsx', 'ts', 'tsx'],
|
||||||
|
fileExtension: options.js ? 'js' : 'tsx',
|
||||||
|
js: options.js,
|
||||||
});
|
});
|
||||||
|
|
||||||
const project = getProjects(host).get(projectName);
|
|
||||||
|
|
||||||
const { className } = names(name);
|
const { className } = names(name);
|
||||||
|
const project = getProjects(host).get(projectName);
|
||||||
const { sourceRoot: projectSourceRoot, projectType } = project;
|
const { sourceRoot: projectSourceRoot, projectType } = project;
|
||||||
|
|
||||||
if (options.export && projectType === 'application') {
|
if (options.export && projectType === 'application') {
|
||||||
@ -47,6 +54,8 @@ export async function normalizeOptions(
|
|||||||
directory,
|
directory,
|
||||||
className,
|
className,
|
||||||
fileName,
|
fileName,
|
||||||
|
fileExtension,
|
||||||
|
fileExtensionType,
|
||||||
filePath,
|
filePath,
|
||||||
projectSourceRoot,
|
projectSourceRoot,
|
||||||
projectName,
|
projectName,
|
||||||
|
|||||||
@ -4,9 +4,13 @@
|
|||||||
export interface Schema {
|
export interface Schema {
|
||||||
path: string;
|
path: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
skipFormat: boolean; // default is false
|
skipFormat?: boolean;
|
||||||
skipTests: boolean; // default is false
|
skipTests?: boolean;
|
||||||
export: boolean; // default is false
|
export?: boolean;
|
||||||
classComponent: boolean; // default is false
|
classComponent?: boolean;
|
||||||
js: boolean; // default is false
|
|
||||||
|
/**
|
||||||
|
* @deprecated Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21.
|
||||||
|
*/
|
||||||
|
js?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,11 +7,15 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol matching the file name. It results in the component `Foo` at `mylib/src/foo.tsx`",
|
"description": "Generate a component with the exported symbol matching the file name. It results in the component `Foo` at `mylib/src/foo.tsx`",
|
||||||
"command": "nx g @nx/expo:component mylib/src/foo"
|
"command": "nx g @nx/expo:component mylib/src/foo.tsx"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a component with the exported symbol different from the file name. It results in the component `Custom` at `mylib/src/foo.tsx`",
|
"description": "Generate a component with the exported symbol different from the file name. It results in the component `Custom` at `mylib/src/foo.tsx`",
|
||||||
"command": "nx g @nx/expo:component mylib/src/foo --name=custom"
|
"command": "nx g @nx/expo:component mylib/src/foo.tsx --name=custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate a component without the providing the file extension. It results in the component `Foo` at `mylib/src/foo.tsx`",
|
||||||
|
"command": "nx g @nx/expo:component mylib/src/foo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Generate a class component at `mylib/src/foo.tsx`",
|
"description": "Generate a class component at `mylib/src/foo.tsx`",
|
||||||
@ -21,7 +25,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
@ -35,7 +39,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
"description": "Skip formatting files.",
|
"description": "Skip formatting files.",
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the class `Foo` at `myapp/src/app/foo.ts`",
|
"description": "Generate the class `Foo` at `myapp/src/app/foo.ts`",
|
||||||
|
"command": "nx g @nx/nest:class myapp/src/app/foo.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the class without providing the file extension. It results in the class `Foo` at `myapp/src/app/foo.ts`",
|
||||||
"command": "nx g @nx/nest:class myapp/src/app/foo"
|
"command": "nx g @nx/nest:class myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the class without the file extension. Relative to the current working directory.",
|
"description": "The file path to the class. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -31,7 +31,9 @@ async function normalizeControllerOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ControllerGeneratorOptions
|
options: ControllerGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'controller',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the controller `FooController` at `myapp/src/app/foo.controller.ts`",
|
"description": "Generate the controller `FooController` at `myapp/src/app/foo.controller.ts`",
|
||||||
|
"command": "nx g @nx/nest:controller myapp/src/app/foo.controller.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the controller without providing the file extension. It results in the controller `FooController` at `myapp/src/app/foo.controller.ts`",
|
||||||
"command": "nx g @nx/nest:controller myapp/src/app/foo"
|
"command": "nx g @nx/nest:controller myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the controller without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the controller. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -22,7 +22,9 @@ async function normalizeDecoratorOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: DecoratorGeneratorOptions
|
options: DecoratorGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'decorator',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the decorator `Foo` at `myapp/src/app/foo.decorator.ts`",
|
"description": "Generate the decorator `Foo` at `myapp/src/app/foo.decorator.ts`",
|
||||||
|
"command": "nx g @nx/nest:decorator myapp/src/app/foo.decorator.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the decorator without providing the file extension. It results in the decorator `Foo` at `myapp/src/app/foo.decorator.ts`",
|
||||||
"command": "nx g @nx/nest:decorator myapp/src/app/foo"
|
"command": "nx g @nx/nest:decorator myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the decorator without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the decorator. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeFilterOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: FilterGeneratorOptions
|
options: FilterGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'filter',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the filter `FooFilter` at `myapp/src/app/foo.filter.ts`",
|
"description": "Generate the filter `FooFilter` at `myapp/src/app/foo.filter.ts`",
|
||||||
|
"command": "nx g @nx/nest:filter myapp/src/app/foo.filter.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the filter without providing the file extension. It results in the filter `FooFilter` at `myapp/src/app/foo.filter.ts`",
|
||||||
"command": "nx g @nx/nest:filter myapp/src/app/foo"
|
"command": "nx g @nx/nest:filter myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the filter without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the filter. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeGatewayOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: GatewayGeneratorOptions
|
options: GatewayGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'gateway',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the gateway `FooGateway` at `myapp/src/app/foo.gateway.ts`",
|
"description": "Generate the gateway `FooGateway` at `myapp/src/app/foo.gateway.ts`",
|
||||||
|
"command": "nx g @nx/nest:gateway myapp/src/app/foo.gateway.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the gateway without providing the file extension. It results in the gateway `FooGateway` at `myapp/src/app/foo.gateway.ts`",
|
||||||
"command": "nx g @nx/nest:gateway myapp/src/app/foo"
|
"command": "nx g @nx/nest:gateway myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the gateway without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the gateway. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeGuardOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: GuardGeneratorOptions
|
options: GuardGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'guard',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the guard `FooGuard` at `myapp/src/app/foo.guard.ts`",
|
"description": "Generate the guard `FooGuard` at `myapp/src/app/foo.guard.ts`",
|
||||||
|
"command": "nx g @nx/nest:guard myapp/src/app/foo.guard.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the guard without providing the file extension. It results in the guard `FooGuard` at `myapp/src/app/foo.guard.ts`",
|
||||||
"command": "nx g @nx/nest:guard myapp/src/app/foo"
|
"command": "nx g @nx/nest:guard myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the guard without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the guard. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeInterceptorOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: InterceptorGeneratorOptions
|
options: InterceptorGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'interceptor',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the interceptor `FooInterceptor` at `myapp/src/app/foo.interceptor.ts`",
|
"description": "Generate the interceptor `FooInterceptor` at `myapp/src/app/foo.interceptor.ts`",
|
||||||
|
"command": "nx g @nx/nest:interceptor myapp/src/app/foo.interceptor.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the interceptor without providing the file extension. It results in the interceptor `FooInterceptor` at `myapp/src/app/foo.interceptor.ts`",
|
||||||
"command": "nx g @nx/nest:interceptor myapp/src/app/foo"
|
"command": "nx g @nx/nest:interceptor myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the interceptor without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the interceptor. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -8,7 +8,11 @@ export async function interfaceGenerator(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
rawOptions: InterfaceGeneratorOptions
|
rawOptions: InterfaceGeneratorOptions
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const options = await normalizeOptions(tree, rawOptions);
|
const options = await normalizeOptions(tree, rawOptions, {
|
||||||
|
allowedFileExtensions: ['ts'],
|
||||||
|
skipLanguageOption: true,
|
||||||
|
suffix: 'interface',
|
||||||
|
});
|
||||||
|
|
||||||
return runNestSchematic(tree, 'interface', options);
|
return runNestSchematic(tree, 'interface', options);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the interface `Foo` at `myapp/src/app/foo.interface.ts`",
|
"description": "Generate the interface `Foo` at `myapp/src/app/foo.interface.ts`",
|
||||||
|
"command": "nx g @nx/nest:interface myapp/src/app/foo.interface.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the interface without providing the file extension. It results in the interface `Foo` at `myapp/src/app/foo.interface.ts`",
|
||||||
"command": "nx g @nx/nest:interface myapp/src/app/foo"
|
"command": "nx g @nx/nest:interface myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the interface without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the interface. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeMiddlewareOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: MiddlewareGeneratorOptions
|
options: MiddlewareGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'middleware',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the middleware `FooMiddleware` at `myapp/src/app/foo.middleware.ts`",
|
"description": "Generate the middleware `FooMiddleware` at `myapp/src/app/foo.middleware.ts`",
|
||||||
|
"command": "nx g @nx/nest:middleware myapp/src/app/foo.middleware.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the middleware without providing the file extension. It results in the middleware `FooMiddleware` at `myapp/src/app/foo.middleware.ts`",
|
||||||
"command": "nx g @nx/nest:middleware myapp/src/app/foo"
|
"command": "nx g @nx/nest:middleware myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the middleware without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the middleware. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -25,7 +25,9 @@ async function normalizeModuleOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ModuleGeneratorOptions
|
options: ModuleGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOption = await normalizeOptions(tree, options);
|
const normalizedOption = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'module',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOption,
|
...normalizedOption,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the module `FooModule` at `myapp/src/app/foo.module.ts`",
|
"description": "Generate the module `FooModule` at `myapp/src/app/foo.module.ts`",
|
||||||
|
"command": "nx g @nx/nest:module myapp/src/app/foo.module.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the module without providing the file extension. It results in the module `FooModule` at `myapp/src/app/foo.module.ts`",
|
||||||
"command": "nx g @nx/nest:module myapp/src/app/foo"
|
"command": "nx g @nx/nest:module myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the module without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the module. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizePipeOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: PipeGeneratorOptions
|
options: PipeGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'pipe',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the pipe `FooPipe` at `myapp/src/app/foo.pipe.ts`",
|
"description": "Generate the pipe `FooPipe` at `myapp/src/app/foo.pipe.ts`",
|
||||||
|
"command": "nx g @nx/nest:pipe myapp/src/app/foo.pipe.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the pipe without providing the file extension. It results in the pipe `FooPipe` at `myapp/src/app/foo.pipe.ts`",
|
||||||
"command": "nx g @nx/nest:pipe myapp/src/app/foo"
|
"command": "nx g @nx/nest:pipe myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the pipe without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the pipe. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the provider `Foo` at `myapp/src/app/foo.ts`",
|
"description": "Generate the provider `Foo` at `myapp/src/app/foo.ts`",
|
||||||
|
"command": "nx g @nx/nest:provider myapp/src/app/foo.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the provider without providing the file extension. It results in the provider `Foo` at `myapp/src/app/foo.ts`",
|
||||||
"command": "nx g @nx/nest:provider myapp/src/app/foo"
|
"command": "nx g @nx/nest:provider myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the provider without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the provider. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeResolverOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ResolverGeneratorOptions
|
options: ResolverGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'resolver',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the resolver `FooResolver` at `myapp/src/app/foo.resolver.ts`",
|
"description": "Generate the resolver `FooResolver` at `myapp/src/app/foo.resolver.ts`",
|
||||||
|
"command": "nx g @nx/nest:resolver myapp/src/app/foo.resolver.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the resolver without providing the file extension. It results in the resolver `FooResolver` at `myapp/src/app/foo.resolver.ts`",
|
||||||
"command": "nx g @nx/nest:resolver myapp/src/app/foo"
|
"command": "nx g @nx/nest:resolver myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the resolver without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the resolver. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import type { Tree } from '@nx/devkit';
|
import type { Tree } from '@nx/devkit';
|
||||||
import type {
|
import type {
|
||||||
NestGeneratorWithLanguageOption,
|
|
||||||
NestGeneratorWithResourceOption,
|
NestGeneratorWithResourceOption,
|
||||||
NestGeneratorWithTestOption,
|
NestGeneratorWithTestOption,
|
||||||
NormalizedOptions,
|
NormalizedOptions,
|
||||||
@ -11,8 +10,7 @@ import {
|
|||||||
unitTestRunnerToSpec,
|
unitTestRunnerToSpec,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
export type ResourceGeneratorOptions = NestGeneratorWithLanguageOption &
|
export type ResourceGeneratorOptions = NestGeneratorWithTestOption &
|
||||||
NestGeneratorWithTestOption &
|
|
||||||
NestGeneratorWithResourceOption;
|
NestGeneratorWithResourceOption;
|
||||||
|
|
||||||
export async function resourceGenerator(
|
export async function resourceGenerator(
|
||||||
@ -30,10 +28,11 @@ async function normalizeResourceOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ResourceGeneratorOptions
|
options: ResourceGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
skipLanguageOption: true,
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
|
||||||
spec: unitTestRunnerToSpec(options.unitTestRunner),
|
spec: unitTestRunnerToSpec(options.unitTestRunner),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the resource without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the resource. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
@ -33,11 +33,6 @@
|
|||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "none"],
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"language": {
|
|
||||||
"description": "Nest class language.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["js", "ts"]
|
|
||||||
},
|
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The transport layer.",
|
"description": "The transport layer.",
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
{
|
{
|
||||||
"description": "Generate the service `FooService` at `myapp/src/app/foo.service.ts`",
|
"description": "Generate the service `FooService` at `myapp/src/app/foo.service.ts`",
|
||||||
|
"command": "nx g @nx/nest:service myapp/src/app/foo.service.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Generate the service without providing the file extension. It results in the service `FooService` at `myapp/src/app/foo.service.ts`",
|
||||||
"command": "nx g @nx/nest:service myapp/src/app/foo"
|
"command": "nx g @nx/nest:service myapp/src/app/foo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"description": "The file path to the service without the file extension and suffix. Relative to the current working directory.",
|
"description": "The file path to the service. Relative to the current working directory.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
|
|||||||
@ -28,7 +28,9 @@ async function normalizeServiceOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ServiceGeneratorOptions
|
options: ServiceGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const normalizedOptions = await normalizeOptions(tree, options);
|
const normalizedOptions = await normalizeOptions(tree, options, {
|
||||||
|
suffix: 'service',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
...normalizedOptions,
|
...normalizedOptions,
|
||||||
language: options.language,
|
language: options.language,
|
||||||
|
|||||||
@ -1,27 +1,53 @@
|
|||||||
import type { Tree } from '@nx/devkit';
|
import type { Tree } from '@nx/devkit';
|
||||||
|
import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
||||||
import type {
|
import type {
|
||||||
NestGeneratorOptions,
|
Language,
|
||||||
|
NestGeneratorWithLanguageOption,
|
||||||
NormalizedOptions,
|
NormalizedOptions,
|
||||||
UnitTestRunner,
|
UnitTestRunner,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
|
||||||
|
|
||||||
export async function normalizeOptions(
|
export async function normalizeOptions(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: NestGeneratorOptions
|
options: NestGeneratorWithLanguageOption,
|
||||||
|
normalizationOptions: {
|
||||||
|
allowedFileExtensions?: Array<'js' | 'ts'>;
|
||||||
|
skipLanguageOption?: boolean;
|
||||||
|
suffix?: string;
|
||||||
|
} = {}
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
const { directory, artifactName } =
|
const {
|
||||||
|
allowedFileExtensions = ['js', 'ts'],
|
||||||
|
skipLanguageOption = false,
|
||||||
|
suffix,
|
||||||
|
} = normalizationOptions;
|
||||||
|
|
||||||
|
const { directory, artifactName, fileExtension } =
|
||||||
await determineArtifactNameAndDirectoryOptions(tree, {
|
await determineArtifactNameAndDirectoryOptions(tree, {
|
||||||
path: options.path,
|
path: options.path,
|
||||||
|
allowedFileExtensions,
|
||||||
|
fileExtension: options.language === 'js' ? 'js' : 'ts',
|
||||||
|
js: options.language ? options.language === 'js' : undefined,
|
||||||
|
jsOptionName: 'language',
|
||||||
});
|
});
|
||||||
|
|
||||||
options.path = undefined; // Now that we have `directory` we don't need `path`
|
options.path = undefined; // Now that we have `directory` we don't need `path`
|
||||||
|
|
||||||
|
if (!skipLanguageOption) {
|
||||||
|
// we assign the language based on the normalized file extension
|
||||||
|
options.language = fileExtension as Language;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = artifactName;
|
||||||
|
if (suffix && artifactName.endsWith(`.${suffix}`)) {
|
||||||
|
// strip the suffix if it exists, the nestjs schematic will always add it
|
||||||
|
name = artifactName.replace(`.${suffix}`, '');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
flat: true,
|
flat: true,
|
||||||
name: artifactName,
|
name,
|
||||||
skipFormat: options.skipFormat,
|
|
||||||
sourceRoot: directory,
|
sourceRoot: directory,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
Generate a component named `MyComponent` at `apps/my-app/src/app/my-component/my-component.tsx`:
|
Generate a component named `MyComponent` at `apps/my-app/src/app/my-component/my-component.tsx`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nx g component apps/my-app/src/app/my-component/my-component
|
nx g component apps/my-app/src/app/my-component/my-component.tsx
|
||||||
```
|
```
|
||||||
|
|
||||||
{% /tab %}
|
{% /tab %}
|
||||||
@ -15,7 +15,16 @@ nx g component apps/my-app/src/app/my-component/my-component
|
|||||||
Generate a component named `Custom` at `apps/my-app/src/app/my-component/my-component.tsx`:
|
Generate a component named `Custom` at `apps/my-app/src/app/my-component/my-component.tsx`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nx g component apps/my-app/src/app/my-component/my-component --name=custom
|
nx g component apps/my-app/src/app/my-component/my-component.tsx --name=custom
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
{% tab label="Create a Component Omitting the File Extension" %}
|
||||||
|
|
||||||
|
Generate a component named `MyComponent` at `apps/my-app/src/app/my-component/my-component.tsx` without specifying the file extension:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
nx g component apps/my-app/src/app/my-component/my-component
|
||||||
```
|
```
|
||||||
|
|
||||||
{% /tab %}
|
{% /tab %}
|
||||||
|
|||||||
@ -40,6 +40,19 @@ describe('component', () => {
|
|||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle path with file extension', async () => {
|
||||||
|
await componentGenerator(tree, {
|
||||||
|
path: `${appName}/components/hello/hello.tsx`,
|
||||||
|
style: 'css',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('my-app/components/hello/hello.tsx')).toBeTruthy();
|
||||||
|
expect(tree.exists('my-app/components/hello/hello.spec.tsx')).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
tree.exists('my-app/components/hello/hello.module.css')
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should generate component in default directory for library', async () => {
|
it('should generate component in default directory for library', async () => {
|
||||||
await componentGenerator(tree, {
|
await componentGenerator(tree, {
|
||||||
name: 'hello',
|
name: 'hello',
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
formatFiles,
|
formatFiles,
|
||||||
getProjects,
|
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
||||||
import type { SupportedStyles } from '@nx/react';
|
import type { SupportedStyles } from '@nx/react';
|
||||||
import { componentGenerator as reactComponentGenerator } from '@nx/react';
|
import { componentGenerator as reactComponentGenerator } from '@nx/react';
|
||||||
|
|
||||||
import { addStyleDependencies } from '../../utils/styles';
|
import { addStyleDependencies } from '../../utils/styles';
|
||||||
import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
|
||||||
|
|
||||||
interface Schema {
|
interface Schema {
|
||||||
path: string;
|
path: string;
|
||||||
@ -24,19 +22,15 @@ interface Schema {
|
|||||||
* extra dependencies for css, sass, less style options.
|
* extra dependencies for css, sass, less style options.
|
||||||
*/
|
*/
|
||||||
export async function componentGenerator(host: Tree, options: Schema) {
|
export async function componentGenerator(host: Tree, options: Schema) {
|
||||||
const {
|
// we only need to provide the path to get the project, we let the react
|
||||||
artifactName: name,
|
// generator handle the rest
|
||||||
directory,
|
const { project: projectName } =
|
||||||
project: projectName,
|
await determineArtifactNameAndDirectoryOptions(host, {
|
||||||
} = await determineArtifactNameAndDirectoryOptions(host, {
|
|
||||||
name: options.name,
|
|
||||||
path: options.path,
|
path: options.path,
|
||||||
fileExtension: 'tsx',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const componentInstall = await reactComponentGenerator(host, {
|
const componentInstall = await reactComponentGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
name,
|
|
||||||
classComponent: false,
|
classComponent: false,
|
||||||
routing: false,
|
routing: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The file path to the component without the file extension. Relative to the current working directory.",
|
"description": "The file path to the component. Relative to the current working directory.",
|
||||||
"$default": {
|
"$default": {
|
||||||
"$source": "argv",
|
"$source": "argv",
|
||||||
"index": 0
|
"index": 0
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
||||||
"default": false
|
"x-deprecated": "Provide the full file path including the file extension in the `path` option. This option will be removed in Nx v21."
|
||||||
},
|
},
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
"description": "Skip formatting files.",
|
"description": "Skip formatting files.",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user