@ngflow/ng-architect 1.2.5 โ†’ 1.2.7

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngflow/ng-architect",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Angular schematics to generate files and maintain clean architecture",
5
5
  "scripts": {
6
6
  "build": "tsc -p tsconfig.json",
@@ -7,77 +7,78 @@ const routes_utils_1 = require("../utils/routes-utils");
7
7
  const structure_resolver_1 = require("../utils/structure-resolver");
8
8
  const options_validator_1 = require("../utils/options-validator");
9
9
  function default_1(options) {
10
- const featureKebab = (0, string_utils_1.toKebabCase)(options.name);
11
- const featurePascal = (0, string_utils_1.toPascalCase)(options.name);
12
- let basePath;
13
- let subFolders = [];
14
- switch (options.structure) {
15
- case 'flat':
16
- basePath = `src/app/${featureKebab}`;
17
- break;
18
- case 'domain-driven':
19
- basePath = `src/app/features/${featureKebab}`;
20
- subFolders = ['pages', 'data', 'models'];
21
- break;
22
- case 'module-driven':
23
- if (!options.module)
24
- throw new Error('module-driven requires --module=<moduleName>');
25
- basePath = `src/app/${options.module}/${featureKebab}`;
26
- subFolders = ['pages', 'data', 'models'];
27
- break;
28
- case 'monorepo':
29
- if (!options.app && !options.lib)
30
- throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
31
- basePath = options.app
32
- ? `apps/${options.app}/src/app/${featureKebab}`
33
- : `libs/${options.lib}/src/lib/${featureKebab}`;
34
- subFolders = ['pages', 'data', 'models'];
35
- break;
36
- default:
37
- throw new Error(`Invalid structure: ${options.structure}`);
38
- }
39
- return (0, schematics_1.chain)([
40
- (tree, context) => {
41
- context.logger.info(`๐ŸŸข Creating feature: ${featurePascal} (${featureKebab})`);
42
- context.logger.info(`Structure: ${options.structure}`);
43
- const resolved = (0, structure_resolver_1.resolveStructure)(tree, options);
44
- options.structure = resolved;
45
- context.logger.info(`๐Ÿ“ Structure resolved to: ${resolved}`);
46
- (0, options_validator_1.validateOptions)(options, resolved);
47
- },
48
- (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [(0, schematics_1.template)({ featureKebab, featurePascal }), (0, schematics_1.move)(basePath)])),
49
- (_tree, context) => {
50
- context.logger.info(`๐ŸŸข Updating app.routes.ts with ${featurePascal}Page...`);
51
- (0, routes_utils_1.updateAppRoutes)(_tree, featureKebab, featurePascal, options.structure, options);
52
- },
53
- (_tree) => {
54
- // Cria subpastas e barrels
10
+ return (tree, context) => {
11
+ const featureKebab = (0, string_utils_1.toKebabCase)(options.name);
12
+ const featurePascal = (0, string_utils_1.toPascalCase)(options.name);
13
+ // ๐Ÿ”น Resolve auto-structure
14
+ const resolvedStructure = (0, structure_resolver_1.resolveStructure)(tree, options);
15
+ options.structure = resolvedStructure;
16
+ context.logger.info(`๐ŸŸข Creating feature: ${featurePascal} (${featureKebab})`);
17
+ context.logger.info(`๐Ÿ“ Structure resolved to: ${resolvedStructure}`);
18
+ // ๐Ÿ”น Validate options according to resolved structure
19
+ (0, options_validator_1.validateOptions)(options, resolvedStructure);
20
+ // ๐Ÿ”น Determine base path and subfolders
21
+ let basePath;
22
+ let subFolders = [];
23
+ switch (resolvedStructure) {
24
+ case 'flat':
25
+ basePath = `src/app/${featureKebab}`;
26
+ break;
27
+ case 'domain-driven':
28
+ basePath = `src/app/features/${featureKebab}`;
29
+ subFolders = ['pages', 'data', 'models'];
30
+ break;
31
+ case 'module-driven':
32
+ if (!options.module)
33
+ throw new Error('module-driven requires --module=<moduleName>');
34
+ basePath = `src/app/${options.module}/${featureKebab}`;
35
+ subFolders = ['pages', 'data', 'models'];
36
+ break;
37
+ case 'monorepo':
38
+ if (!options.app && !options.lib)
39
+ throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
40
+ basePath = options.app
41
+ ? `apps/${options.app}/src/app/${featureKebab}`
42
+ : `libs/${options.lib}/src/lib/${featureKebab}`;
43
+ subFolders = ['pages', 'data', 'models'];
44
+ break;
45
+ default:
46
+ throw new Error(`Invalid structure: ${resolvedStructure}`);
47
+ }
48
+ // ๐Ÿ”น Apply templates and move to proper folder
49
+ const templateRule = (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [(0, schematics_1.template)({ featureKebab, featurePascal }), (0, schematics_1.move)(basePath)]));
50
+ // ๐Ÿ”น Update app routes
51
+ const routesRule = (t, ctx) => {
52
+ ctx.logger.info(`๐ŸŸข Updating routes with ${featurePascal}Page...`);
53
+ (0, routes_utils_1.updateAppRoutes)(t, featureKebab, featurePascal, resolvedStructure, options);
54
+ return t;
55
+ };
56
+ // ๐Ÿ”น Create subfolders and barrels
57
+ const subFoldersRule = (t) => {
55
58
  subFolders.forEach((folder) => {
56
59
  const folderPath = `${basePath}/${folder}`;
57
- if (!_tree.exists(folderPath))
58
- _tree.create(folderPath + '/.gitkeep', '');
59
- // Gera barrel index.ts automaticamente
60
- const files = _tree.getDir(folderPath).subfiles.filter(f => f.endsWith('.ts'));
61
- const barrelContent = files.map(f => {
62
- const name = f.replace('.ts', '');
63
- return `export * from './${name}';`;
64
- }).join('\n');
65
- if (!_tree.exists(`${folderPath}/index.ts`)) {
66
- _tree.create(`${folderPath}/index.ts`, barrelContent);
60
+ if (!t.exists(folderPath))
61
+ t.create(folderPath + '/.gitkeep', '');
62
+ const files = t.getDir(folderPath).subfiles.filter((f) => f.endsWith('.ts'));
63
+ const barrelContent = files
64
+ .map((f) => `export * from './${f.replace('.ts', '')}';`)
65
+ .join('\n');
66
+ if (!t.exists(`${folderPath}/index.ts`)) {
67
+ t.create(`${folderPath}/index.ts`, barrelContent);
67
68
  }
68
69
  else {
69
- // Se jรก existe index.ts, adiciona novos exports sem duplicar
70
- const existing = _tree.read(`${folderPath}/index.ts`).toString('utf-8');
70
+ const existing = t.read(`${folderPath}/index.ts`).toString('utf-8');
71
71
  const newExports = files
72
- .map(f => `export * from './${f.replace('.ts', '')}';`)
73
- .filter(line => !existing.includes(line))
72
+ .map((f) => `export * from './${f.replace('.ts', '')}';`)
73
+ .filter((line) => !existing.includes(line))
74
74
  .join('\n');
75
75
  if (newExports)
76
- _tree.overwrite(`${folderPath}/index.ts`, existing + '\n' + newExports);
76
+ t.overwrite(`${folderPath}/index.ts`, existing + '\n' + newExports);
77
77
  }
78
78
  });
79
- return _tree;
80
- },
81
- ]);
79
+ return t;
80
+ };
81
+ return (0, schematics_1.chain)([templateRule, routesRule, subFoldersRule]);
82
+ };
82
83
  }
83
84
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
@@ -11,93 +11,95 @@ import {
11
11
  } from '@angular-devkit/schematics';
12
12
  import { toKebabCase, toPascalCase } from '../utils/string-utils';
13
13
  import { updateAppRoutes } from '../utils/routes-utils';
14
- import { resolveStructure } from '../utils/structure-resolver';
14
+ import { resolveStructure, Structure } from '../utils/structure-resolver';
15
15
  import { validateOptions } from '../utils/options-validator';
16
16
 
17
17
  export default function (options: any): Rule {
18
- const featureKebab = toKebabCase(options.name);
19
- const featurePascal = toPascalCase(options.name);
20
-
21
- let basePath: string;
22
- let subFolders: string[] = [];
23
-
24
- switch (options.structure) {
25
- case 'flat':
26
-
27
- basePath = `src/app/${featureKebab}`;
28
- break;
29
-
30
- case 'domain-driven':
31
- basePath = `src/app/features/${featureKebab}`;
32
- subFolders = ['pages', 'data', 'models'];
33
- break;
34
-
35
- case 'module-driven':
36
- if (!options.module) throw new Error('module-driven requires --module=<moduleName>');
37
- basePath = `src/app/${options.module}/${featureKebab}`;
38
- subFolders = ['pages', 'data', 'models'];
39
- break;
40
-
41
- case 'monorepo':
42
- if (!options.app && !options.lib)
43
- throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
44
- basePath = options.app
45
- ? `apps/${options.app}/src/app/${featureKebab}`
46
- : `libs/${options.lib}/src/lib/${featureKebab}`;
47
- subFolders = ['pages', 'data', 'models'];
48
- break;
49
-
50
- default:
51
- throw new Error(`Invalid structure: ${options.structure}`);
52
- }
53
-
54
- return chain([
55
- (tree: Tree, context: SchematicContext) => {
56
- context.logger.info(`๐ŸŸข Creating feature: ${featurePascal} (${featureKebab})`);
57
- context.logger.info(`Structure: ${options.structure}`);
58
- const resolved = resolveStructure(tree, options);
59
- options.structure = resolved;
60
-
61
- context.logger.info(`๐Ÿ“ Structure resolved to: ${resolved}`);
62
-
63
- validateOptions(options, resolved);
64
- },
65
-
66
- mergeWith(apply(url('./files'), [template({ featureKebab, featurePascal }), move(basePath)])),
67
-
68
- (_tree: Tree, context: SchematicContext) => {
69
- context.logger.info(`๐ŸŸข Updating app.routes.ts with ${featurePascal}Page...`);
70
-
71
- updateAppRoutes(_tree, featureKebab, featurePascal, options.structure, options);
72
- },
73
-
74
- (_tree: Tree) => {
75
- // Cria subpastas e barrels
18
+ return (tree: Tree, context: SchematicContext) => {
19
+ const featureKebab = toKebabCase(options.name);
20
+ const featurePascal = toPascalCase(options.name);
21
+
22
+ // ๐Ÿ”น Resolve auto-structure
23
+ const resolvedStructure: Structure = resolveStructure(tree, options);
24
+ options.structure = resolvedStructure;
25
+
26
+ context.logger.info(`๐ŸŸข Creating feature: ${featurePascal} (${featureKebab})`);
27
+ context.logger.info(`๐Ÿ“ Structure resolved to: ${resolvedStructure}`);
28
+
29
+ // ๐Ÿ”น Validate options according to resolved structure
30
+ validateOptions(options, resolvedStructure);
31
+
32
+ // ๐Ÿ”น Determine base path and subfolders
33
+ let basePath: string;
34
+ let subFolders: string[] = [];
35
+
36
+ switch (resolvedStructure) {
37
+ case 'flat':
38
+ basePath = `src/app/${featureKebab}`;
39
+ break;
40
+
41
+ case 'domain-driven':
42
+ basePath = `src/app/features/${featureKebab}`;
43
+ subFolders = ['pages', 'data', 'models'];
44
+ break;
45
+
46
+ case 'module-driven':
47
+ if (!options.module)
48
+ throw new Error('module-driven requires --module=<moduleName>');
49
+ basePath = `src/app/${options.module}/${featureKebab}`;
50
+ subFolders = ['pages', 'data', 'models'];
51
+ break;
52
+
53
+ case 'monorepo':
54
+ if (!options.app && !options.lib)
55
+ throw new Error('monorepo requires --app=<appName> or --lib=<libName>');
56
+ basePath = options.app
57
+ ? `apps/${options.app}/src/app/${featureKebab}`
58
+ : `libs/${options.lib}/src/lib/${featureKebab}`;
59
+ subFolders = ['pages', 'data', 'models'];
60
+ break;
61
+
62
+ default:
63
+ throw new Error(`Invalid structure: ${resolvedStructure}`);
64
+ }
65
+
66
+ // ๐Ÿ”น Apply templates and move to proper folder
67
+ const templateRule = mergeWith(
68
+ apply(url('./files'), [template({ featureKebab, featurePascal }), move(basePath)])
69
+ );
70
+
71
+ // ๐Ÿ”น Update app routes
72
+ const routesRule = (t: Tree, ctx: SchematicContext) => {
73
+ ctx.logger.info(`๐ŸŸข Updating routes with ${featurePascal}Page...`);
74
+ updateAppRoutes(t, featureKebab, featurePascal, resolvedStructure, options);
75
+ return t;
76
+ };
77
+
78
+ // ๐Ÿ”น Create subfolders and barrels
79
+ const subFoldersRule = (t: Tree) => {
76
80
  subFolders.forEach((folder) => {
77
81
  const folderPath = `${basePath}/${folder}`;
78
- if (!_tree.exists(folderPath)) _tree.create(folderPath + '/.gitkeep', '');
82
+ if (!t.exists(folderPath)) t.create(folderPath + '/.gitkeep', '');
79
83
 
80
- // Gera barrel index.ts automaticamente
81
- const files = _tree.getDir(folderPath).subfiles.filter(f => f.endsWith('.ts'));
82
- const barrelContent = files.map(f => {
83
- const name = f.replace('.ts', '');
84
- return `export * from './${name}';`;
85
- }).join('\n');
84
+ const files = t.getDir(folderPath).subfiles.filter((f) => f.endsWith('.ts'));
85
+ const barrelContent = files
86
+ .map((f) => `export * from './${f.replace('.ts', '')}';`)
87
+ .join('\n');
86
88
 
87
- if (!_tree.exists(`${folderPath}/index.ts`)) {
88
- _tree.create(`${folderPath}/index.ts`, barrelContent);
89
+ if (!t.exists(`${folderPath}/index.ts`)) {
90
+ t.create(`${folderPath}/index.ts`, barrelContent);
89
91
  } else {
90
- // Se jรก existe index.ts, adiciona novos exports sem duplicar
91
- const existing = _tree.read(`${folderPath}/index.ts`)!.toString('utf-8');
92
+ const existing = t.read(`${folderPath}/index.ts`)!.toString('utf-8');
92
93
  const newExports = files
93
- .map(f => `export * from './${f.replace('.ts','')}';`)
94
- .filter(line => !existing.includes(line))
94
+ .map((f) => `export * from './${f.replace('.ts', '')}';`)
95
+ .filter((line) => !existing.includes(line))
95
96
  .join('\n');
96
- if (newExports) _tree.overwrite(`${folderPath}/index.ts`, existing + '\n' + newExports);
97
+ if (newExports) t.overwrite(`${folderPath}/index.ts`, existing + '\n' + newExports);
97
98
  }
98
99
  });
100
+ return t;
101
+ };
99
102
 
100
- return _tree;
101
- },
102
- ]);
103
+ return chain([templateRule, routesRule, subFoldersRule]);
104
+ };
103
105
  }