đź“”What the hell is a Schema JSON in schematics?

Daniel Barrientos
4 min readNov 29, 2023

--

Introduction

We have already executed our first schematic. Now, we have the opportunity to address the question: “What happens when we need inputs from the user before starting our schematics?” before answer this question we need to understand:

What is a schema json?

JSON schemas are used to validate JSON data. They provide a way to define rules, properties, and configurations for your JSON. An example of this is the angular.json file.

Every JSON object can have a $schema property, which allows us to reference the schema containing all the rules and configurations. The $schema property can point to a local file or a URL link.

You can find more information about JSON schemas here: https://json-schema.org/learn/getting-started-step-by-step

In the context of a schematic, the schema enables us to ask users different types of questions before executing the schematic. However, you might wonder, “Daniel, what if I need to ask a question during the execution of the schematic, rather than just before it?” The simple answer is that schemas do not allow for this. However, there is another approach to accomplish it, which we will explore in a future article.

Go to the action

An scenario can be when you need to create many files with same pattern, for sample: [name].component.ts | [name].service.ts

To accomplish this, we will create a file named schema.json and add this schema to the definition of the schematic in the collection.json as we discussed it in the previous article.

Here you can see all the information about a schema and all the questions that you can make to users.

{
"$schema": "http://json-schema.org/schema", <---- the rules that the json will follow. Help to don't make typos
"$id": "[ID-of-the-schema]",
"title": "[The main reason of the schematic]",
"type": "object", <---- this is because we need to define one or more attribute.
"properties": { <----- All the question that we will ask to the user.
--------------------------------------------------------------------------------
THERE ARE ALL TYPES OF QUESTION THAT YOU CAN MAKE.
--------------------------------------------------------------------------------
"name": { <---- String
"type": "string",
"description": "The name of the resource.",
"$default": {
"$source": "argv",
"index": 0
},
---> This is the text that the user will see.
"x-prompt": "What name would you like to use for this resource (plural, e.g., \"users\")?"
},
"color": { <---- Enum
"type": "string",
"enum": ["red", "green", "blue"]
},
"length": { <----- Number
"type": "number",
"minimum": 0,
"default": 10
},
"interactive": { <---- Boolean
"type": "boolean",
"default": true
},
"config": { <---- Object
"type": "object",
"properties": {
"key": { "type": "string" },
"value": { "type": "string" }
}
},
"items": { <---- Array
"type": "array",
"items": { "type": "string" }
},
"value": { <--- Allow multiples types
"oneOf": [
{ "type": "number" },
{ "type": "string" }
]
}
"profile": { "$ref": "#/definitions/profile" } <---- By reference
},
"definitions": {
"profile": {
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "number" }
}
}
}
--------------------------------------------------------------------------------
The end of the questions
--------------------------------------------------------------------------------
}

Here is the schema that we will use it:

{
"$schema": "http://json-schema.org/schema",
"$id": "MyFirstSchema",
"title": "My first schematic",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the resource.",
"x-prompt": "What name would you like to use for our first schematic?"
}
}
}

But how can we use it into the factory?

Well, first we will create a file at the same level of the schema and factory named: my-schematic.schema.d.ts . If you see, this file has a .d that refers to an interface. It a standard but you can named in any way.

Inside this file will export an interface like this:

export interface SchematicOptions {
name: string;
}

Come back to the factory!

The interface for the parameter of the factory will be this:

import {Rule, Tree} from "@angular-devkit/schematics";
import {SchematicOptions} from "./my-schematic.schema";

export function myFirstSchematic(options: SchematicOptions): Rule {
return (tree: Tree) => {
console.log("This is my first schematic", options);
return tree;
};
}

Run this one more time:

schematics ./src/collection.json:my-schematic

Notes

When we are using the default questions-terminal with schema.json, in some scenarios we need something different. Because these question always happen at the beginning, before the factory function start. However, sometimes we need dynamic questions.

For these reason in another section we’ll create our custom questions terminal.

Happy Coding!

The previous article:

--

--

Daniel Barrientos
Daniel Barrientos

Written by Daniel Barrientos

I'm Principal frontend engineer, Follow me to learn together about web development, UI / UX, and problem solving.

Responses (1)