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

Posted

技术标签:

【中文标题】Angular Schematics:如何在 schema.json 中定义默认变量? (项目名)【英文标题】:Angular Schematics: How to define default variables in schema.json? (projectName) 【发布时间】:2019-06-28 19:26:36 【问题描述】:

如何在 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

根据我的观察,我希望这会被解决为一个值,但我不相信。

提前谢谢大家!

【问题讨论】:

这不是一个答案,只是一个评论:我发现的关于原理图(Angular 7)的最佳文章是medium.com/rocket-fuel/… 这不是这个问题的一个很好的参考。我找到的最接近的东西是来自Hakernoon 的这篇文章,这仍然不是我问题的答案。 【参考方案1】:

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

要从命令行调用此原理图,用户将输入ng new my-application-schematic-with-sso --collection=@simple-schematic --authentication=SSO(如果未明确提供命令行开关,x-prompt 会向用户提供选项列表。另请参阅Angular ng-new schema for style options。

"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 标志,系统将提示用户选择NoneSSO

与您定义的架构和变量相关的一个重要行为可能导致您在原始问题中指出的 undefined 问题(尤其是当您的变量具有默认值时)架构到原理图命令。

例如,ng-new 原理图对象的schema 属性指示如何将提供的 CLI 输入转换为传递给自定义原理图的 corresponding object。


  "$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 属性来调试测试的两个不同屏幕截图:

再次明确指定架构:

【讨论】:

请再次阅读我的问题!这与我的问题完全无关!我问的是由框架动态归档默认值,而不是“如何为用户提供选项”。 我想再看看。我将“那么我如何定义自己的变量?它们实际上是变量吗?还有哪些其他变量可用?”作为您的问题。您能否重申您要解决的问题,即“我想为自定义原理图中的属性添加默认值?” (我想我可以帮忙,一旦我从你那里得到更多的细节,我会修改我的答案)。 当然,太好了!我需要 Angular CLI 来填充运行原理图命令的参数的默认值。例如,“argv”关键字是 CLI 理解并在运行时替换它(或传递)正确值的东西。或者另一个例子,正如我在问题中所描述的那样, "$source": "projectName" 将被替换为实际的项目名称。我需要的是能够告诉 Angular 自己将一个值传递给命令给用户,而不需要每次都编写它。 例如,假设我想获取安装的 angular-core 版本并通过参数将其传递给原理图。【参考方案2】:

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

【讨论】:

这是基本用例,问题是如何使其动态化,而不是“如何提供默认值?”。如何让“YOUR_VALUE”实用多变?【参考方案3】:

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

你可以看看 packages/angular_devkit/core/src/json/schema/registry.ts 您可以在其中找到一个名为 addSmartDefaultProvider<T>(source: string, provider: SmartDefaultProvider<T>)

的方法

看起来他们正在使用这种方法来创建他们所说的“智能默认值”,但并非总是如此。 在packages/angular/cli/utilities/json-schema.ts 中检查argv 是通过const $defaultIndex = (json.isJsonObject($default) && $default['$source'] == 'argv') 完成的所以没有统一的方法。相当hacky恕我直言。

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,
);

如果你要更进一步,你会发现:

Angular-CLI 使用 Ajv 库。 参数 it 代表当前的'Schema Compilation Context' dataPathArr 属性是“Vaidation time variable” ....

【讨论】:

【参考方案4】:

DevRok 就快到了。我认为要完全回答您的问题,我们需要查看addSmartDefaultProvider 的用法。我在 7.3.x 分支中找到了这些参考资料(因为这是我们仍在工作中使用的)。

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

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

Reference 2 在 packages/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 的伪智能默认提供程序。

【讨论】:

【参考方案5】:

不确定你是如何在 schema.json 中设置的...不确定是否有一个键值对(“default”:“value”没有做任何事情)。

所以我在工厂函数 (index.ts) 中使用了 if 语句

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

效果很好。

【讨论】:

以上是关于Angular Schematics:如何在 schema.json 中定义默认变量? (项目名)的主要内容,如果未能解决你的问题,请参考以下文章

如何运行@angular-eslint/schematics:convert-tslint-to-eslint

如何使用 Visual Studio Code 调试 Angular Schematics 实现

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

Angular Schematics 相对路径

找不到模块'@angular-devkit/schematics/tasks'

Angular 6 Schematics 无效源(未定义)