{"id":3736,"date":"2020-03-17T22:04:50","date_gmt":"2020-03-17T21:04:50","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=3736"},"modified":"2020-03-17T22:04:50","modified_gmt":"2020-03-17T21:04:50","slug":"automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/","title":{"rendered":"Automating Your Angular Architecture with Workspace Schematics &#8211; Part 1: Rules and Parameters"},"content":{"rendered":"<p>Defining an architecture is exciting. However, implementing it can also be boring because it involves dealing with the same patterns and practices time and again. Automating this task with scaffolding is the solution. Fortunately, the Angular CLI itself comes with a scaffolding tool called Schematics.<\/p>\n<p>In this article series, I show how to use Schematics within a monorepo. For this, I'm using Workspace Schematics provided by Nx. While everything I show also works with an classic Angular project, Nx provides some tooling and hence increases the convenience.<\/p>\n<p>As always, the <a href=\"https:\/\/github.com\/manfredsteyer\/demo-workspace-schematics\">source code<\/a> can be found in my <a href=\"https:\/\/github.com\/manfredsteyer\/demo-workspace-schematics\">GitHub account<\/a>.<\/p>\n<h2>Example<\/h2>\n<p>The architecture I automate in this article series is subdividing a big application into (more or less) self contained sub domains:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2020\/03\/idea1.png\" alt=\"Architecture with self contained domains\" \/><\/p>\n<p>This style which I described in my <a href=\"https:\/\/www.angulararchitects.io\/aktuelles\/tactical-domain-driven-design-with-monorepos\/\">blog series about Domain Driven Design<\/a> decouples the domains from each other and hence makes breaking changes between domains more unlikely. Also, it limits the complexity. If you already know this article, you can directly proceed with the next section.<\/p>\n<p>In our architecture, each domain has several libraries within a monorepo. Feature libraries implement use cases with smart components. Domain libraries consist of our domain logic and a domain model. Also, there are some other types of libraries as outlined in the <a href=\"https:\/\/www.angulararchitects.io\/aktuelles\/tactical-domain-driven-design-with-monorepos\/\">mentioned blog series<\/a>.<\/p>\n<p>To prevent that the individual libraries depend too much on each other there are access rules. They are implied by the arrows in the last picture. According to that, one layer is only allowed to access layers below. In the simplified version here this means that a feature can access the domain but not vice verse. The more important access rule, however, states that libraries in one domain can only access other libraries in the very same domain as well as in the shared slice.<br \/>\nWithin the mononorepo's <code>lib<\/code> folder there is one sub folder per domain. This folder contains the domain's libraries:<\/p>\n<p><img decoding=\"async\" alt=\"Folders for our architecture\" src=\"\/wp-content\/uploads\/2020\/03\/folder-goal1.png\" style=\"max-width:350px!important\"><\/p>\n<p>Nx allows us to enforce the mentioned access rules between libraries. For this, we have to assign tags to each library within <code>nx.json<\/code>:<\/p>\n<pre><code class=\"language-json\">[...]\n&quot;catalog-domain&quot;: {\n    &quot;tags&quot;: [&quot;domain:catalog&quot;, &quot;type:domain-logic&quot;]\n},\n&quot;ordering-domain&quot;: {\n    &quot;tags&quot;: [&quot;domain:ordering&quot;, &quot;type:domain-logic&quot;]\n},\n[...]<\/code><\/pre>\n<p>Then, within <code>tsconfig.json<\/code> we can use the rule <code>nx-enforce-module-boundaries<\/code> to define restrictions <\/p>\n<pre><code class=\"language-json\">[...]\n&quot;nx-enforce-module-boundaries&quot;: [\n  true,\n  {\n    &quot;allow&quot;: [],\n    &quot;depConstraints&quot;: [\n      {\n        &quot;sourceTag&quot;: &quot;*&quot;,\n        &quot;onlyDependOnLibsWithTags&quot;: [&quot;*&quot;]\n      },\n      {\n        &quot;sourceTag&quot;: &quot;domain:catalog&quot;,\n        &quot;onlyDependOnLibsWithTags&quot;: [&quot;domain:catalog&quot;, &quot;shared&quot;]\n      },\n      {\n        &quot;sourceTag&quot;: &quot;domain:ordering&quot;,\n        &quot;onlyDependOnLibsWithTags&quot;: [&quot;domain:ordering&quot;, &quot;shared&quot;]\n      }\n    ]\n  }\n],\n[...]<\/code><\/pre>\n<p>As you can imagine, while this architecture is clear and prevents coupling, creating all the building blocks as well as configuring the linting rule is monotonous and time-consuming. Fortunately, as the next sections show, we can automate all this with Schematics.<\/p>\n<p>More about this very architecture can be found in my other blog articles here. Also, working with architectures like this one is a big topic in our <a href=\"https:\/\/www.angulararchitects.io\/schulungen\/advanced-angular-enterprise-anwendungen-und-architektur\/\">Angular Workshops<\/a>.<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/schulungen\/advanced-angular-enterprise-anwendungen-und-architektur\/\"><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/workshop1.jpg\"><\/p>\n<p><\/a><\/p>\n<h2>About Workspace Schematics<\/h2>\n<p>To scaffold files the Angular CLI uses a tool called Schematics. Every time we call <code>ng new<\/code>, <code>ng generate<\/code>, <code>ng add<\/code>, and <code>ng update<\/code> the CLI delegates to it. However, it also allows to write custom code generators which are also called schematics.<\/p>\n<p>While we can directly setup a Schematics project and distribute it via npm, Nrwl's Nx provides a more convenient way: It allows to scaffold a new schematic within a workspace like we scaffold components or services. Also, it provides a command to compile and execute it in the same workspace.<\/p>\n<p>As the schematics are part of the monorepo where they are used, this approach is the right one for generating code which is very project specific. <\/p>\n<h2>Scaffolding a workspace schematic<\/h2>\n<p>After creating an Nx workspace using<\/p>\n<pre><code class=\"language-bash\">npx create-nx-workspace@latest e-proc<\/code><\/pre>\n<p>we can scaffold a workspace schematic:<\/p>\n<pre><code class=\"language-bash\">ng g workspace-schematic demo-lib<\/code><\/pre>\n<p>This creates two files -- an <code>index.ts<\/code> with the schematic's implementation and a <code>schema.json<\/code> describing the parameters we can pass to the schematic:<\/p>\n<p><img decoding=\"async\" alt=\"ng g workspace-schematic domain\" src=\"\/wp-content\/uploads\/2020\/03\/ng-g-workspace-schematic1.png\" style=\"max-width:700px!important\"><\/p>\n<p>The generated <code>schema.json<\/code> looks like this:<\/p>\n<pre><code class=\"language-json\">{\n  &quot;$schema&quot;: &quot;http:\/\/json-schema.org\/schema&quot;,\n  &quot;id&quot;: &quot;domain&quot;,\n  &quot;type&quot;: &quot;object&quot;,\n  &quot;properties&quot;: {\n    &quot;name&quot;: {\n      &quot;type&quot;: &quot;string&quot;,\n      &quot;description&quot;: &quot;Library name&quot;,\n      &quot;$default&quot;: {\n        &quot;$source&quot;: &quot;argv&quot;,\n        &quot;index&quot;: 0\n      }\n    }\n  },\n  &quot;required&quot;: [&quot;name&quot;]\n}<\/code><\/pre>\n<p>It just defines a required parameter <code>name<\/code>. According to the <code>$default<\/code> property, it gets the value of the first passed parameter if not specified explicitly using <code>--name<\/code>. Hence, we can call it with the Nx CLI using <\/p>\n<pre><code>nx workspace-schematic domain myDomain<\/code><\/pre>\n<p>or using<\/p>\n<pre><code>nx workspace-schematic domain --name myDomain<\/code><\/pre>\n<p>The generated implementation within <code>index.ts<\/code> just contains a rule factory:<\/p>\n<pre><code class=\"language-typescript\">import { chain, externalSchematic, Rule } from &#039;@angular-devkit\/schematics&#039;;\n\nexport default function(schema: any): Rule {\n  return chain([\n    externalSchematic(&#039;@nrwl\/workspace&#039;, &#039;lib&#039;, {\n      name: schema.name\n    })\n  ]);\n}<\/code><\/pre>\n<p>Rules are the individual steps needed to scaffold files. The returned rule is a <code>chain<\/code> which just calls other rules in sequence. The only rule <code>chain<\/code> currently delegates to is <code>externalSchematic<\/code>. As the name indicates, it is calling another schematic. In this case it is the <code>lib<\/code> schematic which is also called when running <code>ng generate lib<\/code> by hand.<\/p>\n<p>Please also note the <code>schema<\/code> parameter. It contains all passed command line parameters and has the structure described by the <code>schema.json<\/code> file.<\/p>\n<p>After looking at these generated files, let's now find out how to modify them for our own goals.<\/p>\n<h2>Generating a TypeScript Interface for schema.json<\/h2>\n<p>As using any for the schema parameter is somewhat unpretty, let's provide a type for it. In order to not repeat ourselves we should generate it out of the <code>schema.json<\/code>. The npm package <code>json-schema-to-typescript<\/code> can help with this:<\/p>\n<p><img decoding=\"async\" alt=\"npm i json-schema-to-typescript --save-dev\" src=\"\/wp-content\/uploads\/2020\/03\/npm-i-json-schema1.png\" style=\"max-width:500px!important\"><\/p>\n<p>We can call it within a simple node script I'm calling <code>json-schema-to-ts.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">const toTypeScript = require(&#039;json-schema-to-typescript&#039;);\nconst fs = require(&#039;fs&#039;);\n\ntoTypeScript\n    .compileFromFile(&#039;tools\/schematics\/domain\/schema.json&#039;)\n    .then(ts =&gt; fs.writeFileSync(&#039;tools\/schematics\/domain\/schema.ts&#039;, ts));<\/code><\/pre>\n<p>For calling it, I've also defined an npm script in my <code>package.json<\/code>:<\/p>\n<pre><code class=\"language-json\">[...]\n&quot;scripts&quot;: {\n    [...]\n    &quot;build:schema&quot;: &quot;node tools\/schematics\/json-schema-to-ts.js&quot;\n} \n[...]<\/code><\/pre>\n<p>Now, after running<\/p>\n<p><img decoding=\"async\" alt=\"npm run build:schema\" src=\"\/wp-content\/uploads\/2020\/03\/npm-run-build-schema1.png\" style=\"max-width:300px!important\"><\/p>\n<p>we get this file:<\/p>\n<pre><code class=\"language-typescript\">export interface Domain {\n  \/**\n   * Library name\n   *\/\n  name: string;\n  [k: string]: any;\n}<\/code><\/pre>\n<p>Perhaps you've noticed that the name of this interface is the value of the <code>id<\/code> property in the <code>schema.json<\/code>.<\/p>\n<h2>Step 3: Defining Options<\/h2>\n<p>Now, let's add an additional parameter <code>addApp<\/code>:<\/p>\n<pre><code class=\"language-json\">{\n  &quot;$schema&quot;: &quot;http:\/\/json-schema.org\/schema&quot;,\n  &quot;id&quot;: &quot;domain-options&quot;,\n  &quot;type&quot;: &quot;object&quot;,\n  &quot;properties&quot;: {\n    &quot;name&quot;: {\n      &quot;type&quot;: &quot;string&quot;,\n      &quot;description&quot;: &quot;Domain name&quot;,\n      &quot;$default&quot;: {\n        &quot;$source&quot;: &quot;argv&quot;,\n        &quot;index&quot;: 0\n      }\n    },\n    &quot;addApp&quot;: {\n      &quot;type&quot;: &quot;boolean&quot;,\n      &quot;description&quot;: &quot;Add an app for the domain?&quot;,\n      &quot;default&quot;: false\n    }\n  },\n  &quot;required&quot;: [&quot;name&quot;]\n}<\/code><\/pre>\n<p>If set to <code>true<\/code>, it shall also generate an app for the domain we're scaffolding. Also, I've set the <code>id<\/code> property to <code>DomainOptions<\/code> to influence the name of the generated interface.<\/p>\n<p>After calling<\/p>\n<p><img decoding=\"async\" alt=\"npm run build:schema\" src=\"\/wp-content\/uploads\/2020\/03\/npm-run-build-schema1.png\" style=\"max-width:300px!important\"><\/p>\n<p>one more time, we get this:<\/p>\n<pre><code class=\"language-typescript\">export interface DomainOptions {\n  \/**\n   * Domain name\n   *\/\n  name: string;\n  \/**\n   * Add an app for the domain?\n   *\/\n  addApp?: boolean;\n  [k: string]: any;\n}<\/code><\/pre>\n<p>Also, we can now type the options property with this interface:<\/p>\n<pre><code class=\"language-typescript\">export default function(options: DomainOptions): Rule {\n    [...]\n}<\/code><\/pre>\n<h2>Calling Existing Rules<\/h2>\n<p>As we have a property for the <code>addApp<\/code> command line option now, we can use it within the rule:<\/p>\n<pre><code class=\"language-typescript\">  return chain([\n    externalSchematic(&#039;@nrwl\/angular&#039;, &#039;lib&#039;, {\n      name: &#039;domain&#039;,\n      directory: options.name,\n      tags: <code>domain:${options.name},type:domain-logic<\/code>,\n      style: &#039;scss&#039;,\n    }),\n    (!options.addApp) ? \n      noop() : \n      externalSchematic(&#039;@nrwl\/angular&#039;, &#039;app&#039;, {\n        name: options.name,\n        tags: <code>domain:${options.name},type:app<\/code>,\n        style: &#039;scss&#039;,\n      }),\n  ]);<\/code><\/pre>\n<p>This enhanced rule is chaining the <code>noop<\/code> (no operation) rule, if <code>addApp<\/code> is <code>false<\/code>. In this case, nothing happens. Otherwise, it executes the <code>app<\/code> schematic using <code>externalSchematic<\/code>.<\/p>\n<p>Both <code>externalSchematic<\/code> calls also get some parameters, like the library's directory which is the domain name or tags for <code>nx.json<\/code>.<\/p>\n<h2>Creating a Custom Rules<\/h2>\n<p>So far, we used existing rules for our needs. But when it comes to updating the linting rules within <code>tsconfig.json<\/code>, we need to write a custom one.<\/p>\n<p>For this rule, we need a factory with the parameters we want to pass:<\/p>\n<pre><code class=\"language-typescript\">export function updateLintingRules(domainName: string): Rule {\n    return (host: Tree, context: SchematicContext) =&gt; {\n        [...]\n    }\n}<\/code><\/pre>\n<p>The retuned rule is also just a function taking a <code>Tree<\/code> and a <code>SchematicContext<\/code>. The <code>Tree<\/code> represents your file system. Honestly, it is more of a staging area representing your file system. <\/p>\n<p>This is an important concept of Schematics: The changes in the staging environment are only written to hard disk if everything worked. If there was an error, no change is written. This prevents getting an inconsistence state.<\/p>\n<p>The full implementation of this rule is just reading the <code>tslint.json<\/code>. After parsing, the resulting object graph is changed and written back to the same file:<\/p>\n<pre><code class=\"language-typescript\">import { Rule, Tree, SchematicContext  } from &#039;@angular-devkit\/schematics&#039;;\n\nexport function updateLintingRules(domainName: string): Rule {\n    return (host: Tree, context: SchematicContext) =&gt; {\n      const text = host.read(&#039;tslint.json&#039;).toString();\n      const rules = JSON.parse(text);\n\n      \/\/ Make sure, rules[&#039;rules&#039;][&#039;nx-enforce-module-boundaries&#039;][1][&#039;depConstraints&#039;] exists!\n\n      const depConst = rules[&#039;rules&#039;][&#039;nx-enforce-module-boundaries&#039;][1][&#039;depConstraints&#039;];\n\n      depConst.push({\n        &#039;sourceTag&#039;: <code>domain:${domainName}<\/code>,\n        &#039;onlyDependOnLibsWithTags&#039;: [<code>domain:${domainName}<\/code>, &#039;shared&#039;]\n      });\n\n      const newText = JSON.stringify(rules, undefined, 2);\n      host.overwrite(&#039;tslint.json&#039;, newText);\n    }\n  }<\/code><\/pre>\n<p>As you see here, it adds an access restriction preventing libraries in the added domain to access libraries in other domains. The only exception is the shared slice. <\/p>\n<p>After providing this rule, we can call it in our schematic:<\/p>\n<pre><code class=\"language-typescript\">  return chain([\n    externalSchematic(&#039;@nrwl\/angular&#039;, &#039;lib&#039;, {\n      name: &#039;domain&#039;,\n      directory: options.name,\n      tags: <code>domain:${options.name},type:domain-logic<\/code>,\n      style: &#039;scss&#039;,\n    }),\n    (!options.addApp) ? \n      noop() : \n      externalSchematic(&#039;@nrwl\/angular&#039;, &#039;app&#039;, {\n        name: options.name,\n        tags: <code>domain:${options.name},type:app<\/code>,\n        style: &#039;scss&#039;,\n      }),\n    \/\/ Added Rule vvvvvv\n    updateLintingRules(options.name),\n  ]);<\/code><\/pre>\n<h2>Calling the Workspace Schematic<\/h2>\n<p>Now, let's call our workspace schematic. To make my live easier, I've installed the Nx CLI for that globally:<\/p>\n<p><img decoding=\"async\" alt=\"npm install -g @nrwl\/cli\" src=\"\/wp-content\/uploads\/2020\/03\/npm-i-nrwl-cli1.png\" style=\"max-width:300px!important\"><\/p>\n<p>Using it, we can execute our schematic:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2020\/03\/nx-workspace-schematic-domain1.png\" alt=\"ng workspace-schematic domain ordering --add-app\" \/><\/p>\n<p>It created the domain library, the application and adds the access rules to the <code>tslint.json<\/code>.<\/p>\n<h2>Conclusion and Outlook<\/h2>\n<p>Nx makes creating workspace schematics really easy. We can scaffold them with <code>ng generate<\/code> and execute them with <code>nx workspace-schematic<\/code>. <\/p>\n<p>For defining parameters, we modify the <code>schema.json<\/code>. To access them in a typed way, we should generate an interface out of it.<\/p>\n<p>The automation of our repeating tasks is accomplished by rules which are just functions. Besides using existing rules like <code>externalSchematic<\/code> we can also write our own ones.<\/p>\n<p>Besides this, schematics can also <strong>modify existing files and generate new ones by copying templates<\/strong>. The latter ones can contain placeholders which are populated with concrete values. The next article of this series will show more about this possibility.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Defining an architecture is exciting. However, implementing it can also be boring. Automation with scaffolding is the solution. <\/p>\n","protected":false},"author":9,"featured_media":3716,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3736","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-unkategorisiert"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Automating Your Angular Architecture with Workspace Schematics - Part 1: Rules and Parameters - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Automating Your Angular Architecture with Workspace Schematics - Part 1: Rules and Parameters - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"Defining an architecture is exciting. However, implementing it can also be boring. Automation with scaffolding is the solution.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2020-03-17T21:04:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"640\" \/>\n\t<meta property=\"og:image:height\" content=\"427\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Automating Your Angular Architecture with Workspace Schematics &#8211; Part 1: Rules and Parameters\",\"datePublished\":\"2020-03-17T21:04:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\"},\"wordCount\":1265,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif\",\"articleSection\":[\"Unkategorisiert\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\",\"name\":\"Automating Your Angular Architecture with Workspace Schematics - Part 1: Rules and Parameters - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif\",\"datePublished\":\"2020-03-17T21:04:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif\",\"width\":640,\"height\":427},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Automating Your Angular Architecture with Workspace Schematics &#8211; Part 1: Rules and Parameters\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Automating Your Angular Architecture with Workspace Schematics - Part 1: Rules and Parameters - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/","og_locale":"en_US","og_type":"article","og_title":"Automating Your Angular Architecture with Workspace Schematics - Part 1: Rules and Parameters - ANGULARarchitects","og_description":"Defining an architecture is exciting. However, implementing it can also be boring. Automation with scaffolding is the solution.","og_url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/","og_site_name":"ANGULARarchitects","article_published_time":"2020-03-17T21:04:50+00:00","og_image":[{"width":640,"height":427,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif","type":"image\/gif"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Automating Your Angular Architecture with Workspace Schematics &#8211; Part 1: Rules and Parameters","datePublished":"2020-03-17T21:04:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/"},"wordCount":1265,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif","articleSection":["Unkategorisiert"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/","url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/","name":"Automating Your Angular Architecture with Workspace Schematics - Part 1: Rules and Parameters - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif","datePublished":"2020-03-17T21:04:50+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/03\/cover21.gif","width":640,"height":427},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/automating-your-angular-architecture-with-workspace-schematics-part-1-rules-and-parameters\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Automating Your Angular Architecture with Workspace Schematics &#8211; Part 1: Rules and Parameters"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/3736","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=3736"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/3736\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/3716"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=3736"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=3736"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=3736"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}