Angular Schematics:如何在schema.json中定义默认变量? (projectName)

时间:2019-02-05 01:14:18

标签: angular schema default angular-schematics

如何在schema.json中为角度示意图“属性”定义默认变量?

我尝试研究angular source code本身,但无法弄清楚。我发现如果使用关键字“ $ source”,那么它前面的字符串将以某种方式解析为某个值。

例如,“ argv”和“ projectName”是两个变量,当这样编写时,它们将被解析为实际值:

     "project": {
         "alias": "p",
         "type": "string",
         "description": "The name of the project.",
         "$default": {
             "$source": "projectName"
         }
     },

    "name": {
      "type": "string",
      "description": "The package name for the new schematic.",
      "$default": {
        "$source": "argv",
        "index": 0
      }
    },

那么如何定义自己的变量?它们实际上是变量吗?还有哪些其他变量?

我还发现了另一个示例,如果我将其复制粘贴到自己的项目中,将无法正常工作:

    "version": {
      "type": "string",
      "description": "The version of the Angular CLI to use.",
      "visible": false,
      "$default": {
        "$source": "ng-cli-version"
      }
    },

Here find the full code

从我的观察中,我希望可以将其解析为一个值,但是我不敢相信。

提前谢谢大家!

5 个答案:

答案 0 :(得分:0)

您定义的变量当然取决于原理图的行为。例如,我有一个带有自定义变量的new application schematic,以允许用户指定要应用于应用程序的身份验证类型:

要从命令行调用此原理图,用户应输入ng new my-application-schematic-with-sso --collection=@simple-schematic --authentication=SSO(如果未明确提供命令行开关,则x-prompt向用户提供选项列表。另请参见{ {3}}。

"authentication": {
    "description": "The authentication strategy to use",
    "default": "None",
    "x-prompt": {
        "message": "Which authentication strategy would you like to use?",
        "type": "list",
        "items": [
            {
                "value": "None",
                "label": "None"
            },
            {
                "value": "SSO",
                "label": "SSO"
            }
        ]
    }
},

此原理图还利用argv模式捕获工作空间的名称:

"name": {
    "description": "The name of the workspace",
    "type": "string",
    "$default": {
        "$source": "argv",
        "index": 0
    }
},...

因此,调用此原理图的命令行语法类似于ng new my-new-schematic --collection=@simple-schematic,并会生成一个名为 my-new-schematic 的新工作区。由于未提供--authentication标志,因此系统会提示用户选择 SSO

您在原始问题中指出的与您定义的架构和变量相关的一项重要行为可能会导致 undefined 问题(尤其是当变量具有默认值时),从而导致错误链接逻辑示意图命令的模式。

例如,schema逻辑示意图对象的ng-new属性指示如何将提供的CLI输入转换为传递到自定义逻辑示意图的Angular ng-new schema for style options

{
  "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
  "extends": "@schematics/angular",
  "schematics": {
    "ng-new": {
      "description": "new workspace",
      "factory": "./ng-new",
      "schema": "./ng-new/schema.json"
    }
  }
}

根据是否指定了schema属性,从调试测试中获得了两个截屏:

corresponding object

再次使用明确指定的模式: No schema property fails to pick up default values specified

答案 1 :(得分:0)

只需使用"default": "YOUR_VALUE",但不要忘记之后再运行npm run build

答案 2 :(得分:0)

OffTopic:还有interpolation
您可以在packages/_/devkit/package/schema.json中找到它。 ;-)


您可以看看
packages/angular_devkit/core/src/json/schema/registry.ts
在这里可以找到称为
的方法 addSmartDefaultProvider<T>(source: string, provider: SmartDefaultProvider<T>)

似乎他们正在使用此方法来创建他们所谓的“智能默认值”,但并非总是如此。
通过{br />对argv中的packages/angular/cli/utilities/json-schema.ts进行检查 const $defaultIndex = (json.isJsonObject($default) && $default['$source'] == 'argv')
所以没有统一的方法。蛮黑的恕我直言。

addSmartDefaultProvider方法主体中,您将找到以下有趣的块:

// We cheat, heavily.
compilationSchemInfo.smartDefaultRecord.set(
// tslint:disable-next-line:no-any
   JSON.stringify((it as any).dataPathArr.slice(1, (it as any).dataLevel + 1) as string[]),
   schema,
);

如果要进一步走下去,您会发现:

答案 3 :(得分:0)

DevRok快要出现了。我想完全回答您的问题,我们需要研究addSmartDefaultProvider的用法。我在7.3.x分支中找到了这些引用(因为这是我们在工作中仍在使用的)。

Reference 1在package / angular / cli / models / schematic-command.ts中

workflow.registry.addSmartDefaultProvider('projectName', () => {

Reference 2在package / angular / cli / commands / new-impl.ts中

this._workflow.registry.addSmartDefaultProvider('ng-cli-version', () => version);

因此,看来ng-cli-version仅在运行ng new而不是ng generate时才有效。看来ng-cli-versionprojectName是目前唯一定义的智能默认提供程序,但是将来添加更多应该很简单。

出于完整性考虑,我想引用DevRok's answer来引用packages/angular/cli/utilities/json-schema.ts中定义的argv的伪智能默认提供程序。

答案 4 :(得分:0)

不确定如何在schema.json中进行设置...不确定是否有键值对(“默认”:“值”没有任何作用)。

所以我在工厂函数(index.ts)中处理了一条if语句

if (!_options.yourVariable) {
     _options.yourVariable = 'yourDefaultValue'
}

效果很好。