如何在 Angular 示意图中使用当前路径

How to use current path in Angular schematics

我正在开发生成一些文件的原理图。我想在当前目录中有新文件,即

我的项目根目录是 /src/app。当我在文件夹 /src/app/features/f1 中并键入

ng g my:some-schemaitc --name=name

我正在等待新文件

/src/app/features/f1/name.ts

相反,结果是

/src/app/name.ts

我想实现与 ng g class --name=name 相同的行为。当我在目录 /src/app/features/f1 中键入 ng g class --name=class 时,结果将是

/src/app/features/f1/class.ts

我试图模仿 Angular ng g class 行为 schematics source code,但没有令人满意的结果。我的代码几乎一样。

有人用过当前路径吗?

无意间发现了一个全局变量__dirname,它存储了当前路径。例如:

console.log('DIR', __dirname);

按照 angular docs

中提到的步骤进行操作

您会 运行 遇到一些问题。例如

1) const workspaceConfig = tree.read('/angular.json');

// 在使用 'schematics' 命令时为空,但在使用 'ng g' 命令时有效。

2) 类似地,'options.path' 在使用 'schematics' 命令时将是未定义的,但在使用 'ng g' 命令时将起作用。

您需要将路径添加到 schema.json 文件,然后在您的函数中,您应该能够使用 'options.path' 来获取当前位置。然而,正如我提到的,我无法在使用 'schematics' 命令时让它工作。我只能在使用 'ng g' 命令时让它工作。

这里是我的文件的例子

1) ..schematics/ng-generate/customComponent/schema.json

{
    "$schema": "http://json-schema.org/schema",
    "id": "GenerateCustomComponent",
    "title": "Generate Custom Component",
    "type": "object",
    "properties": {
        "name": {
            "description": "The name for the custom component.",
            "type": "string",
            "x-prompt": "What is the name for the custom component?"
        },
        "path": {
            "type": "string",
            "format": "path",
            "description": "The path at which to create the component file, relative to the current workspace. Default is a folder with the same name as the component in the project root.",
            "visible": false
        }
    },
    "required": [
        "name"
    ]
}

2) ..schematics/ng-generate/customComponent/schema.ts

import { Schema as ComponentSChema } from '@schematics/angular/component/schema';

export interface Schema extends ComponentSChema {
    // The name of the custom component
    name: string;
}

2) ..schematics/ng-generate/customComponent/index.ts

import {
  Rule, Tree, SchematicsException,
  apply, url, applyTemplates, move,
  chain, mergeWith
} from '@angular-devkit/schematics';

import { strings, experimental, normalize } from '@angular-devkit/core';

import { Schema as CustomSchema } from './schema';

export function generate(options: CustomSchema): Rule {
    return (tree: Tree) => {
        const workspaceConfig = tree.read('/angular.json'); // will return null when using schematics command but will work when using ng g
        console.log('workspaceConfig::', workspaceConfig);
        console.log('path:', options.path); // will be undefined when using schematics command but will work when using ng g
        
        // from now following along with angular docs with slight modifications. 
        if (workspaceConfig && !options.path) {
            const workspaceContent = workspaceConfig.toString();
            console.log('workspaceContent::', workspaceContent);
            
            const workspace: experimental.workspace.WorkspaceSchema = JSON.parse(workspaceContent);
            console.log('workspace', workspace);
            
            options.project = workspace.defaultProject;
            const projectName = options.project as string;
            const project = workspace.projects[projectName];
            const projectType = project.projectType === 'application' ? 'app' : 'lib';
            console.log('projectType::', projectType);
            
            options.path = `${project.sourceRoot}/${projectType}`;
        }

        
        if (options.path) { 
           // this will be used by the ng g command
            const templateSource = apply(url('./files'), [
                applyTemplates({
                    classify: strings.classify,
                    dasherize: strings.dasherize,
                    name: options.name
                }),
                move(normalize(options.path as string))
            ]);
            return chain([
                mergeWith(templateSource)
            ]);
        } else {
            // this will be used by the schematics command
            const templateSource = apply(url('./files'), [
                applyTemplates({
                    classify: strings.classify,
                    dasherize: strings.dasherize,
                    name: options.name
                })
            ]);
            return chain([
                mergeWith(templateSource)
            ]);
        }
    };
}