@julien-lin/universal-pwa-cli 1.1.3 → 1.2.0

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.
Files changed (3) hide show
  1. package/dist/index.cjs +193 -33
  2. package/dist/index.js +192 -32
  3. package/package.json +3 -2
package/dist/index.cjs CHANGED
@@ -25,10 +25,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/index.ts
27
27
  var import_commander = require("commander");
28
- var import_chalk3 = __toESM(require("chalk"), 1);
29
- var import_fs3 = require("fs");
28
+ var import_chalk4 = __toESM(require("chalk"), 1);
29
+ var import_fs4 = require("fs");
30
30
  var import_url = require("url");
31
- var import_path3 = require("path");
31
+ var import_path4 = require("path");
32
32
 
33
33
  // src/commands/init.ts
34
34
  var import_universal_pwa_core = require("@julien-lin/universal-pwa-core");
@@ -96,16 +96,18 @@ async function initCommand(options = {}) {
96
96
  const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? (0, import_path.join)(result.projectPath, "public") : (0, import_path.join)(result.projectPath, "public"));
97
97
  console.log(import_chalk.default.blue("\u{1F4DD} Generating manifest.json..."));
98
98
  const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
99
+ const normalizedShortName = shortName && typeof shortName === "string" && shortName.trim().length > 0 ? shortName.trim() : void 0;
99
100
  let appShortName;
100
- if (shortName && shortName.length > 0 && shortName.length <= 12) {
101
- appShortName = shortName;
101
+ if (normalizedShortName && normalizedShortName.length > 0 && normalizedShortName.length <= 12) {
102
+ appShortName = normalizedShortName;
102
103
  } else {
103
104
  const fallbackName = appName && appName.length > 0 ? appName : "My PWA";
104
105
  appShortName = fallbackName.substring(0, 12);
105
106
  }
106
- if (!appShortName || appShortName.length === 0) {
107
+ if (!appShortName || appShortName.trim().length === 0) {
107
108
  appShortName = "PWA";
108
109
  }
110
+ appShortName = String(appShortName);
109
111
  let iconPaths = [];
110
112
  if (!skipIcons && iconSource) {
111
113
  const iconSourcePath = (0, import_fs.existsSync)(iconSource) ? iconSource : (0, import_path.join)(result.projectPath, iconSource);
@@ -135,11 +137,12 @@ async function initCommand(options = {}) {
135
137
  result.warnings.push(`Icon source not found: ${iconSourcePath}`);
136
138
  }
137
139
  }
140
+ const finalShortName = appShortName && typeof appShortName === "string" && appShortName.trim().length > 0 ? appShortName.trim().substring(0, 12) : appName && appName.length > 0 ? appName.substring(0, 12) : "PWA";
138
141
  let manifestPath;
139
142
  if (iconPaths.length > 0) {
140
143
  const manifestWithIcons = (0, import_universal_pwa_core2.generateManifest)({
141
144
  name: appName,
142
- shortName: appShortName,
145
+ shortName: finalShortName,
143
146
  startUrl: "/",
144
147
  scope: "/",
145
148
  display: "standalone",
@@ -159,7 +162,7 @@ async function initCommand(options = {}) {
159
162
  console.log(import_chalk.default.yellow("\u26A0 Generating manifest with placeholder icon"));
160
163
  const manifestMinimal = (0, import_universal_pwa_core2.generateManifest)({
161
164
  name: appName,
162
- shortName: appShortName,
165
+ shortName: finalShortName,
163
166
  startUrl: "/",
164
167
  scope: "/",
165
168
  display: "standalone",
@@ -337,13 +340,147 @@ function previewCommand(options = {}) {
337
340
 
338
341
  // src/index.ts
339
342
  var import_universal_pwa_core8 = require("@julien-lin/universal-pwa-core");
343
+
344
+ // src/prompts.ts
345
+ var import_inquirer = __toESM(require("inquirer"), 1);
346
+ var import_fs3 = require("fs");
347
+ var import_path3 = require("path");
348
+ var import_chalk3 = __toESM(require("chalk"), 1);
349
+ function detectProjectName(projectPath) {
350
+ try {
351
+ const packageJsonPath2 = (0, import_path3.join)(projectPath, "package.json");
352
+ if ((0, import_fs3.existsSync)(packageJsonPath2)) {
353
+ const packageJsonContent = (0, import_fs3.readFileSync)(packageJsonPath2, "utf-8");
354
+ const packageJson = JSON.parse(packageJsonContent);
355
+ return packageJson.name || void 0;
356
+ }
357
+ } catch {
358
+ }
359
+ return void 0;
360
+ }
361
+ function findDefaultIconSource(projectPath) {
362
+ const commonPaths = [
363
+ "public/logo.png",
364
+ "public/icon.png",
365
+ "public/favicon.png",
366
+ "src/assets/logo.png",
367
+ "src/assets/icon.png",
368
+ "assets/logo.png",
369
+ "assets/icon.png",
370
+ "logo.png",
371
+ "icon.png"
372
+ ];
373
+ for (const path of commonPaths) {
374
+ const fullPath = (0, import_path3.join)(projectPath, path);
375
+ if ((0, import_fs3.existsSync)(fullPath)) {
376
+ return path;
377
+ }
378
+ }
379
+ return void 0;
380
+ }
381
+ async function promptInitOptions(projectPath, framework) {
382
+ const detectedName = detectProjectName(projectPath);
383
+ const defaultIconSource = findDefaultIconSource(projectPath);
384
+ const defaultName = detectedName || (framework ? `${framework} App` : "My PWA");
385
+ const defaultShortName = defaultName.substring(0, 12);
386
+ console.log(import_chalk3.default.blue("\n\u{1F4CB} Configuration PWA\n"));
387
+ const answers = await import_inquirer.default.prompt([
388
+ {
389
+ type: "input",
390
+ name: "name",
391
+ message: "Nom de l'application:",
392
+ default: defaultName,
393
+ validate: (input) => {
394
+ if (!input || input.trim().length === 0) {
395
+ return "Le nom de l'application est requis";
396
+ }
397
+ if (input.length > 50) {
398
+ return "Le nom doit faire moins de 50 caract\xE8res";
399
+ }
400
+ return true;
401
+ }
402
+ },
403
+ {
404
+ type: "input",
405
+ name: "shortName",
406
+ message: "Nom court (max 12 caract\xE8res):",
407
+ default: defaultShortName,
408
+ validate: (input) => {
409
+ if (!input || input.trim().length === 0) {
410
+ return "Le nom court est requis";
411
+ }
412
+ if (input.length > 12) {
413
+ return "Le nom court doit faire maximum 12 caract\xE8res";
414
+ }
415
+ return true;
416
+ },
417
+ filter: (input) => input.trim().substring(0, 12)
418
+ },
419
+ {
420
+ type: "input",
421
+ name: "iconSource",
422
+ message: "Chemin vers l'image source pour les ic\xF4nes:",
423
+ default: defaultIconSource,
424
+ validate: (input) => {
425
+ if (!input || input.trim().length === 0) {
426
+ return true;
427
+ }
428
+ const fullPath = (0, import_fs3.existsSync)(input) ? input : (0, import_path3.join)(projectPath, input);
429
+ if (!(0, import_fs3.existsSync)(fullPath)) {
430
+ return `Le fichier n'existe pas: ${input}`;
431
+ }
432
+ return true;
433
+ }
434
+ },
435
+ {
436
+ type: "confirm",
437
+ name: "skipIcons",
438
+ message: "G\xE9n\xE9rer les ic\xF4nes PWA?",
439
+ default: true
440
+ },
441
+ {
442
+ type: "input",
443
+ name: "themeColor",
444
+ message: "Couleur du th\xE8me (hex, ex: #ffffff):",
445
+ default: "#ffffff",
446
+ validate: (input) => {
447
+ if (!input || input.trim().length === 0) {
448
+ return true;
449
+ }
450
+ if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
451
+ return "Format hex invalide (ex: #ffffff)";
452
+ }
453
+ return true;
454
+ }
455
+ },
456
+ {
457
+ type: "input",
458
+ name: "backgroundColor",
459
+ message: "Couleur de fond (hex, ex: #000000):",
460
+ default: "#000000",
461
+ validate: (input) => {
462
+ if (!input || input.trim().length === 0) {
463
+ return true;
464
+ }
465
+ if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
466
+ return "Format hex invalide (ex: #000000)";
467
+ }
468
+ return true;
469
+ }
470
+ }
471
+ ]);
472
+ answers.skipIcons = !answers.skipIcons;
473
+ return answers;
474
+ }
475
+
476
+ // src/index.ts
340
477
  var import_meta = {};
341
478
  var __filename = (0, import_url.fileURLToPath)(import_meta.url);
342
- var __dirname = (0, import_path3.dirname)(__filename);
343
- var packageJsonPath = (0, import_path3.join)(__dirname, "../package.json");
479
+ var __dirname = (0, import_path4.dirname)(__filename);
480
+ var packageJsonPath = (0, import_path4.join)(__dirname, "../package.json");
344
481
  var version = "0.0.0";
345
482
  try {
346
- const packageJsonContent = (0, import_fs3.readFileSync)(packageJsonPath, "utf-8");
483
+ const packageJsonContent = (0, import_fs4.readFileSync)(packageJsonPath, "utf-8");
347
484
  const packageJson = JSON.parse(packageJsonContent);
348
485
  version = packageJson.version || "0.0.0";
349
486
  } catch {
@@ -353,21 +490,44 @@ var program = new import_commander.Command();
353
490
  program.name("universal-pwa").description("Transform any web project into a PWA with one click").version(version);
354
491
  program.command("init").description("Initialize PWA in your project").option("-p, --project-path <path>", "Project path", process.cwd()).option("-n, --name <name>", "App name").option("-s, --short-name <shortName>", "App short name (max 12 chars)").option("-i, --icon-source <path>", "Source image for icons").option("-t, --theme-color <color>", "Theme color (hex)").option("-b, --background-color <color>", "Background color (hex)").option("--skip-icons", "Skip icon generation").option("--skip-service-worker", "Skip service worker generation").option("--skip-injection", "Skip HTML meta-tag injection").option("-o, --output-dir <dir>", "Output directory", "public").action(async (options) => {
355
492
  try {
493
+ const projectPath = options.projectPath ?? process.cwd();
494
+ const hasOptions = options.name || options.shortName || options.iconSource || options.themeColor || options.backgroundColor || options.skipIcons !== void 0;
495
+ let finalOptions = { ...options };
496
+ if (!hasOptions) {
497
+ console.log(import_chalk4.default.blue("\u{1F50D} Scanning project..."));
498
+ const scanResult = await (0, import_universal_pwa_core8.scanProject)({
499
+ projectPath,
500
+ includeAssets: false,
501
+ includeArchitecture: false
502
+ });
503
+ console.log(import_chalk4.default.green(`\u2713 Framework detected: ${scanResult.framework.framework ?? "Unknown"}`));
504
+ console.log(import_chalk4.default.green(`\u2713 Architecture: ${scanResult.architecture.architecture}`));
505
+ const promptAnswers = await promptInitOptions(projectPath, scanResult.framework.framework);
506
+ finalOptions = {
507
+ ...options,
508
+ name: promptAnswers.name,
509
+ shortName: promptAnswers.shortName,
510
+ iconSource: promptAnswers.iconSource || void 0,
511
+ themeColor: promptAnswers.themeColor || void 0,
512
+ backgroundColor: promptAnswers.backgroundColor || void 0,
513
+ skipIcons: promptAnswers.skipIcons
514
+ };
515
+ }
356
516
  const result = await initCommand({
357
- projectPath: options.projectPath,
358
- name: options.name,
359
- shortName: options.shortName,
360
- iconSource: options.iconSource,
361
- themeColor: options.themeColor,
362
- backgroundColor: options.backgroundColor,
363
- skipIcons: options.skipIcons,
364
- skipServiceWorker: options.skipServiceWorker,
365
- skipInjection: options.skipInjection,
366
- outputDir: options.outputDir
517
+ projectPath: finalOptions.projectPath,
518
+ name: finalOptions.name,
519
+ shortName: finalOptions.shortName,
520
+ iconSource: finalOptions.iconSource,
521
+ themeColor: finalOptions.themeColor,
522
+ backgroundColor: finalOptions.backgroundColor,
523
+ skipIcons: finalOptions.skipIcons,
524
+ skipServiceWorker: finalOptions.skipServiceWorker,
525
+ skipInjection: finalOptions.skipInjection,
526
+ outputDir: finalOptions.outputDir
367
527
  });
368
528
  process.exit(result.success ? 0 : 1);
369
529
  } catch (error) {
370
- console.error(import_chalk3.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
530
+ console.error(import_chalk4.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
371
531
  process.exit(1);
372
532
  }
373
533
  });
@@ -380,31 +540,31 @@ program.command("preview").description("Preview PWA setup").option("-p, --projec
380
540
  });
381
541
  process.exit(result.success ? 0 : 1);
382
542
  } catch (error) {
383
- console.error(import_chalk3.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
543
+ console.error(import_chalk4.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
384
544
  process.exit(1);
385
545
  }
386
546
  });
387
547
  program.command("scan").description("Scan project and detect framework/architecture").option("-p, --project-path <path>", "Project path", process.cwd()).action(async (options) => {
388
548
  try {
389
- console.log(import_chalk3.default.blue("\u{1F50D} Scanning project..."));
549
+ console.log(import_chalk4.default.blue("\u{1F50D} Scanning project..."));
390
550
  const result = await (0, import_universal_pwa_core8.scanProject)({
391
551
  projectPath: options.projectPath ?? process.cwd(),
392
552
  includeAssets: true,
393
553
  includeArchitecture: true
394
554
  });
395
- console.log(import_chalk3.default.green(`
555
+ console.log(import_chalk4.default.green(`
396
556
  \u2713 Framework: ${result.framework.framework ?? "Unknown"}`));
397
- console.log(import_chalk3.default.green(`\u2713 Architecture: ${result.architecture.architecture}`));
398
- console.log(import_chalk3.default.green(`\u2713 Build Tool: ${result.architecture.buildTool ?? "Unknown"}`));
399
- console.log(import_chalk3.default.gray(`
557
+ console.log(import_chalk4.default.green(`\u2713 Architecture: ${result.architecture.architecture}`));
558
+ console.log(import_chalk4.default.green(`\u2713 Build Tool: ${result.architecture.buildTool ?? "Unknown"}`));
559
+ console.log(import_chalk4.default.gray(`
400
560
  Assets found:`));
401
- console.log(import_chalk3.default.gray(` - JavaScript: ${result.assets.javascript.length} files`));
402
- console.log(import_chalk3.default.gray(` - CSS: ${result.assets.css.length} files`));
403
- console.log(import_chalk3.default.gray(` - Images: ${result.assets.images.length} files`));
404
- console.log(import_chalk3.default.gray(` - Fonts: ${result.assets.fonts.length} files`));
561
+ console.log(import_chalk4.default.gray(` - JavaScript: ${result.assets.javascript.length} files`));
562
+ console.log(import_chalk4.default.gray(` - CSS: ${result.assets.css.length} files`));
563
+ console.log(import_chalk4.default.gray(` - Images: ${result.assets.images.length} files`));
564
+ console.log(import_chalk4.default.gray(` - Fonts: ${result.assets.fonts.length} files`));
405
565
  process.exit(0);
406
566
  } catch (error) {
407
- console.error(import_chalk3.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
567
+ console.error(import_chalk4.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
408
568
  process.exit(1);
409
569
  }
410
570
  });
package/dist/index.js CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk3 from "chalk";
6
- import { readFileSync } from "fs";
5
+ import chalk4 from "chalk";
6
+ import { readFileSync as readFileSync2 } from "fs";
7
7
  import { fileURLToPath } from "url";
8
- import { dirname, join as join3 } from "path";
8
+ import { dirname, join as join4 } from "path";
9
9
 
10
10
  // src/commands/init.ts
11
11
  import { scanProject } from "@julien-lin/universal-pwa-core";
@@ -73,16 +73,18 @@ async function initCommand(options = {}) {
73
73
  const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? join(result.projectPath, "public") : join(result.projectPath, "public"));
74
74
  console.log(chalk.blue("\u{1F4DD} Generating manifest.json..."));
75
75
  const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
76
+ const normalizedShortName = shortName && typeof shortName === "string" && shortName.trim().length > 0 ? shortName.trim() : void 0;
76
77
  let appShortName;
77
- if (shortName && shortName.length > 0 && shortName.length <= 12) {
78
- appShortName = shortName;
78
+ if (normalizedShortName && normalizedShortName.length > 0 && normalizedShortName.length <= 12) {
79
+ appShortName = normalizedShortName;
79
80
  } else {
80
81
  const fallbackName = appName && appName.length > 0 ? appName : "My PWA";
81
82
  appShortName = fallbackName.substring(0, 12);
82
83
  }
83
- if (!appShortName || appShortName.length === 0) {
84
+ if (!appShortName || appShortName.trim().length === 0) {
84
85
  appShortName = "PWA";
85
86
  }
87
+ appShortName = String(appShortName);
86
88
  let iconPaths = [];
87
89
  if (!skipIcons && iconSource) {
88
90
  const iconSourcePath = existsSync(iconSource) ? iconSource : join(result.projectPath, iconSource);
@@ -112,11 +114,12 @@ async function initCommand(options = {}) {
112
114
  result.warnings.push(`Icon source not found: ${iconSourcePath}`);
113
115
  }
114
116
  }
117
+ const finalShortName = appShortName && typeof appShortName === "string" && appShortName.trim().length > 0 ? appShortName.trim().substring(0, 12) : appName && appName.length > 0 ? appName.substring(0, 12) : "PWA";
115
118
  let manifestPath;
116
119
  if (iconPaths.length > 0) {
117
120
  const manifestWithIcons = generateManifest({
118
121
  name: appName,
119
- shortName: appShortName,
122
+ shortName: finalShortName,
120
123
  startUrl: "/",
121
124
  scope: "/",
122
125
  display: "standalone",
@@ -136,7 +139,7 @@ async function initCommand(options = {}) {
136
139
  console.log(chalk.yellow("\u26A0 Generating manifest with placeholder icon"));
137
140
  const manifestMinimal = generateManifest({
138
141
  name: appName,
139
- shortName: appShortName,
142
+ shortName: finalShortName,
140
143
  startUrl: "/",
141
144
  scope: "/",
142
145
  display: "standalone",
@@ -314,12 +317,146 @@ function previewCommand(options = {}) {
314
317
 
315
318
  // src/index.ts
316
319
  import { scanProject as scanProject2 } from "@julien-lin/universal-pwa-core";
320
+
321
+ // src/prompts.ts
322
+ import inquirer from "inquirer";
323
+ import { existsSync as existsSync3, readFileSync } from "fs";
324
+ import { join as join3 } from "path";
325
+ import chalk3 from "chalk";
326
+ function detectProjectName(projectPath) {
327
+ try {
328
+ const packageJsonPath2 = join3(projectPath, "package.json");
329
+ if (existsSync3(packageJsonPath2)) {
330
+ const packageJsonContent = readFileSync(packageJsonPath2, "utf-8");
331
+ const packageJson = JSON.parse(packageJsonContent);
332
+ return packageJson.name || void 0;
333
+ }
334
+ } catch {
335
+ }
336
+ return void 0;
337
+ }
338
+ function findDefaultIconSource(projectPath) {
339
+ const commonPaths = [
340
+ "public/logo.png",
341
+ "public/icon.png",
342
+ "public/favicon.png",
343
+ "src/assets/logo.png",
344
+ "src/assets/icon.png",
345
+ "assets/logo.png",
346
+ "assets/icon.png",
347
+ "logo.png",
348
+ "icon.png"
349
+ ];
350
+ for (const path of commonPaths) {
351
+ const fullPath = join3(projectPath, path);
352
+ if (existsSync3(fullPath)) {
353
+ return path;
354
+ }
355
+ }
356
+ return void 0;
357
+ }
358
+ async function promptInitOptions(projectPath, framework) {
359
+ const detectedName = detectProjectName(projectPath);
360
+ const defaultIconSource = findDefaultIconSource(projectPath);
361
+ const defaultName = detectedName || (framework ? `${framework} App` : "My PWA");
362
+ const defaultShortName = defaultName.substring(0, 12);
363
+ console.log(chalk3.blue("\n\u{1F4CB} Configuration PWA\n"));
364
+ const answers = await inquirer.prompt([
365
+ {
366
+ type: "input",
367
+ name: "name",
368
+ message: "Nom de l'application:",
369
+ default: defaultName,
370
+ validate: (input) => {
371
+ if (!input || input.trim().length === 0) {
372
+ return "Le nom de l'application est requis";
373
+ }
374
+ if (input.length > 50) {
375
+ return "Le nom doit faire moins de 50 caract\xE8res";
376
+ }
377
+ return true;
378
+ }
379
+ },
380
+ {
381
+ type: "input",
382
+ name: "shortName",
383
+ message: "Nom court (max 12 caract\xE8res):",
384
+ default: defaultShortName,
385
+ validate: (input) => {
386
+ if (!input || input.trim().length === 0) {
387
+ return "Le nom court est requis";
388
+ }
389
+ if (input.length > 12) {
390
+ return "Le nom court doit faire maximum 12 caract\xE8res";
391
+ }
392
+ return true;
393
+ },
394
+ filter: (input) => input.trim().substring(0, 12)
395
+ },
396
+ {
397
+ type: "input",
398
+ name: "iconSource",
399
+ message: "Chemin vers l'image source pour les ic\xF4nes:",
400
+ default: defaultIconSource,
401
+ validate: (input) => {
402
+ if (!input || input.trim().length === 0) {
403
+ return true;
404
+ }
405
+ const fullPath = existsSync3(input) ? input : join3(projectPath, input);
406
+ if (!existsSync3(fullPath)) {
407
+ return `Le fichier n'existe pas: ${input}`;
408
+ }
409
+ return true;
410
+ }
411
+ },
412
+ {
413
+ type: "confirm",
414
+ name: "skipIcons",
415
+ message: "G\xE9n\xE9rer les ic\xF4nes PWA?",
416
+ default: true
417
+ },
418
+ {
419
+ type: "input",
420
+ name: "themeColor",
421
+ message: "Couleur du th\xE8me (hex, ex: #ffffff):",
422
+ default: "#ffffff",
423
+ validate: (input) => {
424
+ if (!input || input.trim().length === 0) {
425
+ return true;
426
+ }
427
+ if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
428
+ return "Format hex invalide (ex: #ffffff)";
429
+ }
430
+ return true;
431
+ }
432
+ },
433
+ {
434
+ type: "input",
435
+ name: "backgroundColor",
436
+ message: "Couleur de fond (hex, ex: #000000):",
437
+ default: "#000000",
438
+ validate: (input) => {
439
+ if (!input || input.trim().length === 0) {
440
+ return true;
441
+ }
442
+ if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
443
+ return "Format hex invalide (ex: #000000)";
444
+ }
445
+ return true;
446
+ }
447
+ }
448
+ ]);
449
+ answers.skipIcons = !answers.skipIcons;
450
+ return answers;
451
+ }
452
+
453
+ // src/index.ts
317
454
  var __filename = fileURLToPath(import.meta.url);
318
455
  var __dirname = dirname(__filename);
319
- var packageJsonPath = join3(__dirname, "../package.json");
456
+ var packageJsonPath = join4(__dirname, "../package.json");
320
457
  var version = "0.0.0";
321
458
  try {
322
- const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
459
+ const packageJsonContent = readFileSync2(packageJsonPath, "utf-8");
323
460
  const packageJson = JSON.parse(packageJsonContent);
324
461
  version = packageJson.version || "0.0.0";
325
462
  } catch {
@@ -329,21 +466,44 @@ var program = new Command();
329
466
  program.name("universal-pwa").description("Transform any web project into a PWA with one click").version(version);
330
467
  program.command("init").description("Initialize PWA in your project").option("-p, --project-path <path>", "Project path", process.cwd()).option("-n, --name <name>", "App name").option("-s, --short-name <shortName>", "App short name (max 12 chars)").option("-i, --icon-source <path>", "Source image for icons").option("-t, --theme-color <color>", "Theme color (hex)").option("-b, --background-color <color>", "Background color (hex)").option("--skip-icons", "Skip icon generation").option("--skip-service-worker", "Skip service worker generation").option("--skip-injection", "Skip HTML meta-tag injection").option("-o, --output-dir <dir>", "Output directory", "public").action(async (options) => {
331
468
  try {
469
+ const projectPath = options.projectPath ?? process.cwd();
470
+ const hasOptions = options.name || options.shortName || options.iconSource || options.themeColor || options.backgroundColor || options.skipIcons !== void 0;
471
+ let finalOptions = { ...options };
472
+ if (!hasOptions) {
473
+ console.log(chalk4.blue("\u{1F50D} Scanning project..."));
474
+ const scanResult = await scanProject2({
475
+ projectPath,
476
+ includeAssets: false,
477
+ includeArchitecture: false
478
+ });
479
+ console.log(chalk4.green(`\u2713 Framework detected: ${scanResult.framework.framework ?? "Unknown"}`));
480
+ console.log(chalk4.green(`\u2713 Architecture: ${scanResult.architecture.architecture}`));
481
+ const promptAnswers = await promptInitOptions(projectPath, scanResult.framework.framework);
482
+ finalOptions = {
483
+ ...options,
484
+ name: promptAnswers.name,
485
+ shortName: promptAnswers.shortName,
486
+ iconSource: promptAnswers.iconSource || void 0,
487
+ themeColor: promptAnswers.themeColor || void 0,
488
+ backgroundColor: promptAnswers.backgroundColor || void 0,
489
+ skipIcons: promptAnswers.skipIcons
490
+ };
491
+ }
332
492
  const result = await initCommand({
333
- projectPath: options.projectPath,
334
- name: options.name,
335
- shortName: options.shortName,
336
- iconSource: options.iconSource,
337
- themeColor: options.themeColor,
338
- backgroundColor: options.backgroundColor,
339
- skipIcons: options.skipIcons,
340
- skipServiceWorker: options.skipServiceWorker,
341
- skipInjection: options.skipInjection,
342
- outputDir: options.outputDir
493
+ projectPath: finalOptions.projectPath,
494
+ name: finalOptions.name,
495
+ shortName: finalOptions.shortName,
496
+ iconSource: finalOptions.iconSource,
497
+ themeColor: finalOptions.themeColor,
498
+ backgroundColor: finalOptions.backgroundColor,
499
+ skipIcons: finalOptions.skipIcons,
500
+ skipServiceWorker: finalOptions.skipServiceWorker,
501
+ skipInjection: finalOptions.skipInjection,
502
+ outputDir: finalOptions.outputDir
343
503
  });
344
504
  process.exit(result.success ? 0 : 1);
345
505
  } catch (error) {
346
- console.error(chalk3.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
506
+ console.error(chalk4.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
347
507
  process.exit(1);
348
508
  }
349
509
  });
@@ -356,31 +516,31 @@ program.command("preview").description("Preview PWA setup").option("-p, --projec
356
516
  });
357
517
  process.exit(result.success ? 0 : 1);
358
518
  } catch (error) {
359
- console.error(chalk3.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
519
+ console.error(chalk4.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
360
520
  process.exit(1);
361
521
  }
362
522
  });
363
523
  program.command("scan").description("Scan project and detect framework/architecture").option("-p, --project-path <path>", "Project path", process.cwd()).action(async (options) => {
364
524
  try {
365
- console.log(chalk3.blue("\u{1F50D} Scanning project..."));
525
+ console.log(chalk4.blue("\u{1F50D} Scanning project..."));
366
526
  const result = await scanProject2({
367
527
  projectPath: options.projectPath ?? process.cwd(),
368
528
  includeAssets: true,
369
529
  includeArchitecture: true
370
530
  });
371
- console.log(chalk3.green(`
531
+ console.log(chalk4.green(`
372
532
  \u2713 Framework: ${result.framework.framework ?? "Unknown"}`));
373
- console.log(chalk3.green(`\u2713 Architecture: ${result.architecture.architecture}`));
374
- console.log(chalk3.green(`\u2713 Build Tool: ${result.architecture.buildTool ?? "Unknown"}`));
375
- console.log(chalk3.gray(`
533
+ console.log(chalk4.green(`\u2713 Architecture: ${result.architecture.architecture}`));
534
+ console.log(chalk4.green(`\u2713 Build Tool: ${result.architecture.buildTool ?? "Unknown"}`));
535
+ console.log(chalk4.gray(`
376
536
  Assets found:`));
377
- console.log(chalk3.gray(` - JavaScript: ${result.assets.javascript.length} files`));
378
- console.log(chalk3.gray(` - CSS: ${result.assets.css.length} files`));
379
- console.log(chalk3.gray(` - Images: ${result.assets.images.length} files`));
380
- console.log(chalk3.gray(` - Fonts: ${result.assets.fonts.length} files`));
537
+ console.log(chalk4.gray(` - JavaScript: ${result.assets.javascript.length} files`));
538
+ console.log(chalk4.gray(` - CSS: ${result.assets.css.length} files`));
539
+ console.log(chalk4.gray(` - Images: ${result.assets.images.length} files`));
540
+ console.log(chalk4.gray(` - Fonts: ${result.assets.fonts.length} files`));
381
541
  process.exit(0);
382
542
  } catch (error) {
383
- console.error(chalk3.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
543
+ console.error(chalk4.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
384
544
  process.exit(1);
385
545
  }
386
546
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@julien-lin/universal-pwa-cli",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "description": "CLI pour transformer n'importe quel projet web en PWA",
5
5
  "keywords": [
6
6
  "pwa",
@@ -42,9 +42,10 @@
42
42
  "commander": "^12.1.0",
43
43
  "fs-extra": "^11.3.3",
44
44
  "glob": "^13.0.0",
45
+ "inquirer": "^12.0.0",
45
46
  "pino": "^9.14.0",
46
47
  "zod": "^4.2.1",
47
- "@julien-lin/universal-pwa-core": "^1.1.3"
48
+ "@julien-lin/universal-pwa-core": "^1.2.0"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@vitest/coverage-v8": "^2.1.4",