SlideShare a Scribd company logo
ANGULARANGULAR
SCHEMATICSSCHEMATICS
THE UNKNOWN HEROTHE UNKNOWN HERO
CHRIS NORINGCHRIS NORING
CLOUD DEVELOPER EXPERT AT MICROSOFTCLOUD DEVELOPER EXPERT AT MICROSOFT
Google Developer Expert in Angular and Web Techs
@chris_noring
https://so chris.github.io
Published author
Public Speaker
So ware Engineer
WORKFLOW TOOLWORKFLOW TOOL
CAN APPLY TRANSFORMS TO YOUR PROJECTCAN APPLY TRANSFORMS TO YOUR PROJECT
example of usage:
scaffold: new components, services,
update your code to fix breaking changes in
dependencies.
or add a new configuration option or framework to
an existing project
ANGULAR CLI - SECRET SAUCEANGULAR CLI - SECRET SAUCE
GENERIC FACILITY TO SUPPORT THE CLIGENERIC FACILITY TO SUPPORT THE CLI
SCAFFOLDINGSCAFFOLDING
improve your development productivity
Ease uf use and development
Extensibility and reuseability
Atomicity
Asynchronicity
TREETREE
OVER FILE SYSTEMOVER FILE SYSTEM
not affecting the file system directly,
you describe what transformations you
want done on a Tree
INSTALLATIONINSTALLATION
npm install -g @angular-devkit/schematics-cli
This will install a schematics
executable, which you can use to
create a blank Schematics project
EXAMPLEEXAMPLE
YOUR FIRST SCHEMATICYOUR FIRST SCHEMATIC
schematics blank --name=my-component
Angular Schematics
index.ts, where our rules live
collection.json, a description of our project
INDEX.TSINDEX.TS
return a function of type Rule
options input, is an object representing command
line args
inner function takes Tree and SchematicContext,
tree is file tree
index.ts
COLLECTION.JSONCOLLECTION.JSON
description, description of project
factory, points to the directory/starter module
collection.json
BUILD AND RUNBUILD AND RUN
--name=test, command line arg
npm run build
schematics .:my-component --name=test
it says: nothing to be done!!
not surprised, cause our Rule factory function does
nothing
EXAMPLEEXAMPLE
SCAFFOLD SOME FILES, WITH CONTENTSCAFFOLD SOME FILES, WITH CONTENT
update Rule factory function
create files, with content
tree.create(filename, file-content)
let's create a build and run script
npm run execute
Angular Schematics
we didn't actual create any files, we are in dry-run
mode
It shows what would happen if applied
to a file system
let's shut off dry-run
I don't see a difference??
oh, so they were created in the in the project
Just add the follwing to your schematics executable
--dry-run=false
There are four methods that directly create a change in
a Tree
create
delete
rename
overwrite
TIPS AND TRICKSTIPS AND TRICKS
watch mode, rebuild your project on changes
npm run build -w
Debugging
node --inspect-brk <path_to_schematics>/schematics
.:myComponent --name=test
TESTING OUT YOUR SCHEMATICSTESTING OUT YOUR SCHEMATICS
scaffold an Angular project
npm link to the schematics
ng generate
ng new SchematicsDemo
npm link <path to schematics>
// tip: run pwd and copy result
ng generate my-service:my-service someName
Angular Schematics
Voila, our Vikings are added
EXAMPLEEXAMPLE
USING AN EXISTING SCHEMATICUSING AN EXISTING SCHEMATIC
WHAT IS A COLLECTION?WHAT IS A COLLECTION?
Schematics Collections are sets of named
schematics, that are published and installed by
users.
Angular team publishes and maintains the official
@schematics/angular collection e.g component,
module, application
Scenario: add some disclaimer text on top of
component
We start by scaffolding a project
schematics blank --name=my-external
We need to add two new helper functions:
chain, is a RuleFactory provided by Schematics
library, chains multiple rules together
externalSchematic, also a rule factory
import {
Rule,
SchematicContext,
Tree,
chain,
externalSchematic } from '@angular-devkit/schematics';
install @schematics/angular
imports and runs the schematic
externalSchematic('@schematics/angular', 'component', options)
Next part is our schematic that needs to
go through all files
for each file list it's content and add header text
const headerText = `
@copyright ngVikings, by the community, for the community
`
(tree: Tree, _context: SchematicContext) => {
tree.getDir(options.sourceDir)
.visit(filePath => {
if (!filePath.endsWith('.ts')) {
return;
}
const content = tree.read(filePath);
if (!content) {
return;
}
// Prevent from writing license to files that already ha
if (content.indexOf(licenseText) == -1) {
tree.overwrite(filePath, headerText + content);
}
Building and running the above
Angular Schematics
A scaffolded component
with our header text in place
EXAMPLEEXAMPLE
SCAFFOLD BASED ON TEMPLATESSCAFFOLD BASED ON TEMPLATES
We want to:
define scaffold files
define templates
replace template content with commandline args
Scaffold a new blank project
schematics blank --name=my-template
define template file
you can place them where you want but your
tsconfig.json is set to ignore /files
let's create some template files
Angular Schematics
we are looking to replace name
<%= name %>
let's write some code
export function myTemplate(_options: any): Rule {
_options.path = _options.path ? normalize(_options.path) : _
const templateSource = apply(url("./files"), [
filterTemplates(_options),
template({
...stringUtils,
..._options
}),
move("/src/app/my-template")
// what to do with the files in here
]);
return chain([branchAndMerge(chain([mergeWith(templateSource
}
let's break it down
filterTemplates, function that ensures we get the
template files we want
template, function that takes a template and
content and merge them
move, where we place the end result
if service is NOT specified as command line arg, then
we don't include it else just filter out .bak files
function filterTemplates(options: any): Rule {
if (!options.service) {
return filter(
path =>
!path.match(/.service.ts$/) &&
!path.match(/-item.ts/) &&
!path.match(/.bak$/)
);
}
return filter(path => !path.match(/.bak$/));
}
stringUtils obj containing helper functions for our
template, e.g classify _options obj containing
data that we want to pass to our template, e.g name
template({
...stringUtils,
..._options
})
let's update our template
classify comes from stringUtils, ensures we
get capital letter name name from _options
export class <%= classify(name) %> {
getData() {
// fetch data here
}
}
looking at end result
Angular Schematics
THE ANATOMY OF A TREETHE ANATOMY OF A TREE
is a list of type Action
let's look at what an Action is
tree.actions // Action[]
different type of actions,
path looks interesting
kind is a property that says what type of CRUD
export declare type Action =
CreateFileAction |
OverwriteFileAction |
RenameFileAction |
DeleteFileAction;
export interface ActionBase {
readonly id: number;
readonly parent: number;
readonly path: Path;
}
ok, an Action seems to represent our intent, how do
we read from it?
tree.actions.forEach(action => {
console.log("action kind", action.kind);
console.log("action path", action.path);
let fe = tree.get(action.path);
if (fe) {
console.log("action content", fe.content.toString("utf8"))
}
});
ok so we can list all the things the tree is about to do,
with its content
This is internals, it might change in the near future, still
interesting though
UNDERSTANDING YOUR CODEUNDERSTANDING YOUR CODE
USING THE TYPESCRIPT COMPILERUSING THE TYPESCRIPT COMPILER
We can send in our code into the Typescript compiler
and it will give us a tree representation back
read file
convert file content into a SourceFile
investigate your tree
very simple file
class DemoClass {
constructor(otherDemo: DemoClass, param: string) {}
}
read, create source file
let node = ts.createSourceFile(
'demo.ts',
content,
ts.ScriptTarget.Latest,
true
);
let's try to print our nodes in a nice way
thank you Manfred Steyer for this function
function showTree(node: ts.Node, indent: string = ' '): voi
console.log(indent + ts.SyntaxKind[node.kind]);
if (node.getChildCount() === 0) {
console.log(indent + ' Text: ' + node.getText());
}
for(let child of node.getChildren()) {
showTree(child, indent + ' ');
}
}
showTree(node);
Angular Schematics
TODO show tree content
What about changing the tree?
we need to flatten the tree into a list of nodes, for
convenience
we need to find the correct position to do our
change
we need to create a Change object that says path,
position of change and with what
content
lastly we need to call the following on the tree
beginUpdate, to get a recorder commitUpdate
to make the changes stick
admire our work
gives us a flattened list of Nodes
const nodes = getSourceNodes(componentSource);
you can query nodes by type, find the type you need
according to our AST tree
function getNodeByType(nodes: ts.Node[], type: ts.SyntaxKind)
return nodes.find(n => n.kind === type)[0];
}
// e.g
const node = getNodeByType(
nodes,
ts.SyntaxKind.ConstructorKeyword
)
once you have the correct node, simply insert
before/a er your node
function createChange(path: any, what: string, pos: number) {
return new InsertChange(path, pos, what);
}
createChange('path-to-file', 'insert this', node.pos+1)
interate our list of changes and commit/ save
function applyChanges(path: string, content: string, changes:
tree.create(path, content);
const exportRecorder = tree.beginUpdate(path);
for (const change of changes) {
if (change instanceof InsertChange) {
exportRecorder.insertLeft(change.pos, change.toAdd);
}
}
tree.commitUpdate(exportRecorder);
}
all together now :)
function myRule(options): Rule {
return (tree: Tree, _context: SchematicContext) => {
const componentSource = getTsSource( componentPath,
componentContent
);
const nodes = getSourceNodes(componentSource);
const node = getNodeByType( nodes,
ts.SyntaxKind.ConstructorKeyword
);
const change = createChange( componentPath,
'insert this',
node.pos+1
);
applyChanges( componentPath,
componentContent, [ change ], tree);
FURTHER READINGFURTHER READING
Intro article to Schematics article by Hans from Angula
https://blog.angular.io/schematics-an-introduction-
dc1dfbc2a2b2
Manfred Steyer, 5 blog post series,
https://www.so warearchitekt.at/post/2017/10/29/ge
custom-code-with-the-angular-cli-and-schematics.asp
Manfred Steyer, free book on Schematics,
https://leanpub.com/angular-schematics
Jorge Cano, article, https://medium.com/@jorgeucan
fist-angular-schematics-f711d70cb37c
SUMMARYSUMMARY
Workflow tool
Performs changes on a Tree
Consist of Rules you apply on a Tree
Can be used for scaffolding but also update code
is the secret sauce behind Angular-CLI
THANK YOUTHANK YOU

More Related Content

PDF
NestJS
PDF
Kubernetes and Prometheus
PDF
CI/CD with Jenkins and Docker - DevOps Meetup Day Thailand
ODP
Angular 6 - The Complete Guide
PDF
PDF
Continuous Integration With Jenkins
PPTX
Jenkins CI
PPTX
Angular 9
NestJS
Kubernetes and Prometheus
CI/CD with Jenkins and Docker - DevOps Meetup Day Thailand
Angular 6 - The Complete Guide
Continuous Integration With Jenkins
Jenkins CI
Angular 9

What's hot (20)

PDF
Nest.js Introduction
PDF
Introduction to Docker
PPTX
Multi-Clusters Made Easy with Liqo:
Getting Rid of Your Clusters Keeping Them...
PPTX
Jenkins CI presentation
PPTX
Jenkins tutorial
PDF
Operator SDK for K8s using Go
PDF
MongoDB and Node.js
PDF
Jenkins with SonarQube
PDF
Managing Microservices With The Istio Service Mesh on Kubernetes
PDF
Introduction to docker
PDF
Introduction to DevOps | Edureka
PPTX
Azure Pipelines
PPTX
Introduction to Docker - 2017
PPTX
Jenkins presentation
PPTX
Introduction to jenkins
PPTX
PDF
Containerization using docker
PDF
Extending kubernetes with CustomResourceDefinitions
PPTX
Kubernetes #4 volume &amp; stateful set
PPTX
CICD with Jenkins
Nest.js Introduction
Introduction to Docker
Multi-Clusters Made Easy with Liqo:
Getting Rid of Your Clusters Keeping Them...
Jenkins CI presentation
Jenkins tutorial
Operator SDK for K8s using Go
MongoDB and Node.js
Jenkins with SonarQube
Managing Microservices With The Istio Service Mesh on Kubernetes
Introduction to docker
Introduction to DevOps | Edureka
Azure Pipelines
Introduction to Docker - 2017
Jenkins presentation
Introduction to jenkins
Containerization using docker
Extending kubernetes with CustomResourceDefinitions
Kubernetes #4 volume &amp; stateful set
CICD with Jenkins
Ad

Similar to Angular Schematics (20)

PDF
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
PDF
A Gentle Introduction to Angular Schematics - Angular SF 2019
PDF
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
PDF
Everything You Should Know About the New Angular CLI
PPTX
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
PPTX
Talentica - JS Meetup - Angular Schematics
PDF
Basic overview of Angular
PDF
Angular Weekend
PPTX
Introduction to TypeScript
PDF
React Native Evening
PDF
TypeScript Best Practices
PDF
Node Boot Camp
PDF
James Baxley - Statically typing your GraphQL app
PDF
Forking Oryx at Intalio
PPTX
Advanced angular
PDF
Flow or Type - how to React to that?
PDF
Intro to React
PDF
ES6 General Introduction
PDF
Quick introduction to Angular 4 for AngularJS 1.5 developers
PDF
An Intro To ES6
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Everything You Should Know About the New Angular CLI
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
Talentica - JS Meetup - Angular Schematics
Basic overview of Angular
Angular Weekend
Introduction to TypeScript
React Native Evening
TypeScript Best Practices
Node Boot Camp
James Baxley - Statically typing your GraphQL app
Forking Oryx at Intalio
Advanced angular
Flow or Type - how to React to that?
Intro to React
ES6 General Introduction
Quick introduction to Angular 4 for AngularJS 1.5 developers
An Intro To ES6
Ad

More from Christoffer Noring (20)

PPTX
Azure signalR
PPTX
Game dev 101 part 3
PPTX
Game dev 101 part 2
PPTX
Game dev workshop
PPTX
Deploying your static web app to the Cloud
PPTX
IaaS with ARM templates for Azure
PPTX
Learning Svelte
PPTX
PDF
Design thinking
PDF
Keynote ijs
PDF
Vue fundamentasl with Testing and Vuex
PDF
Ngrx slides
PDF
PPTX
Angular mix chrisnoring
PDF
Nativescript angular
PDF
Graphql, REST and Apollo
PDF
Angular 2 introduction
PDF
Rxjs vienna
PPTX
Rxjs marble-testing
PDF
React lecture
Azure signalR
Game dev 101 part 3
Game dev 101 part 2
Game dev workshop
Deploying your static web app to the Cloud
IaaS with ARM templates for Azure
Learning Svelte
Design thinking
Keynote ijs
Vue fundamentasl with Testing and Vuex
Ngrx slides
Angular mix chrisnoring
Nativescript angular
Graphql, REST and Apollo
Angular 2 introduction
Rxjs vienna
Rxjs marble-testing
React lecture

Recently uploaded (20)

PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Approach and Philosophy of On baking technology
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Encapsulation theory and applications.pdf
PPTX
Big Data Technologies - Introduction.pptx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
cuic standard and advanced reporting.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
A Presentation on Artificial Intelligence
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Approach and Philosophy of On baking technology
Understanding_Digital_Forensics_Presentation.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Encapsulation theory and applications.pdf
Big Data Technologies - Introduction.pptx
Reach Out and Touch Someone: Haptics and Empathic Computing
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
cuic standard and advanced reporting.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Unlocking AI with Model Context Protocol (MCP)
A Presentation on Artificial Intelligence
Diabetes mellitus diagnosis method based random forest with bat algorithm
The Rise and Fall of 3GPP – Time for a Sabbatical?
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx

Angular Schematics

  • 2. CHRIS NORINGCHRIS NORING CLOUD DEVELOPER EXPERT AT MICROSOFTCLOUD DEVELOPER EXPERT AT MICROSOFT Google Developer Expert in Angular and Web Techs @chris_noring https://so chris.github.io Published author Public Speaker So ware Engineer
  • 3. WORKFLOW TOOLWORKFLOW TOOL CAN APPLY TRANSFORMS TO YOUR PROJECTCAN APPLY TRANSFORMS TO YOUR PROJECT example of usage: scaffold: new components, services, update your code to fix breaking changes in dependencies. or add a new configuration option or framework to an existing project
  • 4. ANGULAR CLI - SECRET SAUCEANGULAR CLI - SECRET SAUCE GENERIC FACILITY TO SUPPORT THE CLIGENERIC FACILITY TO SUPPORT THE CLI SCAFFOLDINGSCAFFOLDING improve your development productivity Ease uf use and development Extensibility and reuseability Atomicity Asynchronicity
  • 5. TREETREE OVER FILE SYSTEMOVER FILE SYSTEM not affecting the file system directly, you describe what transformations you want done on a Tree
  • 6. INSTALLATIONINSTALLATION npm install -g @angular-devkit/schematics-cli This will install a schematics executable, which you can use to create a blank Schematics project
  • 10. index.ts, where our rules live collection.json, a description of our project
  • 11. INDEX.TSINDEX.TS return a function of type Rule options input, is an object representing command line args inner function takes Tree and SchematicContext, tree is file tree
  • 13. COLLECTION.JSONCOLLECTION.JSON description, description of project factory, points to the directory/starter module
  • 15. BUILD AND RUNBUILD AND RUN --name=test, command line arg npm run build schematics .:my-component --name=test
  • 16. it says: nothing to be done!!
  • 17. not surprised, cause our Rule factory function does nothing
  • 18. EXAMPLEEXAMPLE SCAFFOLD SOME FILES, WITH CONTENTSCAFFOLD SOME FILES, WITH CONTENT
  • 20. create files, with content tree.create(filename, file-content)
  • 21. let's create a build and run script
  • 24. we didn't actual create any files, we are in dry-run mode It shows what would happen if applied to a file system
  • 25. let's shut off dry-run
  • 26. I don't see a difference??
  • 27. oh, so they were created in the in the project
  • 28. Just add the follwing to your schematics executable --dry-run=false
  • 29. There are four methods that directly create a change in a Tree create delete rename overwrite
  • 30. TIPS AND TRICKSTIPS AND TRICKS
  • 31. watch mode, rebuild your project on changes npm run build -w
  • 33. TESTING OUT YOUR SCHEMATICSTESTING OUT YOUR SCHEMATICS
  • 34. scaffold an Angular project npm link to the schematics ng generate
  • 36. npm link <path to schematics> // tip: run pwd and copy result
  • 39. Voila, our Vikings are added
  • 40. EXAMPLEEXAMPLE USING AN EXISTING SCHEMATICUSING AN EXISTING SCHEMATIC
  • 41. WHAT IS A COLLECTION?WHAT IS A COLLECTION? Schematics Collections are sets of named schematics, that are published and installed by users. Angular team publishes and maintains the official @schematics/angular collection e.g component, module, application
  • 42. Scenario: add some disclaimer text on top of component
  • 43. We start by scaffolding a project schematics blank --name=my-external
  • 44. We need to add two new helper functions: chain, is a RuleFactory provided by Schematics library, chains multiple rules together externalSchematic, also a rule factory
  • 46. install @schematics/angular imports and runs the schematic externalSchematic('@schematics/angular', 'component', options)
  • 47. Next part is our schematic that needs to go through all files for each file list it's content and add header text
  • 48. const headerText = ` @copyright ngVikings, by the community, for the community `
  • 49. (tree: Tree, _context: SchematicContext) => { tree.getDir(options.sourceDir) .visit(filePath => { if (!filePath.endsWith('.ts')) { return; } const content = tree.read(filePath); if (!content) { return; } // Prevent from writing license to files that already ha if (content.indexOf(licenseText) == -1) { tree.overwrite(filePath, headerText + content); }
  • 50. Building and running the above
  • 53. with our header text in place
  • 54. EXAMPLEEXAMPLE SCAFFOLD BASED ON TEMPLATESSCAFFOLD BASED ON TEMPLATES
  • 55. We want to: define scaffold files define templates replace template content with commandline args
  • 56. Scaffold a new blank project
  • 58. define template file you can place them where you want but your tsconfig.json is set to ignore /files
  • 59. let's create some template files
  • 61. we are looking to replace name <%= name %>
  • 63. export function myTemplate(_options: any): Rule { _options.path = _options.path ? normalize(_options.path) : _ const templateSource = apply(url("./files"), [ filterTemplates(_options), template({ ...stringUtils, ..._options }), move("/src/app/my-template") // what to do with the files in here ]); return chain([branchAndMerge(chain([mergeWith(templateSource }
  • 64. let's break it down filterTemplates, function that ensures we get the template files we want template, function that takes a template and content and merge them move, where we place the end result
  • 65. if service is NOT specified as command line arg, then we don't include it else just filter out .bak files function filterTemplates(options: any): Rule { if (!options.service) { return filter( path => !path.match(/.service.ts$/) && !path.match(/-item.ts/) && !path.match(/.bak$/) ); } return filter(path => !path.match(/.bak$/)); }
  • 66. stringUtils obj containing helper functions for our template, e.g classify _options obj containing data that we want to pass to our template, e.g name template({ ...stringUtils, ..._options })
  • 67. let's update our template
  • 68. classify comes from stringUtils, ensures we get capital letter name name from _options export class <%= classify(name) %> { getData() { // fetch data here } }
  • 69. looking at end result
  • 71. THE ANATOMY OF A TREETHE ANATOMY OF A TREE
  • 72. is a list of type Action let's look at what an Action is tree.actions // Action[]
  • 73. different type of actions, path looks interesting kind is a property that says what type of CRUD export declare type Action = CreateFileAction | OverwriteFileAction | RenameFileAction | DeleteFileAction; export interface ActionBase { readonly id: number; readonly parent: number; readonly path: Path; }
  • 74. ok, an Action seems to represent our intent, how do we read from it?
  • 75. tree.actions.forEach(action => { console.log("action kind", action.kind); console.log("action path", action.path); let fe = tree.get(action.path); if (fe) { console.log("action content", fe.content.toString("utf8")) } });
  • 76. ok so we can list all the things the tree is about to do, with its content
  • 77. This is internals, it might change in the near future, still interesting though
  • 78. UNDERSTANDING YOUR CODEUNDERSTANDING YOUR CODE USING THE TYPESCRIPT COMPILERUSING THE TYPESCRIPT COMPILER
  • 79. We can send in our code into the Typescript compiler and it will give us a tree representation back
  • 80. read file convert file content into a SourceFile investigate your tree
  • 81. very simple file class DemoClass { constructor(otherDemo: DemoClass, param: string) {} }
  • 82. read, create source file let node = ts.createSourceFile( 'demo.ts', content, ts.ScriptTarget.Latest, true );
  • 83. let's try to print our nodes in a nice way
  • 84. thank you Manfred Steyer for this function function showTree(node: ts.Node, indent: string = ' '): voi console.log(indent + ts.SyntaxKind[node.kind]); if (node.getChildCount() === 0) { console.log(indent + ' Text: ' + node.getText()); } for(let child of node.getChildren()) { showTree(child, indent + ' '); } } showTree(node);
  • 86. TODO show tree content
  • 87. What about changing the tree?
  • 88. we need to flatten the tree into a list of nodes, for convenience we need to find the correct position to do our change we need to create a Change object that says path, position of change and with what content lastly we need to call the following on the tree beginUpdate, to get a recorder commitUpdate to make the changes stick admire our work
  • 89. gives us a flattened list of Nodes const nodes = getSourceNodes(componentSource);
  • 90. you can query nodes by type, find the type you need according to our AST tree function getNodeByType(nodes: ts.Node[], type: ts.SyntaxKind) return nodes.find(n => n.kind === type)[0]; } // e.g const node = getNodeByType( nodes, ts.SyntaxKind.ConstructorKeyword )
  • 91. once you have the correct node, simply insert before/a er your node function createChange(path: any, what: string, pos: number) { return new InsertChange(path, pos, what); } createChange('path-to-file', 'insert this', node.pos+1)
  • 92. interate our list of changes and commit/ save function applyChanges(path: string, content: string, changes: tree.create(path, content); const exportRecorder = tree.beginUpdate(path); for (const change of changes) { if (change instanceof InsertChange) { exportRecorder.insertLeft(change.pos, change.toAdd); } } tree.commitUpdate(exportRecorder); }
  • 93. all together now :) function myRule(options): Rule { return (tree: Tree, _context: SchematicContext) => { const componentSource = getTsSource( componentPath, componentContent ); const nodes = getSourceNodes(componentSource); const node = getNodeByType( nodes, ts.SyntaxKind.ConstructorKeyword ); const change = createChange( componentPath, 'insert this', node.pos+1 ); applyChanges( componentPath, componentContent, [ change ], tree);
  • 94. FURTHER READINGFURTHER READING Intro article to Schematics article by Hans from Angula https://blog.angular.io/schematics-an-introduction- dc1dfbc2a2b2 Manfred Steyer, 5 blog post series, https://www.so warearchitekt.at/post/2017/10/29/ge custom-code-with-the-angular-cli-and-schematics.asp Manfred Steyer, free book on Schematics, https://leanpub.com/angular-schematics Jorge Cano, article, https://medium.com/@jorgeucan fist-angular-schematics-f711d70cb37c
  • 95. SUMMARYSUMMARY Workflow tool Performs changes on a Tree Consist of Rules you apply on a Tree Can be used for scaffolding but also update code is the secret sauce behind Angular-CLI