Skip to content

Commit efc5d3c

Browse files
committed
feat(feature-gen): support standalone components
1 parent 869f95f commit efc5d3c

File tree

6 files changed

+124
-57
lines changed

6 files changed

+124
-57
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
},
4545
"standalone": {
4646
"type": "boolean",
47-
"default": true,
47+
"default": false,
4848
"description": "Use standalone components?"
4949
}
5050

libs/ddd/src/generators/feature/files/forFeature/__name@dasherize__.component.ts__tmpl__

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { Component, OnInit} from '@angular/core';
2-
import { <%=classify(name)%>Facade } from '<%=workspaceName%>/<%=dasherize(domain)%><%- domainDirectory ? '/' + domainDirectory : '' %>/domain';
1+
import { Component, OnInit } from '@angular/core'; <% if (standalone) { %>
2+
import { CommonModule } from '@angular/common';
3+
<% } %>import { <%=classify(name)%>Facade } from '<%=workspaceName%>/<%=dasherize(domain)%><%- domainDirectory ? '/' + domainDirectory : '' %>/domain';
34

4-
@Component({
5-
selector: '<%=dasherize(domain)%>-<%=dasherize(name)%>',
5+
@Component({ <% if (standalone) { %>
6+
standalone: true,
7+
imports: [CommonModule],
8+
<% } %>selector: '<%=dasherize(domain)%>-<%=dasherize(name)%>',
69
templateUrl: './<%=dasherize(name)%>.component.html',
710
styleUrls: ['./<%=dasherize(name)%>.component.scss']
811
})

libs/ddd/src/generators/feature/files/forFeatureWithNgrx/__name@dasherize__.component.ts__tmpl__

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { Component, OnInit} from '@angular/core';
2-
import { <%=classify(name)%>Facade } from '<%=workspaceName%>/<%=dasherize(domain)%><%- domainDirectory ? '/' + domainDirectory : '' %>/domain';
1+
import { Component, OnInit } from '@angular/core'; <% if (standalone) { %>
2+
import { CommonModule } from '@angular/common';
3+
<% } %>import { <%=classify(name)%>Facade } from '<%=workspaceName%>/<%=dasherize(domain)%><%- domainDirectory ? '/' + domainDirectory : '' %>/domain';
34

4-
@Component({
5-
selector: '<%=dasherize(domain)%>-<%=dasherize(name)%>',
5+
@Component({ <% if (standalone) { %>
6+
standalone: true,
7+
imports: [CommonModule],
8+
<% } %>selector: '<%=dasherize(domain)%>-<%=dasherize(name)%>',
69
templateUrl: './<%=dasherize(name)%>.component.html',
710
styleUrls: ['./<%=dasherize(name)%>.component.scss']
811
})

libs/ddd/src/generators/feature/index.ts

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
import { Tree, formatFiles, installPackagesTask, generateFiles, joinPathFragments } from '@nrwl/devkit';
1+
import {
2+
Tree,
3+
formatFiles,
4+
installPackagesTask,
5+
generateFiles,
6+
joinPathFragments,
7+
} from '@nrwl/devkit';
28
import { libraryGenerator } from '@nrwl/angular/generators';
39
import { FeatureOptions } from './schema';
410
import { strings } from '@angular-devkit/core';
511
import { addTsExport } from '../utils/add-ts-exports';
6-
import { addDeclarationWithExportToNgModule, addImportToNgModule } from '../utils/addToNgModule';
12+
import {
13+
addDeclarationWithExportToNgModule,
14+
addImportToNgModule,
15+
} from '../utils/addToNgModule';
716
import { addNgrxImportsToDomain } from '../utils/add-ngrx-imports-to-domain';
817
import { fileContains } from '../utils/fileContains';
918
import { getWorkspaceScope } from '../utils/get-workspace-scope';
1019

1120
export default async function (tree: Tree, options: FeatureOptions) {
12-
1321
options.app ??= options.domain;
1422
options.domainDirectory ??= '';
1523
options.entity ??= '';
@@ -61,9 +69,8 @@ export default async function (tree: Tree, options: FeatureOptions) {
6169
? `${featureDirectory}/${featureFolderName}`
6270
: featureFolderName;
6371

64-
const featureDirectoryAndFolderNameDasherized = `${featureDirectoryAndFolderName}`
65-
.split('/')
66-
.join('-');
72+
const featureDirectoryAndFolderNameDasherized =
73+
`${featureDirectoryAndFolderName}`.split('/').join('-');
6774

6875
const featureLibFolderPath = `${domainNameAndDirectoryPath}/${featureDirectoryAndFolderName}/src/lib`;
6976
const featureModuleFilepath = `${featureLibFolderPath}/${domainNameAndDirectoryDasherized}-${featureDirectoryAndFolderNameDasherized}.module.ts`;
@@ -79,10 +86,10 @@ export default async function (tree: Tree, options: FeatureOptions) {
7986
);
8087
const appModulePath = `apps/${appDirectoryAndName}/src/app/app.module.ts`;
8188

82-
const requiredAppModulePath = `apps/${appDirectoryAndName}/src/app/app.module.ts`;
83-
if (!options.noApp && !tree.exists(requiredAppModulePath)) {
89+
const requiredAppCompPath = `apps/${appDirectoryAndName}/src/app/app.component.ts`;
90+
if (!options.noApp && !tree.exists(requiredAppCompPath)) {
8491
throw new Error(
85-
`Specified app ${options.app} does not exist: ${requiredAppModulePath} expected!`
92+
`Specified app ${options.app} does not exist: ${requiredAppCompPath} expected!`
8693
);
8794
}
8895

@@ -92,8 +99,6 @@ export default async function (tree: Tree, options: FeatureOptions) {
9299
);
93100
}
94101

95-
// let updatedEntityNameOptions = Object.assign({}, options);
96-
97102
await libraryGenerator(tree, {
98103
name: featureFolderName,
99104
directory: featureDirectory
@@ -103,45 +108,35 @@ export default async function (tree: Tree, options: FeatureOptions) {
103108
prefix: domainNameAndDirectoryDasherized,
104109
publishable: options.type === 'publishable',
105110
buildable: options.type === 'buildable',
106-
importPath: options.importPath
111+
importPath: options.importPath,
112+
skipModule: options.standalone,
107113
});
108114

109-
addImportToNgModule(tree, {
110-
filePath: featureModuleFilepath,
111-
importClassName: domainModuleClassName,
112-
importPath: domainImportPath
113-
});
114-
115-
if (!options.noApp && !options.lazy && tree.exists(appModulePath)) {
116-
addImportToNgModule(tree, {
117-
filePath: appModulePath,
118-
importClassName: featureModuleClassName,
119-
importPath: featureImportPath
115+
if (!options.standalone) {
116+
wireUpNgModules(tree, {
117+
featureModuleFilepath,
118+
domainModuleClassName,
119+
domainImportPath,
120+
options,
121+
appModulePath,
122+
featureModuleClassName,
123+
featureImportPath,
120124
});
121-
122-
const contains = fileContains(tree, appModulePath, 'HttpClientModule');
123-
if (!contains) {
124-
addImportToNgModule(tree, {
125-
filePath: appModulePath,
126-
importClassName: 'HttpClientModule',
127-
importPath: '@angular/common/http'
128-
});
129-
}
130125
}
131126

132127
generate(tree, {
133128
options,
134129
entityName,
135130
domainLibFolderPath,
136131
workspaceName,
137-
featureLibFolderPath
132+
featureLibFolderPath,
138133
});
139134

140135
if (entityName) {
141136
addTsExport(tree, domainIndexPath, [
142137
`./lib/entities/${entityName}`,
143138
`./lib/infrastructure/${entityName}.data.service`,
144-
])
139+
]);
145140
}
146141

147142
if (options.ngrx && entityName && tree.exists(domainModuleFilepath)) {
@@ -159,19 +154,80 @@ export default async function (tree: Tree, options: FeatureOptions) {
159154
`./lib/${featureDirectoryAndNameDasherized}.component`,
160155
]);
161156

162-
addDeclarationWithExportToNgModule(tree, {
163-
filePath: featureModuleFilepath,
164-
importClassName: featureComponentClassName,
165-
importPath: featureComponentImportPath
166-
});
157+
if (!options.standalone) {
158+
addDeclarationWithExportToNgModule(tree, {
159+
filePath: featureModuleFilepath,
160+
importClassName: featureComponentClassName,
161+
importPath: featureComponentImportPath,
162+
});
163+
}
167164

168165
await formatFiles(tree);
169166
return () => {
170167
installPackagesTask(tree);
171168
};
172169
}
173170

174-
function generate(tree: Tree, { options, entityName, domainLibFolderPath, workspaceName, featureLibFolderPath }: { options: FeatureOptions; entityName: string; domainLibFolderPath: string; workspaceName: string; featureLibFolderPath: string; }) {
171+
function wireUpNgModules(
172+
tree: Tree,
173+
{
174+
featureModuleFilepath,
175+
domainModuleClassName,
176+
domainImportPath,
177+
options,
178+
appModulePath,
179+
featureModuleClassName,
180+
featureImportPath,
181+
}: {
182+
featureModuleFilepath: string;
183+
domainModuleClassName: string;
184+
domainImportPath: string;
185+
options: FeatureOptions;
186+
appModulePath: string;
187+
featureModuleClassName: string;
188+
featureImportPath: string;
189+
}
190+
) {
191+
addImportToNgModule(tree, {
192+
filePath: featureModuleFilepath,
193+
importClassName: domainModuleClassName,
194+
importPath: domainImportPath,
195+
});
196+
197+
if (!options.noApp && !options.lazy && tree.exists(appModulePath)) {
198+
addImportToNgModule(tree, {
199+
filePath: appModulePath,
200+
importClassName: featureModuleClassName,
201+
importPath: featureImportPath,
202+
});
203+
204+
const contains = fileContains(tree, appModulePath, 'HttpClientModule');
205+
if (!contains) {
206+
addImportToNgModule(tree, {
207+
filePath: appModulePath,
208+
importClassName: 'HttpClientModule',
209+
importPath: '@angular/common/http',
210+
});
211+
}
212+
}
213+
}
214+
215+
function generate(
216+
tree: Tree,
217+
{
218+
options,
219+
entityName,
220+
domainLibFolderPath,
221+
workspaceName,
222+
featureLibFolderPath,
223+
}: {
224+
options: FeatureOptions;
225+
entityName: string;
226+
domainLibFolderPath: string;
227+
workspaceName: string;
228+
featureLibFolderPath: string;
229+
}
230+
) {
175231
const tmpl = '';
176232
const params = {
177233
...strings,
@@ -182,7 +238,7 @@ function generate(tree: Tree, { options, entityName, domainLibFolderPath, worksp
182238
entityName,
183239
domainLibFolderPath,
184240
featureLibFolderPath,
185-
tmpl
241+
tmpl,
186242
};
187243

188244
if (options.ngrx && entityName) {
@@ -192,16 +248,14 @@ function generate(tree: Tree, { options, entityName, domainLibFolderPath, worksp
192248
domainLibFolderPath,
193249
params
194250
);
195-
}
196-
else if (!options.ngrx && entityName) {
251+
} else if (!options.ngrx && entityName) {
197252
generateFiles(
198253
tree,
199254
joinPathFragments(__dirname, './files/forDomain'),
200255
domainLibFolderPath,
201256
params
202257
);
203-
}
204-
else if (!options.ngrx && !entityName) {
258+
} else if (!options.ngrx && !entityName) {
205259
generateFiles(
206260
tree,
207261
joinPathFragments(__dirname, './files/forDomain/application'),
@@ -217,8 +271,7 @@ function generate(tree: Tree, { options, entityName, domainLibFolderPath, worksp
217271
featureLibFolderPath,
218272
params
219273
);
220-
}
221-
else if (!options.ngrx) {
274+
} else if (!options.ngrx) {
222275
generateFiles(
223276
tree,
224277
joinPathFragments(__dirname, './files/forFeature'),

libs/ddd/src/generators/feature/schema.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"type": "string",
5353
"enum": ["internal", "buildable", "publishable"],
5454
"description": "A type to determine if and how to build the library.",
55-
"default": "buildable"
55+
"default": "internal"
5656
},
5757
"importPath": {
5858
"type": "string",
@@ -67,6 +67,11 @@
6767
"type": "boolean",
6868
"default": false,
6969
"description": "Don't connect the feature lib to an app"
70+
},
71+
"standalone": {
72+
"type": "boolean",
73+
"default": false,
74+
"description": "Use standalone components?"
7075
}
7176
},
7277
"required": ["name", "domain"]

libs/ddd/src/generators/feature/schema.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,8 @@ export interface FeatureOptions {
5858
* Add ngrx for the domain (entity required)
5959
*/
6060
ngrx?: boolean;
61+
62+
standalone: boolean;
63+
6164
[k: string]: any;
6265
}

0 commit comments

Comments
 (0)