Skip to content

Commit 5a5c314

Browse files
Merge branch 'master' into feat/nx-11
2 parents f9acdba + d832f17 commit 5a5c314

37 files changed

+2831
-17090
lines changed

.cz-config.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
module.exports = {
2+
types: [
3+
{ value: 'feat', name: 'feat: A new feature' },
4+
{ value: 'fix', name: 'fix: A bug fix' },
5+
{ value: 'docs', name: 'docs: Documentation only changes' },
6+
{
7+
value: 'cleanup',
8+
name:
9+
'cleanup: A code change that neither fixes a bug nor adds a feature',
10+
},
11+
{
12+
value: 'chore',
13+
name: "chore: Other changes that don't modify src or test files",
14+
},
15+
],
16+
17+
scopes: [
18+
{ name: 'schematics', description: 'anything related to the ddd schematics' },
19+
{ name: 'repo', description: 'anything making improvements on the repo' },
20+
{ name: 'misc', description: 'misc stuff' },
21+
],
22+
23+
allowTicketNumber: true,
24+
isTicketNumberRequired: false,
25+
ticketNumberPrefix: 'TICKET-',
26+
ticketNumberRegExp: '\\d{1,5}',
27+
28+
// it needs to match the value for field type. Eg.: 'fix'
29+
/*
30+
scopeOverrides: {
31+
fix: [
32+
{name: 'merge'},
33+
{name: 'style'},
34+
{name: 'e2eTest'},
35+
{name: 'unitTest'}
36+
]
37+
},
38+
*/
39+
// override the messages, defaults are as follows
40+
messages: {
41+
type: "Select the type of change that you're committing:",
42+
scope: '\nDenote the SCOPE of this change (optional):',
43+
// used if allowCustomScopes is true
44+
customScope: 'Denote the SCOPE of this change:',
45+
subject:
46+
'Write a SHORT, IMPERATIVE (lowercase) description of the change:\n',
47+
body:
48+
'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
49+
breaking: 'List any BREAKING CHANGES (optional):\n',
50+
footer:
51+
'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n',
52+
confirmCommit: 'Are you sure you want to proceed with the commit above?',
53+
},
54+
55+
allowCustomScopes: false,
56+
allowBreakingChanges: ['feat', 'fix'],
57+
// skip any questions you want
58+
skipQuestions: ['ticketNumber'],
59+
60+
// limit subject length
61+
subjectLimit: 100,
62+
// breaklineChar: '|', // It is supported for fields body and footer.
63+
// footerPrefix : 'ISSUES CLOSED:'
64+
// askForBreakingChangeFirst : true, // default is false
65+
};

apps/ddd-e2e/jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module.exports = {
22
name: 'ddd-e2e',
33
preset: '../../jest.config.js',
4-
coverageDirectory: '../../coverage/appsddd-e2e'
4+
coverageDirectory: '../../coverage/appsddd-e2e',
55
};

apps/ddd-e2e/tests/ddd.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import {
33
ensureNxProject,
44
readJson,
55
runNxCommandAsync,
6-
uniq
6+
uniq,
77
} from '@nrwl/nx-plugin/testing';
88
describe('ddd e2e', () => {
9-
it('should create ddd', async done => {
9+
it('should create ddd', async (done) => {
1010
const plugin = uniq('ddd');
1111
ensureNxProject('@angular-architects/ddd', 'dist/libs/ddd');
1212
await runNxCommandAsync(`generate @angular-architects/ddd:ddd ${plugin}`);
@@ -18,7 +18,7 @@ describe('ddd e2e', () => {
1818
});
1919

2020
describe('--directory', () => {
21-
it('should create src in the specified directory', async done => {
21+
it('should create src in the specified directory', async (done) => {
2222
const plugin = uniq('ddd');
2323
ensureNxProject('@angular-architects/ddd', 'dist/libs/ddd');
2424
await runNxCommandAsync(
@@ -32,7 +32,7 @@ describe('ddd e2e', () => {
3232
});
3333

3434
describe('--tags', () => {
35-
it('should add tags to nx.json', async done => {
35+
it('should add tags to nx.json', async (done) => {
3636
const plugin = uniq('ddd');
3737
ensureNxProject('@angular-architects/ddd', 'dist/libs/ddd');
3838
await runNxCommandAsync(

libs/ddd/README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ The generated access restrictions prevent unwanted access between libraries resp
1414
- ⚙️ Generating feature libraries including a feature components using the facades
1515
- 🙅‍♂️ Adding linting rules for access restrictions between domains as proposed by Nrwl
1616
- 🙅‍♀️ Adding linting rules for access restrictions between layers as proposed by Nrwl (supports tslint and eslint)
17-
- 🔥 Optionally generates skeleton for NGRX and integrates it into the DDD design (``--ngrx`` switch)
17+
- 🔥 Optionally generates skeleton for NGRX and integrates it into the DDD design (`--ngrx` switch)
1818

1919
### Features Overview Video
20-
<a href="https://www.youtube.com/watch?v=39JLXMEE7Ds" target="_blank">![Screenshot of Overview Video](https://i.imgur.com/VlTRE80.png)</a>
2120

21+
<a href="https://www.youtube.com/watch?v=39JLXMEE7Ds" target="_blank">![Screenshot of Overview Video](https://i.imgur.com/VlTRE80.png)</a>
2222

2323
## Usage
2424

@@ -38,16 +38,15 @@ ng g @angular-architects/ddd:feature cancel --domain booking
3838
ng g @angular-architects/ddd:feature manage --domain boarding
3939
```
4040

41-
For NGRX support, just add the ``--ngrx`` switch:
41+
For NGRX support, just add the `--ngrx` switch:
4242

4343
```
4444
ng g @angular-architects/ddd:domain booking --addApp --ngrx
4545
ng g @angular-architects/ddd:feature search --domain booking --entity flight --ngrx
4646
[...]
4747
```
4848

49-
50-
This example assumes that you have an app ``flight-app`` in place.
49+
This example assumes that you have an app `flight-app` in place.
5150

5251
These schematics also wire up the individual libs. To see the result, create a dependency graph:
5352

@@ -57,7 +56,7 @@ npm run dep-graph
5756

5857
![dependency graph](https://github.com/angular-architects/nx-ddd-plugin/blob/master/libs/ddd/assets/ddd.png?raw=true)
5958

60-
To see that the skeleton works end-to-end, call the generated feature component in your ``app.component.html``:
59+
To see that the skeleton works end-to-end, call the generated feature component in your `app.component.html`:
6160

6261
```html
6362
<booking-search></booking-search>
@@ -79,7 +78,7 @@ The domain layer is subdivided into three parts:
7978

8079
### Generated Structure for Domain Library
8180

82-
- **application:** Contains application services. This is a DDD term for what we call facades in Angular nowadays. They orchestrate everything for a use case given so that a feature component only needs to communicate with one such facade. Also, it hides details for state management. While the generates facades just use a ``BehaviorSubject``, feel free to add a library like NGRX underneath. As such a modifications changes nothing from the component's perspective, you can use facades to introduce NGRX later on demand.
81+
- **application:** Contains application services. This is a DDD term for what we call facades in Angular nowadays. They orchestrate everything for a use case given so that a feature component only needs to communicate with one such facade. Also, it hides details for state management. While the generates facades just use a `BehaviorSubject`, feel free to add a library like NGRX underneath. As such a modifications changes nothing from the component's perspective, you can use facades to introduce NGRX later on demand.
8382
- **entities:** Client-side data model including logic operating on it (like validations).
8483
- **infrastructure:** Services for communicating with the backend.
8584

@@ -102,6 +101,7 @@ see https://github.com/angular-architects/ddd-demo
102101
- [Our eBook on Angular and architectures](https://leanpub.com/enterprise-angular)
103102
- [Thomas Burlison's article about facades in Angular](https://medium.com/@thomasburlesonIA/push-based-architectures-with-rxjs-81b327d7c32d)
104103

105-
## More
104+
## More
105+
106106
- [Angular Architecture Workshop](https://www.angulararchitects.io/en/angular-workshops/advanced-angular-enterprise-architecture-incl-ivy/)
107107
- [Follow us on Twitter](https://twitter.com/ManfredSteyer)

libs/ddd/collection.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@
2828
"description": "adds a utility library to a domain or as a shared library"
2929
}
3030
}
31-
}
31+
}

libs/ddd/node_modules/.yarn-integrity

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/ddd/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@angular-architects/ddd",
3-
"version": "1.1.0",
3+
"version": "1.2.2",
44
"license": "MIT",
55
"author": "Manfred Steyer",
66
"description": "Nx plugin for structuring a monorepo with domains and layers",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Tree } from '@angular-devkit/schematics';
2+
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
3+
import { NxJson, readJsonInTree } from '@nrwl/workspace';
4+
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
5+
import { join } from 'path';
6+
7+
describe('domain', () => {
8+
let appTree: Tree;
9+
10+
const testRunner = new SchematicTestRunner(
11+
'@angular-architects/ddd',
12+
join(__dirname, '../../../collection.json')
13+
);
14+
15+
function runSchematic<SchemaOptions = any>(
16+
schematicName: string,
17+
options: SchemaOptions,
18+
tree: Tree
19+
) {
20+
return testRunner
21+
.runSchematicAsync(schematicName, options, tree)
22+
.toPromise();
23+
}
24+
25+
beforeEach(() => {
26+
appTree = Tree.empty();
27+
appTree = createEmptyWorkspace(appTree);
28+
});
29+
30+
/**
31+
it('should ........', async () => {
32+
const tree = await runSchematic<UiOptions>(
33+
'ui',
34+
{ name: 'form-components', shared: true },
35+
appTree
36+
);
37+
38+
const nxJson = readJsonInTree<NxJson>(tree, '/nx.json');
39+
expect(nxJson.projects).toEqual({
40+
'........': {
41+
tags: ['domain:abcdefg', 'type:xyz'],
42+
},
43+
});
44+
});
45+
*/
46+
});

libs/ddd/src/schematics/domain/index.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,52 +19,70 @@ import {
1919
} from '../rules';
2020

2121
export default function (options: DomainOptions): Rule {
22-
const libFolder = strings.dasherize(options.name);
22+
const appName = strings.dasherize(options.name);
23+
const appNameAndDirectory = options.appDirectory
24+
? `${options.appDirectory}/${appName}`
25+
: appName;
26+
const appNameAndDirectoryDasherized = strings
27+
.dasherize(appNameAndDirectory)
28+
.split('/')
29+
.join('-');
30+
const appFolderPath = `apps/${appNameAndDirectory}`;
31+
const appModuleFolder = `${appFolderPath}/src/app`;
32+
const appModuleFilepath = `${appModuleFolder}/app.module.ts`;
33+
34+
const libName = strings.dasherize(options.name);
35+
const libNameAndDirectory = options.directory
36+
? `${libName}/${options.directory}`
37+
: libName;
38+
const libNameAndDirectoryDasherized = strings
39+
.dasherize(libNameAndDirectory)
40+
.split('/')
41+
.join('-');
42+
const libFolderPath = `libs/${libNameAndDirectory}`;
43+
const libLibFolder = `${libFolderPath}/domain/src/lib`;
2344

2445
const templateSource = apply(url('./files'), [
2546
template({}),
26-
move(`libs/${libFolder}/domain/src/lib`),
47+
move(`${libLibFolder}`),
2748
]);
2849

29-
const appFolderName = strings.dasherize(options.name);
30-
const appPath = `apps/${appFolderName}/src/app`;
31-
const appModulePath = `${appPath}/app.module.ts`;
32-
3350
if (options.ngrx && !options.addApp) {
3451
throw new Error(
3552
`The 'ngrx' option may only be used when the 'addApp' option is used.`
36-
)
53+
);
3754
}
3855

3956
return chain([
4057
externalSchematic('@nrwl/angular', 'lib', {
4158
name: 'domain',
42-
directory: options.name,
43-
tags: `domain:${options.name},type:domain-logic`,
59+
directory: libNameAndDirectory,
60+
tags: `domain:${libName},type:domain-logic`,
4461
style: 'scss',
45-
prefix: options.name,
62+
prefix: libName,
4663
publishable: options.type === 'publishable',
4764
buildable: options.type === 'buildable',
4865
}),
49-
addDomainToLintingRules(options.name),
66+
addDomainToLintingRules(libName),
5067
mergeWith(templateSource),
5168
!options.addApp
5269
? noop()
5370
: externalSchematic('@nrwl/angular', 'app', {
54-
name: options.name,
55-
tags: `domain:${options.name},type:app`,
71+
name: appName,
72+
directory: options.appDirectory,
73+
tags: `domain:${appName},type:app`,
5674
style: 'scss',
5775
}),
5876
options.addApp && options.ngrx
5977
? chain([
6078
externalSchematic('@ngrx/schematics', 'store', {
61-
project: options.name,
79+
project: appNameAndDirectoryDasherized,
6280
root: true,
6381
minimal: true,
6482
module: 'app.module.ts',
6583
name: 'state',
6684
}),
67-
addNgrxImportsToApp(appModulePath),
85+
addNgrxImportsToApp(appModuleFilepath),
6886
addNgRxToPackageJson(),
6987
])
7088
: noop(),

libs/ddd/src/schematics/domain/schema.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@
55
"properties": {
66
"name": {
77
"type": "string",
8-
"description": "Domain name",
8+
"description": "Grouping name for the Domain",
99
"x-prompt": "What is the name of the domain?",
1010
"$default": {
1111
"$source": "argv",
1212
"index": 0
1313
}
1414
},
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+
},
1523
"addApp": {
1624
"type": "boolean",
1725
"description": "Add an app for the domain?",

0 commit comments

Comments
 (0)