@julien-lin/universal-pwa-cli 1.1.0 → 1.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/dist/index.cjs CHANGED
@@ -93,7 +93,7 @@ async function initCommand(options = {}) {
93
93
  const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? (0, import_path.join)(result.projectPath, "public") : (0, import_path.join)(result.projectPath, "public"));
94
94
  console.log(import_chalk.default.blue("\u{1F4DD} Generating manifest.json..."));
95
95
  const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
96
- const appShortName = shortName ?? appName.substring(0, 12);
96
+ const appShortName = shortName && shortName.length > 0 && shortName.length <= 12 ? shortName : appName.substring(0, 12);
97
97
  let iconPaths = [];
98
98
  if (!skipIcons && iconSource) {
99
99
  const iconSourcePath = (0, import_fs.existsSync)(iconSource) ? iconSource : (0, import_path.join)(result.projectPath, iconSource);
@@ -106,7 +106,14 @@ async function initCommand(options = {}) {
106
106
  });
107
107
  iconPaths = iconResult.icons.map((icon) => icon.src);
108
108
  result.iconsGenerated = iconResult.icons.length;
109
+ const appleTouchIconPath = (0, import_path.join)(finalOutputDir, "apple-touch-icon.png");
110
+ if ((0, import_fs.existsSync)(appleTouchIconPath)) {
111
+ iconPaths.push("/apple-touch-icon.png");
112
+ }
109
113
  console.log(import_chalk.default.green(`\u2713 Generated ${result.iconsGenerated} icons`));
114
+ if ((0, import_fs.existsSync)(appleTouchIconPath)) {
115
+ console.log(import_chalk.default.green(`\u2713 Generated apple-touch-icon.png`));
116
+ }
110
117
  } catch (error) {
111
118
  const errorMessage = error instanceof Error ? error.message : String(error);
112
119
  result.errors.push(`Failed to generate icons: ${errorMessage}`);
@@ -116,6 +123,7 @@ async function initCommand(options = {}) {
116
123
  result.warnings.push(`Icon source not found: ${iconSourcePath}`);
117
124
  }
118
125
  }
126
+ let manifestPath;
119
127
  if (iconPaths.length > 0) {
120
128
  const manifestWithIcons = (0, import_universal_pwa_core2.generateManifest)({
121
129
  name: appName,
@@ -131,11 +139,30 @@ async function initCommand(options = {}) {
131
139
  type: "image/png"
132
140
  }))
133
141
  });
134
- const manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestWithIcons, finalOutputDir);
142
+ manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestWithIcons, finalOutputDir);
135
143
  result.manifestPath = manifestPath;
144
+ console.log(import_chalk.default.green(`\u2713 Manifest generated: ${manifestPath}`));
136
145
  } 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"));
146
+ result.warnings.push("No icons provided. Manifest generated with placeholder icon. Please provide an icon source with --icon-source for production.");
147
+ console.log(import_chalk.default.yellow("\u26A0 Generating manifest with placeholder icon"));
148
+ const manifestMinimal = (0, import_universal_pwa_core2.generateManifest)({
149
+ name: appName,
150
+ shortName: appShortName,
151
+ startUrl: "/",
152
+ scope: "/",
153
+ display: "standalone",
154
+ themeColor: themeColor ?? "#ffffff",
155
+ backgroundColor: backgroundColor ?? "#000000",
156
+ icons: [{
157
+ src: "/icon-192x192.png",
158
+ // Placeholder - l'utilisateur devra ajouter une vraie icône
159
+ sizes: "192x192",
160
+ type: "image/png"
161
+ }]
162
+ });
163
+ manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestMinimal, finalOutputDir);
164
+ result.manifestPath = manifestPath;
165
+ console.log(import_chalk.default.green(`\u2713 Manifest generated: ${manifestPath}`));
139
166
  }
140
167
  if (!skipServiceWorker) {
141
168
  console.log(import_chalk.default.blue("\u2699\uFE0F Generating service worker..."));
@@ -168,22 +195,30 @@ async function initCommand(options = {}) {
168
195
  let injectedCount = 0;
169
196
  for (const htmlFile of htmlFiles.slice(0, 10)) {
170
197
  try {
171
- const normalizePathForInjection = (fullPath, basePath, fallback) => {
198
+ const normalizePathForInjection = (fullPath, basePath, outputDir2, fallback) => {
172
199
  if (!fullPath) return fallback;
173
200
  try {
174
201
  const rel = relativePath(fullPath, basePath);
175
- return rel.startsWith("/") ? rel : `/${rel}`;
202
+ let normalized = rel.startsWith("/") ? rel : `/${rel}`;
203
+ const outputDirName = outputDir2.replace(basePath, "").replace(/^\/+|\/+$/g, "");
204
+ if (outputDirName && normalized.startsWith(`/${outputDirName}/`)) {
205
+ normalized = normalized.replace(`/${outputDirName}/`, "/");
206
+ }
207
+ return normalized;
176
208
  } catch {
177
209
  return fallback;
178
210
  }
179
211
  };
212
+ const appleTouchIconFullPath = (0, import_path.join)(finalOutputDir, "apple-touch-icon.png");
213
+ const appleTouchIconExists = (0, import_fs.existsSync)(appleTouchIconFullPath);
180
214
  const injectionResult = (0, import_universal_pwa_core5.injectMetaTagsInFile)(htmlFile, {
181
- manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, "/manifest.json"),
215
+ manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, finalOutputDir, "/manifest.json"),
182
216
  themeColor: themeColor ?? "#ffffff",
183
217
  backgroundColor: backgroundColor ?? "#000000",
184
- appleTouchIcon: iconPaths.find((p) => p.includes("180")) ?? "/apple-touch-icon.png",
218
+ appleTouchIcon: appleTouchIconExists ? normalizePathForInjection(appleTouchIconFullPath, result.projectPath, finalOutputDir, "/apple-touch-icon.png") : "/apple-touch-icon.png",
219
+ // Placeholder si non généré
185
220
  appleMobileWebAppCapable: true,
186
- serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, "/sw.js")
221
+ serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, finalOutputDir, "/sw.js")
187
222
  });
188
223
  if (injectionResult.injected.length > 0) {
189
224
  injectedCount++;
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ async function initCommand(options = {}) {
70
70
  const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? join(result.projectPath, "public") : join(result.projectPath, "public"));
71
71
  console.log(chalk.blue("\u{1F4DD} Generating manifest.json..."));
72
72
  const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
73
- const appShortName = shortName ?? appName.substring(0, 12);
73
+ const appShortName = shortName && shortName.length > 0 && shortName.length <= 12 ? shortName : appName.substring(0, 12);
74
74
  let iconPaths = [];
75
75
  if (!skipIcons && iconSource) {
76
76
  const iconSourcePath = existsSync(iconSource) ? iconSource : join(result.projectPath, iconSource);
@@ -83,7 +83,14 @@ async function initCommand(options = {}) {
83
83
  });
84
84
  iconPaths = iconResult.icons.map((icon) => icon.src);
85
85
  result.iconsGenerated = iconResult.icons.length;
86
+ const appleTouchIconPath = join(finalOutputDir, "apple-touch-icon.png");
87
+ if (existsSync(appleTouchIconPath)) {
88
+ iconPaths.push("/apple-touch-icon.png");
89
+ }
86
90
  console.log(chalk.green(`\u2713 Generated ${result.iconsGenerated} icons`));
91
+ if (existsSync(appleTouchIconPath)) {
92
+ console.log(chalk.green(`\u2713 Generated apple-touch-icon.png`));
93
+ }
87
94
  } catch (error) {
88
95
  const errorMessage = error instanceof Error ? error.message : String(error);
89
96
  result.errors.push(`Failed to generate icons: ${errorMessage}`);
@@ -93,6 +100,7 @@ async function initCommand(options = {}) {
93
100
  result.warnings.push(`Icon source not found: ${iconSourcePath}`);
94
101
  }
95
102
  }
103
+ let manifestPath;
96
104
  if (iconPaths.length > 0) {
97
105
  const manifestWithIcons = generateManifest({
98
106
  name: appName,
@@ -108,11 +116,30 @@ async function initCommand(options = {}) {
108
116
  type: "image/png"
109
117
  }))
110
118
  });
111
- const manifestPath = generateAndWriteManifest(manifestWithIcons, finalOutputDir);
119
+ manifestPath = generateAndWriteManifest(manifestWithIcons, finalOutputDir);
112
120
  result.manifestPath = manifestPath;
121
+ console.log(chalk.green(`\u2713 Manifest generated: ${manifestPath}`));
113
122
  } 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"));
123
+ result.warnings.push("No icons provided. Manifest generated with placeholder icon. Please provide an icon source with --icon-source for production.");
124
+ console.log(chalk.yellow("\u26A0 Generating manifest with placeholder icon"));
125
+ const manifestMinimal = generateManifest({
126
+ name: appName,
127
+ shortName: appShortName,
128
+ startUrl: "/",
129
+ scope: "/",
130
+ display: "standalone",
131
+ themeColor: themeColor ?? "#ffffff",
132
+ backgroundColor: backgroundColor ?? "#000000",
133
+ icons: [{
134
+ src: "/icon-192x192.png",
135
+ // Placeholder - l'utilisateur devra ajouter une vraie icône
136
+ sizes: "192x192",
137
+ type: "image/png"
138
+ }]
139
+ });
140
+ manifestPath = generateAndWriteManifest(manifestMinimal, finalOutputDir);
141
+ result.manifestPath = manifestPath;
142
+ console.log(chalk.green(`\u2713 Manifest generated: ${manifestPath}`));
116
143
  }
117
144
  if (!skipServiceWorker) {
118
145
  console.log(chalk.blue("\u2699\uFE0F Generating service worker..."));
@@ -145,22 +172,30 @@ async function initCommand(options = {}) {
145
172
  let injectedCount = 0;
146
173
  for (const htmlFile of htmlFiles.slice(0, 10)) {
147
174
  try {
148
- const normalizePathForInjection = (fullPath, basePath, fallback) => {
175
+ const normalizePathForInjection = (fullPath, basePath, outputDir2, fallback) => {
149
176
  if (!fullPath) return fallback;
150
177
  try {
151
178
  const rel = relativePath(fullPath, basePath);
152
- return rel.startsWith("/") ? rel : `/${rel}`;
179
+ let normalized = rel.startsWith("/") ? rel : `/${rel}`;
180
+ const outputDirName = outputDir2.replace(basePath, "").replace(/^\/+|\/+$/g, "");
181
+ if (outputDirName && normalized.startsWith(`/${outputDirName}/`)) {
182
+ normalized = normalized.replace(`/${outputDirName}/`, "/");
183
+ }
184
+ return normalized;
153
185
  } catch {
154
186
  return fallback;
155
187
  }
156
188
  };
189
+ const appleTouchIconFullPath = join(finalOutputDir, "apple-touch-icon.png");
190
+ const appleTouchIconExists = existsSync(appleTouchIconFullPath);
157
191
  const injectionResult = injectMetaTagsInFile(htmlFile, {
158
- manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, "/manifest.json"),
192
+ manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, finalOutputDir, "/manifest.json"),
159
193
  themeColor: themeColor ?? "#ffffff",
160
194
  backgroundColor: backgroundColor ?? "#000000",
161
- appleTouchIcon: iconPaths.find((p) => p.includes("180")) ?? "/apple-touch-icon.png",
195
+ appleTouchIcon: appleTouchIconExists ? normalizePathForInjection(appleTouchIconFullPath, result.projectPath, finalOutputDir, "/apple-touch-icon.png") : "/apple-touch-icon.png",
196
+ // Placeholder si non généré
162
197
  appleMobileWebAppCapable: true,
163
- serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, "/sw.js")
198
+ serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, finalOutputDir, "/sw.js")
164
199
  });
165
200
  if (injectionResult.injected.length > 0) {
166
201
  injectedCount++;
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.1",
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.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@vitest/coverage-v8": "^2.1.4",