@barcidev/ngx-autogen 0.1.18 → 0.1.19

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,10 +1,11 @@
1
1
  {
2
2
  "name": "@barcidev/ngx-autogen",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "A collection of Angular schematics for essential functionalities.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "build": "tsc -p tsconfig.json",
8
+ "release": "npm run build && npm publish --access public",
8
9
  "test": "npm run build && jasmine src/**/*_spec.js",
9
10
  "prepublishOnly": "npm run build"
10
11
  },
@@ -1,4 +1,5 @@
1
- import { TranslationScopeConfig } from '@i18n/transloco.model';
1
+ import { TranslationScopeConfig } from '@barcidev/typed-transloco';
2
+ import { AppLanguageCode } from '@i18n/app.i18n.ts';
2
3
 
3
4
  const esCO = {
4
5
  title: 'Titulo'
@@ -9,7 +10,7 @@ const enUS = {
9
10
 
10
11
  const scope = '<%= name %>' as const;
11
12
 
12
- export const <%= name %>I18n: TranslationScopeConfig<typeof esCO, typeof scope> = {
13
+ export const <%= name %>I18n: TranslationScopeConfig<AppLanguageCode, typeof esCO, typeof scope> = {
13
14
  scope,
14
15
  translations: {
15
16
  'en-US': enUS,
@@ -1,6 +1,3 @@
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
- */
6
- export declare function transloco(options: TranslocoSchemaOptions): Rule;
3
+ export declare function ngAdd(options: TranslocoSchemaOptions): Rule;
@@ -9,22 +9,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.transloco = transloco;
12
+ exports.ngAdd = ngAdd;
13
13
  const schematics_1 = require("@angular-devkit/schematics");
14
- const tasks_1 = require("@angular-devkit/schematics/tasks");
15
- const dependencies_1 = require("@schematics/angular/utility/dependencies");
16
- const rules_1 = require("@schematics/angular/utility/standalone/rules");
14
+ const utility_1 = require("@schematics/angular/utility");
17
15
  const workspace_1 = require("@schematics/angular/utility/workspace");
18
- const path_1 = require("path");
19
- const file_actions_1 = require("../common/file-actions");
20
- const pluralize_1 = require("../common/pluralize");
21
- /**
22
- * Schematic principal para configurar Transloco en un componente específico
23
- */
24
- function transloco(options) {
16
+ const jsonc_parser_1 = require("jsonc-parser");
17
+ function ngAdd(options) {
25
18
  return (tree, _context) => __awaiter(this, void 0, void 0, function* () {
26
- var _a;
27
- // --- 1. CONFIGURACIÓN INICIAL Y WORKSPACE ---
28
19
  const workspace = yield (0, workspace_1.getWorkspace)(tree);
29
20
  if (!options.project) {
30
21
  options.project =
@@ -33,134 +24,131 @@ function transloco(options) {
33
24
  }
34
25
  const project = workspace.projects.get(options.project);
35
26
  if (!project) {
36
- throw new schematics_1.SchematicsException(`El proyecto "${options.project}" no existe.`);
27
+ _context.logger.error(`❌ El proyecto "${options.project}" no existe en el workspace.`);
28
+ return;
37
29
  }
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
40
- const fullPath = process.cwd();
41
- const srcIndex = fullPath.lastIndexOf("src");
42
- const relativePath = srcIndex !== -1
43
- ? fullPath.substring(srcIndex)
44
- : (0, path_1.join)((0, path_1.normalize)("src"), "app");
45
- options.path = (0, path_1.normalize)(relativePath);
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"));
50
- if (!componentFile && !options.name) {
51
- throw new schematics_1.SchematicsException("❌ No se encontró un archivo .ts en este directorio y no se proveyó un --name.");
52
- }
53
- // Normalizamos el nombre (ej. mi-componente.component -> mi-componente)
54
- options.name = componentFile
55
- ? componentFile.replace(".component.ts", "").replace(".ts", "")
56
- : options.name;
57
- const rules = [];
58
- // --- 3. CONFIGURACIÓN GLOBAL (IDEMPOTENTE) ---
59
- const appConfigPath = "src/app/app.config.ts";
60
- const appConfigContent = ((_a = tree.read(appConfigPath)) === null || _a === void 0 ? void 0 : _a.toString()) || "";
61
- if (!appConfigContent.includes("provideTransloco")) {
62
- _context.logger.info("📦 Transloco no detectado. Configurando globalmente...");
63
- // Dependencias y tarea de instalación
64
- rules.push((host) => {
65
- (0, dependencies_1.addPackageJsonDependency)(host, {
66
- type: dependencies_1.NodeDependencyType.Default,
67
- name: "@jsverse/transloco",
68
- version: "^7.0.0",
69
- });
70
- _context.addTask(new tasks_1.NodePackageInstallTask());
71
- return host;
72
- });
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
- `));
85
- }
86
- // --- 4. GENERACIÓN DE ARCHIVOS I18N DEL COMPONENTE ---
87
- rules.push((0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)("./files/component"), [
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) })),
89
- (0, schematics_1.move)(options.path),
90
- ])));
91
- // --- 5. REGISTRO DEL SCOPE EN EL COMPONENTE ---
92
- if (componentFile) {
93
- const componentPath = (0, path_1.join)(options.path, componentFile);
94
- const i18nConstantName = `${schematics_1.strings.camelize(options.name)}I18n`;
95
- rules.push((0, file_actions_1.addProviderToStandaloneComponent)(componentPath, `provideTranslocoScopeWrapper(${i18nConstantName})`, [
96
- {
97
- symbol: `provideTranslocoScopeWrapper`,
98
- path: `@i18n/transloco-wrapper`,
99
- },
100
- {
101
- symbol: i18nConstantName,
102
- path: `./${schematics_1.strings.dasherize(options.name)}.i18n`,
103
- },
104
- ]));
105
- }
106
- // --- 6. SINCRONIZACIÓN DE ARCHIVOS COMUNES Y TSCONFIG ---
107
- rules.push((0, file_actions_1.mergeFilesSmart)("./files/i18n", "src/app/i18n", options, tree));
108
- // Ejecutar actualización de tsconfig
109
- updateTsConfig(tree);
110
- return (0, schematics_1.chain)(rules);
30
+ const projectRoot = project.sourceRoot || "src";
31
+ return (0, schematics_1.chain)([
32
+ (0, schematics_1.externalSchematic)("@barcidev/typed-transloco", "ng-add", {}),
33
+ setupGlobalConfig(options.project, projectRoot),
34
+ createI18nFiles(projectRoot),
35
+ updateTsConfigRule(projectRoot),
36
+ ]);
111
37
  });
112
38
  }
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;
137
- }
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/*";
39
+ // --- 1. CONFIGURACIÓN DEL PROVIDER ---
40
+ function setupGlobalConfig(project, root) {
41
+ return (tree) => {
42
+ const appConfigPath = `${root}/app/app.config.ts`;
43
+ if (!tree.exists(appConfigPath))
44
+ return tree;
45
+ const content = tree.read(appConfigPath).toString();
46
+ if (content.includes("provideTransloco"))
47
+ return tree;
48
+ return (0, utility_1.addRootProvider)(project, ({ code, external }) => code `
49
+ ${external("provideTransloco", "@jsverse/transloco")}({
50
+ config: {
51
+ availableLangs: ['en-US', 'es-CO'],
52
+ defaultLang: 'en-US',
53
+ prodMode: !${external("isDevMode", "@angular/core")}(),
54
+ reRenderOnLangChange: true
55
+ },
56
+ loader: ${external("TranslocoHttpLoader", "@barcidev/typed-transloco")}
57
+ })
58
+ `);
59
+ };
60
+ }
61
+ // --- 2. CREACIÓN DE ARCHIVOS (MODO STANDALONE) ---
62
+ function createI18nFiles(root) {
63
+ return (tree) => {
64
+ const i18nPath = `${root}/app/i18n`;
65
+ const files = [
66
+ {
67
+ path: `${i18nPath}/app-typed-transloco.directive.ts`,
68
+ content: `import { Directive } from '@angular/core';
69
+ import { TypedTranslocoDirective, TypedViewContext } from '@barcidev/typed-transloco';
70
+ import { AppI18nType } from './app.i18n';
71
+
72
+ @Directive({
73
+ selector: '[typedTransloco]',
74
+ standalone: true,
75
+ })
76
+ export class AppTypedTranslocoDirective<
77
+ T extends keyof AppI18nType = keyof AppI18nType,
78
+ > extends TypedTranslocoDirective<T> {
79
+ static override ngTemplateContextGuard<T extends keyof AppI18nType>(
80
+ dir: TypedTranslocoDirective<T>,
81
+ ctx: any,
82
+ ): ctx is TypedViewContext<T extends keyof AppI18nType ? AppI18nType[T] : AppI18nType> {
83
+ return true;
84
+ }
85
+ }`,
86
+ },
87
+ {
88
+ path: `${i18nPath}/app-typed-transloco.pipe.ts`,
89
+ content: `import { Pipe } from '@angular/core';
90
+ import { TypedTranslocoPipe } from '@barcidev/typed-transloco';
91
+ import { AppI18nType } from './app.i18n';
92
+
93
+ @Pipe({
94
+ name: 'typedTransloco',
95
+ standalone: true,
96
+ pure: false,
97
+ })
98
+ export class AppTypedTranslocoPipe extends TypedTranslocoPipe<AppI18nType> {}`,
99
+ },
100
+ {
101
+ path: `${i18nPath}/app.i18n.ts`,
102
+ content: `export const appI18n = {};
103
+ export type AppI18nType = typeof appI18n;
104
+ export type AppLanguageCode = 'en-US' | 'es-CO';`,
105
+ },
106
+ ];
107
+ files.forEach((f) => {
108
+ if (!tree.exists(f.path)) {
109
+ tree.create(f.path, f.content);
110
+ }
111
+ else {
112
+ tree.overwrite(f.path, f.content);
113
+ }
114
+ });
115
+ };
116
+ }
117
+ // --- 3. ACTUALIZACIÓN SEGURA DE TSCONFIG ---
118
+ function updateTsConfigRule(root) {
119
+ return (tree, context) => {
120
+ var _a, _b;
121
+ const tsConfigPath = tree.exists("/tsconfig.app.json")
122
+ ? "/tsconfig.app.json"
123
+ : "/tsconfig.json";
124
+ const buffer = tree.read(tsConfigPath);
125
+ if (!buffer)
126
+ return;
127
+ const content = buffer.toString();
128
+ const tsconfig = (0, jsonc_parser_1.parse)(content);
129
+ const baseUrl = ((_a = tsconfig.compilerOptions) === null || _a === void 0 ? void 0 : _a.baseUrl) || "./";
130
+ let i18nPath = `${root}/app/i18n/*`;
131
+ // Lógica de normalización de path
142
132
  if (baseUrl !== "./" && baseUrl !== ".") {
143
- // Normalizamos la baseUrl eliminando barras iniciales/finales (ej. "src/" -> "src")
144
133
  const normalizedBase = baseUrl.replace(/^\.\/|\/$/g, "");
145
- // Si la baseUrl ya incluye 'src', la recortamos del path del alias
146
134
  if (i18nPath.startsWith(normalizedBase)) {
147
135
  i18nPath = i18nPath.replace(normalizedBase, "").replace(/^\//, "");
148
136
  }
149
137
  }
150
- // 3. Configurar los paths
151
- tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
152
138
  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})`);
139
+ const modificationOptions = {
140
+ formattingOptions: { insertSpaces: true, tabSize: 2 },
141
+ };
142
+ // Usamos jsonc-parser para modificar manteniendo comentarios
143
+ let edits = (0, jsonc_parser_1.modify)(content, ["compilerOptions", "paths", alias], [i18nPath], modificationOptions);
144
+ // Si no existe baseUrl, la añadimos para asegurar consistencia
145
+ if (!((_b = tsconfig.compilerOptions) === null || _b === void 0 ? void 0 : _b.baseUrl)) {
146
+ const baseUrlEdits = (0, jsonc_parser_1.modify)(content, ["compilerOptions", "baseUrl"], "./", modificationOptions);
147
+ edits = [...edits, ...baseUrlEdits];
160
148
  }
161
- }
162
- catch (e) {
163
- console.warn(`⚠️ No se pudo procesar ${tsConfigPath}. Revisa que sea un JSON válido.`);
164
- }
149
+ const updatedContent = (0, jsonc_parser_1.applyEdits)(content, edits);
150
+ tree.overwrite(tsConfigPath, updatedContent);
151
+ context.logger.info(`✅ Alias @i18n configurado en ${tsConfigPath}`);
152
+ };
165
153
  }
166
154
  //# sourceMappingURL=index.js.map
@@ -1,19 +0,0 @@
1
- import { TranslationScopeConfig } from "./transloco.model";
2
-
3
- const esCO = {};
4
-
5
- const enUS: typeof esCO = {};
6
-
7
- const scope = "global" as const;
8
-
9
- export const globalI18n: TranslationScopeConfig<typeof esCO, typeof scope> = {
10
- scope,
11
- translations: {
12
- "en-US": enUS,
13
- "es-CO": esCO,
14
- },
15
- };
16
-
17
- export const appI18n = {
18
- [scope]: globalI18n.translations["es-CO"],
19
- };
@@ -1,10 +0,0 @@
1
- import { HttpClient } from "@angular/common/http";
2
- import { inject, Injectable } from "@angular/core";
3
- import { Translation, TranslocoLoader } from "@jsverse/transloco";
4
-
5
- @Injectable({ providedIn: "root" })
6
- export class TranslocoHttpLoader implements TranslocoLoader {
7
- private _http = inject(HttpClient);
8
-
9
- getTranslation = (): Promise<Translation> => Promise.resolve({});
10
- }
@@ -1,12 +0,0 @@
1
- import { provideTranslocoScope } from '@jsverse/transloco';
2
-
3
- import { TranslationScopeConfig } from './transloco.model';
4
-
5
- export const provideTranslocoScopeWrapper = (config: TranslationScopeConfig) =>
6
- provideTranslocoScope({
7
- alias: config.alias,
8
- loader: Object.fromEntries(
9
- Object.entries(config.translations).map(([lang, translation]) => [lang, () => Promise.resolve(translation)])
10
- ),
11
- scope: config.scope
12
- });
@@ -1,34 +0,0 @@
1
- import { Translation } from "@jsverse/transloco";
2
-
3
- import { appI18n } from "./global.i18n";
4
-
5
- export type AppI18nType = typeof appI18n;
6
-
7
- export type AppLanguageCode = "en-US" | "es-CO";
8
-
9
- export type ConfigTranslation<T> = Record<AppLanguageCode, T>;
10
-
11
- export type TranslationKeys = PathKeys<AppI18nType> | (string & {});
12
- export type TranslationPagesKeys<K extends keyof AppI18nType> =
13
- | PathKeys<AppI18nType[K]>
14
- | (string & {});
15
-
16
- export interface TranslationScopeConfig<T = Translation, U = string> {
17
- alias?: string;
18
- scope: U;
19
- translations: ConfigTranslation<T>;
20
- }
21
-
22
- type PathKeys<T> = T extends object
23
- ? {
24
- [K in keyof T]: K extends number | string
25
- ?
26
- | `${K}`
27
- | (PathKeys<T[K]> extends infer P
28
- ? P extends number | string
29
- ? `${K}.${P}`
30
- : never
31
- : never)
32
- : never;
33
- }[keyof T]
34
- : never;