@barcidev/ngx-autogen 0.1.14 → 0.1.16

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": "@barcidev/ngx-autogen",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "A collection of Angular schematics for essential functionalities.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -28,27 +28,57 @@ exports.mergeFilesSmart = mergeFilesSmart;
28
28
  */
29
29
  function addProviderToStandaloneComponent(componentPath, providerName, imports) {
30
30
  return (tree) => {
31
+ var _a;
31
32
  const text = tree.read(componentPath);
32
- if (!text) {
33
+ if (!text)
33
34
  throw new schematics_2.SchematicsException(`No se encontró el archivo: ${componentPath}`);
34
- }
35
35
  const sourceText = text.toString("utf-8");
36
36
  const source = ts.createSourceFile(componentPath, sourceText, ts.ScriptTarget.Latest, true);
37
37
  const recorder = tree.beginUpdate(componentPath);
38
- // 1. Añadir el provider al array de metadata
39
- const providerChanges = (0, ast_utils_1.addSymbolToNgModuleMetadata)(source, componentPath, "providers", providerName, null);
40
- providerChanges.forEach((change) => {
41
- if (change instanceof change_1.InsertChange) {
42
- recorder.insertLeft(change.pos, change.toAdd);
43
- }
44
- });
45
- // 2. Añadir todos los imports necesarios
38
+ // 1. Gestionar Imports
46
39
  imports.forEach((item) => {
47
40
  const importChange = (0, ast_utils_1.insertImport)(source, componentPath, item.symbol, item.path);
48
41
  if (importChange instanceof change_1.InsertChange) {
49
42
  recorder.insertLeft(importChange.pos, importChange.toAdd);
50
43
  }
51
44
  });
45
+ // 2. Buscar el decorador @Component y su propiedad 'providers'
46
+ const componentClass = source.statements.find((s) => {
47
+ var _a;
48
+ return ts.isClassDeclaration(s) &&
49
+ !!((_a = s.modifiers) === null || _a === void 0 ? void 0 : _a.some((m) => m.kind === ts.SyntaxKind.ExportKeyword));
50
+ });
51
+ if (!componentClass)
52
+ return tree;
53
+ const decorator = (_a = ts
54
+ .getDecorators(componentClass)) === null || _a === void 0 ? void 0 : _a.find((d) => ts.isCallExpression(d.expression) &&
55
+ ts.isIdentifier(d.expression.expression) &&
56
+ d.expression.expression.text === "Component");
57
+ if (decorator && ts.isCallExpression(decorator.expression)) {
58
+ const args = decorator.expression.arguments;
59
+ if (args.length > 0 && ts.isObjectLiteralExpression(args[0])) {
60
+ const objectLiteral = args[0];
61
+ const providersProp = objectLiteral.properties.find((p) => ts.isPropertyAssignment(p) &&
62
+ ts.isIdentifier(p.name) &&
63
+ p.name.text === "providers");
64
+ if (providersProp &&
65
+ ts.isArrayLiteralExpression(providersProp.initializer)) {
66
+ // Caso: El array de providers YA existe
67
+ const elements = providersProp.initializer.elements;
68
+ const pos = elements.length > 0
69
+ ? elements[elements.length - 1].getEnd()
70
+ : providersProp.initializer.getStart() + 1;
71
+ const toAdd = elements.length > 0 ? `, ${providerName}` : providerName;
72
+ recorder.insertRight(pos, toAdd);
73
+ }
74
+ else {
75
+ // Caso: El array de providers NO existe, lo creamos
76
+ const pos = objectLiteral.getStart() + 1;
77
+ const toAdd = `\n providers: [${providerName}],`;
78
+ recorder.insertRight(pos, toAdd);
79
+ }
80
+ }
81
+ }
52
82
  tree.commitUpdate(recorder);
53
83
  return tree;
54
84
  };
@@ -1,4 +1,4 @@
1
- import { TranslationScopeConfig } from 'app/i18n/transloco.model';
1
+ import { TranslationScopeConfig } from '@i18n/transloco.model';
2
2
 
3
3
  const esCO = {
4
4
  title: 'Titulo'
@@ -1,3 +1,6 @@
1
1
  import { Rule } from "@angular-devkit/schematics";
2
2
  import { TranslocoSchemaOptions } from "./scheme";
3
+ /**
4
+ * Schematic principal para configurar Transloco en un componente específico
5
+ */
3
6
  export declare function transloco(options: TranslocoSchemaOptions): Rule;
@@ -18,10 +18,13 @@ const workspace_1 = require("@schematics/angular/utility/workspace");
18
18
  const path_1 = require("path");
19
19
  const file_actions_1 = require("../common/file-actions");
20
20
  const pluralize_1 = require("../common/pluralize");
21
+ /**
22
+ * Schematic principal para configurar Transloco en un componente específico
23
+ */
21
24
  function transloco(options) {
22
25
  return (tree, _context) => __awaiter(this, void 0, void 0, function* () {
23
26
  var _a;
24
- // 1. Configuración del Workspace y Proyecto
27
+ // --- 1. CONFIGURACIÓN INICIAL Y WORKSPACE ---
25
28
  const workspace = yield (0, workspace_1.getWorkspace)(tree);
26
29
  if (!options.project) {
27
30
  options.project =
@@ -32,35 +35,32 @@ function transloco(options) {
32
35
  if (!project) {
33
36
  throw new schematics_1.SchematicsException(`El proyecto "${options.project}" no existe.`);
34
37
  }
35
- // 3. Determinación de rutas para generación de archivos
38
+ // --- 2. DETERMINACIÓN DE RUTAS Y DETECCIÓN DE COMPONENTE ---
39
+ // Resolvemos el path relativo (src/app/...) basado en el directorio de ejecución
36
40
  const fullPath = process.cwd();
37
41
  const srcIndex = fullPath.lastIndexOf("src");
38
42
  const relativePath = srcIndex !== -1
39
43
  ? fullPath.substring(srcIndex)
40
44
  : (0, path_1.join)((0, path_1.normalize)("src"), "app");
41
45
  options.path = (0, path_1.normalize)(relativePath);
42
- const directory = tree.getDir((0, path_1.normalize)(options.path));
43
- console.log(`🔍 Buscando componente en: ${options.path}`);
44
- const componentFile = directory.subfiles.find((file) => file.endsWith(".component.ts"));
45
- console.log(`📄 Componente detectado: ${componentFile || "Ninguno"}`);
46
+ const directory = tree.getDir(options.path);
47
+ // Buscamos el archivo .ts principal del directorio
48
+ const componentFile = directory.subfiles.find((f) => f.endsWith(".component.ts")) ||
49
+ directory.subfiles.find((f) => f.endsWith(".ts"));
46
50
  if (!componentFile && !options.name) {
47
- throw new schematics_1.SchematicsException("❌ No se encontró un archivo *.component.ts en este directorio.");
51
+ throw new schematics_1.SchematicsException("❌ No se encontró un archivo .ts en este directorio y no se proveyó un --name.");
48
52
  }
49
- const componentFileName = componentFile
50
- ? componentFile.replace(".component.ts", "")
53
+ // Normalizamos el nombre (ej. mi-componente.component -> mi-componente)
54
+ options.name = componentFile
55
+ ? componentFile.replace(".component.ts", "").replace(".ts", "")
51
56
  : options.name;
52
- options.name = componentFileName;
53
- console.log(`✅ Nombre del componente para i18n: ${options.name}`);
54
- console.log(`📂 Ruta de generación de archivos i18n: ${options.path}`);
55
- const namePath = options.path; // Generamos archivos en la misma carpeta del componente detectado
56
57
  const rules = [];
57
- // 4. Verificación de instalación de Transloco (Idempotencia)
58
+ // --- 3. CONFIGURACIÓN GLOBAL (IDEMPOTENTE) ---
58
59
  const appConfigPath = "src/app/app.config.ts";
59
60
  const appConfigContent = ((_a = tree.read(appConfigPath)) === null || _a === void 0 ? void 0 : _a.toString()) || "";
60
- const isTranslocoInstalled = appConfigContent.includes("provideTransloco");
61
- if (!isTranslocoInstalled) {
62
- _context.logger.info("📦 Transloco no detectado. Iniciando configuración global...");
63
- // A. Añadir dependencia a package.json
61
+ if (!appConfigContent.includes("provideTransloco")) {
62
+ _context.logger.info("📦 Transloco no detectado. Configurando globalmente...");
63
+ // Dependencias y tarea de instalación
64
64
  rules.push((host) => {
65
65
  (0, dependencies_1.addPackageJsonDependency)(host, {
66
66
  type: dependencies_1.NodeDependencyType.Default,
@@ -70,35 +70,32 @@ function transloco(options) {
70
70
  _context.addTask(new tasks_1.NodePackageInstallTask());
71
71
  return host;
72
72
  });
73
- // B. Inyectar provider global en app.config.ts
74
- rules.push((0, rules_1.addRootProvider)(options.project, ({ code, external }) => {
75
- return code `
76
- ${external("provideTransloco", "@jsverse/transloco")}({
77
- config: {
78
- availableLangs: ['en', 'es'],
79
- defaultLang: 'en',
80
- prodMode: !${external("isDevMode", "@angular/core")}(),
81
- reRenderOnLangChange: true
82
- },
83
- loader: ${external("TranslocoHttpLoader", "./i18n/transloco-loader")}
84
- })
85
- `;
86
- }));
73
+ // Provider global en app.config.ts
74
+ rules.push((0, rules_1.addRootProvider)(options.project, ({ code, external }) => code `
75
+ ${external("provideTransloco", "@jsverse/transloco")}({
76
+ config: {
77
+ availableLangs: ['en', 'es'],
78
+ defaultLang: 'en',
79
+ prodMode: !${external("isDevMode", "@angular/core")}(),
80
+ reRenderOnLangChange: true
81
+ },
82
+ loader: ${external("TranslocoHttpLoader", "@i18n/transloco-loader")}
83
+ })
84
+ `));
87
85
  }
88
- // 5. Generación de archivos i18n del componente
86
+ // --- 4. GENERACIÓN DE ARCHIVOS I18N DEL COMPONENTE ---
89
87
  rules.push((0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)("./files/component"), [
90
88
  (0, schematics_1.applyTemplates)(Object.assign(Object.assign(Object.assign({}, schematics_1.strings), options), { pluralize: (word) => options.lang === "es" ? (0, pluralize_1.pluralizeEs)(word) : (0, pluralize_1.pluralizeEn)(word) })),
91
- (0, schematics_1.move)(namePath),
89
+ (0, schematics_1.move)(options.path),
92
90
  ])));
93
- // 6. Registro del Scope en el Componente Standalone
91
+ // --- 5. REGISTRO DEL SCOPE EN EL COMPONENTE ---
94
92
  if (componentFile) {
95
- const componentPath = (0, path_1.join)(namePath, componentFile);
93
+ const componentPath = (0, path_1.join)(options.path, componentFile);
96
94
  const i18nConstantName = `${schematics_1.strings.camelize(options.name)}I18n`;
97
- console.log(`🔗 Registrando scope de Transloco en ${componentFile} con constante ${i18nConstantName}, este es el path: ${componentPath}`);
98
95
  rules.push((0, file_actions_1.addProviderToStandaloneComponent)(componentPath, `provideTranslocoScopeWrapper(${i18nConstantName})`, [
99
96
  {
100
97
  symbol: `provideTranslocoScopeWrapper`,
101
- path: `src/app/i18n/transloco-loader`, // Ajusta a tu path real de utilidades
98
+ path: `@i18n/transloco-loader`,
102
99
  },
103
100
  {
104
101
  symbol: i18nConstantName,
@@ -106,44 +103,64 @@ function transloco(options) {
106
103
  },
107
104
  ]));
108
105
  }
109
- // 7. Sincronización de archivos i18n comunes
106
+ // --- 6. SINCRONIZACIÓN DE ARCHIVOS COMUNES Y TSCONFIG ---
110
107
  rules.push((0, file_actions_1.mergeFilesSmart)("./files/i18n", "src/app/i18n", options, tree));
108
+ // Ejecutar actualización de tsconfig
111
109
  updateTsConfig(tree);
112
110
  return (0, schematics_1.chain)(rules);
113
111
  });
114
- function updateTsConfig(tree) {
115
- const tsConfigPath = "/tsconfig.json";
116
- const path = tree.exists(tsConfigPath)
117
- ? tsConfigPath
118
- : "/tsconfig.app.json";
119
- const buffer = tree.read(path);
120
- if (!buffer)
121
- return;
122
- let contentText = buffer.toString();
123
- // Limpieza manual de comentarios para evitar que JSON.parse falle
124
- const cleanJson = contentText.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
125
- let tsconfig;
126
- try {
127
- tsconfig = JSON.parse(cleanJson);
112
+ }
113
+ /**
114
+ * Actualiza los paths en tsconfig para soportar el alias @i18n.
115
+ * Detecta la baseUrl existente para calcular la ruta relativa correcta.
116
+ */
117
+ function updateTsConfig(tree) {
118
+ const tsConfigPath = tree.exists("/tsconfig.json")
119
+ ? "/tsconfig.json"
120
+ : "/tsconfig.app.json";
121
+ const buffer = tree.read(tsConfigPath);
122
+ if (!buffer)
123
+ return;
124
+ // Limpieza de comentarios para evitar errores en JSON.parse
125
+ const content = buffer
126
+ .toString()
127
+ .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
128
+ try {
129
+ const tsconfig = JSON.parse(content);
130
+ // Asegurar que exista compilerOptions
131
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
132
+ // 1. Detectar o establecer baseUrl
133
+ // Si no existe, la inicializamos en "./"
134
+ const baseUrl = tsconfig.compilerOptions.baseUrl || "./";
135
+ if (!tsconfig.compilerOptions.baseUrl) {
136
+ tsconfig.compilerOptions.baseUrl = baseUrl;
128
137
  }
129
- catch (e) {
130
- // Si falla, intentamos parsearlo tal cual por si no tiene comentarios
131
- try {
132
- tsconfig = JSON.parse(contentText);
133
- }
134
- catch (innerError) {
135
- throw new schematics_1.SchematicsException(`No se pudo parsear ${path}. Asegúrate de que es un JSON válido.`);
138
+ // 2. Calcular el path del alias basado en la baseUrl
139
+ // Si baseUrl es "./", el path debe ser "src/app/i18n/*"
140
+ // Si baseUrl es "src", el path debe ser "app/i18n/*"
141
+ let i18nPath = "src/app/i18n/*";
142
+ if (baseUrl !== "./" && baseUrl !== ".") {
143
+ // Normalizamos la baseUrl eliminando barras iniciales/finales (ej. "src/" -> "src")
144
+ const normalizedBase = baseUrl.replace(/^\.\/|\/$/g, "");
145
+ // Si la baseUrl ya incluye 'src', la recortamos del path del alias
146
+ if (i18nPath.startsWith(normalizedBase)) {
147
+ i18nPath = i18nPath.replace(normalizedBase, "").replace(/^\//, "");
136
148
  }
137
149
  }
138
- // Configurar los paths
139
- tsconfig.compilerOptions = tsconfig.compilerOptions || {};
150
+ // 3. Configurar los paths
140
151
  tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
141
- const sharedAlias = "@i18n/*";
142
- const sharedPath = ["src/app/i18n/*"];
143
- if (!tsconfig.compilerOptions.paths[sharedAlias]) {
144
- tsconfig.compilerOptions.paths[sharedAlias] = sharedPath;
145
- tree.overwrite(path, JSON.stringify(tsconfig, null, 2));
152
+ const alias = "@i18n/*";
153
+ const pathValue = [i18nPath];
154
+ // Solo actualizamos si el alias no existe o el valor ha cambiado
155
+ if (!tsconfig.compilerOptions.paths[alias] ||
156
+ tsconfig.compilerOptions.paths[alias][0] !== i18nPath) {
157
+ tsconfig.compilerOptions.paths[alias] = pathValue;
158
+ tree.overwrite(tsConfigPath, JSON.stringify(tsconfig, null, 2));
159
+ console.log(`✅ TsConfig actualizado: @i18n -> ${i18nPath} (baseUrl: ${baseUrl})`);
146
160
  }
147
161
  }
162
+ catch (e) {
163
+ console.warn(`⚠️ No se pudo procesar ${tsConfigPath}. Revisa que sea un JSON válido.`);
164
+ }
148
165
  }
149
166
  //# sourceMappingURL=index.js.map