@adobe/aem-cli 16.14.0 → 16.15.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/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [16.15.1](https://github.com/adobe/helix-cli/compare/v16.15.0...v16.15.1) (2025-09-22)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * inject hlx:proxyUrl meta tag for 401 and 403 HTML responses ([ff4f2e8](https://github.com/adobe/helix-cli/commit/ff4f2e84e897676141601fccb165d678715b3ac8)), closes [#2414](https://github.com/adobe/helix-cli/issues/2414)
7
+
8
+ # [16.15.0](https://github.com/adobe/helix-cli/compare/v16.14.0...v16.15.0) (2025-09-22)
9
+
10
+
11
+ ### Features
12
+
13
+ * enable auto-reload for static HTML resources (fixes [#2400](https://github.com/adobe/helix-cli/issues/2400)) ([0866ede](https://github.com/adobe/helix-cli/commit/0866edea1579d6e1c207d756e5ee9dbe266a5e6c))
14
+ * **git-utils:** add DNS-valid tag filtering in getBranch ([fd367c4](https://github.com/adobe/helix-cli/commit/fd367c421187cf75263b32bdc5e83a886f29ef9a))
15
+ * **git-utils:** enhance DNS name validation with stricter rules and length checks ([9702a63](https://github.com/adobe/helix-cli/commit/9702a63a26949d8dce135a17192b6801508d848c))
16
+
1
17
  # [16.14.0](https://github.com/adobe/helix-cli/compare/v16.13.2...v16.14.0) (2025-09-19)
2
18
 
3
19
 
package/README.md CHANGED
@@ -212,6 +212,8 @@ These proxies use a private certificate authority (CA) to sign the certificates
212
212
  servers they intercept. To make Node.js trust the server certificate, you need to add
213
213
  the CA certificate to the list of trusted CAs.
214
214
 
215
+ ### Option 1: Using IT-provided CA certificate
216
+
215
217
  The CA certificate is typically provided by your IT department. You can ask them for
216
218
  the CA certificate and save it to a file, e.g. `my-ca.crt`.
217
219
 
@@ -223,7 +225,29 @@ export NODE_EXTRA_CA_CERTS=my-ca.crt
223
225
  aem up
224
226
  ```
225
227
 
226
- This will make Node.js trust the server certificate and `aem up` should work.
228
+ ### Option 2: Extracting certificate from browser
229
+
230
+ If you don't have access to the CA certificate from your IT department, you can extract it directly
231
+ from your browser:
232
+
233
+ 1. Access the AEM admin URL in your browser (e.g., `https://admin.hlx.page/sidekick/owner-name/repo-name/github-branch-name/config.json`)
234
+ 2. Click on the padlock icon in the address bar and view the certificate details
235
+ 3. Export the certificate chain as a Base64 encoded `.pem` file
236
+ 4. Save it to a directory (e.g., `certs/hlx.page.pem`)
237
+ 5. Set the environment variable and run aem:
238
+
239
+ ```bash
240
+ export NODE_EXTRA_CA_CERTS=./certs/hlx.page.pem
241
+ aem up
242
+ ```
243
+
244
+ On Windows, use `set` instead of `export`:
245
+ ```cmd
246
+ set NODE_EXTRA_CA_CERTS=./certs/hlx.page.pem
247
+ aem up
248
+ ```
249
+
250
+ Either approach will make Node.js trust the server certificate and `aem up` should work.
227
251
 
228
252
  ## `npm install` fails with `File exists: /opt/homebrew/bin/hlx`
229
253
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/aem-cli",
3
- "version": "16.14.0",
3
+ "version": "16.15.1",
4
4
  "description": "AEM CLI",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/git-utils.js CHANGED
@@ -135,6 +135,28 @@ export default class GitUtils {
135
135
  return false;
136
136
  }
137
137
 
138
+ /**
139
+ * Checks if a name is valid for use in a DNS subdomain.
140
+ * DNS labels must:
141
+ * - Be between 1 and 63 characters long
142
+ * - Contain only alphanumeric characters and hyphens
143
+ * - Not start or end with a hyphen
144
+ * - Not contain dots or other special characters
145
+ * @param {string} name the name to validate
146
+ * @returns {boolean} true if valid for DNS
147
+ */
148
+ static isValidDNSName(name) {
149
+ // Check length (DNS labels must be 1-63 characters)
150
+ if (!name || name.length > 63) {
151
+ return false;
152
+ }
153
+
154
+ // DNS labels can only contain alphanumeric characters and hyphens
155
+ // They cannot start or end with hyphens
156
+ // They cannot contain dots or other special characters
157
+ return /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(name);
158
+ }
159
+
138
160
  /**
139
161
  * Returns the name of the current branch. If `HEAD` is at a tag, the name of the tag
140
162
  * will be returned instead, if head is at a commit, fallback will be returned.
@@ -178,7 +200,11 @@ export default class GitUtils {
178
200
  ? await git.resolveRef({ fs, dir, ref: obj.object.object }) // annotated tag
179
201
  : oid; // lightweight tag
180
202
  if (commitSha === rev) {
181
- return tag;
203
+ // Only return tags that are valid for DNS names
204
+ // Skip tags containing dots or other invalid characters
205
+ if (GitUtils.isValidDNSName(tag)) {
206
+ return tag;
207
+ }
182
208
  }
183
209
  }
184
210
 
@@ -13,7 +13,7 @@ import crypto from 'crypto';
13
13
  import express from 'express';
14
14
  import { promisify } from 'util';
15
15
  import path from 'path';
16
- import { lstat } from 'fs/promises';
16
+ import { lstat, readFile } from 'fs/promises';
17
17
  import compression from 'compression';
18
18
  import utils from './utils.js';
19
19
  import RequestContext from './RequestContext.js';
@@ -270,16 +270,32 @@ export class HelixServer extends BaseServer {
270
270
 
271
271
  // try to serve static
272
272
  try {
273
- await sendFile(filePath, {
274
- dotfiles: 'allow',
275
- headers: {
273
+ // Check if it's an HTML file and live reload is enabled
274
+ if (liveReload && filePath.endsWith('.html')) {
275
+ // Read the HTML file and inject the livereload script
276
+ let htmlContent = await readFile(filePath, 'utf-8');
277
+ htmlContent = utils.injectLiveReloadScript(htmlContent, this);
278
+
279
+ res.set({
280
+ 'content-type': 'text/html; charset=utf-8',
276
281
  'access-control-allow-origin': '*',
277
- },
278
- });
279
- if (liveReload) {
282
+ });
283
+ res.send(htmlContent);
280
284
  liveReload.registerFile(ctx.requestId, filePath);
285
+ log.debug(`${pfx}served local HTML file with livereload: ${filePath}`);
286
+ } else {
287
+ // Serve other files normally
288
+ await sendFile(filePath, {
289
+ dotfiles: 'allow',
290
+ headers: {
291
+ 'access-control-allow-origin': '*',
292
+ },
293
+ });
294
+ if (liveReload) {
295
+ liveReload.registerFile(ctx.requestId, filePath);
296
+ }
297
+ log.debug(`${pfx}served local file ${filePath}`);
281
298
  }
282
- log.debug(`${pfx}served local file ${filePath}`);
283
299
  return;
284
300
  } catch (e) {
285
301
  log.debug(`${pfx}unable to deliver local file ${ctx.path} - ${e.stack || e}`);
@@ -325,6 +325,7 @@ window.LiveReloadOptions = {
325
325
  }
326
326
 
327
327
  const isHTML = ret.status === 200 && contentType.indexOf('text/html') === 0;
328
+ const isHTMLWithAuthError = (ret.status === 401 || ret.status === 403) && contentType.indexOf('text/html') === 0;
328
329
  const livereload = isHTML && opts.injectLiveReload;
329
330
  const replaceHead = isHTML && opts.headHtml;
330
331
  const doIndex = isHTML && opts.indexer && url.indexOf('.plain.html') < 0;
@@ -380,6 +381,24 @@ window.LiveReloadOptions = {
380
381
  .send(textBody);
381
382
  return;
382
383
  }
384
+ if (isHTMLWithAuthError) {
385
+ // Handle HTML responses with 401/403 status - inject meta tag
386
+ let textBody = await ret.text();
387
+ if (ctx.log.level === 'silly') {
388
+ ctx.log.trace(textBody);
389
+ ctx.log.trace(`[${id}] <<<--------------------------`);
390
+ }
391
+ textBody = utils.injectMeta(textBody, {
392
+ 'hlx:proxyUrl': url,
393
+ });
394
+
395
+ res
396
+ .set(respHeaders)
397
+ .status(ret.status)
398
+ .send(textBody);
399
+ return;
400
+ }
401
+
383
402
  if (ret.status === 401 || ret.status === 403) {
384
403
  const reqHeaders = req.headers;
385
404
  if (opts.autoLogin && opts.loginPath