@julien-lin/universal-pwa-cli 1.1.0 → 1.1.2

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 CHANGED
@@ -26,6 +26,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  // src/index.ts
27
27
  var import_commander = require("commander");
28
28
  var import_chalk3 = __toESM(require("chalk"), 1);
29
+ var import_fs3 = require("fs");
30
+ var import_url = require("url");
31
+ var import_path3 = require("path");
29
32
 
30
33
  // src/commands/init.ts
31
34
  var import_universal_pwa_core = require("@julien-lin/universal-pwa-core");
@@ -93,7 +96,7 @@ async function initCommand(options = {}) {
93
96
  const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? (0, import_path.join)(result.projectPath, "public") : (0, import_path.join)(result.projectPath, "public"));
94
97
  console.log(import_chalk.default.blue("\u{1F4DD} Generating manifest.json..."));
95
98
  const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
96
- const appShortName = shortName ?? appName.substring(0, 12);
99
+ const appShortName = shortName && shortName.length > 0 && shortName.length <= 12 ? shortName : appName.substring(0, 12);
97
100
  let iconPaths = [];
98
101
  if (!skipIcons && iconSource) {
99
102
  const iconSourcePath = (0, import_fs.existsSync)(iconSource) ? iconSource : (0, import_path.join)(result.projectPath, iconSource);
@@ -106,7 +109,14 @@ async function initCommand(options = {}) {
106
109
  });
107
110
  iconPaths = iconResult.icons.map((icon) => icon.src);
108
111
  result.iconsGenerated = iconResult.icons.length;
112
+ const appleTouchIconPath = (0, import_path.join)(finalOutputDir, "apple-touch-icon.png");
113
+ if ((0, import_fs.existsSync)(appleTouchIconPath)) {
114
+ iconPaths.push("/apple-touch-icon.png");
115
+ }
109
116
  console.log(import_chalk.default.green(`\u2713 Generated ${result.iconsGenerated} icons`));
117
+ if ((0, import_fs.existsSync)(appleTouchIconPath)) {
118
+ console.log(import_chalk.default.green(`\u2713 Generated apple-touch-icon.png`));
119
+ }
110
120
  } catch (error) {
111
121
  const errorMessage = error instanceof Error ? error.message : String(error);
112
122
  result.errors.push(`Failed to generate icons: ${errorMessage}`);
@@ -116,6 +126,7 @@ async function initCommand(options = {}) {
116
126
  result.warnings.push(`Icon source not found: ${iconSourcePath}`);
117
127
  }
118
128
  }
129
+ let manifestPath;
119
130
  if (iconPaths.length > 0) {
120
131
  const manifestWithIcons = (0, import_universal_pwa_core2.generateManifest)({
121
132
  name: appName,
@@ -131,11 +142,30 @@ async function initCommand(options = {}) {
131
142
  type: "image/png"
132
143
  }))
133
144
  });
134
- const manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestWithIcons, finalOutputDir);
145
+ manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestWithIcons, finalOutputDir);
135
146
  result.manifestPath = manifestPath;
147
+ console.log(import_chalk.default.green(`\u2713 Manifest generated: ${manifestPath}`));
136
148
  } else {
137
- result.warnings.push("No icons provided. Manifest requires at least one icon. Please provide an icon source with --icon-source");
138
- console.log(import_chalk.default.yellow("\u26A0 Manifest not generated: icons are required"));
149
+ result.warnings.push("No icons provided. Manifest generated with placeholder icon. Please provide an icon source with --icon-source for production.");
150
+ console.log(import_chalk.default.yellow("\u26A0 Generating manifest with placeholder icon"));
151
+ const manifestMinimal = (0, import_universal_pwa_core2.generateManifest)({
152
+ name: appName,
153
+ shortName: appShortName,
154
+ startUrl: "/",
155
+ scope: "/",
156
+ display: "standalone",
157
+ themeColor: themeColor ?? "#ffffff",
158
+ backgroundColor: backgroundColor ?? "#000000",
159
+ icons: [{
160
+ src: "/icon-192x192.png",
161
+ // Placeholder - l'utilisateur devra ajouter une vraie icône
162
+ sizes: "192x192",
163
+ type: "image/png"
164
+ }]
165
+ });
166
+ manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestMinimal, finalOutputDir);
167
+ result.manifestPath = manifestPath;
168
+ console.log(import_chalk.default.green(`\u2713 Manifest generated: ${manifestPath}`));
139
169
  }
140
170
  if (!skipServiceWorker) {
141
171
  console.log(import_chalk.default.blue("\u2699\uFE0F Generating service worker..."));
@@ -168,22 +198,30 @@ async function initCommand(options = {}) {
168
198
  let injectedCount = 0;
169
199
  for (const htmlFile of htmlFiles.slice(0, 10)) {
170
200
  try {
171
- const normalizePathForInjection = (fullPath, basePath, fallback) => {
201
+ const normalizePathForInjection = (fullPath, basePath, outputDir2, fallback) => {
172
202
  if (!fullPath) return fallback;
173
203
  try {
174
204
  const rel = relativePath(fullPath, basePath);
175
- return rel.startsWith("/") ? rel : `/${rel}`;
205
+ let normalized = rel.startsWith("/") ? rel : `/${rel}`;
206
+ const outputDirName = outputDir2.replace(basePath, "").replace(/^\/+|\/+$/g, "");
207
+ if (outputDirName && normalized.startsWith(`/${outputDirName}/`)) {
208
+ normalized = normalized.replace(`/${outputDirName}/`, "/");
209
+ }
210
+ return normalized;
176
211
  } catch {
177
212
  return fallback;
178
213
  }
179
214
  };
215
+ const appleTouchIconFullPath = (0, import_path.join)(finalOutputDir, "apple-touch-icon.png");
216
+ const appleTouchIconExists = (0, import_fs.existsSync)(appleTouchIconFullPath);
180
217
  const injectionResult = (0, import_universal_pwa_core5.injectMetaTagsInFile)(htmlFile, {
181
- manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, "/manifest.json"),
218
+ manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, finalOutputDir, "/manifest.json"),
182
219
  themeColor: themeColor ?? "#ffffff",
183
220
  backgroundColor: backgroundColor ?? "#000000",
184
- appleTouchIcon: iconPaths.find((p) => p.includes("180")) ?? "/apple-touch-icon.png",
221
+ appleTouchIcon: appleTouchIconExists ? normalizePathForInjection(appleTouchIconFullPath, result.projectPath, finalOutputDir, "/apple-touch-icon.png") : "/apple-touch-icon.png",
222
+ // Placeholder si non généré
185
223
  appleMobileWebAppCapable: true,
186
- serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, "/sw.js")
224
+ serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, finalOutputDir, "/sw.js")
187
225
  });
188
226
  if (injectionResult.injected.length > 0) {
189
227
  injectedCount++;
@@ -290,8 +328,20 @@ function previewCommand(options = {}) {
290
328
 
291
329
  // src/index.ts
292
330
  var import_universal_pwa_core8 = require("@julien-lin/universal-pwa-core");
331
+ var import_meta = {};
332
+ var __filename = (0, import_url.fileURLToPath)(import_meta.url);
333
+ var __dirname = (0, import_path3.dirname)(__filename);
334
+ var packageJsonPath = (0, import_path3.join)(__dirname, "../package.json");
335
+ var version = "0.0.0";
336
+ try {
337
+ const packageJsonContent = (0, import_fs3.readFileSync)(packageJsonPath, "utf-8");
338
+ const packageJson = JSON.parse(packageJsonContent);
339
+ version = packageJson.version || "0.0.0";
340
+ } catch {
341
+ version = "0.0.0";
342
+ }
293
343
  var program = new import_commander.Command();
294
- program.name("universal-pwa").description("Transform any web project into a PWA with one click").version("0.0.0");
344
+ program.name("universal-pwa").description("Transform any web project into a PWA with one click").version(version);
295
345
  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) => {
296
346
  try {
297
347
  const result = await initCommand({
package/dist/index.js CHANGED
@@ -3,6 +3,9 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
  import chalk3 from "chalk";
6
+ import { readFileSync } from "fs";
7
+ import { fileURLToPath } from "url";
8
+ import { dirname, join as join3 } from "path";
6
9
 
7
10
  // src/commands/init.ts
8
11
  import { scanProject } from "@julien-lin/universal-pwa-core";
@@ -70,7 +73,7 @@ async function initCommand(options = {}) {
70
73
  const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? join(result.projectPath, "public") : join(result.projectPath, "public"));
71
74
  console.log(chalk.blue("\u{1F4DD} Generating manifest.json..."));
72
75
  const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
73
- const appShortName = shortName ?? appName.substring(0, 12);
76
+ const appShortName = shortName && shortName.length > 0 && shortName.length <= 12 ? shortName : appName.substring(0, 12);
74
77
  let iconPaths = [];
75
78
  if (!skipIcons && iconSource) {
76
79
  const iconSourcePath = existsSync(iconSource) ? iconSource : join(result.projectPath, iconSource);
@@ -83,7 +86,14 @@ async function initCommand(options = {}) {
83
86
  });
84
87
  iconPaths = iconResult.icons.map((icon) => icon.src);
85
88
  result.iconsGenerated = iconResult.icons.length;
89
+ const appleTouchIconPath = join(finalOutputDir, "apple-touch-icon.png");
90
+ if (existsSync(appleTouchIconPath)) {
91
+ iconPaths.push("/apple-touch-icon.png");
92
+ }
86
93
  console.log(chalk.green(`\u2713 Generated ${result.iconsGenerated} icons`));
94
+ if (existsSync(appleTouchIconPath)) {
95
+ console.log(chalk.green(`\u2713 Generated apple-touch-icon.png`));
96
+ }
87
97
  } catch (error) {
88
98
  const errorMessage = error instanceof Error ? error.message : String(error);
89
99
  result.errors.push(`Failed to generate icons: ${errorMessage}`);
@@ -93,6 +103,7 @@ async function initCommand(options = {}) {
93
103
  result.warnings.push(`Icon source not found: ${iconSourcePath}`);
94
104
  }
95
105
  }
106
+ let manifestPath;
96
107
  if (iconPaths.length > 0) {
97
108
  const manifestWithIcons = generateManifest({
98
109
  name: appName,
@@ -108,11 +119,30 @@ async function initCommand(options = {}) {
108
119
  type: "image/png"
109
120
  }))
110
121
  });
111
- const manifestPath = generateAndWriteManifest(manifestWithIcons, finalOutputDir);
122
+ manifestPath = generateAndWriteManifest(manifestWithIcons, finalOutputDir);
112
123
  result.manifestPath = manifestPath;
124
+ console.log(chalk.green(`\u2713 Manifest generated: ${manifestPath}`));
113
125
  } else {
114
- result.warnings.push("No icons provided. Manifest requires at least one icon. Please provide an icon source with --icon-source");
115
- console.log(chalk.yellow("\u26A0 Manifest not generated: icons are required"));
126
+ result.warnings.push("No icons provided. Manifest generated with placeholder icon. Please provide an icon source with --icon-source for production.");
127
+ console.log(chalk.yellow("\u26A0 Generating manifest with placeholder icon"));
128
+ const manifestMinimal = generateManifest({
129
+ name: appName,
130
+ shortName: appShortName,
131
+ startUrl: "/",
132
+ scope: "/",
133
+ display: "standalone",
134
+ themeColor: themeColor ?? "#ffffff",
135
+ backgroundColor: backgroundColor ?? "#000000",
136
+ icons: [{
137
+ src: "/icon-192x192.png",
138
+ // Placeholder - l'utilisateur devra ajouter une vraie icône
139
+ sizes: "192x192",
140
+ type: "image/png"
141
+ }]
142
+ });
143
+ manifestPath = generateAndWriteManifest(manifestMinimal, finalOutputDir);
144
+ result.manifestPath = manifestPath;
145
+ console.log(chalk.green(`\u2713 Manifest generated: ${manifestPath}`));
116
146
  }
117
147
  if (!skipServiceWorker) {
118
148
  console.log(chalk.blue("\u2699\uFE0F Generating service worker..."));
@@ -145,22 +175,30 @@ async function initCommand(options = {}) {
145
175
  let injectedCount = 0;
146
176
  for (const htmlFile of htmlFiles.slice(0, 10)) {
147
177
  try {
148
- const normalizePathForInjection = (fullPath, basePath, fallback) => {
178
+ const normalizePathForInjection = (fullPath, basePath, outputDir2, fallback) => {
149
179
  if (!fullPath) return fallback;
150
180
  try {
151
181
  const rel = relativePath(fullPath, basePath);
152
- return rel.startsWith("/") ? rel : `/${rel}`;
182
+ let normalized = rel.startsWith("/") ? rel : `/${rel}`;
183
+ const outputDirName = outputDir2.replace(basePath, "").replace(/^\/+|\/+$/g, "");
184
+ if (outputDirName && normalized.startsWith(`/${outputDirName}/`)) {
185
+ normalized = normalized.replace(`/${outputDirName}/`, "/");
186
+ }
187
+ return normalized;
153
188
  } catch {
154
189
  return fallback;
155
190
  }
156
191
  };
192
+ const appleTouchIconFullPath = join(finalOutputDir, "apple-touch-icon.png");
193
+ const appleTouchIconExists = existsSync(appleTouchIconFullPath);
157
194
  const injectionResult = injectMetaTagsInFile(htmlFile, {
158
- manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, "/manifest.json"),
195
+ manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, finalOutputDir, "/manifest.json"),
159
196
  themeColor: themeColor ?? "#ffffff",
160
197
  backgroundColor: backgroundColor ?? "#000000",
161
- appleTouchIcon: iconPaths.find((p) => p.includes("180")) ?? "/apple-touch-icon.png",
198
+ appleTouchIcon: appleTouchIconExists ? normalizePathForInjection(appleTouchIconFullPath, result.projectPath, finalOutputDir, "/apple-touch-icon.png") : "/apple-touch-icon.png",
199
+ // Placeholder si non généré
162
200
  appleMobileWebAppCapable: true,
163
- serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, "/sw.js")
201
+ serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, finalOutputDir, "/sw.js")
164
202
  });
165
203
  if (injectionResult.injected.length > 0) {
166
204
  injectedCount++;
@@ -267,8 +305,19 @@ function previewCommand(options = {}) {
267
305
 
268
306
  // src/index.ts
269
307
  import { scanProject as scanProject2 } from "@julien-lin/universal-pwa-core";
308
+ var __filename = fileURLToPath(import.meta.url);
309
+ var __dirname = dirname(__filename);
310
+ var packageJsonPath = join3(__dirname, "../package.json");
311
+ var version = "0.0.0";
312
+ try {
313
+ const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
314
+ const packageJson = JSON.parse(packageJsonContent);
315
+ version = packageJson.version || "0.0.0";
316
+ } catch {
317
+ version = "0.0.0";
318
+ }
270
319
  var program = new Command();
271
- program.name("universal-pwa").description("Transform any web project into a PWA with one click").version("0.0.0");
320
+ program.name("universal-pwa").description("Transform any web project into a PWA with one click").version(version);
272
321
  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) => {
273
322
  try {
274
323
  const result = await initCommand({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@julien-lin/universal-pwa-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "CLI pour transformer n'importe quel projet web en PWA",
5
5
  "keywords": [
6
6
  "pwa",
@@ -44,7 +44,7 @@
44
44
  "glob": "^13.0.0",
45
45
  "pino": "^9.14.0",
46
46
  "zod": "^4.2.1",
47
- "@julien-lin/universal-pwa-core": "^1.1.0"
47
+ "@julien-lin/universal-pwa-core": "^1.1.2"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@vitest/coverage-v8": "^2.1.4",