@julien-lin/universal-pwa-cli 1.1.4 → 1.2.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/dist/index.cjs +195 -29
- package/dist/index.js +194 -28
- 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
|
|
29
|
-
var
|
|
28
|
+
var import_chalk4 = __toESM(require("chalk"), 1);
|
|
29
|
+
var import_fs4 = require("fs");
|
|
30
30
|
var import_url = require("url");
|
|
31
|
-
var
|
|
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");
|
|
@@ -137,7 +137,16 @@ async function initCommand(options = {}) {
|
|
|
137
137
|
result.warnings.push(`Icon source not found: ${iconSourcePath}`);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
let finalShortName = "PWA";
|
|
141
|
+
if (appShortName && typeof appShortName === "string" && appShortName.trim().length > 0) {
|
|
142
|
+
finalShortName = appShortName.trim().substring(0, 12);
|
|
143
|
+
} else if (appName && typeof appName === "string" && appName.length > 0) {
|
|
144
|
+
finalShortName = appName.substring(0, 12);
|
|
145
|
+
}
|
|
146
|
+
if (!finalShortName || finalShortName.trim().length === 0) {
|
|
147
|
+
finalShortName = "PWA";
|
|
148
|
+
}
|
|
149
|
+
finalShortName = String(finalShortName).trim().substring(0, 12) || "PWA";
|
|
141
150
|
let manifestPath;
|
|
142
151
|
if (iconPaths.length > 0) {
|
|
143
152
|
const manifestWithIcons = (0, import_universal_pwa_core2.generateManifest)({
|
|
@@ -340,13 +349,147 @@ function previewCommand(options = {}) {
|
|
|
340
349
|
|
|
341
350
|
// src/index.ts
|
|
342
351
|
var import_universal_pwa_core8 = require("@julien-lin/universal-pwa-core");
|
|
352
|
+
|
|
353
|
+
// src/prompts.ts
|
|
354
|
+
var import_inquirer = __toESM(require("inquirer"), 1);
|
|
355
|
+
var import_fs3 = require("fs");
|
|
356
|
+
var import_path3 = require("path");
|
|
357
|
+
var import_chalk3 = __toESM(require("chalk"), 1);
|
|
358
|
+
function detectProjectName(projectPath) {
|
|
359
|
+
try {
|
|
360
|
+
const packageJsonPath2 = (0, import_path3.join)(projectPath, "package.json");
|
|
361
|
+
if ((0, import_fs3.existsSync)(packageJsonPath2)) {
|
|
362
|
+
const packageJsonContent = (0, import_fs3.readFileSync)(packageJsonPath2, "utf-8");
|
|
363
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
364
|
+
return packageJson.name || void 0;
|
|
365
|
+
}
|
|
366
|
+
} catch {
|
|
367
|
+
}
|
|
368
|
+
return void 0;
|
|
369
|
+
}
|
|
370
|
+
function findDefaultIconSource(projectPath) {
|
|
371
|
+
const commonPaths = [
|
|
372
|
+
"public/logo.png",
|
|
373
|
+
"public/icon.png",
|
|
374
|
+
"public/favicon.png",
|
|
375
|
+
"src/assets/logo.png",
|
|
376
|
+
"src/assets/icon.png",
|
|
377
|
+
"assets/logo.png",
|
|
378
|
+
"assets/icon.png",
|
|
379
|
+
"logo.png",
|
|
380
|
+
"icon.png"
|
|
381
|
+
];
|
|
382
|
+
for (const path of commonPaths) {
|
|
383
|
+
const fullPath = (0, import_path3.join)(projectPath, path);
|
|
384
|
+
if ((0, import_fs3.existsSync)(fullPath)) {
|
|
385
|
+
return path;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return void 0;
|
|
389
|
+
}
|
|
390
|
+
async function promptInitOptions(projectPath, framework) {
|
|
391
|
+
const detectedName = detectProjectName(projectPath);
|
|
392
|
+
const defaultIconSource = findDefaultIconSource(projectPath);
|
|
393
|
+
const defaultName = detectedName || (framework ? `${framework} App` : "My PWA");
|
|
394
|
+
const defaultShortName = defaultName.substring(0, 12);
|
|
395
|
+
console.log(import_chalk3.default.blue("\n\u{1F4CB} Configuration PWA\n"));
|
|
396
|
+
const answers = await import_inquirer.default.prompt([
|
|
397
|
+
{
|
|
398
|
+
type: "input",
|
|
399
|
+
name: "name",
|
|
400
|
+
message: "Nom de l'application:",
|
|
401
|
+
default: defaultName,
|
|
402
|
+
validate: (input) => {
|
|
403
|
+
if (!input || input.trim().length === 0) {
|
|
404
|
+
return "Le nom de l'application est requis";
|
|
405
|
+
}
|
|
406
|
+
if (input.length > 50) {
|
|
407
|
+
return "Le nom doit faire moins de 50 caract\xE8res";
|
|
408
|
+
}
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
type: "input",
|
|
414
|
+
name: "shortName",
|
|
415
|
+
message: "Nom court (max 12 caract\xE8res):",
|
|
416
|
+
default: defaultShortName,
|
|
417
|
+
validate: (input) => {
|
|
418
|
+
if (!input || input.trim().length === 0) {
|
|
419
|
+
return "Le nom court est requis";
|
|
420
|
+
}
|
|
421
|
+
if (input.length > 12) {
|
|
422
|
+
return "Le nom court doit faire maximum 12 caract\xE8res";
|
|
423
|
+
}
|
|
424
|
+
return true;
|
|
425
|
+
},
|
|
426
|
+
filter: (input) => input.trim().substring(0, 12)
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
type: "input",
|
|
430
|
+
name: "iconSource",
|
|
431
|
+
message: "Chemin vers l'image source pour les ic\xF4nes:",
|
|
432
|
+
default: defaultIconSource,
|
|
433
|
+
validate: (input) => {
|
|
434
|
+
if (!input || input.trim().length === 0) {
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
const fullPath = (0, import_fs3.existsSync)(input) ? input : (0, import_path3.join)(projectPath, input);
|
|
438
|
+
if (!(0, import_fs3.existsSync)(fullPath)) {
|
|
439
|
+
return `Le fichier n'existe pas: ${input}`;
|
|
440
|
+
}
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
type: "confirm",
|
|
446
|
+
name: "skipIcons",
|
|
447
|
+
message: "G\xE9n\xE9rer les ic\xF4nes PWA?",
|
|
448
|
+
default: true
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
type: "input",
|
|
452
|
+
name: "themeColor",
|
|
453
|
+
message: "Couleur du th\xE8me (hex, ex: #ffffff):",
|
|
454
|
+
default: "#ffffff",
|
|
455
|
+
validate: (input) => {
|
|
456
|
+
if (!input || input.trim().length === 0) {
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
|
|
460
|
+
return "Format hex invalide (ex: #ffffff)";
|
|
461
|
+
}
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
type: "input",
|
|
467
|
+
name: "backgroundColor",
|
|
468
|
+
message: "Couleur de fond (hex, ex: #000000):",
|
|
469
|
+
default: "#000000",
|
|
470
|
+
validate: (input) => {
|
|
471
|
+
if (!input || input.trim().length === 0) {
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
|
|
475
|
+
return "Format hex invalide (ex: #000000)";
|
|
476
|
+
}
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
]);
|
|
481
|
+
answers.skipIcons = !answers.skipIcons;
|
|
482
|
+
return answers;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/index.ts
|
|
343
486
|
var import_meta = {};
|
|
344
487
|
var __filename = (0, import_url.fileURLToPath)(import_meta.url);
|
|
345
|
-
var __dirname = (0,
|
|
346
|
-
var packageJsonPath = (0,
|
|
488
|
+
var __dirname = (0, import_path4.dirname)(__filename);
|
|
489
|
+
var packageJsonPath = (0, import_path4.join)(__dirname, "../package.json");
|
|
347
490
|
var version = "0.0.0";
|
|
348
491
|
try {
|
|
349
|
-
const packageJsonContent = (0,
|
|
492
|
+
const packageJsonContent = (0, import_fs4.readFileSync)(packageJsonPath, "utf-8");
|
|
350
493
|
const packageJson = JSON.parse(packageJsonContent);
|
|
351
494
|
version = packageJson.version || "0.0.0";
|
|
352
495
|
} catch {
|
|
@@ -356,21 +499,44 @@ var program = new import_commander.Command();
|
|
|
356
499
|
program.name("universal-pwa").description("Transform any web project into a PWA with one click").version(version);
|
|
357
500
|
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) => {
|
|
358
501
|
try {
|
|
502
|
+
const projectPath = options.projectPath ?? process.cwd();
|
|
503
|
+
const hasOptions = options.name || options.shortName || options.iconSource || options.themeColor || options.backgroundColor || options.skipIcons !== void 0;
|
|
504
|
+
let finalOptions = { ...options };
|
|
505
|
+
if (!hasOptions) {
|
|
506
|
+
console.log(import_chalk4.default.blue("\u{1F50D} Scanning project..."));
|
|
507
|
+
const scanResult = await (0, import_universal_pwa_core8.scanProject)({
|
|
508
|
+
projectPath,
|
|
509
|
+
includeAssets: false,
|
|
510
|
+
includeArchitecture: false
|
|
511
|
+
});
|
|
512
|
+
console.log(import_chalk4.default.green(`\u2713 Framework detected: ${scanResult.framework.framework ?? "Unknown"}`));
|
|
513
|
+
console.log(import_chalk4.default.green(`\u2713 Architecture: ${scanResult.architecture.architecture}`));
|
|
514
|
+
const promptAnswers = await promptInitOptions(projectPath, scanResult.framework.framework);
|
|
515
|
+
finalOptions = {
|
|
516
|
+
...options,
|
|
517
|
+
name: promptAnswers.name,
|
|
518
|
+
shortName: promptAnswers.shortName,
|
|
519
|
+
iconSource: promptAnswers.iconSource || void 0,
|
|
520
|
+
themeColor: promptAnswers.themeColor || void 0,
|
|
521
|
+
backgroundColor: promptAnswers.backgroundColor || void 0,
|
|
522
|
+
skipIcons: promptAnswers.skipIcons
|
|
523
|
+
};
|
|
524
|
+
}
|
|
359
525
|
const result = await initCommand({
|
|
360
|
-
projectPath:
|
|
361
|
-
name:
|
|
362
|
-
shortName:
|
|
363
|
-
iconSource:
|
|
364
|
-
themeColor:
|
|
365
|
-
backgroundColor:
|
|
366
|
-
skipIcons:
|
|
367
|
-
skipServiceWorker:
|
|
368
|
-
skipInjection:
|
|
369
|
-
outputDir:
|
|
526
|
+
projectPath: finalOptions.projectPath,
|
|
527
|
+
name: finalOptions.name,
|
|
528
|
+
shortName: finalOptions.shortName,
|
|
529
|
+
iconSource: finalOptions.iconSource,
|
|
530
|
+
themeColor: finalOptions.themeColor,
|
|
531
|
+
backgroundColor: finalOptions.backgroundColor,
|
|
532
|
+
skipIcons: finalOptions.skipIcons,
|
|
533
|
+
skipServiceWorker: finalOptions.skipServiceWorker,
|
|
534
|
+
skipInjection: finalOptions.skipInjection,
|
|
535
|
+
outputDir: finalOptions.outputDir
|
|
370
536
|
});
|
|
371
537
|
process.exit(result.success ? 0 : 1);
|
|
372
538
|
} catch (error) {
|
|
373
|
-
console.error(
|
|
539
|
+
console.error(import_chalk4.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
374
540
|
process.exit(1);
|
|
375
541
|
}
|
|
376
542
|
});
|
|
@@ -383,31 +549,31 @@ program.command("preview").description("Preview PWA setup").option("-p, --projec
|
|
|
383
549
|
});
|
|
384
550
|
process.exit(result.success ? 0 : 1);
|
|
385
551
|
} catch (error) {
|
|
386
|
-
console.error(
|
|
552
|
+
console.error(import_chalk4.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
387
553
|
process.exit(1);
|
|
388
554
|
}
|
|
389
555
|
});
|
|
390
556
|
program.command("scan").description("Scan project and detect framework/architecture").option("-p, --project-path <path>", "Project path", process.cwd()).action(async (options) => {
|
|
391
557
|
try {
|
|
392
|
-
console.log(
|
|
558
|
+
console.log(import_chalk4.default.blue("\u{1F50D} Scanning project..."));
|
|
393
559
|
const result = await (0, import_universal_pwa_core8.scanProject)({
|
|
394
560
|
projectPath: options.projectPath ?? process.cwd(),
|
|
395
561
|
includeAssets: true,
|
|
396
562
|
includeArchitecture: true
|
|
397
563
|
});
|
|
398
|
-
console.log(
|
|
564
|
+
console.log(import_chalk4.default.green(`
|
|
399
565
|
\u2713 Framework: ${result.framework.framework ?? "Unknown"}`));
|
|
400
|
-
console.log(
|
|
401
|
-
console.log(
|
|
402
|
-
console.log(
|
|
566
|
+
console.log(import_chalk4.default.green(`\u2713 Architecture: ${result.architecture.architecture}`));
|
|
567
|
+
console.log(import_chalk4.default.green(`\u2713 Build Tool: ${result.architecture.buildTool ?? "Unknown"}`));
|
|
568
|
+
console.log(import_chalk4.default.gray(`
|
|
403
569
|
Assets found:`));
|
|
404
|
-
console.log(
|
|
405
|
-
console.log(
|
|
406
|
-
console.log(
|
|
407
|
-
console.log(
|
|
570
|
+
console.log(import_chalk4.default.gray(` - JavaScript: ${result.assets.javascript.length} files`));
|
|
571
|
+
console.log(import_chalk4.default.gray(` - CSS: ${result.assets.css.length} files`));
|
|
572
|
+
console.log(import_chalk4.default.gray(` - Images: ${result.assets.images.length} files`));
|
|
573
|
+
console.log(import_chalk4.default.gray(` - Fonts: ${result.assets.fonts.length} files`));
|
|
408
574
|
process.exit(0);
|
|
409
575
|
} catch (error) {
|
|
410
|
-
console.error(
|
|
576
|
+
console.error(import_chalk4.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
411
577
|
process.exit(1);
|
|
412
578
|
}
|
|
413
579
|
});
|
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
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
|
|
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";
|
|
@@ -114,7 +114,16 @@ async function initCommand(options = {}) {
|
|
|
114
114
|
result.warnings.push(`Icon source not found: ${iconSourcePath}`);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
let finalShortName = "PWA";
|
|
118
|
+
if (appShortName && typeof appShortName === "string" && appShortName.trim().length > 0) {
|
|
119
|
+
finalShortName = appShortName.trim().substring(0, 12);
|
|
120
|
+
} else if (appName && typeof appName === "string" && appName.length > 0) {
|
|
121
|
+
finalShortName = appName.substring(0, 12);
|
|
122
|
+
}
|
|
123
|
+
if (!finalShortName || finalShortName.trim().length === 0) {
|
|
124
|
+
finalShortName = "PWA";
|
|
125
|
+
}
|
|
126
|
+
finalShortName = String(finalShortName).trim().substring(0, 12) || "PWA";
|
|
118
127
|
let manifestPath;
|
|
119
128
|
if (iconPaths.length > 0) {
|
|
120
129
|
const manifestWithIcons = generateManifest({
|
|
@@ -317,12 +326,146 @@ function previewCommand(options = {}) {
|
|
|
317
326
|
|
|
318
327
|
// src/index.ts
|
|
319
328
|
import { scanProject as scanProject2 } from "@julien-lin/universal-pwa-core";
|
|
329
|
+
|
|
330
|
+
// src/prompts.ts
|
|
331
|
+
import inquirer from "inquirer";
|
|
332
|
+
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
333
|
+
import { join as join3 } from "path";
|
|
334
|
+
import chalk3 from "chalk";
|
|
335
|
+
function detectProjectName(projectPath) {
|
|
336
|
+
try {
|
|
337
|
+
const packageJsonPath2 = join3(projectPath, "package.json");
|
|
338
|
+
if (existsSync3(packageJsonPath2)) {
|
|
339
|
+
const packageJsonContent = readFileSync(packageJsonPath2, "utf-8");
|
|
340
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
341
|
+
return packageJson.name || void 0;
|
|
342
|
+
}
|
|
343
|
+
} catch {
|
|
344
|
+
}
|
|
345
|
+
return void 0;
|
|
346
|
+
}
|
|
347
|
+
function findDefaultIconSource(projectPath) {
|
|
348
|
+
const commonPaths = [
|
|
349
|
+
"public/logo.png",
|
|
350
|
+
"public/icon.png",
|
|
351
|
+
"public/favicon.png",
|
|
352
|
+
"src/assets/logo.png",
|
|
353
|
+
"src/assets/icon.png",
|
|
354
|
+
"assets/logo.png",
|
|
355
|
+
"assets/icon.png",
|
|
356
|
+
"logo.png",
|
|
357
|
+
"icon.png"
|
|
358
|
+
];
|
|
359
|
+
for (const path of commonPaths) {
|
|
360
|
+
const fullPath = join3(projectPath, path);
|
|
361
|
+
if (existsSync3(fullPath)) {
|
|
362
|
+
return path;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return void 0;
|
|
366
|
+
}
|
|
367
|
+
async function promptInitOptions(projectPath, framework) {
|
|
368
|
+
const detectedName = detectProjectName(projectPath);
|
|
369
|
+
const defaultIconSource = findDefaultIconSource(projectPath);
|
|
370
|
+
const defaultName = detectedName || (framework ? `${framework} App` : "My PWA");
|
|
371
|
+
const defaultShortName = defaultName.substring(0, 12);
|
|
372
|
+
console.log(chalk3.blue("\n\u{1F4CB} Configuration PWA\n"));
|
|
373
|
+
const answers = await inquirer.prompt([
|
|
374
|
+
{
|
|
375
|
+
type: "input",
|
|
376
|
+
name: "name",
|
|
377
|
+
message: "Nom de l'application:",
|
|
378
|
+
default: defaultName,
|
|
379
|
+
validate: (input) => {
|
|
380
|
+
if (!input || input.trim().length === 0) {
|
|
381
|
+
return "Le nom de l'application est requis";
|
|
382
|
+
}
|
|
383
|
+
if (input.length > 50) {
|
|
384
|
+
return "Le nom doit faire moins de 50 caract\xE8res";
|
|
385
|
+
}
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
type: "input",
|
|
391
|
+
name: "shortName",
|
|
392
|
+
message: "Nom court (max 12 caract\xE8res):",
|
|
393
|
+
default: defaultShortName,
|
|
394
|
+
validate: (input) => {
|
|
395
|
+
if (!input || input.trim().length === 0) {
|
|
396
|
+
return "Le nom court est requis";
|
|
397
|
+
}
|
|
398
|
+
if (input.length > 12) {
|
|
399
|
+
return "Le nom court doit faire maximum 12 caract\xE8res";
|
|
400
|
+
}
|
|
401
|
+
return true;
|
|
402
|
+
},
|
|
403
|
+
filter: (input) => input.trim().substring(0, 12)
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
type: "input",
|
|
407
|
+
name: "iconSource",
|
|
408
|
+
message: "Chemin vers l'image source pour les ic\xF4nes:",
|
|
409
|
+
default: defaultIconSource,
|
|
410
|
+
validate: (input) => {
|
|
411
|
+
if (!input || input.trim().length === 0) {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
const fullPath = existsSync3(input) ? input : join3(projectPath, input);
|
|
415
|
+
if (!existsSync3(fullPath)) {
|
|
416
|
+
return `Le fichier n'existe pas: ${input}`;
|
|
417
|
+
}
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
type: "confirm",
|
|
423
|
+
name: "skipIcons",
|
|
424
|
+
message: "G\xE9n\xE9rer les ic\xF4nes PWA?",
|
|
425
|
+
default: true
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
type: "input",
|
|
429
|
+
name: "themeColor",
|
|
430
|
+
message: "Couleur du th\xE8me (hex, ex: #ffffff):",
|
|
431
|
+
default: "#ffffff",
|
|
432
|
+
validate: (input) => {
|
|
433
|
+
if (!input || input.trim().length === 0) {
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
|
|
437
|
+
return "Format hex invalide (ex: #ffffff)";
|
|
438
|
+
}
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
type: "input",
|
|
444
|
+
name: "backgroundColor",
|
|
445
|
+
message: "Couleur de fond (hex, ex: #000000):",
|
|
446
|
+
default: "#000000",
|
|
447
|
+
validate: (input) => {
|
|
448
|
+
if (!input || input.trim().length === 0) {
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(input.trim())) {
|
|
452
|
+
return "Format hex invalide (ex: #000000)";
|
|
453
|
+
}
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
]);
|
|
458
|
+
answers.skipIcons = !answers.skipIcons;
|
|
459
|
+
return answers;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/index.ts
|
|
320
463
|
var __filename = fileURLToPath(import.meta.url);
|
|
321
464
|
var __dirname = dirname(__filename);
|
|
322
|
-
var packageJsonPath =
|
|
465
|
+
var packageJsonPath = join4(__dirname, "../package.json");
|
|
323
466
|
var version = "0.0.0";
|
|
324
467
|
try {
|
|
325
|
-
const packageJsonContent =
|
|
468
|
+
const packageJsonContent = readFileSync2(packageJsonPath, "utf-8");
|
|
326
469
|
const packageJson = JSON.parse(packageJsonContent);
|
|
327
470
|
version = packageJson.version || "0.0.0";
|
|
328
471
|
} catch {
|
|
@@ -332,21 +475,44 @@ var program = new Command();
|
|
|
332
475
|
program.name("universal-pwa").description("Transform any web project into a PWA with one click").version(version);
|
|
333
476
|
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) => {
|
|
334
477
|
try {
|
|
478
|
+
const projectPath = options.projectPath ?? process.cwd();
|
|
479
|
+
const hasOptions = options.name || options.shortName || options.iconSource || options.themeColor || options.backgroundColor || options.skipIcons !== void 0;
|
|
480
|
+
let finalOptions = { ...options };
|
|
481
|
+
if (!hasOptions) {
|
|
482
|
+
console.log(chalk4.blue("\u{1F50D} Scanning project..."));
|
|
483
|
+
const scanResult = await scanProject2({
|
|
484
|
+
projectPath,
|
|
485
|
+
includeAssets: false,
|
|
486
|
+
includeArchitecture: false
|
|
487
|
+
});
|
|
488
|
+
console.log(chalk4.green(`\u2713 Framework detected: ${scanResult.framework.framework ?? "Unknown"}`));
|
|
489
|
+
console.log(chalk4.green(`\u2713 Architecture: ${scanResult.architecture.architecture}`));
|
|
490
|
+
const promptAnswers = await promptInitOptions(projectPath, scanResult.framework.framework);
|
|
491
|
+
finalOptions = {
|
|
492
|
+
...options,
|
|
493
|
+
name: promptAnswers.name,
|
|
494
|
+
shortName: promptAnswers.shortName,
|
|
495
|
+
iconSource: promptAnswers.iconSource || void 0,
|
|
496
|
+
themeColor: promptAnswers.themeColor || void 0,
|
|
497
|
+
backgroundColor: promptAnswers.backgroundColor || void 0,
|
|
498
|
+
skipIcons: promptAnswers.skipIcons
|
|
499
|
+
};
|
|
500
|
+
}
|
|
335
501
|
const result = await initCommand({
|
|
336
|
-
projectPath:
|
|
337
|
-
name:
|
|
338
|
-
shortName:
|
|
339
|
-
iconSource:
|
|
340
|
-
themeColor:
|
|
341
|
-
backgroundColor:
|
|
342
|
-
skipIcons:
|
|
343
|
-
skipServiceWorker:
|
|
344
|
-
skipInjection:
|
|
345
|
-
outputDir:
|
|
502
|
+
projectPath: finalOptions.projectPath,
|
|
503
|
+
name: finalOptions.name,
|
|
504
|
+
shortName: finalOptions.shortName,
|
|
505
|
+
iconSource: finalOptions.iconSource,
|
|
506
|
+
themeColor: finalOptions.themeColor,
|
|
507
|
+
backgroundColor: finalOptions.backgroundColor,
|
|
508
|
+
skipIcons: finalOptions.skipIcons,
|
|
509
|
+
skipServiceWorker: finalOptions.skipServiceWorker,
|
|
510
|
+
skipInjection: finalOptions.skipInjection,
|
|
511
|
+
outputDir: finalOptions.outputDir
|
|
346
512
|
});
|
|
347
513
|
process.exit(result.success ? 0 : 1);
|
|
348
514
|
} catch (error) {
|
|
349
|
-
console.error(
|
|
515
|
+
console.error(chalk4.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
350
516
|
process.exit(1);
|
|
351
517
|
}
|
|
352
518
|
});
|
|
@@ -359,31 +525,31 @@ program.command("preview").description("Preview PWA setup").option("-p, --projec
|
|
|
359
525
|
});
|
|
360
526
|
process.exit(result.success ? 0 : 1);
|
|
361
527
|
} catch (error) {
|
|
362
|
-
console.error(
|
|
528
|
+
console.error(chalk4.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
363
529
|
process.exit(1);
|
|
364
530
|
}
|
|
365
531
|
});
|
|
366
532
|
program.command("scan").description("Scan project and detect framework/architecture").option("-p, --project-path <path>", "Project path", process.cwd()).action(async (options) => {
|
|
367
533
|
try {
|
|
368
|
-
console.log(
|
|
534
|
+
console.log(chalk4.blue("\u{1F50D} Scanning project..."));
|
|
369
535
|
const result = await scanProject2({
|
|
370
536
|
projectPath: options.projectPath ?? process.cwd(),
|
|
371
537
|
includeAssets: true,
|
|
372
538
|
includeArchitecture: true
|
|
373
539
|
});
|
|
374
|
-
console.log(
|
|
540
|
+
console.log(chalk4.green(`
|
|
375
541
|
\u2713 Framework: ${result.framework.framework ?? "Unknown"}`));
|
|
376
|
-
console.log(
|
|
377
|
-
console.log(
|
|
378
|
-
console.log(
|
|
542
|
+
console.log(chalk4.green(`\u2713 Architecture: ${result.architecture.architecture}`));
|
|
543
|
+
console.log(chalk4.green(`\u2713 Build Tool: ${result.architecture.buildTool ?? "Unknown"}`));
|
|
544
|
+
console.log(chalk4.gray(`
|
|
379
545
|
Assets found:`));
|
|
380
|
-
console.log(
|
|
381
|
-
console.log(
|
|
382
|
-
console.log(
|
|
383
|
-
console.log(
|
|
546
|
+
console.log(chalk4.gray(` - JavaScript: ${result.assets.javascript.length} files`));
|
|
547
|
+
console.log(chalk4.gray(` - CSS: ${result.assets.css.length} files`));
|
|
548
|
+
console.log(chalk4.gray(` - Images: ${result.assets.images.length} files`));
|
|
549
|
+
console.log(chalk4.gray(` - Fonts: ${result.assets.fonts.length} files`));
|
|
384
550
|
process.exit(0);
|
|
385
551
|
} catch (error) {
|
|
386
|
-
console.error(
|
|
552
|
+
console.error(chalk4.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
387
553
|
process.exit(1);
|
|
388
554
|
}
|
|
389
555
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@julien-lin/universal-pwa-cli",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
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
|
|
48
|
+
"@julien-lin/universal-pwa-core": "^1.2.1"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@vitest/coverage-v8": "^2.1.4",
|