Customizing generator options
Adding a TypeScript schema
To create a TypeScript schema to use in your generator function, define a TypeScript file next to your schema.json named schema.ts. Inside the schema.ts, define an interface to match the properties in your schema.json file, and whether they are required.
export interface GeneratorOptions {
  name: string;
  type?: string;
}
Import the TypeScript schema into your generator file and replace the any in your generator function with the interface.
import { Tree, formatFiles, installPackagesTask } from '@nrwl/devkit';
import { libraryGenerator } from '@nrwl/js';
export default async function (tree: Tree, schema: GeneratorOptions) {
  await libraryGenerator(tree, { name: `${schema.name}-${schema.type || ''}` });
  await formatFiles(tree);
  return () => {
    installPackagesTask(tree);
  };
}
Adding static options
Static options for a generator don't prompt the user for input. To add a static option, define a key in the schema.json file with the option name, and define an object with its type, description, and optional default value.
{
  "$schema": "http://json-schema.org/schema",
  "id": "my-generator",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Library name",
      "$default": {
        "$source": "argv",
        "index": 0
      }
    },
    "type": {
      "type": "string",
      "description": "Provide the library type, such as 'data-access' or 'state'"
    }
  },
  "required": ["name"]
}
If you run the generator without providing a value for the type, it is not included in the generated name of the library.
Adding dynamic prompts
Dynamic options can prompt the user to select from a list of options. To define a prompt, add a x-prompt property to the option object, set the type to list, and define an items array for the choices.
{
  "$schema": "http://json-schema.org/schema",
  "id": "my-generator",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Library name",
      "$default": {
        "$source": "argv",
        "index": 0
      }
    },
    "type": {
      "type": "string",
      "description": "Provide the library type",
      "x-prompt": {
        "message": "Which type of library would you like to generate?",
        "type": "list",
        "items": [
          {
            "value": "data-access",
            "label": "Data Access"
          },
          {
            "value": "feature",
            "label": "Feature"
          },
          {
            "value": "state",
            "label": "State Management"
          }
        ]
      }
    }
  },
  "required": ["name"]
}
Running the generator without providing a value for the type will prompt the user to make a selection.
Selecting a project
There's a special dynamic option property that populates a selection list with your workspace's projects. Add "x-dropdown": "projects" to your object to provide the prompt.
{
  "$schema": "http://json-schema.org/schema",
  "id": "my-generator",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Component name",
      "$default": {
        "$source": "argv",
        "index": 0
      }
    },
    "project": {
      "type": "string",
      "description": "The project where the component will be located.",
      "x-prompt": "Which project will this component be located in?",
      "x-dropdown": "projects"
    }
  },
  "required": ["name", "project"]
}
All configurable schema options
Properties tagged with ⚠️ are required. Others are optional.
Schema
{
  "properties": {
    "name": {} // see Properties
  },
  "required": [],
  "description": "",
  "definitions": {}, // same as "properties"
  "additionalProperties": false
}
⚠️ properties
The properties of a generator. Properties are listed by name:
{
  "properties_name": {
    // properties configuration
  }
}
The available options of the properties' configuration can be seen in the Properties section.
required
The property keys that are required. Example:
{
  "properties": {
    "name": {
      "type": "string"
    },
    "type": {
      "type": "string"
    }
  },
  "required": ["name"]
}
In this example, the property name is required, while the property type is optional. You can define your TypeScript schema like this:
interface Schema {
  name: string; // required
  type?: string; // optional
}
description
The description of your schema for users to understand what they can do with the generator.
Example: A exception class generator.
definitions
Define an auxiliary schema in order to be reused and combined later on. Examples:
{
  "$id": "https://example.com/schemas/customer",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "shipping_address": { "$ref": "/schemas/address" },
    "billing_address": { "$ref": "/schemas/address" }
  },
  "required": [
    "first_name",
    "last_name",
    "shipping_address",
    "billing_address"
  ],
  "$defs": {
    "address": {
      "$id": "/schemas/address",
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city": { "type": "string" },
        "state": { "$ref": "#/definitions/state" }
      },
      "required": ["street_address", "city", "state"],
      "definitions": {
        "state": { "enum": ["CA", "NY", "... etc ..."] }
      }
    }
  }
}
In this example, we defined the state in the definitions and reference it later by $ref.
Reference 1: JSON Schema > Definitions & References
Reference 2: Understanding JSON Schema > Extending Recursive Schemas
additionalProperties
Specify whether the additional properties in the input are allowed. Example:
{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
  },
  "additionalProperties": false
}
In this example, this schema only accepts the properties that are explicitly defined in the properties object such like:
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }
Any additional properties will be considered invalid.
{
  "number": 1600,
  "street_name": "Pennsylvania",
  "street_type": "Avenue",
  "direction": "NW"
}
The above examples are from Understanding JSON schema > Additional Properties. There are more details in that tutorial.
Properties
{
  "type": "",
  "required": [],
  "enum": [],
  "properties": {},
  "oneOf": [],
  "anyOf": [],
  "allOf": [],
  "items": [],
  "alias": "",
  "aliases": [],
  "description": "",
  "format": "",
  "visible": false,
  "default": "",
  "$ref": "",
  "$default": {
    "$source": "argv",
    "index": 0
  },
  "additionalProperties": false,
  "x-prompt": {
    "message": "",
    "type": "",
    "items": [],
    "multiselect": false
  },
  "x-deprecated": false,
  "x-priority": "important",
  "x-dropdown": "projects"
}
Options available in number type:
{
  "multipleOf": 5,
  "minimum": 5,
  "exclusiveMinimum": 4,
  "maximum": 200,
  "exclusiveMaximum": 201
}
Options available in string type:
{
  "pattern": "\\d+",
  "minLength": 10,
  "maxLength": 100
}
type
The type of the input. Can be one of string, number, bigint, boolean, object or array.
Example:
{
  "type": "string",
  "minLength": "10"
}
required
The property keys that are required. Example:
{
  "properties": {
    "a": {
      "type": "boolean"
    },
    "b": {
      "type": "boolean"
    }
  },
  "required": ["a"]
}
In this example, the property a is required, while the property b is optional.
enum
Make sure that the value is in the enumeration. Example:
{
  "type": "string",
  "enum": ["foo", "bar"]
  // valid case: `foo`, `bar`
  // invalid case: any other string like `hello`
}
properties
The sub-properties of a property. Example:
{
  "index": {
    "description": "Configures the generation of the application's HTML index.",
    "type": "object",
    "properties": {
      "input": {
        "type": "string",
        "minLength": 1,
        "description": "The path of a file to use for the application's generated HTML index."
      },
      "output": {
        "type": "string",
        "minLength": 1,
        "default": "index.html",
        "description": "The output path of the application's generated HTML index file. The full provided path will be used and will be considered relative to the application's configured output path."
      }
    },
    "required": ["input"]
  }
}
In this example, the property index is a object, which accepts two properties: input and output.
oneOf
Only accepts a value that matches one of the condition properties. Example:
{
  "sourceMap": {
    "description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
    "default": true,
    "oneOf": [
      {
        "type": "boolean"
      },
      {
        "type": "string"
      }
    ]
  }
}
In this example, sourceMap accepts a value whose type is either boolean or string. Another example:
{
  "optimization": {
    "description": "Enables optimization of the build output.",
    "oneOf": [
      {
        "type": "object",
        "properties": {
          "scripts": {
            "type": "boolean",
            "description": "Enables optimization of the scripts output.",
            "default": true
          },
          "styles": {
            "type": "boolean",
            "description": "Enables optimization of the styles output.",
            "default": true
          }
        },
        "additionalProperties": false
      },
      {
        "type": "boolean"
      }
    ]
  }
}
optimization accepts either an object that includes scripts and styles properties, or a boolean that switches the optimization on or off.
anyOf
Only accepts a value that matches one of the condition properties. Example:
{
  "format": {
    "type": "string",
    "description": "ESLint Output formatter (https://eslint.org/docs/user-guide/formatters).",
    "default": "stylish",
    "anyOf": [
      {
        "enum": [
          "stylish",
          "compact",
          "codeframe",
          "unix",
          "visualstudio",
          "table",
          "checkstyle",
          "html",
          "jslint-xml",
          "json",
          "json-with-metadata",
          "junit",
          "tap"
        ]
      },
      { "minLength": 1 }
    ]
  }
}
In this example, format accepts a string listed in the enum property, and/or a string whose minimum length is larger than 1.
allOf
Only accepts a value that matches all the condition properties. Example:
{
  "a": {
    "type": "number",
    "allOf": [{ "multipleOf": 5 }, { "multipleOf": 3 }]
  }
}
In this example, a only accepts a value that can be divided by 5 and 3.
alias
The alias of this property. Example:
{
  "tags": {
    "type": "string",
    "description": "Add tags to the project (used for linting)",
    "alias": "t"
  },
  "directory": {
    "type": "string",
    "description": "A directory where the project is placed",
    "alias": "d"
  }
}
You can pass either --tags or -t to provide the value of the property tag; either --directory or -d to provide the value of the property directory.
aliases
Mostly same as alias, but it can accept multiple aliases. Example:
{
  "directory": {
    "description": "Directory where the generated files are placed.",
    "type": "string",
    "aliases": ["dir", "path"]
  }
}
You can pass either --dir, --path or even --directory to provide the value of the property directory.
description
The description for users of your property. Example:
{
  "flat": {
    "description": "Flag to indicate if a directory is created.",
    "type": "boolean",
    "default": false
  }
}
format
The format of this property. Available options are: path, html-selector, etc. Example:
{
  "prefix": {
    "type": "string",
    "format": "html-selector",
    "description": "The prefix to apply to generated selectors.",
    "alias": "p"
  }
}
In this example, the value provided for prefix should be formatted using the html-selector schema.
visible
Indicate whether the property should be visible in the configuration UI. Example:
{
  "path": {
    "format": "path",
    "visible": false
  }
}
In this example, the path won't be visible in the configuration UI, and will apply a default value.
default
The default value of this property. Example:
{
  "linter": {
    "description": "The tool to use for running lint checks.",
    "type": "string",
    "enum": ["eslint", "tslint"],
    "default": "eslint"
  }
}
In this example, linter will pick eslint when users do not provide the value explicitly.
$ref
Reference to a schema. Examples can be seen in the definitions section.
$default
The default source of this property. The full declaration of $default is:
// with ? - optional
// without ? - required
// | - or
$default?: { $source: 'argv'; index: number } | { $source: 'projectName' };
Example of $source: argv:
{
  "name": {
    "type": "string",
    "description": "Library name",
    "$default": {
      "$source": "argv",
      "index": 0
    },
    "x-prompt": "What name would you like to use for the library?",
    "pattern": "^[a-zA-Z].*$"
  }
}
name will pick the first argument of the command line as the default value.
Example of $source: projectName:
{
  "project": {
    "type": "string",
    "description": "The name of the project.",
    "alias": "p",
    "$default": {
      "$source": "projectName"
    },
    "x-prompt": "What is the name of the project for the migration?"
  }
}
project will pick the default project name as the default value.
additionalProperties
See the above additionalProperties section.
x-prompt
Prompt and help user to input the value of the property. It can be a string or a object. The full declaration is:
// with ? - optional
// without ? - required
// | - or
'x-prompt'?:
  | string
  | { message: string; type: string; items: any[]; multiselect?: boolean };
The string x-prompt example:
{
  "name": {
    "type": "string",
    "description": "Library name",
    "$default": {
      "$source": "argv",
      "index": 0
    },
    "x-prompt": "What is your desired library name?"
  }
}
The object example can be seen at Adding dynamic prompts.
⚠️ x-prompt > message
The prompt message.
Example: Which type of library would you like to generate?
⚠️ x-prompt > type
The type of the prompt.
⚠️ x-prompt > items
The choice of the prompt. The x-prompt.type must be list. The declaration of items is:
// with ? - optional
// without ? - required
// | - or
items?: (string | { name: string; message: string })[];
Example that contains value and label:
{
  "style": {
    "description": "The file extension to be used for style files.",
    "type": "string",
    "default": "css",
    "enum": ["css", "scss", "sass", "less"],
    "x-prompt": {
      "message": "Which stylesheet format would you like to use?",
      "type": "list",
      "items": [
        {
          "value": "css",
          "label": "CSS"
        },
        {
          "value": "scss",
          "label": "SASS(.scss)  [ http://sass-lang.com   ]"
        },
        {
          "value": "sass",
          "label": "SASS(.sass)  [ http://sass-lang.com   ]"
        },
        {
          "value": "less",
          "label": "LESS         [ http://lesscss.org     ]"
        }
      ]
    }
  }
}
x-prompt > multiselect
Allow to multi-select in the prompt.
x-deprecated
Indicate whether the property is deprecated. Can be a boolean or a string. The boolean example:
{
  "setupFile": {
    "description": "The name of a setup file used by Jest. (use Jest config file https://jestjs.io/docs/en/configuration#setupfilesafterenv-array)",
    "type": "string",
    "x-deprecated": true
  }
}
This indicates that the property setupFile is deprecated without a reason. The string example:
{
  "tsSpecConfig": {
    "type": "string",
    "description": "The tsconfig file for specs.",
    "x-deprecated": "Use the `tsconfig` property for `ts-jest` in the e2e project `jest.config.js` file. It will be removed in the next major release."
  }
}
This indicates that users should use the tsconfig property rather than specify this property.
x-priority
Indicates the priority of a property. Can either be important or internal. This will be used to sort the properties on nx.dev, in Nx Console and when calling a generator with --help. important properties are displayed right after required ones while internal properties are shown at the end or hidden.
{
  "directory": {
    "description": "The directory of the new application.",
    "type": "string",
    "x-priority": "important"
  }
}
x-dropdown
Populates the list of projects in your workspace to a selection prompt.
{
  "project": {
    "description": "The project where the component will be located.",
    "type": "string",
    "x-prompt": "Which project will this component be located in?",
    "x-dropdown": "projects"
  }
}
number specific: multipleOf
Make sure that the number can be divided by the specified number. Example:
{
  "a": {
    "type": "number",
    "multipleOf": 5
  }
}
In this example, a only accepts the value that can be divided by 5.
number specific: minimum
Make sure that the number is greater than or equal to the specified number.
{
  "value": {
    "type": "number",
    "minimum": 5
  }
}
In this example, value only accepts a value that is greater than or equal to 5 (value >= 5).
You can read more at Understanding JSON schema.
number specific: exclusiveMinimum
Make sure that the number is greater than the specified number.
{
  "value": {
    "type": "number",
    "exclusiveMinimum": 4
  }
}
In this example, value only accepts a value that is greater than 4 (value > 4).
You can read more at Understanding JSON schema.
number specific: maximum
Make sure that the number is less than or equal to the specified number.
{
  "value": {
    "type": "number",
    "maximum": 200
  }
}
In this example, value only accepts a value that is less than or equal to 200 (value <= 200).
You can read more at Understanding JSON schema.
number specific: exclusiveMaximum
Make sure that the number is less than the specified number.
{
  "value": {
    "type": "number",
    "maximum": 201
  }
}
In this example, value only accepts a value that is less than 201 (value < 201).
You can read more at Understanding JSON schema.
string specific: pattern
Make sure that the string matches the Regexp pattern.
{
  "value": {
    "type": "string",
    "pattern": "^\\d+$"
  }
}
In this example, value requires the value to match the ^\\d+$ pattern, which is a regular expression that matches a string that contains only digits.
string specific: minLength
Make sure that the string length is greater than or equal to the specified value.
{
  "value": {
    "type": "string",
    "minLength": 10
  }
}
In this example, value requires the value to be at least 10 characters long.
string specific: maxLength
Make sure that the string length is less than or equal to the specified value.
{
  "value": {
    "type": "string",
    "maxLength": 10
  }
}
In this example, value requires the value to be at most 10 characters long.
More information
The current configurable options (and its parse method) can be found here. You would need a basic knowledge of TypeScript to read this.
Most examples are referenced from the codebase of Nx. Thanks to everyone who have ever contributed to Nx!