tailjng 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -44,7 +44,7 @@ El CLI instala **dependencias transitivas** automáticamente (ej. `button` → `
44
44
  - Angular **19.2+** (19.x dentro del mismo major; no Angular 20/21 aún)
45
45
  - Tailwind CSS **4.x** (incluido si eliges Tailwind al crear el proyecto con `ng new`)
46
46
  -{
47
- - Peers: `lucide-angular`, `date-fns`, `exceljs`, `xlsx`, `file-saver` (el CLI los instala con `init:app` si faltan)
47
+ - Peers: `lucide-angular`, `date-fns`, `exceljs`, `file-saver` (el CLI los instala con `init:app` si faltan)
48
48
  - Estilos globales en **CSS o SCSS** — `init:app` detecta cuál usa tu app
49
49
 
50
50
  ---
@@ -170,7 +170,6 @@ async function runInitApp() {
170
170
  installPackages(workspaceRoot, missingDev, true);
171
171
  }
172
172
 
173
- const { appRoot } = resolveAppPaths(workspaceRoot, selectedApp);
174
173
  ensureProjectColorsConfig(workspaceRoot, appRoot, overwrite);
175
174
 
176
175
  const hasAppConfig = fileExists(appConfigPath);
@@ -1,192 +1,192 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { COLORS } = require('../settings/colors');
4
- const { RUNTIME_PACKAGES, DEV_PACKAGES, installPackages } = require('../settings/init-packages');
5
- const { buildPathsJson, buildPathsReadme } = require('../templates/app.generator');
6
- const {
7
- findAngularWorkspace,
8
- readJson,
9
- getApplicationProjects,
10
- resolveAppPaths,
11
- getBuildOptions,
12
- detectStyleLanguage,
13
- getPrimaryStyleEntry,
14
- writeFileSafe,
15
- ensureTailjngStylesInAngularJson,
16
- patchIndexHtml,
17
- patchAppConfig,
18
- getMissingPackages,
19
- resolveRuntimePackages,
20
- resolveDevPackages,
21
- hasTailwindSetup,
22
- getTailjngSafelistCssImport,
23
- ensureTailjngSafelistImport,
24
- alignAngularAnimationsInPackageJson,
25
- resolveStyleFilePath,
26
- fileExists,
27
- } = require('../settings/project-utils');
28
- const {
29
- ensureProjectColorsConfig,
30
- patchAppConfigColors,
31
- COLORS_FILES,
32
- } = require('../settings/colors-config-utils');
33
-
34
- function resolveTargetPath(workspaceRoot, appProject, relativePath, appRootRelative = false) {
35
- const appRoot = path.join(workspaceRoot, appProject.root || '');
36
-
37
- if (appRootRelative) {
38
- return path.join(appRoot, relativePath);
39
- }
40
-
41
- if (relativePath.startsWith('projects/')) {
42
- return path.join(workspaceRoot, relativePath);
43
- }
44
-
45
- return path.join(workspaceRoot, appProject.sourceRoot, relativePath.replace(/^src\//, ''));
46
- }
47
-
48
- async function runSyncApp() {
49
- const workspace = findAngularWorkspace(process.cwd());
50
-
51
- if (!workspace) {
52
- console.error(`${COLORS.red}[tailjng CLI] ERROR: angular.json not found. Run this inside an Angular project.${COLORS.reset}`);
53
- process.exit(1);
54
- }
55
-
56
- const { workspaceRoot, angularJsonPath } = workspace;
57
- const angularJson = readJson(angularJsonPath);
58
- const apps = getApplicationProjects(angularJson);
59
-
60
- if (apps.length === 0) {
61
- console.error(`${COLORS.red}[tailjng CLI] ERROR: No application project found in angular.json.${COLORS.reset}`);
62
- process.exit(1);
63
- }
64
-
65
- const selectedApp = apps[0];
66
- const { appRoot, srcRoot } = resolveAppPaths(workspaceRoot, selectedApp);
67
- const buildOptions = getBuildOptions(angularJson, selectedApp.name);
68
- const styleLanguage = detectStyleLanguage(buildOptions);
69
- const primaryStylePath = getPrimaryStyleEntry(buildOptions);
70
- const primaryStyleFullPath = resolveStyleFilePath(workspaceRoot, primaryStylePath, selectedApp);
71
- const indexPath = path.join(workspaceRoot, buildOptions.index || path.join(selectedApp.sourceRoot, 'index.html'));
72
- const appConfigPath = path.join(srcRoot, 'app', 'app.config.ts');
73
- const packageJsonPath = path.join(workspaceRoot, 'package.json');
74
- const packageJson = fileExists(packageJsonPath) ? readJson(packageJsonPath) : { dependencies: {}, devDependencies: {} };
75
- const tailwindReady = hasTailwindSetup(workspaceRoot, packageJson, primaryStylePath);
76
- const installDeps = !process.argv.includes('--no-install');
77
- const componentsPath = 'src/app/tailjng';
78
-
79
- console.log(`\n${COLORS.bright}${COLORS.blue}[tailjng CLI] sync:app${COLORS.reset}`);
80
- console.log(`${COLORS.dim}Updates integration only — does not overwrite your config (environment, providers, styles).${COLORS.reset}`);
81
- console.log(`${COLORS.dim}Workspace: ${workspaceRoot} | App: ${selectedApp.name}${COLORS.reset}\n`);
82
-
83
- if (!packageJson.dependencies?.tailjng) {
84
- console.log(`${COLORS.yellow}[tailjng CLI] WARNING: tailjng is not in package.json. Run: npm install tailjng@latest --legacy-peer-deps${COLORS.reset}`);
85
- }
86
-
87
- let changes = 0;
88
-
89
- const animationsAligned = alignAngularAnimationsInPackageJson(workspaceRoot);
90
- if (animationsAligned.changed) {
91
- changes += 1;
92
- console.log(`${COLORS.green}✔ Aligned @angular/animations → ${animationsAligned.version}${COLORS.reset}`);
93
- Object.assign(packageJson, readJson(packageJsonPath));
94
- }
95
-
96
- if (installDeps) {
97
- const runtimePackages = resolveRuntimePackages(packageJson, RUNTIME_PACKAGES, workspaceRoot);
98
- const devPackages = resolveDevPackages(packageJson, DEV_PACKAGES, tailwindReady);
99
- const missingRuntime = Object.fromEntries(getMissingPackages(packageJson, runtimePackages, workspaceRoot));
100
- const missingDev = Object.fromEntries(getMissingPackages(packageJson, devPackages, workspaceRoot));
101
-
102
- if (Object.keys(missingRuntime).length > 0) {
103
- installPackages(workspaceRoot, missingRuntime, false);
104
- changes += 1;
105
- console.log(`${COLORS.green}✔ Installed missing runtime packages${COLORS.reset}`);
106
- }
107
-
108
- if (Object.keys(missingDev).length > 0) {
109
- installPackages(workspaceRoot, missingDev, true);
110
- changes += 1;
111
- console.log(`${COLORS.green}✔ Installed missing dev packages${COLORS.reset}`);
112
- }
113
-
114
- if (Object.keys(missingRuntime).length === 0 && Object.keys(missingDev).length === 0) {
115
- console.log(`${COLORS.dim}↷ Dependencies already satisfied${COLORS.reset}`);
116
- }
117
- } else {
118
- console.log(`${COLORS.dim}↷ Skipped dependency install (--no-install)${COLORS.reset}`);
119
- }
120
-
121
- const pathsJsonPath = resolveTargetPath(workspaceRoot, selectedApp, '.tailjng/paths.json', true);
122
- if (writeFileSafe(pathsJsonPath, buildPathsJson(componentsPath), false)) {
123
- changes += 1;
124
- console.log(`${COLORS.green}✔ Created ${path.relative(workspaceRoot, pathsJsonPath)}${COLORS.reset}`);
125
- }
126
-
127
- const pathsReadmePath = resolveTargetPath(workspaceRoot, selectedApp, '.tailjng/README.md', true);
128
- if (writeFileSafe(pathsReadmePath, buildPathsReadme(), false)) {
129
- changes += 1;
130
- console.log(`${COLORS.green}✔ Created ${path.relative(workspaceRoot, pathsReadmePath)}${COLORS.reset}`);
131
- }
132
-
133
- const colorsResult = ensureProjectColorsConfig(workspaceRoot, appRoot, false);
134
- if (colorsResult.created > 0) {
135
- changes += colorsResult.created;
136
- } else if (colorsResult.skipped === COLORS_FILES.length) {
137
- console.log(`${COLORS.dim}↷ Project colors config already present${COLORS.reset}`);
138
- }
139
-
140
- const safelistImport = getTailjngSafelistCssImport(workspaceRoot, primaryStylePath, selectedApp);
141
- const safelistPatched = ensureTailjngSafelistImport(primaryStyleFullPath, safelistImport);
142
- if (safelistPatched.changed) {
143
- changes += 1;
144
- const label = safelistPatched.migrated
145
- ? 'Migrated colors safelist to project folder'
146
- : 'Added tailjng colors safelist';
147
- console.log(`${COLORS.green}✔ ${label} → ${path.relative(workspaceRoot, primaryStyleFullPath)}${COLORS.reset}`);
148
- } else {
149
- console.log(`${COLORS.dim}↷ Colors safelist already in styles${COLORS.reset}`);
150
- }
151
-
152
- const stylesPatched = ensureTailjngStylesInAngularJson(angularJsonPath, selectedApp.name, styleLanguage);
153
- if (stylesPatched.changed) {
154
- changes += 1;
155
- console.log(`${COLORS.green}✔ Added node_modules/tailjng/src/styles.css to angular.json${COLORS.reset}`);
156
- } else {
157
- console.log(`${COLORS.dim}↷ tailjng styles already in angular.json${COLORS.reset}`);
158
- }
159
-
160
- if (fileExists(appConfigPath)) {
161
- const patched = patchAppConfig(appConfigPath);
162
- if (patched.changed) {
163
- changes += 1;
164
- console.log(`${COLORS.green}✔ Patched app.config.ts (added tailjngProviders)${COLORS.reset}`);
165
- }
166
-
167
- const colorsPatched = patchAppConfigColors(appConfigPath, srcRoot);
168
- if (colorsPatched.changed) {
169
- changes += 1;
170
- console.log(`${COLORS.green}✔ Linked tailjngColorsProvider from src/app/tailjng/colors/${COLORS.reset}`);
171
- }
172
- }
173
-
174
- if (patchIndexHtml(indexPath)) {
175
- changes += 1;
176
- console.log(`${COLORS.green}✔ Patched index.html (body classes)${COLORS.reset}`);
177
- }
178
-
179
- console.log(`\n${COLORS.greenBright}${COLORS.bright}[tailjng CLI] sync:app completed.${COLORS.reset}`);
180
- console.log(`${COLORS.dim}Changes applied: ${changes}${COLORS.reset}`);
181
-
182
- if (changes === 0) {
183
- console.log(`${COLORS.cyan}Project already up to date with this tailjng version.${COLORS.reset}`);
184
- }
185
-
186
- console.log(`\n${COLORS.dim}Tip: update UI components with ${COLORS.cyan}npx tailjng add <name>${COLORS.reset}${COLORS.dim} (asks before overwrite).${COLORS.reset}\n`);
187
- }
188
-
189
- runSyncApp().catch((error) => {
190
- console.error(`${COLORS.red}[tailjng CLI] sync:app failed:${COLORS.reset}`, error);
191
- process.exit(1);
192
- });
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { COLORS } = require('../settings/colors');
4
+ const { RUNTIME_PACKAGES, DEV_PACKAGES, installPackages } = require('../settings/init-packages');
5
+ const { buildPathsJson, buildPathsReadme } = require('../templates/app.generator');
6
+ const {
7
+ findAngularWorkspace,
8
+ readJson,
9
+ getApplicationProjects,
10
+ resolveAppPaths,
11
+ getBuildOptions,
12
+ detectStyleLanguage,
13
+ getPrimaryStyleEntry,
14
+ writeFileSafe,
15
+ ensureTailjngStylesInAngularJson,
16
+ patchIndexHtml,
17
+ patchAppConfig,
18
+ getMissingPackages,
19
+ resolveRuntimePackages,
20
+ resolveDevPackages,
21
+ hasTailwindSetup,
22
+ getTailjngSafelistCssImport,
23
+ ensureTailjngSafelistImport,
24
+ alignAngularAnimationsInPackageJson,
25
+ resolveStyleFilePath,
26
+ fileExists,
27
+ } = require('../settings/project-utils');
28
+ const {
29
+ ensureProjectColorsConfig,
30
+ patchAppConfigColors,
31
+ COLORS_FILES,
32
+ } = require('../settings/colors-config-utils');
33
+
34
+ function resolveTargetPath(workspaceRoot, appProject, relativePath, appRootRelative = false) {
35
+ const appRoot = path.join(workspaceRoot, appProject.root || '');
36
+
37
+ if (appRootRelative) {
38
+ return path.join(appRoot, relativePath);
39
+ }
40
+
41
+ if (relativePath.startsWith('projects/')) {
42
+ return path.join(workspaceRoot, relativePath);
43
+ }
44
+
45
+ return path.join(workspaceRoot, appProject.sourceRoot, relativePath.replace(/^src\//, ''));
46
+ }
47
+
48
+ async function runSyncApp() {
49
+ const workspace = findAngularWorkspace(process.cwd());
50
+
51
+ if (!workspace) {
52
+ console.error(`${COLORS.red}[tailjng CLI] ERROR: angular.json not found. Run this inside an Angular project.${COLORS.reset}`);
53
+ process.exit(1);
54
+ }
55
+
56
+ const { workspaceRoot, angularJsonPath } = workspace;
57
+ const angularJson = readJson(angularJsonPath);
58
+ const apps = getApplicationProjects(angularJson);
59
+
60
+ if (apps.length === 0) {
61
+ console.error(`${COLORS.red}[tailjng CLI] ERROR: No application project found in angular.json.${COLORS.reset}`);
62
+ process.exit(1);
63
+ }
64
+
65
+ const selectedApp = apps[0];
66
+ const { appRoot, srcRoot } = resolveAppPaths(workspaceRoot, selectedApp);
67
+ const buildOptions = getBuildOptions(angularJson, selectedApp.name);
68
+ const styleLanguage = detectStyleLanguage(buildOptions);
69
+ const primaryStylePath = getPrimaryStyleEntry(buildOptions);
70
+ const primaryStyleFullPath = resolveStyleFilePath(workspaceRoot, primaryStylePath, selectedApp);
71
+ const indexPath = path.join(workspaceRoot, buildOptions.index || path.join(selectedApp.sourceRoot, 'index.html'));
72
+ const appConfigPath = path.join(srcRoot, 'app', 'app.config.ts');
73
+ const packageJsonPath = path.join(workspaceRoot, 'package.json');
74
+ const packageJson = fileExists(packageJsonPath) ? readJson(packageJsonPath) : { dependencies: {}, devDependencies: {} };
75
+ const tailwindReady = hasTailwindSetup(workspaceRoot, packageJson, primaryStylePath);
76
+ const installDeps = !process.argv.includes('--no-install');
77
+ const componentsPath = 'src/app/tailjng';
78
+
79
+ console.log(`\n${COLORS.bright}${COLORS.blue}[tailjng CLI] sync:app${COLORS.reset}`);
80
+ console.log(`${COLORS.dim}Updates integration only — does not overwrite your config (environment, providers, styles).${COLORS.reset}`);
81
+ console.log(`${COLORS.dim}Workspace: ${workspaceRoot} | App: ${selectedApp.name}${COLORS.reset}\n`);
82
+
83
+ if (!packageJson.dependencies?.tailjng) {
84
+ console.log(`${COLORS.yellow}[tailjng CLI] WARNING: tailjng is not in package.json. Run: npm install tailjng@latest --legacy-peer-deps${COLORS.reset}`);
85
+ }
86
+
87
+ let changes = 0;
88
+
89
+ const animationsAligned = alignAngularAnimationsInPackageJson(workspaceRoot);
90
+ if (animationsAligned.changed) {
91
+ changes += 1;
92
+ console.log(`${COLORS.green}✔ Aligned @angular/animations → ${animationsAligned.version}${COLORS.reset}`);
93
+ Object.assign(packageJson, readJson(packageJsonPath));
94
+ }
95
+
96
+ if (installDeps) {
97
+ const runtimePackages = resolveRuntimePackages(packageJson, RUNTIME_PACKAGES, workspaceRoot);
98
+ const devPackages = resolveDevPackages(packageJson, DEV_PACKAGES, tailwindReady);
99
+ const missingRuntime = Object.fromEntries(getMissingPackages(packageJson, runtimePackages, workspaceRoot));
100
+ const missingDev = Object.fromEntries(getMissingPackages(packageJson, devPackages, workspaceRoot));
101
+
102
+ if (Object.keys(missingRuntime).length > 0) {
103
+ installPackages(workspaceRoot, missingRuntime, false);
104
+ changes += 1;
105
+ console.log(`${COLORS.green}✔ Installed missing runtime packages${COLORS.reset}`);
106
+ }
107
+
108
+ if (Object.keys(missingDev).length > 0) {
109
+ installPackages(workspaceRoot, missingDev, true);
110
+ changes += 1;
111
+ console.log(`${COLORS.green}✔ Installed missing dev packages${COLORS.reset}`);
112
+ }
113
+
114
+ if (Object.keys(missingRuntime).length === 0 && Object.keys(missingDev).length === 0) {
115
+ console.log(`${COLORS.dim}↷ Dependencies already satisfied${COLORS.reset}`);
116
+ }
117
+ } else {
118
+ console.log(`${COLORS.dim}↷ Skipped dependency install (--no-install)${COLORS.reset}`);
119
+ }
120
+
121
+ const pathsJsonPath = resolveTargetPath(workspaceRoot, selectedApp, '.tailjng/paths.json', true);
122
+ if (writeFileSafe(pathsJsonPath, buildPathsJson(componentsPath), false)) {
123
+ changes += 1;
124
+ console.log(`${COLORS.green}✔ Created ${path.relative(workspaceRoot, pathsJsonPath)}${COLORS.reset}`);
125
+ }
126
+
127
+ const pathsReadmePath = resolveTargetPath(workspaceRoot, selectedApp, '.tailjng/README.md', true);
128
+ if (writeFileSafe(pathsReadmePath, buildPathsReadme(), false)) {
129
+ changes += 1;
130
+ console.log(`${COLORS.green}✔ Created ${path.relative(workspaceRoot, pathsReadmePath)}${COLORS.reset}`);
131
+ }
132
+
133
+ const colorsResult = ensureProjectColorsConfig(workspaceRoot, appRoot, false);
134
+ if (colorsResult.created > 0) {
135
+ changes += colorsResult.created;
136
+ } else if (colorsResult.skipped === COLORS_FILES.length) {
137
+ console.log(`${COLORS.dim}↷ Project colors config already present${COLORS.reset}`);
138
+ }
139
+
140
+ const safelistImport = getTailjngSafelistCssImport(workspaceRoot, primaryStylePath, selectedApp);
141
+ const safelistPatched = ensureTailjngSafelistImport(primaryStyleFullPath, safelistImport);
142
+ if (safelistPatched.changed) {
143
+ changes += 1;
144
+ const label = safelistPatched.migrated
145
+ ? 'Migrated colors safelist to project folder'
146
+ : 'Added tailjng colors safelist';
147
+ console.log(`${COLORS.green}✔ ${label} → ${path.relative(workspaceRoot, primaryStyleFullPath)}${COLORS.reset}`);
148
+ } else {
149
+ console.log(`${COLORS.dim}↷ Colors safelist already in styles${COLORS.reset}`);
150
+ }
151
+
152
+ const stylesPatched = ensureTailjngStylesInAngularJson(angularJsonPath, selectedApp.name, styleLanguage);
153
+ if (stylesPatched.changed) {
154
+ changes += 1;
155
+ console.log(`${COLORS.green}✔ Added node_modules/tailjng/src/styles.css to angular.json${COLORS.reset}`);
156
+ } else {
157
+ console.log(`${COLORS.dim}↷ tailjng styles already in angular.json${COLORS.reset}`);
158
+ }
159
+
160
+ if (fileExists(appConfigPath)) {
161
+ const patched = patchAppConfig(appConfigPath);
162
+ if (patched.changed) {
163
+ changes += 1;
164
+ console.log(`${COLORS.green}✔ Patched app.config.ts (added tailjngProviders)${COLORS.reset}`);
165
+ }
166
+
167
+ const colorsPatched = patchAppConfigColors(appConfigPath, srcRoot);
168
+ if (colorsPatched.changed) {
169
+ changes += 1;
170
+ console.log(`${COLORS.green}✔ Linked tailjngColorsProvider from src/app/tailjng/colors/${COLORS.reset}`);
171
+ }
172
+ }
173
+
174
+ if (patchIndexHtml(indexPath)) {
175
+ changes += 1;
176
+ console.log(`${COLORS.green}✔ Patched index.html (body classes)${COLORS.reset}`);
177
+ }
178
+
179
+ console.log(`\n${COLORS.greenBright}${COLORS.bright}[tailjng CLI] sync:app completed.${COLORS.reset}`);
180
+ console.log(`${COLORS.dim}Changes applied: ${changes}${COLORS.reset}`);
181
+
182
+ if (changes === 0) {
183
+ console.log(`${COLORS.cyan}Project already up to date with this tailjng version.${COLORS.reset}`);
184
+ }
185
+
186
+ console.log(`\n${COLORS.dim}Tip: update UI components with ${COLORS.cyan}npx tailjng add <name>${COLORS.reset}${COLORS.dim} (asks before overwrite).${COLORS.reset}\n`);
187
+ }
188
+
189
+ runSyncApp().catch((error) => {
190
+ console.error(`${COLORS.red}[tailjng CLI] sync:app failed:${COLORS.reset}`, error);
191
+ process.exit(1);
192
+ });