tailjng 0.1.0 → 0.1.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/README.md CHANGED
@@ -41,9 +41,10 @@ El CLI instala **dependencias transitivas** automáticamente (ej. `button` → `
41
41
 
42
42
  ## Requisitos
43
43
 
44
- - Angular **19.2+**
45
- - Tailwind CSS **4.x**
44
+ - Angular **19.2+** (19.x dentro del mismo major; no Angular 20/21 aún)
45
+ - Tailwind CSS **4.x** (incluido si eliges Tailwind al crear el proyecto con `ng new`)
46
46
  - Peers: `lucide-angular`, `date-fns`, `exceljs`, `xlsx` (el CLI los instala con `init:app` si faltan)
47
+ - Estilos globales en **CSS o SCSS** — `init:app` detecta cuál usa tu app
47
48
 
48
49
  ---
49
50
 
@@ -20,11 +20,13 @@ const {
20
20
  patchAppConfig,
21
21
  patchAppComponentForAlerts,
22
22
  getMissingPackages,
23
+ resolveRuntimePackages,
24
+ resolveDevPackages,
25
+ hasTailwindSetup,
23
26
  fileExists,
24
27
  } = require('../settings/project-utils');
25
28
 
26
29
  const RUNTIME_PACKAGES = {
27
- '@angular/animations': '^19.2.0',
28
30
  'lucide-angular': '^0.525.0',
29
31
  '@ng-icons/lucide': '>=32.0.0',
30
32
  'date-fns': '^4.1.0',
@@ -82,10 +84,19 @@ function installPackages(workspaceRoot, packages, isDev = false) {
82
84
  const flag = isDev ? '--save-dev' : '--save';
83
85
  console.log(`${COLORS.blue}[tailjng CLI] Installing ${isDev ? 'dev ' : ''}dependencies...${COLORS.reset}`);
84
86
 
87
+ const run = (extra = '') => {
88
+ execSync(`npm install ${flag} ${extra} ${spec}`.replace(/\s+/g, ' ').trim(), {
89
+ cwd: workspaceRoot,
90
+ stdio: 'inherit',
91
+ shell: true,
92
+ });
93
+ };
94
+
85
95
  try {
86
- execSync(`npm install ${flag} ${spec}`, { cwd: workspaceRoot, stdio: 'inherit' });
96
+ run();
87
97
  } catch {
88
- execSync(`npm install ${flag} ${spec}`, { cwd: workspaceRoot, stdio: 'inherit', shell: true });
98
+ console.log(`${COLORS.yellow}[tailjng CLI] Retrying with --legacy-peer-deps...${COLORS.reset}`);
99
+ run('--legacy-peer-deps');
89
100
  }
90
101
  }
91
102
 
@@ -158,6 +169,7 @@ async function runInitApp() {
158
169
 
159
170
  const packageJsonPath = path.join(workspaceRoot, 'package.json');
160
171
  const packageJson = fileExists(packageJsonPath) ? readJson(packageJsonPath) : { dependencies: {}, devDependencies: {} };
172
+ const tailwindReady = hasTailwindSetup(workspaceRoot, packageJson, primaryStylePath);
161
173
 
162
174
  if (!packageJson.dependencies?.tailjng) {
163
175
  console.log(`${COLORS.yellow}[tailjng CLI] WARNING: tailjng is not in package.json dependencies.${COLORS.reset}`);
@@ -165,8 +177,19 @@ async function runInitApp() {
165
177
  }
166
178
 
167
179
  if (installDeps) {
168
- const missingRuntime = Object.fromEntries(getMissingPackages(packageJson, RUNTIME_PACKAGES));
169
- const missingDev = Object.fromEntries(getMissingPackages(packageJson, DEV_PACKAGES));
180
+ if (tailwindReady) {
181
+ console.log(`${COLORS.cyan}[tailjng CLI] Tailwind already configured — skipping Tailwind/PostCSS packages and .postcssrc.json${COLORS.reset}`);
182
+ }
183
+
184
+ const runtimePackages = resolveRuntimePackages(packageJson, RUNTIME_PACKAGES);
185
+ const devPackages = resolveDevPackages(packageJson, DEV_PACKAGES, tailwindReady);
186
+ const missingRuntime = Object.fromEntries(getMissingPackages(packageJson, runtimePackages));
187
+ const missingDev = Object.fromEntries(getMissingPackages(packageJson, devPackages));
188
+
189
+ if (missingRuntime['@angular/animations']) {
190
+ console.log(`${COLORS.dim}[tailjng CLI] Adding @angular/animations aligned with @angular/core${COLORS.reset}`);
191
+ }
192
+
170
193
  installPackages(workspaceRoot, missingRuntime, false);
171
194
  installPackages(workspaceRoot, missingDev, true);
172
195
  }
@@ -192,6 +215,12 @@ async function runInitApp() {
192
215
  }
193
216
 
194
217
  for (const file of files) {
218
+ if (tailwindReady && file.relativePath === '.postcssrc.json') {
219
+ skipped += 1;
220
+ console.log(`${COLORS.yellow}↷ Skipped (Tailwind already configured) ${file.relativePath}${COLORS.reset}`);
221
+ continue;
222
+ }
223
+
195
224
  const targetPath = resolveTargetPath(workspaceRoot, selectedApp, file.relativePath, file.appRootRelative);
196
225
  const isPrimaryStyles = file.relativePath === primaryStylePath;
197
226
  const forceWrite = isPrimaryStyles && shouldWriteStyles(targetPath);
@@ -236,6 +265,10 @@ async function runInitApp() {
236
265
  }
237
266
  }
238
267
 
268
+ if (tailwindReady && !shouldWriteStyles(path.join(workspaceRoot, primaryStylePath))) {
269
+ console.log(`${COLORS.yellow}[tailjng CLI] Tip: add tailjng @theme tokens to your existing styles if components look unstyled.${COLORS.reset}`);
270
+ }
271
+
239
272
  console.log(`\n${COLORS.greenBright}${COLORS.bright}[tailjng CLI] init:app completed.${COLORS.reset}`);
240
273
  console.log(`${COLORS.dim}Created: ${created} | Skipped: ${skipped}${COLORS.reset}`);
241
274
  console.log(`\n${COLORS.cyan}Project ready. Install components when you need them:${COLORS.reset}`);
@@ -201,6 +201,72 @@ function getMissingPackages(packageJson, packages) {
201
201
  return Object.entries(packages).filter(([name]) => !deps[name]);
202
202
  }
203
203
 
204
+ function getMergedDependencies(packageJson) {
205
+ return { ...packageJson.dependencies, ...packageJson.devDependencies };
206
+ }
207
+
208
+ /** Alinea @angular/animations con la línea de @angular/core del proyecto (evita ERESOLVE 19.2.0 vs 19.2.25). */
209
+ function resolveRuntimePackages(packageJson, basePackages) {
210
+ const packages = { ...basePackages };
211
+ const deps = getMergedDependencies(packageJson);
212
+
213
+ if (deps['@angular/animations']) {
214
+ delete packages['@angular/animations'];
215
+ } else if (deps['@angular/core']) {
216
+ packages['@angular/animations'] = deps['@angular/core'];
217
+ }
218
+
219
+ return packages;
220
+ }
221
+
222
+ function resolveDevPackages(packageJson, basePackages, tailwindReady) {
223
+ const packages = { ...basePackages };
224
+ if (!tailwindReady) return packages;
225
+
226
+ for (const name of ['tailwindcss', '@tailwindcss/postcss', 'postcss', 'autoprefixer']) {
227
+ if (getMergedDependencies(packageJson)[name]) {
228
+ delete packages[name];
229
+ }
230
+ }
231
+ return packages;
232
+ }
233
+
234
+ function hasTailwindSetup(workspaceRoot, packageJson, primaryStylePath) {
235
+ const deps = getMergedDependencies(packageJson);
236
+ if (deps.tailwindcss || deps['@tailwindcss/postcss']) {
237
+ return true;
238
+ }
239
+
240
+ const postcssConfigs = [
241
+ '.postcssrc.json',
242
+ 'postcss.config.js',
243
+ 'postcss.config.mjs',
244
+ 'postcss.config.cjs',
245
+ ];
246
+
247
+ for (const configName of postcssConfigs) {
248
+ const configPath = path.join(workspaceRoot, configName);
249
+ if (!fs.existsSync(configPath)) continue;
250
+ const content = fs.readFileSync(configPath, 'utf8');
251
+ if (/tailwindcss|@tailwindcss\/postcss/.test(content)) {
252
+ return true;
253
+ }
254
+ }
255
+
256
+ const stylePath = path.isAbsolute(primaryStylePath)
257
+ ? primaryStylePath
258
+ : path.join(workspaceRoot, primaryStylePath);
259
+
260
+ if (fs.existsSync(stylePath)) {
261
+ const content = fs.readFileSync(stylePath, 'utf8');
262
+ if (/tailwindcss/.test(content)) {
263
+ return true;
264
+ }
265
+ }
266
+
267
+ return false;
268
+ }
269
+
204
270
  module.exports = {
205
271
  findAngularWorkspace,
206
272
  readJson,
@@ -216,5 +282,9 @@ module.exports = {
216
282
  patchAppConfig,
217
283
  patchAppComponentForAlerts,
218
284
  getMissingPackages,
285
+ getMergedDependencies,
286
+ resolveRuntimePackages,
287
+ resolveDevPackages,
288
+ hasTailwindSetup,
219
289
  fileExists,
220
290
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailjng",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^19.2.0",
6
6
  "@angular/core": "^19.2.0",
Binary file
package/tailjng-0.1.0.tgz DELETED
Binary file