├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── README.md ├── apps ├── .gitkeep ├── checkin-e2e │ ├── .eslintrc.json │ ├── cypress.config.ts │ ├── project.json │ ├── src │ │ ├── e2e │ │ │ └── app.cy.ts │ │ ├── fixtures │ │ │ └── example.json │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── e2e.ts │ └── tsconfig.json ├── checkin │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ └── app.config.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── ddd-e2e │ ├── jest.config.ts │ ├── project.json │ ├── tests │ │ └── ddd.spec.ts │ ├── tsconfig.json │ └── tsconfig.spec.json ├── demo-app-e2e │ ├── .eslintrc.json │ ├── cypress.json │ ├── project.json │ ├── src │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── app.spec.ts │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── index.ts │ └── tsconfig.json ├── demo-app │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ │ ├── app │ │ │ ├── app.component.css │ │ │ ├── app.component.html │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ └── nx-welcome.component.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── styles.css │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── feature-e2e │ ├── .eslintrc.json │ ├── cypress.config.ts │ ├── project.json │ ├── src │ │ ├── e2e │ │ │ └── app.cy.ts │ │ ├── fixtures │ │ │ └── example.json │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── e2e.ts │ └── tsconfig.json ├── feature │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ └── app.config.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── styles.scss │ │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── miles-e2e │ ├── .eslintrc.json │ ├── cypress.config.ts │ ├── project.json │ ├── src │ │ ├── e2e │ │ │ └── app.cy.ts │ │ ├── fixtures │ │ │ └── example.json │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── e2e.ts │ └── tsconfig.json └── miles │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── src │ ├── app │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ └── app.config.ts │ ├── assets │ │ └── .gitkeep │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── styles.scss │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── decorate-angular-cli.js ├── jest.config.ts ├── jest.preset.js ├── libs ├── .gitkeep ├── checkin │ ├── domain │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── jest.config.ts │ │ ├── project.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── lib │ │ │ │ ├── application │ │ │ │ │ ├── .gitkeep │ │ │ │ │ └── manage.facade.ts │ │ │ │ ├── entities │ │ │ │ │ ├── .gitkeep │ │ │ │ │ └── ticket.ts │ │ │ │ └── infrastructure │ │ │ │ │ ├── .gitkeep │ │ │ │ │ └── ticket.data.service.ts │ │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json │ └── feature-manage │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── jest.config.ts │ │ ├── project.json │ │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── manage.component.html │ │ │ ├── manage.component.scss │ │ │ └── manage.component.ts │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json ├── ddd │ ├── .eslintrc.json │ ├── README.md │ ├── assets │ │ ├── ddd-libs.png │ │ ├── ddd.png │ │ ├── domain-layer.png │ │ ├── linting-1.png │ │ ├── linting-2.png │ │ ├── linting-3.png │ │ └── result.png │ ├── collection.json │ ├── executors.json │ ├── generators.json │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ │ ├── executors │ │ │ └── build │ │ │ │ ├── executor.spec.ts │ │ │ │ ├── executor.ts │ │ │ │ ├── schema.d.ts │ │ │ │ └── schema.json │ │ ├── generators │ │ │ ├── api │ │ │ │ ├── index.ts │ │ │ │ ├── schema.json │ │ │ │ └── schema.ts │ │ │ ├── ddd │ │ │ │ ├── files │ │ │ │ │ └── src │ │ │ │ │ │ └── index.ts__template__ │ │ │ │ ├── generator.spec.ts │ │ │ │ ├── generator.ts │ │ │ │ ├── schema.d.ts │ │ │ │ └── schema.json │ │ │ ├── domain │ │ │ │ ├── files │ │ │ │ │ ├── .gitkeep │ │ │ │ │ ├── domain-lib │ │ │ │ │ │ ├── application │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ ├── entities │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ └── infrastructure │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── standalone-app │ │ │ │ │ │ └── app │ │ │ │ │ │ │ ├── app.component.html__tmpl__ │ │ │ │ │ │ │ ├── app.component.spec.ts__tmpl__ │ │ │ │ │ │ │ ├── app.component.ts__tmpl__ │ │ │ │ │ │ │ └── app.config.ts__tmpl__ │ │ │ │ │ └── standalone-lib │ │ │ │ │ │ ├── index.ts__tmpl__ │ │ │ │ │ │ └── lib │ │ │ │ │ │ └── providers.ts__tmpl__ │ │ │ │ ├── index.ts │ │ │ │ ├── schema.json │ │ │ │ └── schema.ts │ │ │ ├── feature │ │ │ │ ├── files │ │ │ │ │ ├── forDomain │ │ │ │ │ │ ├── application │ │ │ │ │ │ │ └── __name@dasherize__.facade.ts__tmpl__ │ │ │ │ │ │ ├── entities │ │ │ │ │ │ │ └── __entity@dasherize__.ts__tmpl__ │ │ │ │ │ │ └── infrastructure │ │ │ │ │ │ │ └── __entity@dasherize__.data.service.ts__tmpl__ │ │ │ │ │ ├── forDomainWithNgrx │ │ │ │ │ │ ├── +state │ │ │ │ │ │ │ └── __entity@dasherize__ │ │ │ │ │ │ │ │ ├── __entity@dasherize__.actions.ts__tmpl__ │ │ │ │ │ │ │ │ ├── __entity@dasherize__.effects.ts__tmpl__ │ │ │ │ │ │ │ │ └── __entity@dasherize__.reducer.ts__tmpl__ │ │ │ │ │ │ ├── application │ │ │ │ │ │ │ └── __name@dasherize__.facade.ts__tmpl__ │ │ │ │ │ │ ├── entities │ │ │ │ │ │ │ └── __entity@dasherize__.ts__tmpl__ │ │ │ │ │ │ └── infrastructure │ │ │ │ │ │ │ └── __entity@dasherize__.data.service.ts__tmpl__ │ │ │ │ │ ├── forFeature │ │ │ │ │ │ ├── __name@dasherize__.component.html__tmpl__ │ │ │ │ │ │ ├── __name@dasherize__.component.scss__tmpl__ │ │ │ │ │ │ └── __name@dasherize__.component.ts__tmpl__ │ │ │ │ │ └── forFeatureWithNgrx │ │ │ │ │ │ ├── __name@dasherize__.component.html__tmpl__ │ │ │ │ │ │ ├── __name@dasherize__.component.scss__tmpl__ │ │ │ │ │ │ └── __name@dasherize__.component.ts__tmpl__ │ │ │ │ ├── index.ts │ │ │ │ ├── schema.json │ │ │ │ └── schema.ts │ │ │ ├── init │ │ │ │ ├── index.ts │ │ │ │ ├── schema.json │ │ │ │ └── schematic.ts │ │ │ ├── ui │ │ │ │ ├── index.ts │ │ │ │ ├── schema.json │ │ │ │ └── schema.ts │ │ │ ├── util │ │ │ │ ├── index.ts │ │ │ │ ├── schema.json │ │ │ │ └── schema.ts │ │ │ └── utils │ │ │ │ ├── add-ngrx-imports-to-domain.ts │ │ │ │ ├── add-ts-exports.ts │ │ │ │ ├── addToNgModule.ts │ │ │ │ ├── check-rule-exists.ts │ │ │ │ ├── delete-default-component.ts │ │ │ │ ├── fileContains.ts │ │ │ │ ├── find-array-literal.ts │ │ │ │ ├── get-workspace-scope.ts │ │ │ │ ├── ngrx-version.ts │ │ │ │ ├── npm.ts │ │ │ │ ├── update-dep-const.ts │ │ │ │ └── validate-inputs.ts │ │ ├── index.ts │ │ └── schematics │ │ │ ├── ng-add │ │ │ ├── index.ts │ │ │ └── schema.json │ │ │ ├── rules │ │ │ └── init-linting-rules.ts │ │ │ └── utils │ │ │ ├── check-rule-exists.ts │ │ │ ├── ngrx-version.ts │ │ │ └── update-dep-const.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json └── miles │ ├── domain │ ├── .eslintrc.json │ ├── README.md │ ├── jest.config.ts │ ├── project.json │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── application │ │ │ │ ├── .gitkeep │ │ │ │ └── manage.facade.ts │ │ │ ├── entities │ │ │ │ ├── .gitkeep │ │ │ │ └── ticket.ts │ │ │ ├── infrastructure │ │ │ │ ├── .gitkeep │ │ │ │ └── ticket.data.service.ts │ │ │ └── miles-domain │ │ │ │ ├── miles-domain.component.css │ │ │ │ ├── miles-domain.component.html │ │ │ │ ├── miles-domain.component.spec.ts │ │ │ │ └── miles-domain.component.ts │ │ └── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json │ └── feature-manage │ ├── .eslintrc.json │ ├── README.md │ ├── jest.config.ts │ ├── project.json │ ├── src │ ├── index.ts │ ├── lib │ │ ├── manage.component.html │ │ ├── manage.component.scss │ │ ├── manage.component.ts │ │ └── miles-feature-manage │ │ │ ├── miles-feature-manage.component.css │ │ │ ├── miles-feature-manage.component.html │ │ │ ├── miles-feature-manage.component.spec.ts │ │ │ └── miles-feature-manage.component.ts │ └── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── migrations.json ├── nx.json ├── package-lock.json ├── package.json ├── tools └── tsconfig.tools.json ├── tsconfig.base.json └── update.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "type:app", 17 | "onlyDependOnLibsWithTags": [ 18 | "type:api", 19 | "type:feature", 20 | "type:ui", 21 | "type:domain-logic", 22 | "type:util" 23 | ] 24 | }, 25 | { 26 | "sourceTag": "type:api", 27 | "onlyDependOnLibsWithTags": [ 28 | "type:ui", 29 | "type:domain-logic", 30 | "type:util" 31 | ] 32 | }, 33 | { 34 | "sourceTag": "type:feature", 35 | "onlyDependOnLibsWithTags": [ 36 | "type:ui", 37 | "type:domain-logic", 38 | "type:util" 39 | ] 40 | }, 41 | { 42 | "sourceTag": "type:ui", 43 | "onlyDependOnLibsWithTags": ["type:domain-logic", "type:util"] 44 | }, 45 | { 46 | "sourceTag": "type:domain-logic", 47 | "onlyDependOnLibsWithTags": ["type:util"] 48 | }, 49 | { 50 | "sourceTag": "domain:shared", 51 | "onlyDependOnLibsWithTags": ["domain:shared"] 52 | }, 53 | { 54 | "sourceTag": "domain:luggage", 55 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 56 | }, 57 | { 58 | "sourceTag": "domain:luggage", 59 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 60 | }, 61 | { 62 | "sourceTag": "domain:luggage", 63 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 64 | }, 65 | { 66 | "sourceTag": "domain:luggage", 67 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 68 | }, 69 | { 70 | "sourceTag": "domain:luggage", 71 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 72 | }, 73 | { 74 | "sourceTag": "domain:luggage", 75 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 76 | }, 77 | { 78 | "sourceTag": "domain:luggage", 79 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 80 | }, 81 | { 82 | "sourceTag": "domain:luggage", 83 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 84 | }, 85 | { 86 | "sourceTag": "domain:luggage", 87 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 88 | }, 89 | { 90 | "sourceTag": "domain:luggage", 91 | "onlyDependOnLibsWithTags": ["domain:luggage", "domain:shared"] 92 | }, 93 | { 94 | "sourceTag": "domain:boarding", 95 | "onlyDependOnLibsWithTags": ["domain:boarding", "domain:shared"] 96 | }, 97 | { 98 | "sourceTag": "domain:checkin", 99 | "onlyDependOnLibsWithTags": ["domain:checkin", "domain:shared"] 100 | }, 101 | { 102 | "sourceTag": "domain:feature", 103 | "onlyDependOnLibsWithTags": ["domain:feature", "domain:shared"] 104 | }, 105 | { 106 | "sourceTag": "domain:miles", 107 | "onlyDependOnLibsWithTags": ["domain:miles", "domain:shared"] 108 | } 109 | ] 110 | } 111 | ] 112 | } 113 | }, 114 | { 115 | "files": ["*.ts", "*.tsx"], 116 | "extends": ["plugin:@nx/typescript"], 117 | "rules": {} 118 | }, 119 | { 120 | "files": ["*.js", "*.jsx"], 121 | "extends": ["plugin:@nx/javascript"], 122 | "rules": {} 123 | }, 124 | { 125 | "files": "*.json", 126 | "parser": "jsonc-eslint-parser", 127 | "rules": {} 128 | } 129 | ] 130 | } 131 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | # Angular & NX 42 | .angular 43 | .nx/cache 44 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | 6 | .angular 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "angular.ng-template", 4 | "nrwl.angular-console", 5 | "esbenp.prettier-vscode", 6 | "firsttris.vscode-jest-runner", 7 | "dbaeumer.vscode-eslint" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "json" 4 | ], 5 | "files.exclude": { 6 | "**/.git": true, 7 | "**/.svn": true, 8 | "**/.hg": true, 9 | "**/CVS": true, 10 | "**/.DS_Store": true, 11 | "**/Thumbs.db": true 12 | }, 13 | "hide-files.files": [] 14 | } 15 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/.gitkeep -------------------------------------------------------------------------------- /apps/checkin-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/checkin-e2e/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress'; 2 | import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; 3 | 4 | export default defineConfig({ 5 | e2e: nxE2EPreset(__dirname), 6 | }); 7 | -------------------------------------------------------------------------------- /apps/checkin-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "checkin-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/checkin-e2e/src", 5 | "projectType": "application", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nx/cypress:cypress", 9 | "options": { 10 | "cypressConfig": "apps/checkin-e2e/cypress.config.ts", 11 | "devServerTarget": "checkin:serve:development", 12 | "testingType": "e2e" 13 | }, 14 | "configurations": { 15 | "production": { 16 | "devServerTarget": "checkin:serve:production" 17 | }, 18 | "ci": { 19 | "devServerTarget": "checkin:serve-static" 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": ["apps/checkin-e2e/**/*.{js,ts}"] 28 | } 29 | } 30 | }, 31 | "tags": [], 32 | "implicitDependencies": ["checkin"] 33 | } 34 | -------------------------------------------------------------------------------- /apps/checkin-e2e/src/e2e/app.cy.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('checkin', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome checkin'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/checkin-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/checkin-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/checkin-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/checkin-e2e/src/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/checkin-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /apps/checkin/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "angularArchitects", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "angular-architects", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/checkin/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'checkin', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/apps/checkin', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/checkin/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "checkin", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "prefix": "angular-architects", 6 | "sourceRoot": "apps/checkin/src", 7 | "tags": ["domain:checkin", "type:app"], 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:browser", 11 | "outputs": ["{options.outputPath}"], 12 | "options": { 13 | "outputPath": "dist/apps/checkin", 14 | "index": "apps/checkin/src/index.html", 15 | "main": "apps/checkin/src/main.ts", 16 | "polyfills": ["zone.js"], 17 | "tsConfig": "apps/checkin/tsconfig.app.json", 18 | "assets": ["apps/checkin/src/favicon.ico", "apps/checkin/src/assets"], 19 | "styles": ["apps/checkin/src/styles.scss"], 20 | "scripts": [] 21 | }, 22 | "configurations": { 23 | "production": { 24 | "budgets": [ 25 | { 26 | "type": "initial", 27 | "maximumWarning": "500kb", 28 | "maximumError": "1mb" 29 | }, 30 | { 31 | "type": "anyComponentStyle", 32 | "maximumWarning": "2kb", 33 | "maximumError": "4kb" 34 | } 35 | ], 36 | "outputHashing": "all" 37 | }, 38 | "development": { 39 | "buildOptimizer": false, 40 | "optimization": false, 41 | "vendorChunk": true, 42 | "extractLicenses": false, 43 | "sourceMap": true, 44 | "namedChunks": true 45 | } 46 | }, 47 | "defaultConfiguration": "production" 48 | }, 49 | "serve": { 50 | "executor": "@angular-devkit/build-angular:dev-server", 51 | "configurations": { 52 | "production": { 53 | "browserTarget": "checkin:build:production" 54 | }, 55 | "development": { 56 | "browserTarget": "checkin:build:development" 57 | } 58 | }, 59 | "defaultConfiguration": "development" 60 | }, 61 | "extract-i18n": { 62 | "executor": "@angular-devkit/build-angular:extract-i18n", 63 | "options": { 64 | "browserTarget": "checkin:build" 65 | } 66 | }, 67 | "lint": { 68 | "executor": "@nx/linter:eslint", 69 | "outputs": ["{options.outputFile}"], 70 | "options": { 71 | "lintFilePatterns": ["apps/checkin/**/*.ts", "apps/checkin/**/*.html"] 72 | } 73 | }, 74 | "test": { 75 | "executor": "@nx/jest:jest", 76 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 77 | "options": { 78 | "jestConfig": "apps/checkin/jest.config.ts", 79 | "passWithNoTests": true 80 | }, 81 | "configurations": { 82 | "ci": { 83 | "ci": true, 84 | "codeCoverage": true 85 | } 86 | } 87 | }, 88 | "serve-static": { 89 | "executor": "@nx/web:file-server", 90 | "options": { 91 | "buildTarget": "checkin:build" 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /apps/checkin/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |

checkin

2 | -------------------------------------------------------------------------------- /apps/checkin/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/checkin/src/app/app.component.scss -------------------------------------------------------------------------------- /apps/checkin/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'luggage'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('luggage'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain( 28 | 'Welcome luggage' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/checkin/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { ManageComponent } from '@angular-architects/checkin/feature-manage'; 4 | 5 | @Component({ 6 | standalone: true, 7 | imports: [CommonModule, ManageComponent], 8 | selector: 'angular-architects-root', 9 | templateUrl: './app.component.html', 10 | styleUrls: ['./app.component.scss'], 11 | }) 12 | export class AppComponent { 13 | title = 'checkin'; 14 | } 15 | -------------------------------------------------------------------------------- /apps/checkin/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig } from '@angular/core'; 2 | 3 | export const appConfig: ApplicationConfig = { 4 | providers: [], 5 | }; 6 | -------------------------------------------------------------------------------- /apps/checkin/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/checkin/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/checkin/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/checkin/src/favicon.ico -------------------------------------------------------------------------------- /apps/checkin/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | checkin 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/checkin/src/main.ts: -------------------------------------------------------------------------------- 1 | import { HttpClientModule } from '@angular/common/http'; 2 | import { enableProdMode, importProvidersFrom } from '@angular/core'; 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | 5 | import { AppComponent } from './app/app.component'; 6 | 7 | bootstrapApplication(AppComponent, { 8 | providers: [importProvidersFrom(HttpClientModule)], 9 | }); 10 | -------------------------------------------------------------------------------- /apps/checkin/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/checkin/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /apps/checkin/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/checkin/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/checkin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.app.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | }, 21 | { 22 | "path": "./tsconfig.editor.json" 23 | } 24 | ], 25 | "extends": "../../tsconfig.base.json", 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/checkin/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/ddd-e2e/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'ddd-e2e', 4 | preset: '../../jest.preset.js', 5 | globals: {}, 6 | transform: { 7 | '^.+\\.[tj]s$': [ 8 | 'ts-jest', 9 | { 10 | tsconfig: '/tsconfig.spec.json', 11 | }, 12 | ], 13 | }, 14 | moduleFileExtensions: ['ts', 'js', 'html'], 15 | coverageDirectory: '../../coverage/apps/ddd-e2e', 16 | }; 17 | -------------------------------------------------------------------------------- /apps/ddd-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddd-e2e", 3 | "$schema": "..\\..\\node_modules\\nx\\schemas\\project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/ddd-e2e/src", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nx/jest:jest", 9 | "options": { 10 | "jestConfig": "apps/ddd-e2e/jest.config.ts", 11 | "runInBand": true 12 | }, 13 | "dependsOn": ["ddd:build"] 14 | } 15 | }, 16 | "tags": [], 17 | "implicitDependencies": ["ddd"] 18 | } 19 | -------------------------------------------------------------------------------- /apps/ddd-e2e/tests/ddd.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | checkFilesExist, 3 | ensureNxProject, 4 | readJson, 5 | runNxCommandAsync, 6 | uniq, 7 | } from '@nx/plugin/testing'; 8 | 9 | describe('ddd e2e', () => { 10 | // Setting up individual workspaces per 11 | // test can cause e2e runs to take a long time. 12 | // For this reason, we recommend each suite only 13 | // consumes 1 workspace. The tests should each operate 14 | // on a unique project in the workspace, such that they 15 | // are not dependant on one another. 16 | beforeAll(() => { 17 | ensureNxProject('@ddd-plugin/ddd', 'dist/libs/ddd'); 18 | }); 19 | 20 | afterAll(() => { 21 | // `nx reset` kills the daemon, and performs 22 | // some work which can help clean up e2e leftovers 23 | runNxCommandAsync('reset'); 24 | }); 25 | 26 | it('should create ddd', async () => { 27 | const project = uniq('ddd'); 28 | await runNxCommandAsync(`generate @ddd-plugin/ddd:ddd ${project}`); 29 | const result = await runNxCommandAsync(`build ${project}`); 30 | expect(result.stdout).toContain('Executor ran'); 31 | }, 120000); 32 | 33 | describe('--directory', () => { 34 | it('should create src in the specified directory', async () => { 35 | const project = uniq('ddd'); 36 | await runNxCommandAsync( 37 | `generate @ddd-plugin/ddd:ddd ${project} --directory subdir` 38 | ); 39 | expect(() => 40 | checkFilesExist(`libs/subdir/${project}/src/index.ts`) 41 | ).not.toThrow(); 42 | }, 120000); 43 | }); 44 | 45 | describe('--tags', () => { 46 | it('should add tags to the project', async () => { 47 | const projectName = uniq('ddd'); 48 | ensureNxProject('@ddd-plugin/ddd', 'dist/libs/ddd'); 49 | await runNxCommandAsync( 50 | `generate @ddd-plugin/ddd:ddd ${projectName} --tags e2etag,e2ePackage` 51 | ); 52 | const project = readJson(`libs/${projectName}/project.json`); 53 | expect(project.tags).toEqual(['e2etag', 'e2ePackage']); 54 | }, 120000); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /apps/ddd-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.spec.json" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/ddd-e2e/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["src/plugins/index.js"], 11 | "rules": { 12 | "@typescript-eslint/no-var-requires": "off", 13 | "no-undef": "off" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "supportFile": "./src/support/index.ts", 7 | "pluginsFile": false, 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/demo-app-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/demo-app-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-app-e2e", 3 | "$schema": "..\\..\\node_modules\\nx\\schemas\\project-schema.json", 4 | "sourceRoot": "apps/demo-app-e2e/src", 5 | "projectType": "application", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nx/cypress:cypress", 9 | "options": { 10 | "cypressConfig": "apps/demo-app-e2e/cypress.json", 11 | "devServerTarget": "demo-app:serve:development" 12 | }, 13 | "configurations": { 14 | "production": { 15 | "devServerTarget": "demo-app:serve:production" 16 | } 17 | } 18 | }, 19 | "lint": { 20 | "executor": "@nx/linter:eslint", 21 | "outputs": ["{options.outputFile}"], 22 | "options": { 23 | "lintFilePatterns": ["apps/demo-app-e2e/**/*.{js,ts}"] 24 | } 25 | } 26 | }, 27 | "tags": [], 28 | "implicitDependencies": ["demo-app"] 29 | } 30 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('demo-app', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome demo-app'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/demo-app-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js"], 16 | "angularCompilerOptions": { 17 | "enableI18nLegacyMessageIdFormat": false, 18 | "strictInjectionParameters": true, 19 | "strictInputAccessModifiers": true, 20 | "strictTemplates": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /apps/demo-app/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /apps/demo-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "dddPlugin", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "ddd-plugin", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/demo-app/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'demo-app', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: {}, 7 | coverageDirectory: '../../coverage/apps/demo-app', 8 | transform: { 9 | '^.+\\.(ts|mjs|js|html)$': [ 10 | 'jest-preset-angular', 11 | { 12 | tsconfig: '/tsconfig.spec.json', 13 | stringifyContentPathRegex: '\\.(html|svg)$', 14 | }, 15 | ], 16 | }, 17 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/serializers/no-ng-attributes', 20 | 'jest-preset-angular/build/serializers/ng-snapshot', 21 | 'jest-preset-angular/build/serializers/html-comment', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /apps/demo-app/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-app", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/demo-app/src", 6 | "prefix": "ddd-plugin", 7 | "targets": { 8 | "build": { 9 | "executor": "@angular-devkit/build-angular:browser", 10 | "outputs": ["{options.outputPath}"], 11 | "options": { 12 | "outputPath": "dist/apps/demo-app", 13 | "index": "apps/demo-app/src/index.html", 14 | "main": "apps/demo-app/src/main.ts", 15 | "polyfills": "apps/demo-app/src/polyfills.ts", 16 | "tsConfig": "apps/demo-app/tsconfig.app.json", 17 | "assets": ["apps/demo-app/src/favicon.ico", "apps/demo-app/src/assets"], 18 | "styles": ["apps/demo-app/src/styles.css"], 19 | "scripts": [] 20 | }, 21 | "configurations": { 22 | "production": { 23 | "budgets": [ 24 | { 25 | "type": "initial", 26 | "maximumWarning": "500kb", 27 | "maximumError": "1mb" 28 | }, 29 | { 30 | "type": "anyComponentStyle", 31 | "maximumWarning": "2kb", 32 | "maximumError": "4kb" 33 | } 34 | ], 35 | "fileReplacements": [ 36 | { 37 | "replace": "apps/demo-app/src/environments/environment.ts", 38 | "with": "apps/demo-app/src/environments/environment.prod.ts" 39 | } 40 | ], 41 | "outputHashing": "all" 42 | }, 43 | "development": { 44 | "buildOptimizer": false, 45 | "optimization": false, 46 | "vendorChunk": true, 47 | "extractLicenses": false, 48 | "sourceMap": true, 49 | "namedChunks": true 50 | } 51 | }, 52 | "defaultConfiguration": "production" 53 | }, 54 | "serve": { 55 | "executor": "@angular-devkit/build-angular:dev-server", 56 | "configurations": { 57 | "production": { 58 | "browserTarget": "demo-app:build:production" 59 | }, 60 | "development": { 61 | "browserTarget": "demo-app:build:development" 62 | } 63 | }, 64 | "defaultConfiguration": "development" 65 | }, 66 | "extract-i18n": { 67 | "executor": "@angular-devkit/build-angular:extract-i18n", 68 | "options": { 69 | "browserTarget": "demo-app:build" 70 | } 71 | }, 72 | "lint": { 73 | "executor": "@nx/linter:eslint", 74 | "options": { 75 | "lintFilePatterns": ["apps/demo-app/**/*.ts", "apps/demo-app/**/*.html"] 76 | } 77 | }, 78 | "test": { 79 | "executor": "@nx/jest:jest", 80 | "outputs": ["{workspaceRoot}/coverage/apps/demo-app"], 81 | "options": { 82 | "jestConfig": "apps/demo-app/jest.config.ts", 83 | "passWithNoTests": true 84 | } 85 | } 86 | }, 87 | "tags": [] 88 | } 89 | -------------------------------------------------------------------------------- /apps/demo-app/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/demo-app/src/app/app.component.css -------------------------------------------------------------------------------- /apps/demo-app/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/demo-app/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | import { NxWelcomeComponent } from './nx-welcome.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | declarations: [AppComponent, NxWelcomeComponent], 9 | }).compileComponents(); 10 | }); 11 | 12 | it('should create the app', () => { 13 | const fixture = TestBed.createComponent(AppComponent); 14 | const app = fixture.componentInstance; 15 | expect(app).toBeTruthy(); 16 | }); 17 | 18 | it(`should have as title 'demo-app'`, () => { 19 | const fixture = TestBed.createComponent(AppComponent); 20 | const app = fixture.componentInstance; 21 | expect(app.title).toEqual('demo-app'); 22 | }); 23 | 24 | it('should render title', () => { 25 | const fixture = TestBed.createComponent(AppComponent); 26 | fixture.detectChanges(); 27 | const compiled = fixture.nativeElement as HTMLElement; 28 | expect(compiled.querySelector('h1')?.textContent).toContain( 29 | 'Welcome demo-app' 30 | ); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /apps/demo-app/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'ddd-plugin-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'], 7 | }) 8 | export class AppComponent { 9 | title = 'demo-app'; 10 | } 11 | -------------------------------------------------------------------------------- /apps/demo-app/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { NxWelcomeComponent } from './nx-welcome.component'; 6 | 7 | @NgModule({ 8 | declarations: [AppComponent, NxWelcomeComponent], 9 | imports: [BrowserModule], 10 | providers: [], 11 | bootstrap: [AppComponent], 12 | }) 13 | export class AppModule {} 14 | -------------------------------------------------------------------------------- /apps/demo-app/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/demo-app/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/demo-app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/demo-app/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/demo-app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/demo-app/src/favicon.ico -------------------------------------------------------------------------------- /apps/demo-app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DemoApp 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/demo-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/demo-app/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | -------------------------------------------------------------------------------- /apps/demo-app/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/demo-app/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/demo-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["**/*.test.ts", "**/*.spec.ts", "jest.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/demo-app/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "target": "es2020", 18 | "forceConsistentCasingInFileNames": true, 19 | "strict": true, 20 | "noImplicitOverride": true, 21 | "noPropertyAccessFromIndexSignature": true, 22 | "noImplicitReturns": true, 23 | "noFallthroughCasesInSwitch": true 24 | }, 25 | "angularCompilerOptions": { 26 | "enableI18nLegacyMessageIdFormat": false, 27 | "strictInjectionParameters": true, 28 | "strictInputAccessModifiers": true, 29 | "strictTemplates": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/demo-app/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/feature-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/feature-e2e/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress'; 2 | import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; 3 | 4 | export default defineConfig({ 5 | e2e: nxE2EPreset(__dirname), 6 | }); 7 | -------------------------------------------------------------------------------- /apps/feature-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feature-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/feature-e2e/src", 5 | "projectType": "application", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nx/cypress:cypress", 9 | "options": { 10 | "cypressConfig": "apps/feature-e2e/cypress.config.ts", 11 | "devServerTarget": "feature:serve:development", 12 | "testingType": "e2e" 13 | }, 14 | "configurations": { 15 | "production": { 16 | "devServerTarget": "feature:serve:production" 17 | }, 18 | "ci": { 19 | "devServerTarget": "feature:serve-static" 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": ["apps/feature-e2e/**/*.{js,ts}"] 28 | } 29 | } 30 | }, 31 | "tags": [], 32 | "implicitDependencies": ["feature"] 33 | } 34 | -------------------------------------------------------------------------------- /apps/feature-e2e/src/e2e/app.cy.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('feature', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome feature'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/feature-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/feature-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/feature-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/feature-e2e/src/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/feature-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /apps/feature/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "angularArchitects", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "angular-architects", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/feature/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'feature', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/apps/feature', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/feature/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feature", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "prefix": "angular-architects", 6 | "sourceRoot": "apps/feature/src", 7 | "tags": ["domain:feature", "type:app"], 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:browser", 11 | "outputs": ["{options.outputPath}"], 12 | "options": { 13 | "outputPath": "dist/apps/feature", 14 | "index": "apps/feature/src/index.html", 15 | "main": "apps/feature/src/main.ts", 16 | "polyfills": ["zone.js"], 17 | "tsConfig": "apps/feature/tsconfig.app.json", 18 | "assets": ["apps/feature/src/favicon.ico", "apps/feature/src/assets"], 19 | "styles": ["apps/feature/src/styles.scss"], 20 | "scripts": [] 21 | }, 22 | "configurations": { 23 | "production": { 24 | "budgets": [ 25 | { 26 | "type": "initial", 27 | "maximumWarning": "500kb", 28 | "maximumError": "1mb" 29 | }, 30 | { 31 | "type": "anyComponentStyle", 32 | "maximumWarning": "2kb", 33 | "maximumError": "4kb" 34 | } 35 | ], 36 | "outputHashing": "all" 37 | }, 38 | "development": { 39 | "buildOptimizer": false, 40 | "optimization": false, 41 | "vendorChunk": true, 42 | "extractLicenses": false, 43 | "sourceMap": true, 44 | "namedChunks": true 45 | } 46 | }, 47 | "defaultConfiguration": "production" 48 | }, 49 | "serve": { 50 | "executor": "@angular-devkit/build-angular:dev-server", 51 | "configurations": { 52 | "production": { 53 | "browserTarget": "feature:build:production" 54 | }, 55 | "development": { 56 | "browserTarget": "feature:build:development" 57 | } 58 | }, 59 | "defaultConfiguration": "development" 60 | }, 61 | "extract-i18n": { 62 | "executor": "@angular-devkit/build-angular:extract-i18n", 63 | "options": { 64 | "browserTarget": "feature:build" 65 | } 66 | }, 67 | "lint": { 68 | "executor": "@nx/linter:eslint", 69 | "outputs": ["{options.outputFile}"], 70 | "options": { 71 | "lintFilePatterns": ["apps/feature/**/*.ts", "apps/feature/**/*.html"] 72 | } 73 | }, 74 | "test": { 75 | "executor": "@nx/jest:jest", 76 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 77 | "options": { 78 | "jestConfig": "apps/feature/jest.config.ts", 79 | "passWithNoTests": true 80 | }, 81 | "configurations": { 82 | "ci": { 83 | "ci": true, 84 | "codeCoverage": true 85 | } 86 | } 87 | }, 88 | "serve-static": { 89 | "executor": "@nx/web:file-server", 90 | "options": { 91 | "buildTarget": "feature:build" 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /apps/feature/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |

feature

2 | -------------------------------------------------------------------------------- /apps/feature/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/feature/src/app/app.component.scss -------------------------------------------------------------------------------- /apps/feature/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'luggage'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('luggage'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain( 28 | 'Welcome luggage' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/feature/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | standalone: true, 6 | imports: [CommonModule], 7 | selector: 'angular-architects-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.scss'], 10 | }) 11 | export class AppComponent { 12 | title = 'feature'; 13 | } 14 | -------------------------------------------------------------------------------- /apps/feature/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig } from '@angular/core'; 2 | 3 | export const appConfig: ApplicationConfig = { 4 | providers: [], 5 | }; 6 | -------------------------------------------------------------------------------- /apps/feature/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/feature/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/feature/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/feature/src/favicon.ico -------------------------------------------------------------------------------- /apps/feature/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | feature 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/feature/src/main.ts: -------------------------------------------------------------------------------- 1 | import { HttpClientModule } from '@angular/common/http'; 2 | import { enableProdMode, importProvidersFrom } from '@angular/core'; 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | 5 | import { AppComponent } from './app/app.component'; 6 | import { environment } from './environments/environment'; 7 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } 11 | 12 | bootstrapApplication(AppComponent, { 13 | providers: [importProvidersFrom(HttpClientModule)], 14 | }); 15 | -------------------------------------------------------------------------------- /apps/feature/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/feature/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /apps/feature/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/feature/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/feature/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.app.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | }, 21 | { 22 | "path": "./tsconfig.editor.json" 23 | } 24 | ], 25 | "extends": "../../tsconfig.base.json", 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/feature/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/miles-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/miles-e2e/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress'; 2 | import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; 3 | 4 | export default defineConfig({ 5 | e2e: nxE2EPreset(__dirname), 6 | }); 7 | -------------------------------------------------------------------------------- /apps/miles-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "miles-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/miles-e2e/src", 5 | "projectType": "application", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nx/cypress:cypress", 9 | "options": { 10 | "cypressConfig": "apps/miles-e2e/cypress.config.ts", 11 | "devServerTarget": "miles:serve:development", 12 | "testingType": "e2e" 13 | }, 14 | "configurations": { 15 | "production": { 16 | "devServerTarget": "miles:serve:production" 17 | }, 18 | "ci": { 19 | "devServerTarget": "miles:serve-static" 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": ["apps/miles-e2e/**/*.{js,ts}"] 28 | } 29 | } 30 | }, 31 | "tags": [], 32 | "implicitDependencies": ["miles"] 33 | } 34 | -------------------------------------------------------------------------------- /apps/miles-e2e/src/e2e/app.cy.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('miles', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome miles'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/miles-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/miles-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/miles-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/miles-e2e/src/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/miles-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /apps/miles/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "angularArchitects", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "angular-architects", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/miles/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'miles', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/apps/miles', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/miles/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "miles", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "prefix": "angular-architects", 6 | "sourceRoot": "apps/miles/src", 7 | "tags": ["domain:miles", "type:app"], 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:browser", 11 | "outputs": ["{options.outputPath}"], 12 | "options": { 13 | "outputPath": "dist/apps/miles", 14 | "index": "apps/miles/src/index.html", 15 | "main": "apps/miles/src/main.ts", 16 | "polyfills": ["zone.js"], 17 | "tsConfig": "apps/miles/tsconfig.app.json", 18 | "assets": ["apps/miles/src/favicon.ico", "apps/miles/src/assets"], 19 | "styles": ["apps/miles/src/styles.scss"], 20 | "scripts": [] 21 | }, 22 | "configurations": { 23 | "production": { 24 | "budgets": [ 25 | { 26 | "type": "initial", 27 | "maximumWarning": "500kb", 28 | "maximumError": "1mb" 29 | }, 30 | { 31 | "type": "anyComponentStyle", 32 | "maximumWarning": "2kb", 33 | "maximumError": "4kb" 34 | } 35 | ], 36 | "outputHashing": "all" 37 | }, 38 | "development": { 39 | "buildOptimizer": false, 40 | "optimization": false, 41 | "vendorChunk": true, 42 | "extractLicenses": false, 43 | "sourceMap": true, 44 | "namedChunks": true 45 | } 46 | }, 47 | "defaultConfiguration": "production" 48 | }, 49 | "serve": { 50 | "executor": "@angular-devkit/build-angular:dev-server", 51 | "configurations": { 52 | "production": { 53 | "browserTarget": "miles:build:production" 54 | }, 55 | "development": { 56 | "browserTarget": "miles:build:development" 57 | } 58 | }, 59 | "defaultConfiguration": "development" 60 | }, 61 | "extract-i18n": { 62 | "executor": "@angular-devkit/build-angular:extract-i18n", 63 | "options": { 64 | "browserTarget": "miles:build" 65 | } 66 | }, 67 | "lint": { 68 | "executor": "@nx/linter:eslint", 69 | "outputs": ["{options.outputFile}"], 70 | "options": { 71 | "lintFilePatterns": ["apps/miles/**/*.ts", "apps/miles/**/*.html"] 72 | } 73 | }, 74 | "test": { 75 | "executor": "@nx/jest:jest", 76 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 77 | "options": { 78 | "jestConfig": "apps/miles/jest.config.ts", 79 | "passWithNoTests": true 80 | }, 81 | "configurations": { 82 | "ci": { 83 | "ci": true, 84 | "codeCoverage": true 85 | } 86 | } 87 | }, 88 | "serve-static": { 89 | "executor": "@nx/web:file-server", 90 | "options": { 91 | "buildTarget": "miles:build" 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /apps/miles/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |

miles

2 | -------------------------------------------------------------------------------- /apps/miles/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/miles/src/app/app.component.scss -------------------------------------------------------------------------------- /apps/miles/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'luggage'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('luggage'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain( 28 | 'Welcome luggage' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/miles/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { ManageComponent } from '@angular-architects/miles/feature-manage'; 2 | import { CommonModule } from '@angular/common'; 3 | import { Component } from '@angular/core'; 4 | 5 | @Component({ 6 | standalone: true, 7 | imports: [CommonModule, ManageComponent], 8 | selector: 'angular-architects-root', 9 | templateUrl: './app.component.html', 10 | styleUrls: ['./app.component.scss'], 11 | }) 12 | export class AppComponent { 13 | title = 'miles'; 14 | } 15 | -------------------------------------------------------------------------------- /apps/miles/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig } from '@angular/core'; 2 | 3 | export const appConfig: ApplicationConfig = { 4 | providers: [], 5 | }; 6 | -------------------------------------------------------------------------------- /apps/miles/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/miles/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/miles/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/apps/miles/src/favicon.ico -------------------------------------------------------------------------------- /apps/miles/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | miles 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/miles/src/main.ts: -------------------------------------------------------------------------------- 1 | import { HttpClientModule } from '@angular/common/http'; 2 | import { enableProdMode, importProvidersFrom } from '@angular/core'; 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | 5 | import { AppComponent } from './app/app.component'; 6 | 7 | bootstrapApplication(AppComponent, { 8 | providers: [importProvidersFrom(HttpClientModule)], 9 | }); 10 | -------------------------------------------------------------------------------- /apps/miles/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/miles/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /apps/miles/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/miles/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/miles/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.app.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | }, 21 | { 22 | "path": "./tsconfig.editor.json" 23 | } 24 | ], 25 | "extends": "../../tsconfig.base.json", 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/miles/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /decorate-angular-cli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching 3 | * and faster execution of tasks. 4 | * 5 | * It does this by: 6 | * 7 | * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command. 8 | * - Symlinking the ng to nx command, so all commands run through the Nx CLI 9 | * - Updating the package.json postinstall script to give you control over this script 10 | * 11 | * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it. 12 | * Every command you run should work the same when using the Nx CLI, except faster. 13 | * 14 | * Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case, 15 | * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked. 16 | * The Nx CLI simply does some optimizations before invoking the Angular CLI. 17 | * 18 | * To opt out of this patch: 19 | * - Replace occurrences of nx with ng in your package.json 20 | * - Remove the script from your postinstall script in your package.json 21 | * - Delete and reinstall your node_modules 22 | */ 23 | 24 | const fs = require('fs'); 25 | const os = require('os'); 26 | const cp = require('child_process'); 27 | const isWindows = os.platform() === 'win32'; 28 | let output; 29 | try { 30 | output = require('@nx/workspace').output; 31 | } catch (e) { 32 | console.warn( 33 | 'Angular CLI could not be decorated to enable computation caching. Please ensure @nx/workspace is installed.' 34 | ); 35 | process.exit(0); 36 | } 37 | 38 | /** 39 | * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still 40 | * invoke the Nx CLI and get the benefits of computation caching. 41 | */ 42 | function symlinkNgCLItoNxCLI() { 43 | try { 44 | const ngPath = './node_modules/.bin/ng'; 45 | const nxPath = './node_modules/.bin/nx'; 46 | if (isWindows) { 47 | /** 48 | * This is the most reliable way to create symlink-like behavior on Windows. 49 | * Such that it works in all shells and works with npx. 50 | */ 51 | ['', '.cmd', '.ps1'].forEach((ext) => { 52 | if (fs.existsSync(nxPath + ext)) 53 | fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext)); 54 | }); 55 | } else { 56 | // If unix-based, symlink 57 | cp.execSync(`ln -sf ./nx ${ngPath}`); 58 | } 59 | } catch (e) { 60 | output.error({ 61 | title: 62 | 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + 63 | e.message, 64 | }); 65 | throw e; 66 | } 67 | } 68 | 69 | try { 70 | symlinkNgCLItoNxCLI(); 71 | require('nx/src/adapter/decorate-cli').decorateCli(); 72 | output.log({ 73 | title: 'Angular CLI has been decorated to enable computation caching.', 74 | }); 75 | } catch (e) { 76 | output.error({ 77 | title: 'Decoration of the Angular CLI did not complete successfully', 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjects } from '@nx/jest'; 2 | 3 | export default { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { 4 | ...nxPreset, 5 | /* TODO: Update to latest Jest snapshotFormat 6 | * By default Nx has kept the older style of Jest Snapshot formats 7 | * to prevent breaking of any existing tests with snapshots. 8 | * It's recommend you update to the latest format. 9 | * You can do this by removing snapshotFormat property 10 | * and running tests with --update-snapshot flag. 11 | * Example: "nx affected --targets=test --update-snapshot" 12 | * More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format 13 | */ 14 | snapshotFormat: { escapeString: true, printBasicPrototype: true }, 15 | }; 16 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/.gitkeep -------------------------------------------------------------------------------- /libs/checkin/domain/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "checkin", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "checkin", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /libs/checkin/domain/README.md: -------------------------------------------------------------------------------- 1 | # checkin-domain 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test checkin-domain` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/checkin/domain/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'checkin-domain', 4 | preset: '../../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../../coverage/libs/checkin/domain', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /libs/checkin/domain/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "checkin-domain", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/checkin/domain/src", 5 | "prefix": "checkin", 6 | "tags": ["domain:checkin", "type:domain-logic"], 7 | "projectType": "library", 8 | "targets": { 9 | "test": { 10 | "executor": "@nx/jest:jest", 11 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 12 | "options": { 13 | "jestConfig": "libs/checkin/domain/jest.config.ts", 14 | "passWithNoTests": true 15 | }, 16 | "configurations": { 17 | "ci": { 18 | "ci": true, 19 | "codeCoverage": true 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": [ 28 | "libs/checkin/domain/**/*.ts", 29 | "libs/checkin/domain/**/*.html" 30 | ] 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libs/checkin/domain/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/entities/ticket'; 2 | export * from './lib/infrastructure/ticket.data.service'; 3 | 4 | export * from './lib/application/manage.facade'; 5 | -------------------------------------------------------------------------------- /libs/checkin/domain/src/lib/application/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/checkin/domain/src/lib/application/.gitkeep -------------------------------------------------------------------------------- /libs/checkin/domain/src/lib/application/manage.facade.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { BehaviorSubject } from 'rxjs'; 3 | 4 | import { Ticket } from '../entities/ticket'; 5 | import { TicketDataService } from '../infrastructure/ticket.data.service'; 6 | 7 | @Injectable({ providedIn: 'root' }) 8 | export class ManageFacade { 9 | private ticketListSubject = new BehaviorSubject([]); 10 | ticketList$ = this.ticketListSubject.asObservable(); 11 | 12 | constructor(private ticketDataService: TicketDataService) {} 13 | 14 | load(): void { 15 | this.ticketDataService.load().subscribe({ 16 | next: (ticketList) => { 17 | this.ticketListSubject.next(ticketList); 18 | }, 19 | error: (err) => { 20 | console.error('err', err); 21 | }, 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /libs/checkin/domain/src/lib/entities/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/checkin/domain/src/lib/entities/.gitkeep -------------------------------------------------------------------------------- /libs/checkin/domain/src/lib/entities/ticket.ts: -------------------------------------------------------------------------------- 1 | export interface Ticket { 2 | id: number; 3 | name: string; 4 | description: string; 5 | } 6 | -------------------------------------------------------------------------------- /libs/checkin/domain/src/lib/infrastructure/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/checkin/domain/src/lib/infrastructure/.gitkeep -------------------------------------------------------------------------------- /libs/checkin/domain/src/lib/infrastructure/ticket.data.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; 3 | import { Observable, of } from 'rxjs'; 4 | import { Ticket } from '../entities/ticket'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class TicketDataService { 8 | constructor(private http: HttpClient) {} 9 | 10 | load(): Observable { 11 | // Uncomment if needed 12 | /* 13 | const url = '...'; 14 | const params = new HttpParams().set('param', 'value'); 15 | const headers = new HttpHeaders().set('Accept', 'application/json'); 16 | return this.http.get(url, {params, headers}); 17 | */ 18 | 19 | return of([ 20 | { id: 1, name: 'Lorem ipsum', description: 'Lorem ipsum dolor sit amet' }, 21 | { 22 | id: 2, 23 | name: 'At vero eos', 24 | description: 'At vero eos et accusam et justo duo dolores', 25 | }, 26 | { 27 | id: 3, 28 | name: 'Duis autem', 29 | description: 'Duis autem vel eum iriure dolor in hendrerit', 30 | }, 31 | ]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /libs/checkin/domain/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /libs/checkin/domain/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ], 16 | "extends": "../../../tsconfig.base.json" 17 | } 18 | -------------------------------------------------------------------------------- /libs/checkin/domain/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "src/**/*.spec.ts", 12 | "src/test-setup.ts", 13 | "jest.config.ts", 14 | "src/**/*.test.ts" 15 | ], 16 | "include": ["src/**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /libs/checkin/domain/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "checkin", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "checkin", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/README.md: -------------------------------------------------------------------------------- 1 | # checkin-feature-manage 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test checkin-feature-manage` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'checkin-feature-manage', 4 | preset: '../../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../../coverage/libs/checkin/feature-manage', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "checkin-feature-manage", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/checkin/feature-manage/src", 5 | "prefix": "checkin", 6 | "tags": ["domain:checkin", "type:feature"], 7 | "projectType": "library", 8 | "targets": { 9 | "test": { 10 | "executor": "@nx/jest:jest", 11 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 12 | "options": { 13 | "jestConfig": "libs/checkin/feature-manage/jest.config.ts", 14 | "passWithNoTests": true 15 | }, 16 | "configurations": { 17 | "ci": { 18 | "ci": true, 19 | "codeCoverage": true 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": [ 28 | "libs/checkin/feature-manage/**/*.ts", 29 | "libs/checkin/feature-manage/**/*.html" 30 | ] 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/manage.component'; 2 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/src/lib/manage.component.html: -------------------------------------------------------------------------------- 1 |

checkin-manage

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
{{ ticket.id }}{{ ticket.name }}{{ ticket.description }}
10 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/src/lib/manage.component.scss: -------------------------------------------------------------------------------- 1 | .table td { 2 | border: 1px solid; 3 | padding: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/src/lib/manage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { ManageFacade } from '@angular-architects/checkin/domain'; 4 | 5 | @Component({ 6 | standalone: true, 7 | imports: [CommonModule], 8 | selector: 'checkin-manage', 9 | templateUrl: './manage.component.html', 10 | styleUrls: ['./manage.component.scss'], 11 | }) 12 | export class ManageComponent implements OnInit { 13 | ticketList$ = this.manageFacade.ticketList$; 14 | 15 | constructor(private manageFacade: ManageFacade) {} 16 | 17 | ngOnInit() { 18 | this.load(); 19 | } 20 | 21 | load(): void { 22 | this.manageFacade.load(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ], 16 | "extends": "../../../tsconfig.base.json" 17 | } 18 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "src/**/*.spec.ts", 12 | "src/test-setup.ts", 13 | "jest.config.ts", 14 | "src/**/*.test.ts" 15 | ], 16 | "include": ["src/**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /libs/checkin/feature-manage/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/ddd/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["./package.json", "./generators.json", "./executors.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/nx-plugin-checks": "error" 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /libs/ddd/assets/ddd-libs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/ddd-libs.png -------------------------------------------------------------------------------- /libs/ddd/assets/ddd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/ddd.png -------------------------------------------------------------------------------- /libs/ddd/assets/domain-layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/domain-layer.png -------------------------------------------------------------------------------- /libs/ddd/assets/linting-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/linting-1.png -------------------------------------------------------------------------------- /libs/ddd/assets/linting-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/linting-2.png -------------------------------------------------------------------------------- /libs/ddd/assets/linting-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/linting-3.png -------------------------------------------------------------------------------- /libs/ddd/assets/result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/assets/result.png -------------------------------------------------------------------------------- /libs/ddd/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@angular-architects/ddd", 3 | "version": "0.0.1", 4 | "schematics": { 5 | "ng-add": { 6 | "factory": "./src/schematics/ng-add/index", 7 | "description": "adds initial access restrictions to linting rules", 8 | "schema": "./src/schematics/ng-add/schema.json" 9 | } 10 | }, 11 | "generators": { 12 | "init": { 13 | "factory": "./src/generators/init/index", 14 | "description": "adds initial access restrictions to linting rules", 15 | "schema": "./src/generators/init/schema.json" 16 | }, 17 | "domain": { 18 | "factory": "./src/generators/domain/index", 19 | "schema": "./src/generators/domain/schema.json", 20 | "description": "domain generator" 21 | }, 22 | "feature": { 23 | "factory": "./src/generators/feature/index", 24 | "schema": "./src/generators/feature/schema.json", 25 | "description": "adds a feature lib to a domain" 26 | }, 27 | "ui": { 28 | "factory": "./src/generators/ui/index", 29 | "schema": "./src/generators/ui/schema.json", 30 | "description": "adds a UI library to a domain or as a shared library" 31 | }, 32 | "api": { 33 | "factory": "./src/generators/api/index", 34 | "schema": "./src/generators/api/schema.json", 35 | "description": "adds a API library to a domain or as a shared library" 36 | }, 37 | "util": { 38 | "factory": "./src/generators/util/index", 39 | "schema": "./src/generators/util/schema.json", 40 | "description": "adds a utility library to a domain or as a shared library" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /libs/ddd/executors.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "executors": { 4 | "build": { 5 | "implementation": "./src/executors/build/executor", 6 | "schema": "./src/executors/build/schema.json", 7 | "description": "build executor" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/ddd/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "name": "ddd", 4 | "version": "0.0.1", 5 | "generators": { 6 | "ddd": { 7 | "factory": "./src/generators/ddd/generator", 8 | "schema": "./src/generators/ddd/schema.json", 9 | "description": "ddd generator" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /libs/ddd/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'ddd', 4 | preset: '../../jest.preset.js', 5 | globals: {}, 6 | transform: { 7 | '^.+\\.[tj]s$': [ 8 | 'ts-jest', 9 | { 10 | tsconfig: '/tsconfig.spec.json', 11 | }, 12 | ], 13 | }, 14 | moduleFileExtensions: ['ts', 'js', 'html'], 15 | coverageDirectory: '../../coverage/libs/ddd', 16 | }; 17 | -------------------------------------------------------------------------------- /libs/ddd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@angular-architects/ddd", 3 | "version": "19.0.6", 4 | "license": "MIT", 5 | "author": "Manfred Steyer", 6 | "description": "Nx plugin for structuring a monorepo with domain driven design", 7 | "repository": { 8 | "type": "github", 9 | "url": "https://github.com/angular-architects/nx-ddd-plugin" 10 | }, 11 | "engines": { 12 | "node": ">=18", 13 | "npm": ">=9", 14 | "yarn": "^1.22.17" 15 | }, 16 | "dependencies": { 17 | "tslib": "^2.3.1" 18 | }, 19 | "optionalDependencies": { 20 | "@ngrx/schematics": "^19.0.0" 21 | }, 22 | "peerDependencies": { 23 | "@angular/core": "^19.0.0", 24 | "@nx/angular": ">=20.0.0" 25 | }, 26 | "main": "src/index.js", 27 | "schematics": "./collection.json", 28 | "generators": "./collection.json" 29 | } 30 | -------------------------------------------------------------------------------- /libs/ddd/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddd", 3 | "$schema": "..\\..\\node_modules\\nx\\schemas\\project-schema.json", 4 | "sourceRoot": "libs/ddd/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/js:tsc", 9 | "outputs": ["{options.outputPath}"], 10 | "options": { 11 | "outputPath": "dist/libs/ddd", 12 | "main": "libs/ddd/src/index.ts", 13 | "tsConfig": "libs/ddd/tsconfig.lib.json", 14 | "assets": [ 15 | "libs/ddd/*.md", 16 | { 17 | "input": "./libs/ddd/src", 18 | "glob": "**/!(*.ts)", 19 | "output": "./src" 20 | }, 21 | { 22 | "input": "./libs/ddd/src", 23 | "glob": "**/*.d.ts", 24 | "output": "./src" 25 | }, 26 | { 27 | "input": "./libs/ddd", 28 | "glob": "generators.json", 29 | "output": "." 30 | }, 31 | { 32 | "input": "./libs/ddd", 33 | "glob": "collection.json", 34 | "output": "." 35 | }, 36 | { 37 | "input": "./libs/ddd", 38 | "glob": "executors.json", 39 | "output": "." 40 | } 41 | ] 42 | } 43 | }, 44 | "lint": { 45 | "executor": "@nx/linter:eslint", 46 | "outputs": ["{options.outputFile}"], 47 | "options": { 48 | "lintFilePatterns": [ 49 | "libs/ddd/**/*.ts", 50 | "libs/ddd/generators.json", 51 | "libs/ddd/executors.json", 52 | "libs/ddd/package.json" 53 | ] 54 | } 55 | }, 56 | "test": { 57 | "executor": "@nx/jest:jest", 58 | "outputs": ["{workspaceRoot}/coverage/libs/ddd"], 59 | "options": { 60 | "jestConfig": "libs/ddd/jest.config.ts", 61 | "passWithNoTests": true 62 | } 63 | } 64 | }, 65 | "tags": [] 66 | } 67 | -------------------------------------------------------------------------------- /libs/ddd/src/executors/build/executor.spec.ts: -------------------------------------------------------------------------------- 1 | import { BuildExecutorSchema } from './schema'; 2 | import executor from './executor'; 3 | 4 | const options: BuildExecutorSchema = {}; 5 | 6 | describe('Build Executor', () => { 7 | it('can run', async () => { 8 | const output = await executor(options); 9 | expect(output.success).toBe(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /libs/ddd/src/executors/build/executor.ts: -------------------------------------------------------------------------------- 1 | import { BuildExecutorSchema } from './schema'; 2 | 3 | export default async function runExecutor(options: BuildExecutorSchema) { 4 | console.log('Executor ran for Build', options); 5 | return { 6 | success: true, 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /libs/ddd/src/executors/build/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface BuildExecutorSchema {} // eslint-disable-line 2 | -------------------------------------------------------------------------------- /libs/ddd/src/executors/build/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "cli": "nx", 4 | "title": "Build executor", 5 | "description": "", 6 | "type": "object", 7 | "properties": {}, 8 | "required": [] 9 | } 10 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/api/index.ts: -------------------------------------------------------------------------------- 1 | import { Tree, formatFiles } from '@nx/devkit'; 2 | import { libraryGenerator } from '@nx/angular/generators'; 3 | import { ApiOptions } from './schema'; 4 | import { strings } from '@angular-devkit/core'; 5 | import { validateInputs } from '../utils/validate-inputs'; 6 | import { deleteDefaultComponent } from '../utils/delete-default-component'; 7 | import { getWorkspaceScope } from '../utils/get-workspace-scope'; 8 | 9 | export default async function (tree: Tree, options: ApiOptions) { 10 | validateInputs(options); 11 | 12 | const workspaceName = getWorkspaceScope(tree); 13 | 14 | const libName = options.name 15 | ? `api-${strings.dasherize(options.name)}` 16 | : 'api'; 17 | const libDirectory = options.directory 18 | ? strings.dasherize(options.directory) 19 | : libName; 20 | const domainName = options.shared ? 'shared' : options.domain; 21 | const isPublishableLib = options.type === 'publishable'; 22 | 23 | // additions for Nx20 by LXT 24 | const finalName = domainName + '-' + libName; 25 | const finalDirectory = `libs/${domainName}/${libDirectory}`; 26 | 27 | const prefix = strings.dasherize(finalName).split('/').join('-'); 28 | const importPath = `${workspaceName}/${domainName}/${libDirectory}`; 29 | 30 | await libraryGenerator(tree, { 31 | name: finalName, 32 | prefix: prefix, 33 | directory: finalDirectory, 34 | tags: `domain:${domainName},domain:${domainName}/${libName},type:api`, 35 | publishable: isPublishableLib, 36 | buildable: options.type === 'buildable', 37 | importPath: options.importPath ?? importPath, 38 | standalone: options.standalone, 39 | }); 40 | 41 | deleteDefaultComponent(tree, finalDirectory, finalName); 42 | 43 | console.info( 44 | `\nHINT: Don\'t forget to extend the rules in your "eslint.config.js" to allow selected domains to access this API.\nFor this, add the tag domain:${domainName}/${libName} to the respective domains' rule sets.\n ` 45 | ); 46 | 47 | await formatFiles(tree); 48 | } 49 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/api/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "api", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Name of the API library", 9 | "$default": { 10 | "$source": "argv", 11 | "index": 0 12 | } 13 | }, 14 | "shared": { 15 | "type": "boolean", 16 | "description": "Whether the library should be shared across all domains.", 17 | "default": false 18 | }, 19 | "domain": { 20 | "type": "string", 21 | "description": "Domain name, if the library belongs to a certain domain." 22 | }, 23 | "directory": { 24 | "type": "string", 25 | "description": "Subpath of the library beneath the domain or shared folder." 26 | }, 27 | "importPath": { 28 | "type": "string", 29 | "description": "For publishable libs: Official package name used in import statements" 30 | }, 31 | "type": { 32 | "type": "string", 33 | "enum": [ 34 | "internal", 35 | "buildable", 36 | "publishable" 37 | ], 38 | "description": "A type to determine if and how to build the library.", 39 | "default": "internal" 40 | }, 41 | "standalone": { 42 | "type": "boolean", 43 | "default": true, 44 | "description": "Use standalone components?" 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/api/schema.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This file was automatically generated by json-schema-to-typescript. 4 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 5 | * and run json-schema-to-typescript to regenerate this file. 6 | */ 7 | 8 | export interface ApiOptions { 9 | /** 10 | * Name of the UI library 11 | */ 12 | name: string; 13 | /** 14 | * Whether the library should be shared across all domains. 15 | */ 16 | shared?: boolean; 17 | /** 18 | * Domain name, if the library belongs to a certain domain. 19 | */ 20 | domain?: string; 21 | /** 22 | * Subpath of the library beneath the domain or shared folder. 23 | */ 24 | directory?: string; 25 | /** 26 | * For publishable libs: Official package name used in import statements 27 | */ 28 | importPath?: string; 29 | /** 30 | * A type to determine if and how to build the library. 31 | */ 32 | type?: "internal" | "buildable" | "publishable"; 33 | 34 | standalone: boolean; 35 | 36 | [k: string]: any; 37 | } 38 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ddd/files/src/index.ts__template__: -------------------------------------------------------------------------------- 1 | const variable = "<%= projectName %>"; -------------------------------------------------------------------------------- /libs/ddd/src/generators/ddd/generator.spec.ts: -------------------------------------------------------------------------------- 1 | import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; 2 | import { Tree, readProjectConfiguration } from '@nx/devkit'; 3 | 4 | import generator from './generator'; 5 | import { DddGeneratorSchema } from './schema'; 6 | 7 | describe('ddd generator', () => { 8 | let appTree: Tree; 9 | const options: DddGeneratorSchema = { name: 'test' }; 10 | 11 | beforeEach(() => { 12 | appTree = createTreeWithEmptyWorkspace(); 13 | }); 14 | 15 | it('should run successfully', async () => { 16 | await generator(appTree, options); 17 | const config = readProjectConfiguration(appTree, 'test'); 18 | expect(config).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ddd/generator.ts: -------------------------------------------------------------------------------- 1 | import { 2 | addProjectConfiguration, 3 | formatFiles, 4 | generateFiles, 5 | getWorkspaceLayout, 6 | names, 7 | offsetFromRoot, 8 | Tree, 9 | } from '@nx/devkit'; 10 | import * as path from 'path'; 11 | import { DddGeneratorSchema } from './schema'; 12 | 13 | interface NormalizedSchema extends DddGeneratorSchema { 14 | projectName: string; 15 | projectRoot: string; 16 | projectDirectory: string; 17 | parsedTags: string[]; 18 | } 19 | 20 | function normalizeOptions( 21 | tree: Tree, 22 | options: DddGeneratorSchema 23 | ): NormalizedSchema { 24 | const name = names(options.name).fileName; 25 | const projectDirectory = options.directory 26 | ? `${names(options.directory).fileName}/${name}` 27 | : name; 28 | const projectName = projectDirectory.replace(new RegExp('/', 'g'), '-'); 29 | const projectRoot = `${getWorkspaceLayout(tree).libsDir}/${projectDirectory}`; 30 | const parsedTags = options.tags 31 | ? options.tags.split(',').map((s) => s.trim()) 32 | : []; 33 | 34 | return { 35 | ...options, 36 | projectName, 37 | projectRoot, 38 | projectDirectory, 39 | parsedTags, 40 | }; 41 | } 42 | 43 | function addFiles(tree: Tree, options: NormalizedSchema) { 44 | const templateOptions = { 45 | ...options, 46 | ...names(options.name), 47 | offsetFromRoot: offsetFromRoot(options.projectRoot), 48 | template: '', 49 | }; 50 | generateFiles( 51 | tree, 52 | path.join(__dirname, 'files'), 53 | options.projectRoot, 54 | templateOptions 55 | ); 56 | } 57 | 58 | export default async function (tree: Tree, options: DddGeneratorSchema) { 59 | const normalizedOptions = normalizeOptions(tree, options); 60 | addProjectConfiguration(tree, normalizedOptions.projectName, { 61 | root: normalizedOptions.projectRoot, 62 | projectType: 'library', 63 | sourceRoot: `${normalizedOptions.projectRoot}/src`, 64 | targets: { 65 | build: { 66 | executor: '@ddd-plugin/ddd:build', 67 | }, 68 | }, 69 | tags: normalizedOptions.parsedTags, 70 | }); 71 | addFiles(tree, normalizedOptions); 72 | await formatFiles(tree); 73 | } 74 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ddd/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface DddGeneratorSchema { 2 | name: string; 3 | tags?: string; 4 | directory?: string; 5 | } 6 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ddd/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "cli": "nx", 4 | "$id": "Ddd", 5 | "title": "", 6 | "type": "object", 7 | "properties": { 8 | "name": { 9 | "type": "string", 10 | "description": "", 11 | "$default": { 12 | "$source": "argv", 13 | "index": 0 14 | }, 15 | "x-prompt": "What name would you like to use?" 16 | }, 17 | "tags": { 18 | "type": "string", 19 | "description": "Add tags to the project (used for linting)", 20 | "alias": "t" 21 | }, 22 | "directory": { 23 | "type": "string", 24 | "description": "A directory where the project is placed", 25 | "alias": "d" 26 | } 27 | }, 28 | "required": ["name"] 29 | } 30 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/src/generators/domain/files/.gitkeep -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/domain-lib/application/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/src/generators/domain/files/domain-lib/application/.gitkeep -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/domain-lib/entities/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/src/generators/domain/files/domain-lib/entities/.gitkeep -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/domain-lib/infrastructure/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/src/generators/domain/files/domain-lib/infrastructure/.gitkeep -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/standalone-app/app/app.component.html__tmpl__: -------------------------------------------------------------------------------- 1 |

<%=name%>

-------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/standalone-app/app/app.component.spec.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'luggage'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('luggage'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain( 28 | 'Welcome luggage' 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/standalone-app/app/app.component.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | standalone: true, 6 | imports: [ 7 | CommonModule 8 | ], 9 | selector: 'app-root', 10 | templateUrl: './app.component.html', 11 | styleUrls: ['./app.component.scss'] 12 | }) 13 | export class AppComponent { 14 | title = '<%=name%>'; 15 | } 16 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/standalone-app/app/app.config.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; 2 | import { provideRouter } from '@angular/router'; 3 | import { provideHttpClient } from '@angular/common/http'; 4 | <% if (ngrx) { %> 5 | import { isDevMode } from '@angular/core'; 6 | import { provideEffects } from '@ngrx/effects'; 7 | import { provideStore } from '@ngrx/store'; 8 | import { provideStoreDevtools } from '@ngrx/store-devtools'; 9 | import { provide<%=className%>Domain } from '<%=npmScope%>/<%=fileName%>/domain'; 10 | <% } %> 11 | import { appRoutes } from './app.routes'; 12 | 13 | export const appConfig: ApplicationConfig = { 14 | providers: [ 15 | provideZoneChangeDetection({ eventCoalescing: true }), 16 | provideRouter(appRoutes), 17 | provideHttpClient(), <% if (ngrx) { %> 18 | provideStore(), 19 | provideEffects([]), 20 | ... (isDevMode()) ? [provideStoreDevtools()] : [], 21 | provide<%=className%>Domain() <% } %> 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/standalone-lib/index.ts__tmpl__: -------------------------------------------------------------------------------- 1 | export * from './lib/providers'; 2 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/files/standalone-lib/lib/providers.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { provideEffects } from '@ngrx/effects'; 2 | import { provideState } from '@ngrx/store'; 3 | 4 | export function provide<%=className%>Domain() { 5 | // prettier-ignore 6 | return [ 7 | ]; 8 | } 9 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "domain", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Grouping name for the Domain", 9 | "x-prompt": "What is the name of the domain?", 10 | "$default": { 11 | "$source": "argv", 12 | "index": 0 13 | } 14 | }, 15 | "appDirectory": { 16 | "type": "string", 17 | "description": "Grouping folder within the apps directory" 18 | }, 19 | "directory": { 20 | "type": "string", 21 | "description": "Subpath of the domain within libs directory" 22 | }, 23 | "addApp": { 24 | "type": "boolean", 25 | "description": "Add an app for the domain?", 26 | "x-prompt": "Would you like to add an associated application?", 27 | "default": false 28 | }, 29 | "ngrx": { 30 | "type": "boolean", 31 | "default": false, 32 | "description": "Add ngrx for the associated app (addApp required)" 33 | }, 34 | "type": { 35 | "type": "string", 36 | "enum": [ 37 | "internal", 38 | "buildable", 39 | "publishable" 40 | ], 41 | "description": "A type to determine if and how to build the library.", 42 | "default": "internal" 43 | }, 44 | "importPath": { 45 | "type": "string", 46 | "description": "For publishable libs: Official package name used in import statements" 47 | }, 48 | "standalone": { 49 | "type": "boolean", 50 | "default": true, 51 | "description": "Use standalone components?" 52 | } 53 | }, 54 | "required": [ 55 | "name" 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/domain/schema.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This file was automatically generated by json-schema-to-typescript. 4 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 5 | * and run json-schema-to-typescript to regenerate this file. 6 | */ 7 | 8 | export interface DomainOptions { 9 | /** 10 | * Grouping name for the Domain 11 | */ 12 | name: string; 13 | /** 14 | * Grouping folder within the apps directory 15 | */ 16 | appDirectory?: string; 17 | /** 18 | * Subpath of the domain within libs directory 19 | */ 20 | directory?: string; 21 | /** 22 | * Add an app for the domain? 23 | */ 24 | addApp?: boolean; 25 | /** 26 | * Add ngrx for the associated app (addApp required) 27 | */ 28 | ngrx?: boolean; 29 | /** 30 | * A type to determine if and how to build the library. 31 | */ 32 | type?: "internal" | "buildable" | "publishable"; 33 | /** 34 | * For publishable libs: Official package name used in import statements 35 | */ 36 | importPath?: string; 37 | standalone: boolean; 38 | [k: string]: any; 39 | } 40 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomain/application/__name@dasherize__.facade.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { BehaviorSubject } from 'rxjs'; 3 | <% if (entity) { %> 4 | import { <%=classify(entity)%> } from '../entities/<%=dasherize(entity)%>'; 5 | import { <%=classify(entity)%>DataService } from '../infrastructure/<%=dasherize(entity)%>.data.service'; 6 | <% } %> 7 | 8 | @Injectable({ providedIn: 'root' }) 9 | export class <%=classify(name)%>Facade { 10 | <% if (entity) { %> 11 | private <%=camelize(entity)%>ListSubject = new BehaviorSubject<<%=classify(entity)%>[]>([]); 12 | <%=camelize(entity)%>List$ = this.<%=camelize(entity)%>ListSubject.asObservable(); 13 | 14 | constructor(private <%=camelize(entity)%>DataService: <%=classify(entity)%>DataService) { 15 | } 16 | 17 | load(): void { 18 | this.<%=camelize(entity)%>DataService.load().subscribe({ 19 | next: <%=camelize(entity)%>List => { 20 | this.<%=camelize(entity)%>ListSubject.next(<%=camelize(entity)%>List) 21 | }, 22 | error: err => { 23 | console.error('err', err); 24 | } 25 | }); 26 | } 27 | <% } %> 28 | } 29 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomain/entities/__entity@dasherize__.ts__tmpl__: -------------------------------------------------------------------------------- 1 | export interface <%=classify(entity)%> { 2 | id: number; 3 | name: string; 4 | description: string; 5 | } 6 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomain/infrastructure/__entity@dasherize__.data.service.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import {Injectable, inject} from '@angular/core'; 2 | import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; 3 | import {Observable, of} from 'rxjs'; 4 | import {<%=classify(entity)%>} from '../entities/<%=dasherize(entity)%>'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class <%=classify(entity)%>DataService { 8 | 9 | private http = inject(HttpClient); 10 | 11 | load(): Observable<<%=classify(entity)%>[]> { 12 | 13 | // Uncomment if needed 14 | /* 15 | const url = '...'; 16 | const params = new HttpParams().set('param', 'value'); 17 | const headers = new HttpHeaders().set('Accept', 'application/json'); 18 | return this.http.get<<%=classify(entity)%>[]>(url, {params, headers}); 19 | */ 20 | 21 | return of([ 22 | {id: 1, name: 'Lorem ipsum', description: 'Lorem ipsum dolor sit amet'}, 23 | {id: 2, name: 'At vero eos', description: 'At vero eos et accusam et justo duo dolores'}, 24 | {id: 3, name: 'Duis autem', description: 'Duis autem vel eum iriure dolor in hendrerit'}, 25 | ]); 26 | } 27 | } -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomainWithNgrx/+state/__entity@dasherize__/__entity@dasherize__.actions.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { createActionGroup, emptyProps, props } from '@ngrx/store'; 2 | import { <%= classify(entity) %> } from '../../entities/<%= dasherize(entity) %>'; 3 | 4 | export const <%= camelize(entity) %>Actions = createActionGroup({ 5 | source: '<%= classify(entity) %>', 6 | events: { 7 | load<%= classify(entity) %>: emptyProps(), 8 | load<%= classify(entity) %>Success: props<{ <%= camelize(entity) %>List: <%= classify(entity) %>[] }>(), 9 | load<%= classify(entity) %>Failure: props<{ error: unknown }>() 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomainWithNgrx/+state/__entity@dasherize__/__entity@dasherize__.effects.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from '@angular/core'; 2 | import { createEffect, Actions, ofType } from '@ngrx/effects'; 3 | import { catchError, map, switchMap } from 'rxjs/operators'; 4 | import { of } from 'rxjs'; 5 | import { <%= camelize(entity) %>Actions } from './<%= dasherize(entity) %>.actions'; 6 | import { <%= classify(entity) %>DataService } from '../../infrastructure/<%= dasherize(entity) %>.data.service'; 7 | 8 | @Injectable() 9 | export class <%= classify(entity) %>Effects { 10 | 11 | private actions$ = inject(Actions); 12 | private <%= camelize(entity) %>DataService = inject(<%= classify(entity) %>DataService); 13 | 14 | load<%= classify(entity) %>$ = createEffect(() => 15 | this.actions$.pipe( 16 | ofType(<%= camelize(entity) %>Actions.load<%= classify(entity) %>), 17 | switchMap((/* action */) => 18 | this.<%= camelize(entity) %>DataService.load().pipe( 19 | map((<%= camelize(entity) %>List) => <%= camelize(entity) %>Actions.load<%= classify(entity) %>Success({ <%= camelize(entity) %>List })), 20 | catchError((error) => of(<%= camelize(entity) %>Actions.load<%= classify(entity) %>Failure({ error }))) 21 | ) 22 | ) 23 | ) 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomainWithNgrx/+state/__entity@dasherize__/__entity@dasherize__.reducer.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { createReducer, on, createFeature, createSelector } from '@ngrx/store'; 2 | import { EntityAdapter, createEntityAdapter } from '@ngrx/entity'; 3 | 4 | import { <%= camelize(entity) %>Actions } from './<%= dasherize(entity) %>.actions'; 5 | import { <%= classify(entity) %> } from '../../entities/<%= dasherize(entity) %>'; 6 | 7 | export interface TransientState { 8 | selectedId: string | number | undefined; 9 | loaded: boolean; 10 | error: unknown | undefined; 11 | } 12 | 13 | const adapter: EntityAdapter<<%= classify(entity) %>> = 14 | createEntityAdapter<<%= classify(entity) %>>(); 15 | 16 | export const initialState = adapter.getInitialState({ 17 | loaded: false, 18 | selectedId: undefined, 19 | error: undefined 20 | }); 21 | 22 | export const <%= camelize(entity) %>Feature = createFeature({ 23 | name: '<%=camelize(domain)%><%= classify(entity) %>', 24 | reducer: createReducer( 25 | initialState, 26 | on(<%= camelize(entity) %>Actions.load<%= classify(entity) %>, (state) => ({ 27 | ...state, 28 | loaded: false, 29 | error: null, 30 | })), 31 | on(<%= camelize(entity) %>Actions.load<%= classify(entity) %>Success, (state, action) => 32 | adapter.upsertMany(action.<%= camelize(entity) %>List, { ...state, loaded: true }) 33 | ), 34 | on(<%= camelize(entity) %>Actions.load<%= classify(entity) %>Failure, (state, action) => ({ 35 | ...state, 36 | error: action.error 37 | })) 38 | ), 39 | extraSelectors: ( 40 | { select<%=classify(domain)%><%= classify(entity) %>State, selectSelectedId }, 41 | selectors = adapter.getSelectors(select<%=classify(domain)%><%= classify(entity) %>State) 42 | ) => ({ 43 | selectAll: selectors.selectAll, 44 | selectSelected: createSelector( 45 | selectors.selectAll, 46 | selectSelectedId, 47 | (all, id) => all.find(e => e.id === id) 48 | ) 49 | }) 50 | }); 51 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomainWithNgrx/application/__name@dasherize__.facade.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { Injectable, inject } from '@angular/core'; 2 | import { select, Store } from '@ngrx/store'; 3 | import { <%= camelize(entity) %>Actions } from '../+state/<%= dasherize(entity) %>/<%= dasherize(entity) %>.actions'; 4 | import { <%= camelize(entity) %>Feature } from '../+state/<%= dasherize(entity) %>/<%= dasherize(entity) %>.reducer'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class <%= classify(name) %>Facade { 8 | private store = inject(Store); 9 | 10 | loaded$ = this.store.pipe(select(<%= camelize(entity) %>Feature.selectLoaded)); 11 | <%= camelize(entity) %>List$ = this.store.pipe(select(<%= camelize(entity) %>Feature.selectAll)); 12 | selected<%= classify(entity) %>$ = this.store.pipe(select(<%= camelize(entity) %>Feature.selectSelected)); 13 | 14 | load(): void { 15 | this.store.dispatch(<%= camelize(entity) %>Actions.load<%= classify(entity) %>()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomainWithNgrx/entities/__entity@dasherize__.ts__tmpl__: -------------------------------------------------------------------------------- 1 | export interface <%=classify(entity)%> { 2 | id: number; 3 | name: string; 4 | description: string; 5 | } 6 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forDomainWithNgrx/infrastructure/__entity@dasherize__.data.service.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import {Injectable, inject} from '@angular/core'; 2 | import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; 3 | import {Observable, of} from 'rxjs'; 4 | import {<%=classify(entity)%>} from '../entities/<%=dasherize(entity)%>'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class <%=classify(entity)%>DataService { 8 | 9 | private http = inject(HttpClient); 10 | 11 | load(): Observable<<%=classify(entity)%>[]> { 12 | 13 | // Uncomment if needed 14 | /* 15 | const url = '...'; 16 | const params = new HttpParams().set('param', 'value'); 17 | const headers = new HttpHeaders().set('Accept', 'application/json'); 18 | return this.http.get<<%=classify(entity)%>[]>(url, {params, headers}); 19 | */ 20 | 21 | return of([ 22 | {id: 1, name: 'Lorem ipsum', description: 'Lorem ipsum dolor sit amet'}, 23 | {id: 2, name: 'At vero eos', description: 'At vero eos et accusam et justo duo dolores'}, 24 | {id: 3, name: 'Duis autem', description: 'Duis autem vel eum iriure dolor in hendrerit'}, 25 | ]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forFeature/__name@dasherize__.component.html__tmpl__: -------------------------------------------------------------------------------- 1 |

<%=domain%>-<%=name%>

2 | <% if(entity) { %> 3 | 4 | 5 | 6 | 7 | 8 | 9 |
{{<%=camelize(entity)%>.id}}{{<%=camelize(entity)%>.name}}{{<%=camelize(entity)%>.description}}
10 | <% } %> 11 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forFeature/__name@dasherize__.component.scss__tmpl__: -------------------------------------------------------------------------------- 1 | .table td { 2 | border: 1px solid; 3 | padding: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forFeature/__name@dasherize__.component.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { Component, inject, OnInit } from '@angular/core'; <% if (standalone) { %> 2 | import { CommonModule } from '@angular/common'; 3 | <% } %>import { <%=classify(name)%>Facade } from '<%=workspaceName%>/<%=dasherize(domain)%><%- domainDirectory ? '/' + domainDirectory : '' %>/domain'; 4 | 5 | @Component({ <% if (standalone) { %> 6 | standalone: true, 7 | imports: [CommonModule], 8 | <% } %>selector: '<%=dasherize(flatDomain)%>-feature-<%=dasherize(name)%>', 9 | templateUrl: './<%=dasherize(name)%>.component.html', 10 | styleUrls: ['./<%=dasherize(name)%>.component.scss'] 11 | }) 12 | export class <%=classify(name)%>Component implements OnInit { 13 | 14 | private <%=camelize(name)%>Facade = inject(<%=classify(name)%>Facade); 15 | <% if (entity) { %> 16 | <%=camelize(entity)%>List$ = this.<%=camelize(name)%>Facade.<%=camelize(entity)%>List$; 17 | <% } %> 18 | 19 | <% if (entity) { %> 20 | ngOnInit() { 21 | this.load(); 22 | } 23 | 24 | load(): void { 25 | this.<%=camelize(name)%>Facade.load(); 26 | } 27 | <% } else { %> 28 | ngOnInit() { 29 | } 30 | <% } %> 31 | } 32 | 33 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forFeatureWithNgrx/__name@dasherize__.component.html__tmpl__: -------------------------------------------------------------------------------- 1 |

<%=domain%>-<%=name%>

2 | <% if(entity) { %> 3 | 4 | 5 | 6 | 7 | 8 | 9 |
{{<%=camelize(entity)%>.id}}{{<%=camelize(entity)%>.name}}{{<%=camelize(entity)%>.description}}
10 | <% } %> 11 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forFeatureWithNgrx/__name@dasherize__.component.scss__tmpl__: -------------------------------------------------------------------------------- 1 | .table td { 2 | border: 1px solid; 3 | padding: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/files/forFeatureWithNgrx/__name@dasherize__.component.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { Component, inject, OnInit } from '@angular/core'; <% if (standalone) { %> 2 | import { CommonModule } from '@angular/common'; 3 | <% } %>import { <%=classify(name)%>Facade } from '<%=workspaceName%>/<%=dasherize(domain)%><%- domainDirectory ? '/' + domainDirectory : '' %>/domain'; 4 | 5 | @Component({ <% if (standalone) { %> 6 | standalone: true, 7 | imports: [CommonModule], 8 | <% } %>selector: '<%=dasherize(flatDomain)%>-feature-<%=dasherize(name)%>', 9 | templateUrl: './<%=dasherize(name)%>.component.html', 10 | styleUrls: ['./<%=dasherize(name)%>.component.scss'] 11 | }) 12 | export class <%=classify(name)%>Component implements OnInit { 13 | 14 | private <%=camelize(name)%>Facade = inject(<%=classify(name)%>Facade); 15 | <% if (entity) { %> 16 | <%=camelize(entity)%>List$ = this.<%=camelize(name)%>Facade.<%=camelize(entity)%>List$; 17 | <% } %> 18 | 19 | <% if (entity) { %> 20 | ngOnInit() { 21 | this.load(); 22 | } 23 | 24 | load(): void { 25 | this.<%=camelize(name)%>Facade.load(); 26 | } 27 | <% } else { %> 28 | ngOnInit() { 29 | } 30 | <% } %> 31 | } 32 | 33 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "feature", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Library name", 9 | "x-prompt": "What is the name of the library?", 10 | "$default": { 11 | "$source": "argv", 12 | "index": 0 13 | } 14 | }, 15 | "directory": { 16 | "type": "string", 17 | "description": "Subpath within libs directory" 18 | }, 19 | "prefix": { 20 | "type": "boolean", 21 | "description": "Apply the \"feature-\" prefix?", 22 | "default": true 23 | }, 24 | "domain": { 25 | "type": "string", 26 | "x-prompt": "What is the name of the associated domain?", 27 | "description": "Domain name" 28 | }, 29 | "domainDirectory": { 30 | "type": "string", 31 | "description": "Domain name" 32 | }, 33 | "app": { 34 | "type": "string", 35 | "description": "app name" 36 | }, 37 | "appDirectory": { 38 | "type": "string", 39 | "description": "Subpath within app directory" 40 | }, 41 | "lazy": { 42 | "type": "boolean", 43 | "description": "Is this feature module lazy loaded?", 44 | "default": false 45 | }, 46 | "entity": { 47 | "type": "string", 48 | "description": "Optional entity to create for this feature" 49 | }, 50 | "type": { 51 | "type": "string", 52 | "enum": [ 53 | "internal", 54 | "buildable", 55 | "publishable" 56 | ], 57 | "description": "A type to determine if and how to build the library.", 58 | "default": "internal" 59 | }, 60 | "importPath": { 61 | "type": "string", 62 | "description": "For publishable libs: Official package name used in import statements" 63 | }, 64 | "ngrx": { 65 | "type": "boolean", 66 | "default": false, 67 | "description": "Add ngrx for the domain (entity required)" 68 | }, 69 | "noApp": { 70 | "type": "boolean", 71 | "default": false, 72 | "description": "Don't connect the feature lib to an app" 73 | }, 74 | "standalone": { 75 | "type": "boolean", 76 | "default": true, 77 | "description": "Use standalone components?" 78 | } 79 | }, 80 | "required": [ 81 | "name", 82 | "domain" 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/feature/schema.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This file was automatically generated by json-schema-to-typescript. 4 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 5 | * and run json-schema-to-typescript to regenerate this file. 6 | */ 7 | 8 | export interface FeatureOptions { 9 | /** 10 | * Library name 11 | */ 12 | name: string; 13 | /** 14 | * Subpath within libs directory 15 | */ 16 | directory?: string; 17 | /** 18 | * Apply the "feature-" prefix? 19 | */ 20 | prefix?: boolean; 21 | /** 22 | * Domain name 23 | */ 24 | domain: string; 25 | /** 26 | * Domain name 27 | */ 28 | domainDirectory?: string; 29 | /** 30 | * Don't connect this feature lib to an app 31 | */ 32 | noApp?: boolean; 33 | /** 34 | * app name 35 | */ 36 | app?: string; 37 | /** 38 | * Subpath within app directory 39 | */ 40 | appDirectory?: string; 41 | /** 42 | * Is this feature module lazy loaded? 43 | */ 44 | lazy?: boolean; 45 | /** 46 | * Optional entity to create for this feature 47 | */ 48 | entity?: string; 49 | /** 50 | * A type to determine if and how to build the library. 51 | */ 52 | type?: "internal" | "buildable" | "publishable"; 53 | /** 54 | * For publishable libs: Official package name used in import statements 55 | */ 56 | importPath?: string; 57 | /** 58 | * Add ngrx for the domain (entity required) 59 | */ 60 | ngrx?: boolean; 61 | 62 | standalone: boolean; 63 | 64 | [k: string]: any; 65 | } 66 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/init/index.ts: -------------------------------------------------------------------------------- 1 | import { formatFiles, Tree } from '@nx/devkit'; 2 | import { updateDepConst } from '../utils/update-dep-const'; 3 | 4 | export default async function (tree: Tree, schema: any) { 5 | updateDepConst(tree, (depConst) => { 6 | const jokerIndex = depConst.findIndex( 7 | (entry) => 8 | entry['sourceTag'] && 9 | entry['sourceTag'] === '*' && 10 | entry['onlyDependOnLibsWithTags'] && 11 | Array.isArray(entry['onlyDependOnLibsWithTags']) && 12 | entry['onlyDependOnLibsWithTags'].length > 0 && 13 | entry['onlyDependOnLibsWithTags'][0] === '*' 14 | ); 15 | 16 | if (jokerIndex !== -1) { 17 | depConst.splice(jokerIndex, 1); 18 | } 19 | 20 | depConst.push({ 21 | sourceTag: 'type:app', 22 | onlyDependOnLibsWithTags: [ 23 | 'type:api', 24 | 'type:feature', 25 | 'type:ui', 26 | 'type:domain-logic', 27 | 'type:util', 28 | ], 29 | }); 30 | 31 | depConst.push({ 32 | sourceTag: 'type:api', 33 | onlyDependOnLibsWithTags: ['type:ui', 'type:domain-logic', 'type:util'], 34 | }); 35 | 36 | depConst.push({ 37 | sourceTag: 'type:feature', 38 | onlyDependOnLibsWithTags: ['type:ui', 'type:domain-logic', 'type:util'], 39 | }); 40 | 41 | depConst.push({ 42 | sourceTag: 'type:ui', 43 | onlyDependOnLibsWithTags: ['type:domain-logic', 'type:util'], 44 | }); 45 | 46 | depConst.push({ 47 | sourceTag: 'type:domain-logic', 48 | onlyDependOnLibsWithTags: ['type:util'], 49 | }); 50 | 51 | depConst.push({ 52 | sourceTag: 'domain:shared', 53 | onlyDependOnLibsWithTags: ['domain:shared'], 54 | }); 55 | }); 56 | 57 | await formatFiles(tree); 58 | } 59 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/init/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "init", 4 | "type": "object", 5 | "properties": {} 6 | } 7 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/init/schematic.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import generator from './index'; 3 | 4 | export default convertNxGenerator(generator); 5 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ui/index.ts: -------------------------------------------------------------------------------- 1 | import { Tree, formatFiles } from '@nx/devkit'; 2 | import { libraryGenerator } from '@nx/angular/generators'; 3 | import { UiOptions } from './schema'; 4 | import { strings } from '@angular-devkit/core'; 5 | import { validateInputs } from '../utils/validate-inputs'; 6 | import { deleteDefaultComponent } from '../utils/delete-default-component'; 7 | import { getWorkspaceScope } from '../utils/get-workspace-scope'; 8 | 9 | export default async function (tree: Tree, options: UiOptions) { 10 | validateInputs(options); 11 | 12 | const workspaceName = getWorkspaceScope(tree); 13 | 14 | const libName = `ui-${strings.dasherize(options.name)}`; 15 | const libDirectory = options.directory ? strings.dasherize(options.directory) : libName; 16 | const domainName = options.shared ? 'shared' : options.domain; 17 | const isPublishableLib = options.type === 'publishable'; 18 | 19 | // additions for Nx20 by LXT 20 | const finalName = domainName + '-' + libName; 21 | const finalDirectory = `libs/${domainName}/${libDirectory}`; 22 | 23 | const prefix = strings.dasherize(finalName).split('/').join('-'); 24 | const importPath = `${workspaceName}/${domainName}/${libDirectory}`; 25 | 26 | await libraryGenerator(tree, { 27 | name: finalName, 28 | prefix: prefix, 29 | directory: finalDirectory, 30 | tags: `domain:${domainName},type:ui`, 31 | publishable: isPublishableLib, 32 | buildable: options.type === 'buildable', 33 | importPath: options.importPath ?? importPath, 34 | standalone: options.standalone, 35 | }); 36 | 37 | deleteDefaultComponent( 38 | tree, 39 | finalDirectory, 40 | finalName 41 | ); 42 | 43 | await formatFiles(tree); 44 | } 45 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ui/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "ui", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Name of the UI library", 9 | "$default": { 10 | "$source": "argv", 11 | "index": 0 12 | } 13 | }, 14 | "shared": { 15 | "type": "boolean", 16 | "description": "Whether the library should be shared across all domains.", 17 | "default": false 18 | }, 19 | "domain": { 20 | "type": "string", 21 | "description": "Domain name, if the library belongs to a certain domain." 22 | }, 23 | "directory": { 24 | "type": "string", 25 | "description": "Subpath of the library beneath the domain or shared folder." 26 | }, 27 | "importPath": { 28 | "type": "string", 29 | "description": "For publishable libs: Official package name used in import statements" 30 | }, 31 | "type": { 32 | "type": "string", 33 | "enum": [ 34 | "internal", 35 | "buildable", 36 | "publishable" 37 | ], 38 | "description": "A type to determine if and how to build the library.", 39 | "default": "internal" 40 | }, 41 | "standalone": { 42 | "type": "boolean", 43 | "default": true, 44 | "description": "Use standalone components?" 45 | } 46 | }, 47 | "required": [ 48 | "name" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/ui/schema.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This file was automatically generated by json-schema-to-typescript. 4 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 5 | * and run json-schema-to-typescript to regenerate this file. 6 | */ 7 | 8 | export interface UiOptions { 9 | /** 10 | * Name of the UI library 11 | */ 12 | name: string; 13 | /** 14 | * Whether the library should be shared across all domains. 15 | */ 16 | shared?: boolean; 17 | /** 18 | * Domain name, if the library belongs to a certain domain. 19 | */ 20 | domain?: string; 21 | /** 22 | * Subpath of the library beneath the domain or shared folder. 23 | */ 24 | directory?: string; 25 | /** 26 | * For publishable libs: Official package name used in import statements 27 | */ 28 | importPath?: string; 29 | /** 30 | * A type to determine if and how to build the library. 31 | */ 32 | 33 | standalone: boolean; 34 | 35 | type?: "internal" | "buildable" | "publishable"; 36 | [k: string]: any; 37 | } 38 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/util/index.ts: -------------------------------------------------------------------------------- 1 | import { Tree, formatFiles } from '@nx/devkit'; 2 | import { libraryGenerator } from '@nx/angular/generators'; 3 | import { UtilOptions } from './schema'; 4 | import { strings } from '@angular-devkit/core'; 5 | import { validateInputs } from '../utils/validate-inputs'; 6 | import { deleteDefaultComponent } from '../utils/delete-default-component'; 7 | import { getWorkspaceScope } from '../utils/get-workspace-scope'; 8 | 9 | export default async function (tree: Tree, options: UtilOptions) { 10 | validateInputs(options); 11 | 12 | const workspaceName = getWorkspaceScope(tree); 13 | 14 | const libName = `util-${strings.dasherize(options.name)}`; 15 | const libDirectory = options.directory ? strings.dasherize(options.directory) : libName; 16 | const domainName = options.shared ? 'shared' : options.domain; 17 | const isPublishableLib = options.type === 'publishable'; 18 | 19 | // additions for Nx20 by LXT 20 | const finalName = domainName + '-' + libName; 21 | const finalDirectory = `libs/${domainName}/${libDirectory}`; 22 | 23 | const prefix = strings.dasherize(finalName).split('/').join('-'); 24 | const importPath = `${workspaceName}/${domainName}/${libDirectory}`; 25 | 26 | await libraryGenerator(tree, { 27 | name: finalName, 28 | prefix: prefix, 29 | directory: finalDirectory, 30 | tags: `domain:${domainName},type:util`, 31 | publishable: isPublishableLib, 32 | buildable: options.type === 'buildable', 33 | importPath: options.importPath ?? importPath, 34 | standalone: options.standalone, 35 | }); 36 | 37 | deleteDefaultComponent( 38 | tree, 39 | finalDirectory, 40 | finalName 41 | ); 42 | 43 | await formatFiles(tree); 44 | } 45 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/util/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "util", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Name of the utility library", 9 | "$default": { 10 | "$source": "argv", 11 | "index": 0 12 | } 13 | }, 14 | "shared": { 15 | "type": "boolean", 16 | "description": "Whether the library should be shared across all domains.", 17 | "default": false 18 | }, 19 | "domain": { 20 | "type": "string", 21 | "description": "Domain name, if the library belongs to a certain domain." 22 | }, 23 | "directory": { 24 | "type": "string", 25 | "description": "Subpath of the library beneath the domain or shared folder." 26 | }, 27 | "importPath": { 28 | "type": "string", 29 | "description": "For publishable libs: Official package name used in import statements" 30 | }, 31 | "type": { 32 | "type": "string", 33 | "enum": [ 34 | "internal", 35 | "buildable", 36 | "publishable" 37 | ], 38 | "description": "A type to determine if and how to build the library.", 39 | "default": "internal" 40 | }, 41 | "standalone": { 42 | "type": "boolean", 43 | "default": true, 44 | "description": "Use standalone components?" 45 | } 46 | }, 47 | "required": [ 48 | "name" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/util/schema.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This file was automatically generated by json-schema-to-typescript. 4 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 5 | * and run json-schema-to-typescript to regenerate this file. 6 | */ 7 | 8 | export interface UtilOptions { 9 | /** 10 | * Name of the utility library 11 | */ 12 | name: string; 13 | /** 14 | * Whether the library should be shared across all domains. 15 | */ 16 | shared?: boolean; 17 | /** 18 | * Domain name, if the library belongs to a certain domain. 19 | */ 20 | domain?: string; 21 | /** 22 | * Subpath of the library beneath the domain or shared folder. 23 | */ 24 | directory?: string; 25 | /** 26 | * For publishable libs: Official package name used in import statements 27 | */ 28 | importPath?: string; 29 | /** 30 | * A type to determine if and how to build the library. 31 | */ 32 | type?: "internal" | "buildable" | "publishable"; 33 | 34 | standalone: boolean; 35 | 36 | [k: string]: any; 37 | } 38 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/add-ngrx-imports-to-domain.ts: -------------------------------------------------------------------------------- 1 | import { insertNgModuleProperty } from '@nx/angular/src/generators/utils'; 2 | import { Tree } from '@nx/devkit'; 3 | import { classify, dasherize } from '@nx/devkit/src/utils/string-utils'; 4 | import { addImportToTsModule } from './addToNgModule'; 5 | import { fileContains } from './fileContains'; 6 | 7 | /** 8 | * addNgrxImportsToDomain 9 | * @param modulePath the path of the module the import is being included in 10 | * @param entityName the name of the entity 11 | */ 12 | export function addNgrxImportsToDomain( 13 | tree: Tree, 14 | modulePath: string, 15 | entityName: string 16 | ): void { 17 | const pathPrefix = `./+state/${dasherize(entityName)}/${dasherize( 18 | entityName 19 | )}`; 20 | const reducerPath = `${pathPrefix}.reducer`; 21 | const reducerImports = `from${classify(entityName)}`; 22 | const effectsName = `${classify(entityName)}Effects`; 23 | const effectsPath = `${pathPrefix}.effects`; 24 | 25 | const classfiedEntityName = classify(entityName); 26 | const fromFeature = `from${classfiedEntityName}`; 27 | const storeForFeature = `StoreModule.forFeature(${fromFeature}.${classfiedEntityName.toUpperCase()}_FEATURE_KEY, ${fromFeature}.reducer)`; 28 | const effectsForFeature = `EffectsModule.forFeature([${effectsName}])`; 29 | 30 | if (!tree.exists(modulePath)) { 31 | return; 32 | } 33 | 34 | addImportToTsModule(tree, { 35 | filePath: modulePath, 36 | importClassName: effectsName, 37 | importPath: effectsPath, 38 | }); 39 | 40 | addImportAllToTsModule(tree, { 41 | filePath: modulePath, 42 | importAs: reducerImports, 43 | importPath: reducerPath, 44 | }); 45 | 46 | const containsStore = fileContains(tree, modulePath, 'StoreModule'); 47 | 48 | if (!containsStore) { 49 | addImportToTsModule(tree, { 50 | filePath: modulePath, 51 | importClassName: 'StoreModule', 52 | importPath: '@ngrx/store', 53 | }); 54 | } 55 | 56 | const containsEffects = fileContains(tree, modulePath, 'EffectsModule'); 57 | 58 | if (!containsEffects) { 59 | addImportToTsModule(tree, { 60 | filePath: modulePath, 61 | importClassName: 'EffectsModule', 62 | importPath: '@ngrx/effects', 63 | }); 64 | } 65 | 66 | insertNgModuleProperty(tree, modulePath, storeForFeature, 'imports'); 67 | 68 | insertNgModuleProperty(tree, modulePath, effectsForFeature, 'imports'); 69 | } 70 | 71 | function addImportAllToTsModule( 72 | tree: Tree, 73 | options: { filePath: string; importAs: string; importPath: string } 74 | ) { 75 | const content = tree.read(options.filePath).toString('utf-8'); 76 | const updated = `import * as ${options.importAs} from '${options.importPath}';\n${content}`; 77 | tree.write(options.filePath, updated); 78 | } 79 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/add-ts-exports.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | 3 | /** 4 | * addTsExport 5 | * @param filePath path of the file to export from 6 | * @param filesToExport files to export 7 | */ 8 | export function addTsExport( 9 | tree: Tree, 10 | filePath: string, 11 | filesToExport: string[] 12 | ): void { 13 | let content = tree.read(filePath) + '\n'; 14 | 15 | for (const file of filesToExport) { 16 | content += `export * from '${file}';\n`; 17 | } 18 | 19 | tree.write(filePath, content); 20 | } 21 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/addToNgModule.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | import * as ts from 'typescript'; 3 | import { insertImport } from '@nx/js'; 4 | import { insertNgModuleProperty } from '@nx/angular/src/generators/utils'; 5 | 6 | export function addDeclarationToNgModule( 7 | tree: Tree, 8 | { 9 | filePath, 10 | importClassName, 11 | importPath, 12 | }: { filePath: string; importClassName: string; importPath: string } 13 | ) { 14 | addImportToTsModule(tree, { filePath, importClassName, importPath }); 15 | insertNgModuleProperty(tree, filePath, importClassName, 'declarations'); 16 | } 17 | 18 | export function addDeclarationWithExportToNgModule( 19 | tree: Tree, 20 | { 21 | filePath, 22 | importClassName, 23 | importPath, 24 | }: { filePath: string; importClassName: string; importPath: string } 25 | ) { 26 | addDeclarationToNgModule(tree, { filePath, importClassName, importPath }); 27 | insertNgModuleProperty(tree, filePath, importClassName, 'exports'); 28 | } 29 | 30 | export function addImportToNgModule( 31 | tree: Tree, 32 | { 33 | filePath, 34 | importClassName, 35 | importPath, 36 | }: { filePath: string; importClassName: string; importPath: string } 37 | ) { 38 | addImportToTsModule(tree, { filePath, importClassName, importPath }); 39 | insertNgModuleProperty(tree, filePath, importClassName, 'imports'); 40 | } 41 | 42 | export function addImportToTsModule( 43 | tree: Tree, 44 | { 45 | filePath, 46 | importClassName, 47 | importPath, 48 | }: { filePath: string; importClassName: string; importPath: string } 49 | ) { 50 | const moduleSource = tree.read(filePath).toString('utf-8'); 51 | 52 | let sourceFile = ts.createSourceFile( 53 | filePath, 54 | moduleSource, 55 | ts.ScriptTarget.Latest, 56 | true 57 | ); 58 | 59 | insertImport(tree, sourceFile, filePath, importClassName, importPath); 60 | } 61 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/check-rule-exists.ts: -------------------------------------------------------------------------------- 1 | import { SchematicContext } from '@angular-devkit/schematics'; 2 | 3 | export function checkRuleExists( 4 | filePath: string, 5 | rule: string, 6 | rules: object 7 | ) { 8 | if (!rules['rules']) { 9 | console.info(`${filePath}: rules expected`); 10 | return false; 11 | } 12 | 13 | if (!rules['rules'][rule]) { 14 | console.info(`${filePath}: ${rule} expected`); 15 | return false; 16 | } 17 | 18 | if (rules['rules'][rule]['length'] < 2) { 19 | console.info(`${filePath}: ${rule}.1 unexpected`); 20 | return false; 21 | } 22 | 23 | if (!rules['rules'][rule][1]['depConstraints']) { 24 | console.info(`${filePath}: ${rule}.1.depConstraints expected.`); 25 | return false; 26 | } 27 | 28 | if (!Array.isArray(rules['rules'][rule][1]['depConstraints'])) { 29 | console.info( 30 | `${filePath}: ${rule}.1.depConstraints expected to be an array.` 31 | ); 32 | return false; 33 | } 34 | 35 | return true; 36 | } 37 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/delete-default-component.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | import * as path from 'path'; 3 | 4 | export function deleteDefaultComponent(tree: Tree, finalDirectory: string, finalName: string, deleteIndex = true): void { 5 | const dirToDel = path.join(finalDirectory, 'src', 'lib', finalName); 6 | //console.log('dirToDel', dirToDel); 7 | let deleted = false; 8 | if (tree.exists(dirToDel)) { 9 | tree.delete(dirToDel); 10 | deleted = true; 11 | } 12 | 13 | const index = path.join(finalDirectory, 'src', 'index.ts'); 14 | if (deleteIndex && deleted && tree.exists(index)) { 15 | const contents = tree.read(index, 'utf-8'); 16 | const rest = contents.split('\n').slice(1); 17 | tree.write(index, (rest || []).join('\n')); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/fileContains.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | 3 | export function fileContains( 4 | tree: Tree, 5 | appModulePath: string, 6 | subStr: string 7 | ) { 8 | return tree.read(appModulePath).toString('utf-8').indexOf(subStr) !== -1; 9 | } 10 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/find-array-literal.ts: -------------------------------------------------------------------------------- 1 | import { tsquery } from '@phenomnomnominal/tsquery'; 2 | 3 | export function findArrayLiteral(code: string, propName: string): number { 4 | const ast = tsquery.ast(code); 5 | const nodes = tsquery(ast, `PropertyAssignment[name.escapedText=${propName}] ArrayLiteralExpression`); 6 | if (nodes.length === 0) { 7 | return -1; 8 | } 9 | const node = nodes[0]; 10 | const bracket = code.indexOf('[', node.pos); 11 | return bracket+1; 12 | } -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/get-workspace-scope.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | import { getNpmScope } from './npm'; 3 | 4 | export function getWorkspaceScope(tree: Tree) { 5 | return getNpmScope(tree); 6 | } 7 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/ngrx-version.ts: -------------------------------------------------------------------------------- 1 | export const NGRX_VERSION = '^18.0.0'; 2 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/npm.ts: -------------------------------------------------------------------------------- 1 | import { Tree, readJson } from "@nx/devkit"; 2 | 3 | export function getNpmScope(tree: Tree) { 4 | const { name } = tree.exists('package.json') 5 | ? readJson<{ name?: string }>(tree, 'package.json') 6 | : { name: null }; 7 | 8 | if (name?.startsWith('@')) { 9 | return name.split('/')[0]; 10 | } 11 | } -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/update-dep-const.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | import { checkRuleExists } from './check-rule-exists'; 3 | 4 | const allowAll = /\s*\{\s*sourceTag:\s*'\*',\s*onlyDependOnLibsWithTags:\s*\['\*'\],?\s*\}\s*,?/; 5 | const depConstraints = /depConstraints:\s*\[\s*/; 6 | 7 | 8 | export function updateDepConst( 9 | host: Tree, 10 | update: (depConst: Array) => void 11 | ) { 12 | let filePath = 'tslint.json'; 13 | const rule = 'nx-enforce-module-boundaries'; 14 | let isJson = true; 15 | let newText = ''; 16 | 17 | if (!host.exists('tslint.json')) { 18 | if (host.exists('.eslintrc.json')) { 19 | filePath = '.eslintrc.json'; 20 | console.info('Found .eslintrc.json'); 21 | } else if (host.exists('.eslintrc')) { 22 | filePath = '.eslintrc'; 23 | console.info('Found .eslintrc'); 24 | } else if (host.exists('eslint.config.cjs')) { 25 | filePath = 'eslint.config.cjs'; 26 | console.info('Found .eslintrc'); 27 | isJson = false; 28 | } 29 | else { 30 | console.info( 31 | 'Cannot add linting rules: linting config file does not exist' 32 | ); 33 | return; 34 | } 35 | } 36 | 37 | const text = host.read(filePath).toString(); 38 | 39 | if (isJson) { 40 | const json = JSON.parse(text); 41 | let rules = json; 42 | if (rules['overrides']) { 43 | const overrides = rules['overrides']; 44 | rules = overrides.find( 45 | (e) => e.rules && e.rules['@nx/enforce-module-boundaries'] 46 | ); 47 | } 48 | 49 | if (!checkRuleExists(filePath, rule, rules)) return; 50 | 51 | const depConst = rules['rules'][rule][1]['depConstraints'] as Array; 52 | update(depConst); 53 | newText = JSON.stringify(json, undefined, 2); 54 | 55 | } 56 | else { 57 | const rules = new Array(); 58 | update(rules); 59 | const code = trim(JSON.stringify(rules, null, 2)) + ','; 60 | newText = text.replace(allowAll, ''); 61 | newText = newText.replace(depConstraints, 'depConstraints: [\n' + code); 62 | } 63 | 64 | host.write(filePath, newText); 65 | } 66 | 67 | function trim(str: string) { 68 | 69 | if (str.startsWith('[')) { 70 | str = str.substring(1); 71 | } 72 | 73 | if (str.endsWith(']')) { 74 | str = str.substring(0, str.length-1); 75 | } 76 | 77 | return str.trim(); 78 | } 79 | -------------------------------------------------------------------------------- /libs/ddd/src/generators/utils/validate-inputs.ts: -------------------------------------------------------------------------------- 1 | import { UiOptions } from '../ui/schema'; 2 | 3 | export function validateInputs(options: UiOptions): void { 4 | if (options.shared && options.domain) { 5 | throw new Error(`A UI library should either belong to a specific domain or be shared globally. 6 | If you want to share a UI library across multiple specific domains, 7 | consider using an API library. Hence, you should not provide the shared option in combination 8 | with the domain option.`); 9 | } 10 | 11 | if (!options.shared && !options.domain) { 12 | throw new Error(`A UI library should either belong to a domain or be shared globally. 13 | Please provide either of these two options: --domain / --shared`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libs/ddd/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/ddd/src/index.ts -------------------------------------------------------------------------------- /libs/ddd/src/schematics/ng-add/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | chain, 3 | Rule 4 | } from '@angular-devkit/schematics'; 5 | 6 | // In Nx 13.4.1, we had issues with converting generators to schematics 7 | // Hence, we haven't removed this sole ng-add schematic so far 8 | import { initLintingRules } from '../rules/init-linting-rules'; 9 | 10 | export default function(): Rule { 11 | return chain([ 12 | initLintingRules(), 13 | ]); 14 | } 15 | -------------------------------------------------------------------------------- /libs/ddd/src/schematics/ng-add/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "feature-options", 4 | "type": "object", 5 | "properties": {} 6 | } 7 | -------------------------------------------------------------------------------- /libs/ddd/src/schematics/rules/init-linting-rules.ts: -------------------------------------------------------------------------------- 1 | import { Rule, Tree, SchematicContext } from '@angular-devkit/schematics'; 2 | import { updateDepConst } from '../utils/update-dep-const'; 3 | 4 | /** 5 | * initLintingRules 6 | * initialize the linting rules to enforce dependency constraints inside tslint.json 7 | */ 8 | 9 | export function initLintingRules(): Rule { 10 | return (host: Tree, context: SchematicContext) => { 11 | updateDepConst(host, context, (depConst) => { 12 | const jokerIndex = depConst.findIndex( 13 | (entry) => 14 | entry['sourceTag'] && 15 | entry['sourceTag'] === '*' && 16 | entry['onlyDependOnLibsWithTags'] && 17 | Array.isArray(entry['onlyDependOnLibsWithTags']) && 18 | entry['onlyDependOnLibsWithTags'].length > 0 && 19 | entry['onlyDependOnLibsWithTags'][0] === '*' 20 | ); 21 | 22 | if (jokerIndex !== -1) { 23 | depConst.splice(jokerIndex, 1); 24 | } 25 | 26 | depConst.push({ 27 | sourceTag: 'type:app', 28 | onlyDependOnLibsWithTags: [ 29 | 'type:api', 30 | 'type:feature', 31 | 'type:ui', 32 | 'type:domain-logic', 33 | 'type:util', 34 | ], 35 | }); 36 | 37 | depConst.push({ 38 | sourceTag: 'type:api', 39 | onlyDependOnLibsWithTags: ['type:ui', 'type:domain-logic', 'type:util'], 40 | }); 41 | 42 | depConst.push({ 43 | sourceTag: 'type:feature', 44 | onlyDependOnLibsWithTags: ['type:ui', 'type:domain-logic', 'type:util'], 45 | }); 46 | 47 | depConst.push({ 48 | sourceTag: 'type:ui', 49 | onlyDependOnLibsWithTags: ['type:domain-logic', 'type:util'], 50 | }); 51 | 52 | depConst.push({ 53 | sourceTag: 'type:domain-logic', 54 | onlyDependOnLibsWithTags: ['type:util'], 55 | }); 56 | 57 | depConst.push({ 58 | sourceTag: 'domain:shared', 59 | onlyDependOnLibsWithTags: ['domain:shared'], 60 | }); 61 | }); 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /libs/ddd/src/schematics/utils/check-rule-exists.ts: -------------------------------------------------------------------------------- 1 | import { SchematicContext } from '@angular-devkit/schematics'; 2 | 3 | export function checkRuleExists( 4 | filePath: string, 5 | rule: string, 6 | rules: object, 7 | context: SchematicContext 8 | ) { 9 | if (!rules['rules']) { 10 | context.logger.info(`${filePath}: rules expected`); 11 | return false; 12 | } 13 | 14 | if (!rules['rules'][rule]) { 15 | context.logger.info(`${filePath}: ${rule} expected`); 16 | return false; 17 | } 18 | 19 | if (rules['rules'][rule]['length'] < 2) { 20 | context.logger.info(`${filePath}: ${rule}.1 unexpected`); 21 | return false; 22 | } 23 | 24 | if (!rules['rules'][rule][1]['depConstraints']) { 25 | context.logger.info(`${filePath}: ${rule}.1.depConstraints expected.`); 26 | return false; 27 | } 28 | 29 | if (!Array.isArray(rules['rules'][rule][1]['depConstraints'])) { 30 | context.logger.info( 31 | `${filePath}: ${rule}.1.depConstraints expected to be an array.` 32 | ); 33 | return false; 34 | } 35 | 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /libs/ddd/src/schematics/utils/ngrx-version.ts: -------------------------------------------------------------------------------- 1 | export const NGRX_VERSION = '^18.0.0'; 2 | -------------------------------------------------------------------------------- /libs/ddd/src/schematics/utils/update-dep-const.ts: -------------------------------------------------------------------------------- 1 | import { Tree, SchematicContext } from '@angular-devkit/schematics'; 2 | import { checkRuleExists } from './check-rule-exists'; 3 | 4 | export function updateDepConst( 5 | host: Tree, 6 | context: SchematicContext, 7 | update: (depConst: Array) => void 8 | ) { 9 | let filePath = 'tslint.json'; 10 | let rule = 'nx-enforce-module-boundaries'; 11 | 12 | if (!host.exists('tslint.json')) { 13 | if (host.exists('.eslintrc.json')) { 14 | filePath = '.eslintrc.json'; 15 | rule = '@nx/enforce-module-boundaries'; 16 | context.logger.info( 17 | 'Found .eslintrc.json' 18 | ); 19 | } else if (host.exists('.eslintrc')) { 20 | filePath = '.eslintrc'; 21 | rule = '@nx/enforce-module-boundaries'; 22 | context.logger.info( 23 | 'Did not find .eslintrc.json but found .eslintrc' 24 | ); 25 | } else { 26 | context.logger.info( 27 | 'Cannot add linting rules: linting config file does not exist' 28 | ); 29 | return; 30 | } 31 | } 32 | 33 | const text = host.read(filePath).toString(); 34 | const json = JSON.parse(text); 35 | let rules = json; 36 | if (rules['overrides']) { 37 | const overrides = rules['overrides']; 38 | rules = overrides.find( 39 | (e) => e.rules && e.rules['@nx/enforce-module-boundaries'] 40 | ); 41 | } 42 | 43 | if (!checkRuleExists(filePath, rule, rules, context)) return; 44 | 45 | const depConst = rules['rules'][rule][1]['depConstraints'] as Array; 46 | update(depConst); 47 | 48 | const newText = JSON.stringify(json, undefined, 2); 49 | host.overwrite(filePath, newText); 50 | } 51 | -------------------------------------------------------------------------------- /libs/ddd/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/ddd/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": [] 7 | }, 8 | "include": ["**/*.ts"], 9 | "exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/ddd/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/miles/domain/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "miles", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "miles", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /libs/miles/domain/README.md: -------------------------------------------------------------------------------- 1 | # miles-domain 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test miles-domain` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/miles/domain/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'miles-domain', 4 | preset: '../../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../../coverage/libs/miles/domain', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /libs/miles/domain/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "miles-domain", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/miles/domain/src", 5 | "prefix": "miles", 6 | "tags": ["domain:miles", "type:domain-logic"], 7 | "projectType": "library", 8 | "targets": { 9 | "test": { 10 | "executor": "@nx/jest:jest", 11 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 12 | "options": { 13 | "jestConfig": "libs/miles/domain/jest.config.ts", 14 | "passWithNoTests": true 15 | }, 16 | "configurations": { 17 | "ci": { 18 | "ci": true, 19 | "codeCoverage": true 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": [ 28 | "libs/miles/domain/**/*.ts", 29 | "libs/miles/domain/**/*.html" 30 | ] 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libs/miles/domain/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/miles-domain/miles-domain.component'; 2 | 3 | export * from './lib/entities/ticket'; 4 | export * from './lib/infrastructure/ticket.data.service'; 5 | 6 | export * from './lib/application/manage.facade'; 7 | -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/application/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/miles/domain/src/lib/application/.gitkeep -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/application/manage.facade.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { BehaviorSubject } from 'rxjs'; 3 | 4 | import { Ticket } from '../entities/ticket'; 5 | import { TicketDataService } from '../infrastructure/ticket.data.service'; 6 | 7 | @Injectable({ providedIn: 'root' }) 8 | export class ManageFacade { 9 | private ticketListSubject = new BehaviorSubject([]); 10 | ticketList$ = this.ticketListSubject.asObservable(); 11 | 12 | constructor(private ticketDataService: TicketDataService) {} 13 | 14 | load(): void { 15 | this.ticketDataService.load().subscribe({ 16 | next: (ticketList) => { 17 | this.ticketListSubject.next(ticketList); 18 | }, 19 | error: (err) => { 20 | console.error('err', err); 21 | }, 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/entities/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/miles/domain/src/lib/entities/.gitkeep -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/entities/ticket.ts: -------------------------------------------------------------------------------- 1 | export interface Ticket { 2 | id: number; 3 | name: string; 4 | description: string; 5 | } 6 | -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/infrastructure/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/miles/domain/src/lib/infrastructure/.gitkeep -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/infrastructure/ticket.data.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; 3 | import { Observable, of } from 'rxjs'; 4 | import { Ticket } from '../entities/ticket'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class TicketDataService { 8 | constructor(private http: HttpClient) {} 9 | 10 | load(): Observable { 11 | // Uncomment if needed 12 | /* 13 | const url = '...'; 14 | const params = new HttpParams().set('param', 'value'); 15 | const headers = new HttpHeaders().set('Accept', 'application/json'); 16 | return this.http.get(url, {params, headers}); 17 | */ 18 | 19 | return of([ 20 | { id: 1, name: 'Lorem ipsum', description: 'Lorem ipsum dolor sit amet' }, 21 | { 22 | id: 2, 23 | name: 'At vero eos', 24 | description: 'At vero eos et accusam et justo duo dolores', 25 | }, 26 | { 27 | id: 3, 28 | name: 'Duis autem', 29 | description: 'Duis autem vel eum iriure dolor in hendrerit', 30 | }, 31 | ]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/miles-domain/miles-domain.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/miles/domain/src/lib/miles-domain/miles-domain.component.css -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/miles-domain/miles-domain.component.html: -------------------------------------------------------------------------------- 1 |

miles-domain works!

2 | -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/miles-domain/miles-domain.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MilesDomainComponent } from './miles-domain.component'; 3 | 4 | describe('MilesDomainComponent', () => { 5 | let component: MilesDomainComponent; 6 | let fixture: ComponentFixture; 7 | 8 | beforeEach(async () => { 9 | await TestBed.configureTestingModule({ 10 | imports: [MilesDomainComponent], 11 | }).compileComponents(); 12 | 13 | fixture = TestBed.createComponent(MilesDomainComponent); 14 | component = fixture.componentInstance; 15 | fixture.detectChanges(); 16 | }); 17 | 18 | it('should create', () => { 19 | expect(component).toBeTruthy(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /libs/miles/domain/src/lib/miles-domain/miles-domain.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | @Component({ 5 | selector: 'miles-miles-domain', 6 | standalone: true, 7 | imports: [CommonModule], 8 | templateUrl: './miles-domain.component.html', 9 | styleUrls: ['./miles-domain.component.css'], 10 | }) 11 | export class MilesDomainComponent {} 12 | -------------------------------------------------------------------------------- /libs/miles/domain/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /libs/miles/domain/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ], 16 | "extends": "../../../tsconfig.base.json" 17 | } 18 | -------------------------------------------------------------------------------- /libs/miles/domain/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "src/**/*.spec.ts", 12 | "src/test-setup.ts", 13 | "jest.config.ts", 14 | "src/**/*.test.ts" 15 | ], 16 | "include": ["src/**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /libs/miles/domain/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "miles", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "miles", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/README.md: -------------------------------------------------------------------------------- 1 | # miles-feature-manage 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test miles-feature-manage` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'miles-feature-manage', 4 | preset: '../../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../../coverage/libs/miles/feature-manage', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "miles-feature-manage", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/miles/feature-manage/src", 5 | "prefix": "miles", 6 | "tags": ["domain:miles", "type:feature"], 7 | "projectType": "library", 8 | "targets": { 9 | "test": { 10 | "executor": "@nx/jest:jest", 11 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 12 | "options": { 13 | "jestConfig": "libs/miles/feature-manage/jest.config.ts", 14 | "passWithNoTests": true 15 | }, 16 | "configurations": { 17 | "ci": { 18 | "ci": true, 19 | "codeCoverage": true 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": [ 28 | "libs/miles/feature-manage/**/*.ts", 29 | "libs/miles/feature-manage/**/*.html" 30 | ] 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/miles-feature-manage/miles-feature-manage.component'; 2 | 3 | export * from './lib/manage.component'; 4 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/manage.component.html: -------------------------------------------------------------------------------- 1 |

miles-manage

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
{{ ticket.id }}{{ ticket.name }}{{ ticket.description }}
10 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/manage.component.scss: -------------------------------------------------------------------------------- 1 | .table td { 2 | border: 1px solid; 3 | padding: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/manage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { ManageFacade } from '@angular-architects/miles/domain'; 4 | 5 | @Component({ 6 | standalone: true, 7 | imports: [CommonModule], 8 | selector: 'miles-manage', 9 | templateUrl: './manage.component.html', 10 | styleUrls: ['./manage.component.scss'], 11 | }) 12 | export class ManageComponent implements OnInit { 13 | ticketList$ = this.manageFacade.ticketList$; 14 | 15 | constructor(private manageFacade: ManageFacade) {} 16 | 17 | ngOnInit() { 18 | this.load(); 19 | } 20 | 21 | load(): void { 22 | this.manageFacade.load(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/miles-feature-manage/miles-feature-manage.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-architects/nx-ddd-plugin/eb00cacbff9dc4de63b8f70abcc8d601abb34fb1/libs/miles/feature-manage/src/lib/miles-feature-manage/miles-feature-manage.component.css -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/miles-feature-manage/miles-feature-manage.component.html: -------------------------------------------------------------------------------- 1 |

miles-feature-manage works!

2 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/miles-feature-manage/miles-feature-manage.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MilesFeatureManageComponent } from './miles-feature-manage.component'; 3 | 4 | describe('MilesFeatureManageComponent', () => { 5 | let component: MilesFeatureManageComponent; 6 | let fixture: ComponentFixture; 7 | 8 | beforeEach(async () => { 9 | await TestBed.configureTestingModule({ 10 | imports: [MilesFeatureManageComponent], 11 | }).compileComponents(); 12 | 13 | fixture = TestBed.createComponent(MilesFeatureManageComponent); 14 | component = fixture.componentInstance; 15 | fixture.detectChanges(); 16 | }); 17 | 18 | it('should create', () => { 19 | expect(component).toBeTruthy(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/lib/miles-feature-manage/miles-feature-manage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | @Component({ 5 | selector: 'miles-miles-feature-manage', 6 | standalone: true, 7 | imports: [CommonModule], 8 | templateUrl: './miles-feature-manage.component.html', 9 | styleUrls: ['./miles-feature-manage.component.css'], 10 | }) 11 | export class MilesFeatureManageComponent {} 12 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ], 16 | "extends": "../../../tsconfig.base.json" 17 | } 18 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "src/**/*.spec.ts", 12 | "src/test-setup.ts", 13 | "jest.config.ts", 14 | "src/**/*.test.ts" 15 | ], 16 | "include": ["src/**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /libs/miles/feature-manage/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "migrations": [ 3 | { 4 | "cli": "nx", 5 | "version": "16.6.0-beta.6", 6 | "description": "Prefix outputs with {workspaceRoot}/{projectRoot} if needed", 7 | "implementation": "./src/migrations/update-15-0-0/prefix-outputs", 8 | "package": "nx", 9 | "name": "16.6.0-prefix-outputs" 10 | }, 11 | { 12 | "cli": "nx", 13 | "version": "16.4.0-beta.10", 14 | "description": "Remove tsconfig.e2e.json and add settings to project tsconfig.json. tsConfigs executor option is now deprecated. The project level tsconfig.json file should be used instead.", 15 | "implementation": "./src/migrations/update-16-4-0/tsconfig-sourcemaps", 16 | "package": "@nx/cypress", 17 | "name": "update-16-3-0-remove-old-tsconfigs" 18 | }, 19 | { 20 | "cli": "nx", 21 | "version": "16.6.0-beta.0", 22 | "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", 23 | "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps", 24 | "package": "@nx/js", 25 | "name": "explicitly-set-projects-to-update-buildable-deps" 26 | }, 27 | { 28 | "cli": "nx", 29 | "version": "16.5.0-beta.2", 30 | "description": "Add test-setup.ts to ignored files in production input", 31 | "implementation": "./src/migrations/update-16-5-0/add-test-setup-to-inputs-ignore", 32 | "package": "@nx/jest", 33 | "name": "add-test-setup-to-inputs-ignore" 34 | }, 35 | { 36 | "cli": "nx", 37 | "version": "16.4.0-beta.6", 38 | "requires": { 39 | "@angular-eslint/eslint-plugin-template": ">=16.0.0" 40 | }, 41 | "description": "Remove the 'accessibility-' prefix from '@angular-eslint/eslint-plugin-template' rules.", 42 | "factory": "./src/migrations/update-16-4-0/rename-angular-eslint-accesibility-rules", 43 | "package": "@nx/angular", 44 | "name": "rename-angular-eslint-accesibility-rules" 45 | }, 46 | { 47 | "cli": "nx", 48 | "version": "16.4.0-beta.11", 49 | "requires": { 50 | "@angular/core": ">=16.1.0" 51 | }, 52 | "description": "Update the @angular/cli package version to ~16.1.0.", 53 | "factory": "./src/migrations/update-16-4-0/update-angular-cli", 54 | "package": "@nx/angular", 55 | "name": "update-angular-cli-version-16-1-0" 56 | }, 57 | { 58 | "cli": "nx", 59 | "version": "16.6.0-beta.0", 60 | "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", 61 | "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps", 62 | "package": "@nx/angular", 63 | "name": "explicitly-set-projects-to-update-buildable-deps" 64 | }, 65 | { 66 | "cli": "nx", 67 | "version": "16.7.0-beta.6", 68 | "requires": { 69 | "@angular/core": ">=16.2.0" 70 | }, 71 | "description": "Update the @angular/cli package version to ~16.2.0.", 72 | "factory": "./src/migrations/update-16-7-0/update-angular-cli", 73 | "package": "@nx/angular", 74 | "name": "update-angular-cli-version-16-2-0" 75 | } 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 3 | "affected": { 4 | "defaultBase": "master" 5 | }, 6 | "cli": { 7 | "packageManager": "npm" 8 | }, 9 | "tasksRunnerOptions": { 10 | "default": { 11 | "runner": "nx/tasks-runners/default", 12 | "options": { 13 | "cacheableOperations": ["build", "lint", "test", "e2e"] 14 | } 15 | } 16 | }, 17 | "targetDefaults": { 18 | "build": { 19 | "dependsOn": ["^build"], 20 | "inputs": ["production", "^production"] 21 | }, 22 | "lint": { 23 | "inputs": ["default", "{workspaceRoot}/.eslintrc.json"] 24 | }, 25 | "e2e": { 26 | "inputs": ["default", "^production"] 27 | }, 28 | "test": { 29 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"] 30 | } 31 | }, 32 | "generators": { 33 | "@nx/angular:application": { 34 | "style": "css", 35 | "linter": "eslint", 36 | "unitTestRunner": "jest", 37 | "e2eTestRunner": "cypress" 38 | }, 39 | "@nx/angular:library": { 40 | "linter": "eslint", 41 | "unitTestRunner": "jest" 42 | }, 43 | "@nx/angular:component": { 44 | "style": "css" 45 | } 46 | }, 47 | "namedInputs": { 48 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 49 | "sharedGlobals": [], 50 | "production": [ 51 | "default", 52 | "!{projectRoot}/.eslintrc.json", 53 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", 54 | "!{projectRoot}/tsconfig.spec.json", 55 | "!{projectRoot}/jest.config.[jt]s" 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddd-plugin", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "nx", 7 | "start": "nx serve", 8 | "build": "nx build", 9 | "test": "nx test", 10 | "reset": "rm -rf node_modules && rm package-lock.json && npm i", 11 | "build-pack": "nx b ddd && npm pack dist/libs/ddd" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "16.2.3", 16 | "@angular/common": "16.2.3", 17 | "@angular/compiler": "16.2.3", 18 | "@angular/core": "16.2.3", 19 | "@angular/forms": "16.2.3", 20 | "@angular/platform-browser": "16.2.3", 21 | "@angular/platform-browser-dynamic": "16.2.3", 22 | "@angular/router": "16.2.3", 23 | "@ngrx/effects": "16.0.0", 24 | "@ngrx/entity": "16.0.0", 25 | "@ngrx/store": "16.0.0", 26 | "@ngrx/store-devtools": "16.0.0", 27 | "@nx/angular": "16.7.4", 28 | "@nx/plugin": "16.7.4", 29 | "@phenomnomnominal/tsquery": "^5.0.1", 30 | "@swc/helpers": "0.5.1", 31 | "rxjs": "7.8.1", 32 | "tslib": "^2.5.2", 33 | "zone.js": "~0.13.0" 34 | }, 35 | "devDependencies": { 36 | "@angular-devkit/build-angular": "16.2.1", 37 | "@angular-devkit/core": "16.2.1", 38 | "@angular-devkit/schematics": "16.2.1", 39 | "@angular-eslint/eslint-plugin": "16.0.2", 40 | "@angular-eslint/eslint-plugin-template": "16.0.2", 41 | "@angular-eslint/template-parser": "16.0.2", 42 | "@angular/cli": "~16.0.2", 43 | "@angular/compiler-cli": "16.2.3", 44 | "@angular/language-service": "16.2.3", 45 | "@ngrx/schematics": "16.0.0", 46 | "@nx/cypress": "16.7.4", 47 | "@nx/devkit": "16.7.4", 48 | "@nx/eslint-plugin": "16.7.4", 49 | "@nx/jest": "16.7.4", 50 | "@nx/js": "16.7.4", 51 | "@nx/linter": "16.7.4", 52 | "@nx/web": "16.7.4", 53 | "@nx/workspace": "16.7.4", 54 | "@schematics/angular": "16.2.1", 55 | "@swc-node/register": "^1.6.5", 56 | "@swc/cli": "0.1.62", 57 | "@swc/core": "^1.3.59", 58 | "@types/jest": "29.5.1", 59 | "@types/node": "20.2.1", 60 | "@typescript-eslint/eslint-plugin": "5.60.1", 61 | "@typescript-eslint/parser": "5.60.1", 62 | "cypress": "12.16.0", 63 | "eslint": "8.46.0", 64 | "eslint-config-prettier": "8.8.0", 65 | "eslint-plugin-cypress": "2.13.4", 66 | "jest": "29.5.0", 67 | "jest-environment-jsdom": "29.5.0", 68 | "jest-preset-angular": "13.1.1", 69 | "jsonc-eslint-parser": "^2.3.0", 70 | "nx": "16.7.4", 71 | "prettier": "^2.8.8", 72 | "ts-jest": "29.1.0", 73 | "ts-node": "10.9.1", 74 | "tslib": "^2.5.2", 75 | "typescript": "5.1.6" 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@angular-architects/checkin/domain": [ 19 | "libs/checkin/domain/src/index.ts" 20 | ], 21 | "@angular-architects/checkin/feature-manage": [ 22 | "libs/checkin/feature-manage/src/index.ts" 23 | ], 24 | "@angular-architects/ddd": ["libs/ddd/src/index.ts"], 25 | "@angular-architects/feature/domain": [ 26 | "libs/feature/domain/src/index.ts" 27 | ], 28 | "@angular-architects/miles/domain": ["libs/miles/domain/src/index.ts"], 29 | "@angular-architects/miles/feature-manage": [ 30 | "libs/miles/feature-manage/src/index.ts" 31 | ] 32 | } 33 | }, 34 | "exclude": ["node_modules", "tmp"] 35 | } 36 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | npx nx build ddd 2 | npm unpublish @angular-architects/ddd@19.0.6 -f --registry http://localhost:4873 3 | npm publish dist/libs/ddd --registry http://localhost:4873 4 | --------------------------------------------------------------------------------