@ngflow/ng-architect 1.1.3 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ng-architect/component/index.js +48 -3
- package/src/ng-architect/component/index.js.map +1 -1
- package/src/ng-architect/component/index.ts +56 -5
- package/src/ng-architect/component/schema.json +9 -9
- package/src/ng-architect/feature/index.js +62 -18
- package/src/ng-architect/feature/index.js.map +1 -1
- package/src/ng-architect/feature/index.ts +71 -25
- package/src/ng-architect/feature/schema.json +26 -4
- package/src/ng-architect/service/index.js +47 -3
- package/src/ng-architect/service/index.js.map +1 -1
- package/src/ng-architect/service/index.ts +57 -6
- package/src/ng-architect/service/schema.json +9 -9
- package/src/ng-architect/utils/routes-utils.js +61 -0
- package/src/ng-architect/utils/routes-utils.js.map +1 -0
- package/src/ng-architect/utils/routes-utils.ts +74 -0
package/package.json
CHANGED
|
@@ -3,17 +3,62 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = default_1;
|
|
4
4
|
const schematics_1 = require("@angular-devkit/schematics");
|
|
5
5
|
const string_utils_1 = require("../utils/string-utils");
|
|
6
|
+
const routes_utils_1 = require("../utils/routes-utils");
|
|
6
7
|
function default_1(options) {
|
|
7
8
|
const componentKebab = (0, string_utils_1.toKebabCase)(options.name);
|
|
8
9
|
const componentPascal = (0, string_utils_1.toPascalCase)(options.name);
|
|
10
|
+
let basePath;
|
|
11
|
+
let subFolders = [];
|
|
12
|
+
switch (options.structure) {
|
|
13
|
+
case 'flat':
|
|
14
|
+
basePath = `src/app/${componentKebab}`;
|
|
15
|
+
break;
|
|
16
|
+
case 'domain-driven':
|
|
17
|
+
basePath = `src/app/features/${componentKebab}`;
|
|
18
|
+
subFolders = ['pages', 'data', 'models'];
|
|
19
|
+
break;
|
|
20
|
+
case 'module-driven':
|
|
21
|
+
if (!options.module)
|
|
22
|
+
throw new Error('module-driven requires --module=<moduleName>');
|
|
23
|
+
basePath = `src/app/${options.module}/${componentKebab}`;
|
|
24
|
+
subFolders = ['pages', 'data', 'models'];
|
|
25
|
+
break;
|
|
26
|
+
case 'monorepo':
|
|
27
|
+
if (!options.app && !options.lib)
|
|
28
|
+
throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
|
|
29
|
+
basePath = options.app
|
|
30
|
+
? `apps/${options.app}/src/app/${componentKebab}`
|
|
31
|
+
: `libs/${options.lib}/src/lib/${componentKebab}`;
|
|
32
|
+
subFolders = ['pages', 'data', 'models'];
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Invalid structure: ${options.structure}`);
|
|
36
|
+
}
|
|
9
37
|
return (0, schematics_1.chain)([
|
|
10
38
|
(_tree, context) => {
|
|
11
|
-
context.logger.info(
|
|
39
|
+
context.logger.info(`🟢 Creating component: ${componentPascal} (${componentKebab})`);
|
|
40
|
+
context.logger.info(`Structure: ${options.structure}`);
|
|
12
41
|
},
|
|
13
42
|
(0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [
|
|
14
43
|
(0, schematics_1.template)({ componentKebab, componentPascal, module: options.module }),
|
|
15
|
-
(0, schematics_1.move)(
|
|
16
|
-
]))
|
|
44
|
+
(0, schematics_1.move)(basePath),
|
|
45
|
+
])),
|
|
46
|
+
(_tree, context) => {
|
|
47
|
+
// Atualiza app.routes.ts apenas se tiver pages
|
|
48
|
+
if (subFolders.includes('pages')) {
|
|
49
|
+
context.logger.info(`🟢 Updating app.routes.ts with ${componentPascal}Page...`);
|
|
50
|
+
(0, routes_utils_1.updateAppRoutes)(_tree, componentKebab, componentPascal, options.structure, options);
|
|
51
|
+
}
|
|
52
|
+
// Cria subpastas e barrels
|
|
53
|
+
subFolders.forEach((folder) => {
|
|
54
|
+
const folderPath = `${basePath}/${folder}`;
|
|
55
|
+
if (!_tree.exists(folderPath))
|
|
56
|
+
_tree.create(folderPath + '/.gitkeep', '');
|
|
57
|
+
if (!_tree.exists(`${folderPath}/index.ts`))
|
|
58
|
+
_tree.create(`${folderPath}/index.ts`, '');
|
|
59
|
+
});
|
|
60
|
+
return _tree;
|
|
61
|
+
},
|
|
17
62
|
]);
|
|
18
63
|
}
|
|
19
64
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,24 +7,75 @@ import {
|
|
|
7
7
|
mergeWith,
|
|
8
8
|
move,
|
|
9
9
|
template,
|
|
10
|
-
url
|
|
10
|
+
url,
|
|
11
11
|
} from '@angular-devkit/schematics';
|
|
12
12
|
import { toKebabCase, toPascalCase } from '../utils/string-utils';
|
|
13
|
+
import { updateAppRoutes } from '../utils/routes-utils';
|
|
13
14
|
|
|
14
15
|
export default function(options: any): Rule {
|
|
15
16
|
const componentKebab = toKebabCase(options.name);
|
|
16
17
|
const componentPascal = toPascalCase(options.name);
|
|
17
18
|
|
|
19
|
+
let basePath: string;
|
|
20
|
+
let subFolders: string[] = [];
|
|
21
|
+
|
|
22
|
+
switch (options.structure) {
|
|
23
|
+
case 'flat':
|
|
24
|
+
basePath = `src/app/${componentKebab}`;
|
|
25
|
+
break;
|
|
26
|
+
|
|
27
|
+
case 'domain-driven':
|
|
28
|
+
basePath = `src/app/features/${componentKebab}`;
|
|
29
|
+
subFolders = ['pages', 'data', 'models'];
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
case 'module-driven':
|
|
33
|
+
if (!options.module) throw new Error('module-driven requires --module=<moduleName>');
|
|
34
|
+
basePath = `src/app/${options.module}/${componentKebab}`;
|
|
35
|
+
subFolders = ['pages', 'data', 'models'];
|
|
36
|
+
break;
|
|
37
|
+
|
|
38
|
+
case 'monorepo':
|
|
39
|
+
if (!options.app && !options.lib)
|
|
40
|
+
throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
|
|
41
|
+
basePath = options.app
|
|
42
|
+
? `apps/${options.app}/src/app/${componentKebab}`
|
|
43
|
+
: `libs/${options.lib}/src/lib/${componentKebab}`;
|
|
44
|
+
subFolders = ['pages', 'data', 'models'];
|
|
45
|
+
break;
|
|
46
|
+
|
|
47
|
+
default:
|
|
48
|
+
throw new Error(`Invalid structure: ${options.structure}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
18
51
|
return chain([
|
|
19
52
|
(_tree: Tree, context: SchematicContext) => {
|
|
20
|
-
context.logger.info(
|
|
53
|
+
context.logger.info(`🟢 Creating component: ${componentPascal} (${componentKebab})`);
|
|
54
|
+
context.logger.info(`Structure: ${options.structure}`);
|
|
21
55
|
},
|
|
56
|
+
|
|
22
57
|
mergeWith(
|
|
23
58
|
apply(url('./files'), [
|
|
24
59
|
template({ componentKebab, componentPascal, module: options.module }),
|
|
25
|
-
move(
|
|
26
|
-
|
|
60
|
+
move(basePath),
|
|
27
61
|
])
|
|
28
|
-
)
|
|
62
|
+
),
|
|
63
|
+
|
|
64
|
+
(_tree: Tree, context: SchematicContext) => {
|
|
65
|
+
// Atualiza app.routes.ts apenas se tiver pages
|
|
66
|
+
if (subFolders.includes('pages')) {
|
|
67
|
+
context.logger.info(`🟢 Updating app.routes.ts with ${componentPascal}Page...`);
|
|
68
|
+
updateAppRoutes(_tree, componentKebab, componentPascal, options.structure, options);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Cria subpastas e barrels
|
|
72
|
+
subFolders.forEach((folder) => {
|
|
73
|
+
const folderPath = `${basePath}/${folder}`;
|
|
74
|
+
if (!_tree.exists(folderPath)) _tree.create(folderPath + '/.gitkeep', '');
|
|
75
|
+
if (!_tree.exists(`${folderPath}/index.ts`)) _tree.create(`${folderPath}/index.ts`, '');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return _tree;
|
|
79
|
+
},
|
|
29
80
|
]);
|
|
30
81
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "
|
|
3
|
+
"$id": "NgArchitectComponentSchema",
|
|
4
4
|
"title": "Angular Component Generator",
|
|
5
5
|
"description": "Generates a reusable Angular component",
|
|
6
|
-
|
|
6
|
+
"type": "object",
|
|
7
7
|
"properties": {
|
|
8
|
-
"name": {
|
|
8
|
+
"name": { "type": "string", "description": "Component name" },
|
|
9
|
+
"structure": {
|
|
9
10
|
"type": "string",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
11
|
+
"enum": ["flat", "domain-driven", "module-driven", "monorepo"],
|
|
12
|
+
"default": "domain-driven"
|
|
12
13
|
},
|
|
13
|
-
"module": {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
14
|
+
"module": { "type": "string", "description": "Module name (for module-driven structure)" },
|
|
15
|
+
"app": { "type": "string", "description": "App name (for monorepo)" },
|
|
16
|
+
"lib": { "type": "string", "description": "Lib name (for monorepo)" }
|
|
17
17
|
},
|
|
18
18
|
"required": ["name"]
|
|
19
19
|
}
|
|
@@ -3,31 +3,75 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = default_1;
|
|
4
4
|
const schematics_1 = require("@angular-devkit/schematics");
|
|
5
5
|
const string_utils_1 = require("../utils/string-utils");
|
|
6
|
-
const
|
|
6
|
+
const routes_utils_1 = require("../utils/routes-utils");
|
|
7
7
|
function default_1(options) {
|
|
8
8
|
const featureKebab = (0, string_utils_1.toKebabCase)(options.name);
|
|
9
9
|
const featurePascal = (0, string_utils_1.toPascalCase)(options.name);
|
|
10
|
+
let basePath;
|
|
11
|
+
let subFolders = [];
|
|
12
|
+
switch (options.structure) {
|
|
13
|
+
case 'flat':
|
|
14
|
+
basePath = `src/app/${featureKebab}`;
|
|
15
|
+
break;
|
|
16
|
+
case 'domain-driven':
|
|
17
|
+
basePath = `src/app/features/${featureKebab}`;
|
|
18
|
+
subFolders = ['pages', 'data', 'models'];
|
|
19
|
+
break;
|
|
20
|
+
case 'module-driven':
|
|
21
|
+
if (!options.module)
|
|
22
|
+
throw new Error('module-driven requires --module=<moduleName>');
|
|
23
|
+
basePath = `src/app/${options.module}/${featureKebab}`;
|
|
24
|
+
subFolders = ['pages', 'data', 'models'];
|
|
25
|
+
break;
|
|
26
|
+
case 'monorepo':
|
|
27
|
+
if (!options.app && !options.lib)
|
|
28
|
+
throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
|
|
29
|
+
basePath = options.app
|
|
30
|
+
? `apps/${options.app}/src/app/${featureKebab}`
|
|
31
|
+
: `libs/${options.lib}/src/lib/${featureKebab}`;
|
|
32
|
+
subFolders = ['pages', 'data', 'models'];
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Invalid structure: ${options.structure}`);
|
|
36
|
+
}
|
|
10
37
|
return (0, schematics_1.chain)([
|
|
11
|
-
// Log inicial
|
|
12
38
|
(_tree, context) => {
|
|
13
|
-
context.logger.info(
|
|
39
|
+
context.logger.info(`🟢 Creating feature: ${featurePascal} (${featureKebab})`);
|
|
40
|
+
context.logger.info(`Structure: ${options.structure}`);
|
|
14
41
|
},
|
|
15
|
-
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
(0,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
(0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [(0, schematics_1.template)({ featureKebab, featurePascal }), (0, schematics_1.move)(basePath)])),
|
|
43
|
+
(_tree, context) => {
|
|
44
|
+
context.logger.info(`🟢 Updating app.routes.ts with ${featurePascal}Page...`);
|
|
45
|
+
(0, routes_utils_1.updateAppRoutes)(_tree, featureKebab, featurePascal, options.structure, options);
|
|
46
|
+
},
|
|
47
|
+
(_tree) => {
|
|
48
|
+
// Cria subpastas e barrels
|
|
49
|
+
subFolders.forEach((folder) => {
|
|
50
|
+
const folderPath = `${basePath}/${folder}`;
|
|
51
|
+
if (!_tree.exists(folderPath))
|
|
52
|
+
_tree.create(folderPath + '/.gitkeep', '');
|
|
53
|
+
// Gera barrel index.ts automaticamente
|
|
54
|
+
const files = _tree.getDir(folderPath).subfiles.filter(f => f.endsWith('.ts'));
|
|
55
|
+
const barrelContent = files.map(f => {
|
|
56
|
+
const name = f.replace('.ts', '');
|
|
57
|
+
return `export * from './${name}';`;
|
|
58
|
+
}).join('\n');
|
|
59
|
+
if (!_tree.exists(`${folderPath}/index.ts`)) {
|
|
60
|
+
_tree.create(`${folderPath}/index.ts`, barrelContent);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Se já existe index.ts, adiciona novos exports sem duplicar
|
|
64
|
+
const existing = _tree.read(`${folderPath}/index.ts`).toString('utf-8');
|
|
65
|
+
const newExports = files
|
|
66
|
+
.map(f => `export * from './${f.replace('.ts', '')}';`)
|
|
67
|
+
.filter(line => !existing.includes(line))
|
|
68
|
+
.join('\n');
|
|
69
|
+
if (newExports)
|
|
70
|
+
_tree.overwrite(`${folderPath}/index.ts`, existing + '\n' + newExports);
|
|
71
|
+
}
|
|
28
72
|
});
|
|
29
|
-
return
|
|
30
|
-
}
|
|
73
|
+
return _tree;
|
|
74
|
+
},
|
|
31
75
|
]);
|
|
32
76
|
}
|
|
33
77
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;AAcA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,44 +4,90 @@ import {
|
|
|
4
4
|
Tree,
|
|
5
5
|
apply,
|
|
6
6
|
chain,
|
|
7
|
-
filter,
|
|
8
7
|
mergeWith,
|
|
8
|
+
move,
|
|
9
9
|
template,
|
|
10
|
-
url
|
|
10
|
+
url,
|
|
11
11
|
} from '@angular-devkit/schematics';
|
|
12
12
|
import { toKebabCase, toPascalCase } from '../utils/string-utils';
|
|
13
|
-
import {
|
|
13
|
+
import { updateAppRoutes } from '../utils/routes-utils';
|
|
14
14
|
|
|
15
|
-
export default function (options:
|
|
15
|
+
export default function (options: any): Rule {
|
|
16
16
|
const featureKebab = toKebabCase(options.name);
|
|
17
17
|
const featurePascal = toPascalCase(options.name);
|
|
18
18
|
|
|
19
|
+
let basePath: string;
|
|
20
|
+
let subFolders: string[] = [];
|
|
21
|
+
|
|
22
|
+
switch (options.structure) {
|
|
23
|
+
case 'flat':
|
|
24
|
+
basePath = `src/app/${featureKebab}`;
|
|
25
|
+
break;
|
|
26
|
+
|
|
27
|
+
case 'domain-driven':
|
|
28
|
+
basePath = `src/app/features/${featureKebab}`;
|
|
29
|
+
subFolders = ['pages', 'data', 'models'];
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
case 'module-driven':
|
|
33
|
+
if (!options.module) throw new Error('module-driven requires --module=<moduleName>');
|
|
34
|
+
basePath = `src/app/${options.module}/${featureKebab}`;
|
|
35
|
+
subFolders = ['pages', 'data', 'models'];
|
|
36
|
+
break;
|
|
37
|
+
|
|
38
|
+
case 'monorepo':
|
|
39
|
+
if (!options.app && !options.lib)
|
|
40
|
+
throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
|
|
41
|
+
basePath = options.app
|
|
42
|
+
? `apps/${options.app}/src/app/${featureKebab}`
|
|
43
|
+
: `libs/${options.lib}/src/lib/${featureKebab}`;
|
|
44
|
+
subFolders = ['pages', 'data', 'models'];
|
|
45
|
+
break;
|
|
46
|
+
|
|
47
|
+
default:
|
|
48
|
+
throw new Error(`Invalid structure: ${options.structure}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
19
51
|
return chain([
|
|
20
|
-
// Log inicial
|
|
21
52
|
(_tree: Tree, context: SchematicContext) => {
|
|
22
|
-
context.logger.info(
|
|
53
|
+
context.logger.info(`🟢 Creating feature: ${featurePascal} (${featureKebab})`);
|
|
54
|
+
context.logger.info(`Structure: ${options.structure}`);
|
|
23
55
|
},
|
|
24
56
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
57
|
+
mergeWith(apply(url('./files'), [template({ featureKebab, featurePascal }), move(basePath)])),
|
|
58
|
+
|
|
59
|
+
(_tree: Tree, context: SchematicContext) => {
|
|
60
|
+
context.logger.info(`🟢 Updating app.routes.ts with ${featurePascal}Page...`);
|
|
61
|
+
updateAppRoutes(_tree, featureKebab, featurePascal, options.structure, options);
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
(_tree: Tree) => {
|
|
65
|
+
// Cria subpastas e barrels
|
|
66
|
+
subFolders.forEach((folder) => {
|
|
67
|
+
const folderPath = `${basePath}/${folder}`;
|
|
68
|
+
if (!_tree.exists(folderPath)) _tree.create(folderPath + '/.gitkeep', '');
|
|
69
|
+
|
|
70
|
+
// Gera barrel index.ts automaticamente
|
|
71
|
+
const files = _tree.getDir(folderPath).subfiles.filter(f => f.endsWith('.ts'));
|
|
72
|
+
const barrelContent = files.map(f => {
|
|
73
|
+
const name = f.replace('.ts', '');
|
|
74
|
+
return `export * from './${name}';`;
|
|
75
|
+
}).join('\n');
|
|
76
|
+
|
|
77
|
+
if (!_tree.exists(`${folderPath}/index.ts`)) {
|
|
78
|
+
_tree.create(`${folderPath}/index.ts`, barrelContent);
|
|
79
|
+
} else {
|
|
80
|
+
// Se já existe index.ts, adiciona novos exports sem duplicar
|
|
81
|
+
const existing = _tree.read(`${folderPath}/index.ts`)!.toString('utf-8');
|
|
82
|
+
const newExports = files
|
|
83
|
+
.map(f => `export * from './${f.replace('.ts','')}';`)
|
|
84
|
+
.filter(line => !existing.includes(line))
|
|
85
|
+
.join('\n');
|
|
86
|
+
if (newExports) _tree.overwrite(`${folderPath}/index.ts`, existing + '\n' + newExports);
|
|
87
|
+
}
|
|
42
88
|
});
|
|
43
89
|
|
|
44
|
-
return
|
|
45
|
-
}
|
|
90
|
+
return _tree;
|
|
91
|
+
},
|
|
46
92
|
]);
|
|
47
93
|
}
|
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "
|
|
3
|
+
"$id": "NgArchitectFeatureSchema",
|
|
4
4
|
"title": "Angular Feature Generator",
|
|
5
5
|
"description": "Generates a complete Angular feature with pages, services, store, models and routes",
|
|
6
|
-
|
|
6
|
+
"type": "object",
|
|
7
7
|
"properties": {
|
|
8
8
|
"name": {
|
|
9
9
|
"type": "string",
|
|
10
|
-
"description": "
|
|
11
|
-
|
|
10
|
+
"description": "Feature name"
|
|
11
|
+
},
|
|
12
|
+
"structure": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"enum": ["flat", "domain-driven", "module-driven", "monorepo"],
|
|
15
|
+
"default": "domain-driven",
|
|
16
|
+
"description": "Project structure for feature"
|
|
17
|
+
},
|
|
18
|
+
"module": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Module name (required for module-driven structure)"
|
|
21
|
+
},
|
|
22
|
+
"app": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "App name (required for monorepo app structure)"
|
|
25
|
+
},
|
|
26
|
+
"lib": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Lib name (required for monorepo lib structure)"
|
|
29
|
+
},
|
|
30
|
+
"store": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"description": "Generate store for feature",
|
|
33
|
+
"default": false
|
|
12
34
|
}
|
|
13
35
|
},
|
|
14
36
|
"required": ["name"]
|
|
@@ -6,14 +6,58 @@ const string_utils_1 = require("../utils/string-utils");
|
|
|
6
6
|
function default_1(options) {
|
|
7
7
|
const serviceKebab = (0, string_utils_1.toKebabCase)(options.name);
|
|
8
8
|
const servicePascal = (0, string_utils_1.toPascalCase)(options.name);
|
|
9
|
+
let basePath;
|
|
10
|
+
switch (options.structure) {
|
|
11
|
+
case 'flat':
|
|
12
|
+
basePath = `src/app/${serviceKebab}`;
|
|
13
|
+
break;
|
|
14
|
+
case 'domain-driven':
|
|
15
|
+
basePath = `src/app/features/${serviceKebab}/data`;
|
|
16
|
+
break;
|
|
17
|
+
case 'module-driven':
|
|
18
|
+
if (!options.module)
|
|
19
|
+
throw new Error('module-driven requires --module=<moduleName>');
|
|
20
|
+
basePath = `src/app/${options.module}/${serviceKebab}/data`;
|
|
21
|
+
break;
|
|
22
|
+
case 'monorepo':
|
|
23
|
+
if (!options.app && !options.lib)
|
|
24
|
+
throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
|
|
25
|
+
basePath = options.app
|
|
26
|
+
? `apps/${options.app}/src/app/${serviceKebab}/data`
|
|
27
|
+
: `libs/${options.lib}/src/lib/${serviceKebab}/data`;
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
throw new Error(`Invalid structure: ${options.structure}`);
|
|
31
|
+
}
|
|
9
32
|
return (0, schematics_1.chain)([
|
|
10
33
|
(_tree, context) => {
|
|
11
|
-
context.logger.info(
|
|
34
|
+
context.logger.info(`🟢 Creating service: ${servicePascal} (${serviceKebab})`);
|
|
12
35
|
},
|
|
13
36
|
(0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [
|
|
14
37
|
(0, schematics_1.template)({ serviceKebab, servicePascal, store: options.store }),
|
|
15
|
-
(0, schematics_1.move)(
|
|
16
|
-
]))
|
|
38
|
+
(0, schematics_1.move)(basePath),
|
|
39
|
+
])),
|
|
40
|
+
(_tree) => {
|
|
41
|
+
// Criar barrel index.ts automático na pasta do serviço
|
|
42
|
+
const dir = _tree.getDir(basePath);
|
|
43
|
+
const tsFiles = dir.subfiles.filter(f => f.endsWith('.ts') && f !== 'index.ts');
|
|
44
|
+
if (tsFiles.length) {
|
|
45
|
+
const barrelContent = tsFiles.map(f => `export * from './${f.replace('.ts', '')}';`).join('\n');
|
|
46
|
+
if (!_tree.exists(`${basePath}/index.ts`)) {
|
|
47
|
+
_tree.create(`${basePath}/index.ts`, barrelContent);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const existing = _tree.read(`${basePath}/index.ts`).toString('utf-8');
|
|
51
|
+
const newExports = tsFiles
|
|
52
|
+
.map(f => `export * from './${f.replace('.ts', '')}';`)
|
|
53
|
+
.filter(line => !existing.includes(line))
|
|
54
|
+
.join('\n');
|
|
55
|
+
if (newExports)
|
|
56
|
+
_tree.overwrite(`${basePath}/index.ts`, existing + '\n' + newExports);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return _tree;
|
|
60
|
+
},
|
|
17
61
|
]);
|
|
18
62
|
}
|
|
19
63
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;AAaA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;AAaA,4BAkEC;AA/ED,2DAUoC;AACpC,wDAAkE;AAElE,mBAAwB,OAAY;IAClC,MAAM,YAAY,GAAG,IAAA,0BAAW,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,aAAa,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD,IAAI,QAAgB,CAAC;IAErB,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;QAC1B,KAAK,MAAM;YACT,QAAQ,GAAG,WAAW,YAAY,EAAE,CAAC;YACrC,MAAM;QAER,KAAK,eAAe;YAClB,QAAQ,GAAG,oBAAoB,YAAY,OAAO,CAAC;YACnD,MAAM;QAER,KAAK,eAAe;YAClB,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YACrF,QAAQ,GAAG,WAAW,OAAO,CAAC,MAAM,IAAI,YAAY,OAAO,CAAC;YAC5D,MAAM;QAER,KAAK,UAAU;YACb,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG;gBAC9B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC1E,QAAQ,GAAG,OAAO,CAAC,GAAG;gBACpB,CAAC,CAAC,QAAQ,OAAO,CAAC,GAAG,YAAY,YAAY,OAAO;gBACpD,CAAC,CAAC,QAAQ,OAAO,CAAC,GAAG,YAAY,YAAY,OAAO,CAAC;YACvD,MAAM;QAER;YACE,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,IAAA,kBAAK,EAAC;QACX,CAAC,KAAW,EAAE,OAAyB,EAAE,EAAE;YACzC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,aAAa,KAAK,YAAY,GAAG,CAAC,CAAC;QACjF,CAAC;QAED,IAAA,sBAAS,EACP,IAAA,kBAAK,EAAC,IAAA,gBAAG,EAAC,SAAS,CAAC,EAAE;YACpB,IAAA,qBAAQ,EAAC,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;YAC/D,IAAA,iBAAI,EAAC,QAAQ,CAAC;SACf,CAAC,CACH;QAED,CAAC,KAAW,EAAE,EAAE;YACd,uDAAuD;YACvD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC;YAEhF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/F,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,QAAQ,WAAW,CAAC,EAAE,CAAC;oBAC1C,KAAK,CAAC,MAAM,CAAC,GAAG,QAAQ,WAAW,EAAE,aAAa,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,WAAW,CAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBACvE,MAAM,UAAU,GAAG,OAAO;yBACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAC,EAAE,CAAC,IAAI,CAAC;yBACrD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;yBACxC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACd,IAAI,UAAU;wBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,QAAQ,WAAW,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,CAAC,CAAC;gBACxF,CAAC;YACH,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
apply,
|
|
6
6
|
chain,
|
|
7
7
|
mergeWith,
|
|
8
|
+
move,
|
|
8
9
|
template,
|
|
9
|
-
url
|
|
10
|
-
move
|
|
10
|
+
url
|
|
11
11
|
} from '@angular-devkit/schematics';
|
|
12
12
|
import { toKebabCase, toPascalCase } from '../utils/string-utils';
|
|
13
13
|
|
|
@@ -15,15 +15,66 @@ export default function(options: any): Rule {
|
|
|
15
15
|
const serviceKebab = toKebabCase(options.name);
|
|
16
16
|
const servicePascal = toPascalCase(options.name);
|
|
17
17
|
|
|
18
|
+
let basePath: string;
|
|
19
|
+
|
|
20
|
+
switch (options.structure) {
|
|
21
|
+
case 'flat':
|
|
22
|
+
basePath = `src/app/${serviceKebab}`;
|
|
23
|
+
break;
|
|
24
|
+
|
|
25
|
+
case 'domain-driven':
|
|
26
|
+
basePath = `src/app/features/${serviceKebab}/data`;
|
|
27
|
+
break;
|
|
28
|
+
|
|
29
|
+
case 'module-driven':
|
|
30
|
+
if (!options.module) throw new Error('module-driven requires --module=<moduleName>');
|
|
31
|
+
basePath = `src/app/${options.module}/${serviceKebab}/data`;
|
|
32
|
+
break;
|
|
33
|
+
|
|
34
|
+
case 'monorepo':
|
|
35
|
+
if (!options.app && !options.lib)
|
|
36
|
+
throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
|
|
37
|
+
basePath = options.app
|
|
38
|
+
? `apps/${options.app}/src/app/${serviceKebab}/data`
|
|
39
|
+
: `libs/${options.lib}/src/lib/${serviceKebab}/data`;
|
|
40
|
+
break;
|
|
41
|
+
|
|
42
|
+
default:
|
|
43
|
+
throw new Error(`Invalid structure: ${options.structure}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
18
46
|
return chain([
|
|
19
47
|
(_tree: Tree, context: SchematicContext) => {
|
|
20
|
-
context.logger.info(
|
|
48
|
+
context.logger.info(`🟢 Creating service: ${servicePascal} (${serviceKebab})`);
|
|
21
49
|
},
|
|
50
|
+
|
|
22
51
|
mergeWith(
|
|
23
52
|
apply(url('./files'), [
|
|
24
53
|
template({ serviceKebab, servicePascal, store: options.store }),
|
|
25
|
-
move(
|
|
54
|
+
move(basePath),
|
|
26
55
|
])
|
|
27
|
-
)
|
|
28
|
-
|
|
56
|
+
),
|
|
57
|
+
|
|
58
|
+
(_tree: Tree) => {
|
|
59
|
+
// Criar barrel index.ts automático na pasta do serviço
|
|
60
|
+
const dir = _tree.getDir(basePath);
|
|
61
|
+
const tsFiles = dir.subfiles.filter(f => f.endsWith('.ts') && f !== 'index.ts');
|
|
62
|
+
|
|
63
|
+
if (tsFiles.length) {
|
|
64
|
+
const barrelContent = tsFiles.map(f => `export * from './${f.replace('.ts','')}';`).join('\n');
|
|
65
|
+
if (!_tree.exists(`${basePath}/index.ts`)) {
|
|
66
|
+
_tree.create(`${basePath}/index.ts`, barrelContent);
|
|
67
|
+
} else {
|
|
68
|
+
const existing = _tree.read(`${basePath}/index.ts`)!.toString('utf-8');
|
|
69
|
+
const newExports = tsFiles
|
|
70
|
+
.map(f => `export * from './${f.replace('.ts','')}';`)
|
|
71
|
+
.filter(line => !existing.includes(line))
|
|
72
|
+
.join('\n');
|
|
73
|
+
if (newExports) _tree.overwrite(`${basePath}/index.ts`, existing + '\n' + newExports);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return _tree;
|
|
78
|
+
},
|
|
79
|
+
]);
|
|
29
80
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "
|
|
3
|
+
"$id": "NgArchitectServiceSchema",
|
|
4
4
|
"title": "Angular Service Generator",
|
|
5
5
|
"description": "Generates an Angular service with optional store and tests",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|
|
8
|
-
"name": {
|
|
8
|
+
"name": { "type": "string", "description": "Service name" },
|
|
9
|
+
"structure": {
|
|
9
10
|
"type": "string",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
11
|
+
"enum": ["flat", "domain-driven", "module-driven", "monorepo"],
|
|
12
|
+
"default": "domain-driven"
|
|
12
13
|
},
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
14
|
+
"module": { "type": "string", "description": "Module name (for module-driven structure)" },
|
|
15
|
+
"app": { "type": "string", "description": "App name (for monorepo)" },
|
|
16
|
+
"lib": { "type": "string", "description": "Lib name (for monorepo)" },
|
|
17
|
+
"store": { "type": "boolean", "description": "Generate store for service", "default": false }
|
|
18
18
|
},
|
|
19
19
|
"required": ["name"]
|
|
20
20
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateAppRoutes = updateAppRoutes;
|
|
4
|
+
function updateAppRoutes(tree, featureKebab, featurePascal, structure, options) {
|
|
5
|
+
var _a;
|
|
6
|
+
let routesFilePath = '';
|
|
7
|
+
// Determina o caminho do arquivo de rotas
|
|
8
|
+
switch (structure) {
|
|
9
|
+
case 'flat':
|
|
10
|
+
case 'domain-driven':
|
|
11
|
+
case 'module-driven':
|
|
12
|
+
routesFilePath = 'src/app/app.routes.ts';
|
|
13
|
+
break;
|
|
14
|
+
case 'monorepo':
|
|
15
|
+
if (options.app) {
|
|
16
|
+
routesFilePath = `apps/${options.app}/src/app/app.routes.ts`;
|
|
17
|
+
}
|
|
18
|
+
else if (options.lib) {
|
|
19
|
+
// libs normalmente não têm routes.ts global
|
|
20
|
+
routesFilePath = `libs/${options.lib}/src/lib/lib.routes.ts`;
|
|
21
|
+
if (!tree.exists(routesFilePath)) {
|
|
22
|
+
tree.create(routesFilePath, `import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
throw new Error(`Invalid structure: ${structure}`);
|
|
28
|
+
}
|
|
29
|
+
// Criar arquivo se não existir
|
|
30
|
+
if (!tree.exists(routesFilePath)) {
|
|
31
|
+
tree.create(routesFilePath, `import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n`);
|
|
32
|
+
}
|
|
33
|
+
let content = ((_a = tree.read(routesFilePath)) === null || _a === void 0 ? void 0 : _a.toString('utf-8')) || '';
|
|
34
|
+
// Gerar import path
|
|
35
|
+
const importPath = (() => {
|
|
36
|
+
switch (structure) {
|
|
37
|
+
case 'flat':
|
|
38
|
+
return `./${featureKebab}/${featureKebab}.page`;
|
|
39
|
+
case 'domain-driven':
|
|
40
|
+
return `./features/${featureKebab}/pages/${featureKebab}.page`;
|
|
41
|
+
case 'module-driven':
|
|
42
|
+
return `./${options.module}/${featureKebab}/pages/${featureKebab}.page`;
|
|
43
|
+
case 'monorepo':
|
|
44
|
+
return `./${featureKebab}/pages/${featureKebab}.page`;
|
|
45
|
+
}
|
|
46
|
+
})();
|
|
47
|
+
const importStatement = `import { ${featurePascal}Page } from '${importPath}';\n`;
|
|
48
|
+
// Determinar rota (lazy-load para module/domain-driven)
|
|
49
|
+
const routeEntry = structure === 'module-driven' || structure === 'domain-driven'
|
|
50
|
+
? ` { path: '${featureKebab}', loadChildren: () => import('${importPath.replace('.page', '.module')}').then(m => m.${featurePascal}Module) },`
|
|
51
|
+
: ` { path: '${featureKebab}', component: ${featurePascal}Page },`;
|
|
52
|
+
// Evitar duplicação
|
|
53
|
+
if (!content.includes(importStatement)) {
|
|
54
|
+
content = importStatement + content;
|
|
55
|
+
}
|
|
56
|
+
if (!content.includes(routeEntry)) {
|
|
57
|
+
content = content.replace(/export const routes: Routes = \[/, (match) => match + '\n' + routeEntry);
|
|
58
|
+
}
|
|
59
|
+
tree.overwrite(routesFilePath, content);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=routes-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes-utils.js","sourceRoot":"","sources":["routes-utils.ts"],"names":[],"mappings":";;AAEA,0CAuEC;AAvED,SAAgB,eAAe,CAC7B,IAAU,EACV,YAAoB,EACpB,aAAqB,EACrB,SAAiB,EACjB,OAAY;;IAEZ,IAAI,cAAc,GAAW,EAAE,CAAC;IAEhC,0CAA0C;IAC1C,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC;QACZ,KAAK,eAAe,CAAC;QACrB,KAAK,eAAe;YAClB,cAAc,GAAG,uBAAuB,CAAC;YACzC,MAAM;QAER,KAAK,UAAU;YACb,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAChB,cAAc,GAAG,QAAQ,OAAO,CAAC,GAAG,wBAAwB,CAAC;YAC/D,CAAC;iBAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBACvB,4CAA4C;gBAC5C,cAAc,GAAG,QAAQ,OAAO,CAAC,GAAG,wBAAwB,CAAC;gBAC7D,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;oBACjC,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,kFAAkF,CAAC,CAAC;gBAClH,CAAC;YACH,CAAC;YACD,MAAM;QAER;YACE,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,+BAA+B;IAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,kFAAkF,CAAC,CAAC;IAClH,CAAC;IAED,IAAI,OAAO,GAAG,CAAA,MAAA,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,0CAAE,QAAQ,CAAC,OAAO,CAAC,KAAI,EAAE,CAAC;IAEjE,oBAAoB;IACpB,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE;QACvB,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,MAAM;gBACT,OAAO,KAAK,YAAY,IAAI,YAAY,OAAO,CAAC;YAClD,KAAK,eAAe;gBAClB,OAAO,cAAc,YAAY,UAAU,YAAY,OAAO,CAAC;YACjE,KAAK,eAAe;gBAClB,OAAO,KAAK,OAAO,CAAC,MAAM,IAAI,YAAY,UAAU,YAAY,OAAO,CAAC;YAC1E,KAAK,UAAU;gBACb,OAAO,KAAK,YAAY,UAAU,YAAY,OAAO,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,eAAe,GAAG,YAAY,aAAa,gBAAgB,UAAU,MAAM,CAAC;IAElF,wDAAwD;IACxD,MAAM,UAAU,GACd,SAAS,KAAK,eAAe,IAAI,SAAS,KAAK,eAAe;QAC5D,CAAC,CAAC,cAAc,YAAY,kCAAkC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,kBAAkB,aAAa,YAAY;QAC/I,CAAC,CAAC,cAAc,YAAY,iBAAiB,aAAa,SAAS,CAAC;IAExE,oBAAoB;IACpB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACvC,OAAO,GAAG,eAAe,GAAG,OAAO,CAAC;IACtC,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,kCAAkC,EAAE,CAAC,KAAY,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,GAAG,UAAU,CAAC,CAAC;IAC7G,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Tree } from '@angular-devkit/schematics';
|
|
2
|
+
|
|
3
|
+
export function updateAppRoutes(
|
|
4
|
+
tree: Tree,
|
|
5
|
+
featureKebab: string,
|
|
6
|
+
featurePascal: string,
|
|
7
|
+
structure: string,
|
|
8
|
+
options: any
|
|
9
|
+
) {
|
|
10
|
+
let routesFilePath: string = '';
|
|
11
|
+
|
|
12
|
+
// Determina o caminho do arquivo de rotas
|
|
13
|
+
switch (structure) {
|
|
14
|
+
case 'flat':
|
|
15
|
+
case 'domain-driven':
|
|
16
|
+
case 'module-driven':
|
|
17
|
+
routesFilePath = 'src/app/app.routes.ts';
|
|
18
|
+
break;
|
|
19
|
+
|
|
20
|
+
case 'monorepo':
|
|
21
|
+
if (options.app) {
|
|
22
|
+
routesFilePath = `apps/${options.app}/src/app/app.routes.ts`;
|
|
23
|
+
} else if (options.lib) {
|
|
24
|
+
// libs normalmente não têm routes.ts global
|
|
25
|
+
routesFilePath = `libs/${options.lib}/src/lib/lib.routes.ts`;
|
|
26
|
+
if (!tree.exists(routesFilePath)) {
|
|
27
|
+
tree.create(routesFilePath, `import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
default:
|
|
33
|
+
throw new Error(`Invalid structure: ${structure}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Criar arquivo se não existir
|
|
37
|
+
if (!tree.exists(routesFilePath)) {
|
|
38
|
+
tree.create(routesFilePath, `import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let content = tree.read(routesFilePath)?.toString('utf-8') || '';
|
|
42
|
+
|
|
43
|
+
// Gerar import path
|
|
44
|
+
const importPath = (() => {
|
|
45
|
+
switch (structure) {
|
|
46
|
+
case 'flat':
|
|
47
|
+
return `./${featureKebab}/${featureKebab}.page`;
|
|
48
|
+
case 'domain-driven':
|
|
49
|
+
return `./features/${featureKebab}/pages/${featureKebab}.page`;
|
|
50
|
+
case 'module-driven':
|
|
51
|
+
return `./${options.module}/${featureKebab}/pages/${featureKebab}.page`;
|
|
52
|
+
case 'monorepo':
|
|
53
|
+
return `./${featureKebab}/pages/${featureKebab}.page`;
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
|
|
57
|
+
const importStatement = `import { ${featurePascal}Page } from '${importPath}';\n`;
|
|
58
|
+
|
|
59
|
+
// Determinar rota (lazy-load para module/domain-driven)
|
|
60
|
+
const routeEntry =
|
|
61
|
+
structure === 'module-driven' || structure === 'domain-driven'
|
|
62
|
+
? ` { path: '${featureKebab}', loadChildren: () => import('${importPath.replace('.page', '.module')}').then(m => m.${featurePascal}Module) },`
|
|
63
|
+
: ` { path: '${featureKebab}', component: ${featurePascal}Page },`;
|
|
64
|
+
|
|
65
|
+
// Evitar duplicação
|
|
66
|
+
if (!content.includes(importStatement)) {
|
|
67
|
+
content = importStatement + content;
|
|
68
|
+
}
|
|
69
|
+
if (!content.includes(routeEntry)) {
|
|
70
|
+
content = content.replace(/export const routes: Routes = \[/, (match:string) => match + '\n' + routeEntry);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
tree.overwrite(routesFilePath, content);
|
|
74
|
+
}
|