@adobe/helix-config-storage 2.2.11 → 2.2.13

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,17 @@
1
+ ## [2.2.13](https://github.com/adobe/helix-config-storage/compare/v2.2.12...v2.2.13) (2025-06-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * ensure that purge receives empty old config ([#143](https://github.com/adobe/helix-config-storage/issues/143)) ([77bab30](https://github.com/adobe/helix-config-storage/commit/77bab30a36aa8a817f1d45307447ec62e1ee39ae))
7
+
8
+ ## [2.2.12](https://github.com/adobe/helix-config-storage/compare/v2.2.11...v2.2.12) (2025-06-18)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * respect profile when validating for new site configs ([#142](https://github.com/adobe/helix-config-storage/issues/142)) ([ad9e784](https://github.com/adobe/helix-config-storage/commit/ad9e7847d305726ac6987b6138b523a2ce867011))
14
+
1
15
  ## [2.2.11](https://github.com/adobe/helix-config-storage/compare/v2.2.10...v2.2.11) (2025-06-13)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-config-storage",
3
- "version": "2.2.11",
3
+ "version": "2.2.13",
4
4
  "description": "Helix Config Storage",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -36,8 +36,8 @@
36
36
  "reporter-options": "configFile=.mocha-multi.json"
37
37
  },
38
38
  "devDependencies": {
39
- "@adobe/eslint-config-helix": "3.0.3",
40
- "@eslint/config-helpers": "0.2.2",
39
+ "@adobe/eslint-config-helix": "3.0.4",
40
+ "@eslint/config-helpers": "0.2.3",
41
41
  "@semantic-release/changelog": "6.0.3",
42
42
  "@semantic-release/git": "10.0.1",
43
43
  "@semantic-release/npm": "12.0.1",
@@ -47,7 +47,7 @@
47
47
  "husky": "9.1.7",
48
48
  "json-schema-to-typescript": "15.0.4",
49
49
  "junit-report-builder": "5.1.1",
50
- "lint-staged": "16.1.0",
50
+ "lint-staged": "16.1.2",
51
51
  "mocha": "11.6.0",
52
52
  "mocha-multi-reporters": "1.5.1",
53
53
  "mocha-suppress-logs": "0.5.1",
@@ -520,9 +520,15 @@ export class ConfigStore {
520
520
  // we don't allow to define created
521
521
  delete data.created;
522
522
  this.#updateTimeStamps(data);
523
+ let oldConfig = {};
524
+ if (this.type === 'sites') {
525
+ // for a new site using a profile, we get the aggregate of the same profile.
526
+ // this allows to validate the protected properties like features and limits.
527
+ oldConfig = await this.getAggregatedConfig(ctx, { extends: data.extends });
528
+ }
523
529
  const config = await this.getAggregatedConfig(ctx, data);
524
530
  await this.validate(ctx, config);
525
- await this.validatePermissions(ctx, {}, config);
531
+ await this.validatePermissions(ctx, oldConfig, config);
526
532
  await storage.put(this.key, JSON.stringify(data), 'application/json');
527
533
  await this.purge(ctx, null, config);
528
534
  }
@@ -726,16 +732,19 @@ export class ConfigStore {
726
732
  config.created = oldConfig?.created;
727
733
  this.#updateTimeStamps(config);
728
734
  let newConfig = config;
735
+ let purgeConfig = oldConfig;
729
736
  if (this.type === 'sites') {
730
- // apply profile
731
- oldConfig = await this.getAggregatedConfig(ctx, oldConfig);
737
+ // apply profile: for a new site using a profile, we get the aggregate of the same profile.
738
+ // this allows to validate the protected properties like features and limits.
739
+ oldConfig = await this.getAggregatedConfig(ctx, oldConfig ?? { extends: newConfig.extends });
740
+ purgeConfig = await this.getAggregatedConfig(ctx, purgeConfig);
732
741
  newConfig = await this.getAggregatedConfig(ctx, newConfig);
733
742
  }
734
743
 
735
744
  await this.validate(ctx, newConfig);
736
745
  await this.validatePermissions(ctx, oldConfig, newConfig);
737
746
  await storage.put(this.key, JSON.stringify(config), 'application/json');
738
- await this.purge(ctx, oldConfig, newConfig);
747
+ await this.purge(ctx, purgeConfig, newConfig);
739
748
  return ret ?? redact(data, frag);
740
749
  }
741
750
 
@@ -35,6 +35,7 @@ export interface HelixOrgConfig {
35
35
  users?: Users;
36
36
  groups?: Groups;
37
37
  secrets?: Secrets;
38
+ apiKeys?: ApiKeys;
38
39
  tokens?: Tokens;
39
40
  access?: OrgAccessConfig;
40
41
  }
@@ -86,6 +87,29 @@ export interface Secrets {
86
87
  description?: string;
87
88
  };
88
89
  }
90
+ /**
91
+ * Stores information about generated admin API keys. The keys listed here have no operational meaning, but are used to track the keys that have been generated.
92
+ */
93
+ export interface ApiKeys {
94
+ /**
95
+ * This interface was referenced by `ApiKeys`'s JSON-Schema definition
96
+ * via the `patternProperty` "^[a-zA-Z0-9-_]+$".
97
+ */
98
+ [k: string]: {
99
+ /**
100
+ * the API token id (jti)
101
+ */
102
+ id: string;
103
+ created: string;
104
+ expiration: string;
105
+ roles: string[];
106
+ /**
107
+ * the subject of the API token (sub)
108
+ */
109
+ subject: string;
110
+ description?: string;
111
+ };
112
+ }
89
113
  /**
90
114
  * @deprecated
91
115
  * site tokens. deprecated: use the org secrets instead.
@@ -134,13 +134,19 @@ export interface CDNConfig {
134
134
  prod?: FastlyCDNConfig | CloudflareCDNConfig | AkamaiCDNConfig | ManagedCDNConfig | CloudfrontCDNConfig | EmptyConfig;
135
135
  live?: {
136
136
  /**
137
- * Sidekick config to override the default preview host. it supports parameters $owner and $repo
137
+ * Sidekick config to override the default previewHost. it supports parameters $owner and $repo
138
138
  */
139
139
  host: string;
140
140
  };
141
141
  preview?: {
142
142
  /**
143
- * Sidekick config to override the default live host. it supports parameters $owner and $repo
143
+ * Sidekick config to override the default liveHost. it supports parameters $owner and $repo
144
+ */
145
+ host: string;
146
+ };
147
+ review?: {
148
+ /**
149
+ * Sidekick config to override the default reviewHost. it supports parameters $owner and $repo
144
150
  */
145
151
  host: string;
146
152
  };
@@ -339,22 +345,60 @@ export interface Group {
339
345
  }[];
340
346
  }
341
347
  export interface SidekickConfig {
348
+ /**
349
+ * The label of the custom editing environment.
350
+ */
351
+ editUrlLabel?: string;
352
+ /**
353
+ * The URL pattern for the custom editing environment. Supports placeholders like {{contentSourceUrl}} or {{pathname}}.
354
+ */
355
+ editUrlPattern?: string;
356
+ /**
357
+ * The host name of the production website (overrides cdn.prod.host)
358
+ */
359
+ host?: string;
360
+ /**
361
+ * The host name of the live environment (overrides cdn.live.host, defaults to *.aem.live)
362
+ */
363
+ liveHost?: string;
342
364
  plugins?: SidekickPlugin[];
343
- [k: string]: unknown;
344
- }
345
- export interface SidekickPlugin {
346
365
  /**
347
- * The unique plugin ID
366
+ * The host name of the preview environment (overrides cdn.preview.host, defaults to *.aem.page)
348
367
  */
349
- id: string;
368
+ previewHost?: string;
350
369
  /**
351
- * The button text
370
+ * The name of the project to display in the sidekick
352
371
  */
353
- title?: string;
372
+ project?: string;
354
373
  /**
355
- * The URL to open when the button is clicked
374
+ * The host name of the review environment (overrides cdn.review.host, defaults to *.aem.reviews)
356
375
  */
357
- url?: string;
376
+ reviewHost?: string;
377
+ specialViews?: SidekickSpecialView[];
378
+ /**
379
+ * Additional hosts that are trusted to use the sidekick authentication
380
+ */
381
+ trustedHosts?: string[];
382
+ }
383
+ export interface SidekickPlugin {
384
+ /**
385
+ * The variant of the badge following the Adobe Spectrum badge variants
386
+ */
387
+ badgeVariant?:
388
+ | 'gray'
389
+ | 'red'
390
+ | 'orange'
391
+ | 'yellow'
392
+ | 'chartreuse'
393
+ | 'celery'
394
+ | 'green'
395
+ | 'seafoam'
396
+ | 'cyan'
397
+ | 'blue'
398
+ | 'indigo'
399
+ | 'purple'
400
+ | 'fuchsia'
401
+ | 'magenta';
358
402
  /**
359
403
  * The ID of the container to add this plugin to
360
404
  */
@@ -362,21 +406,29 @@ export interface SidekickPlugin {
362
406
  /**
363
407
  * The environments to display this plugin in
364
408
  */
365
- environments?: string & ('any' | 'dev' | 'admin' | 'edit' | 'preview' | 'live' | 'prod' | 'review')[];
409
+ environments?: string & ('any' | 'dev' | 'admin' | 'edit' | 'preview' | 'review' | 'live' | 'prod')[];
366
410
  /**
367
411
  * The name of a custom event to fire when the button is clicked (defaults to id)
368
412
  */
369
413
  event?: string;
370
414
  /**
371
- * Exclude the plugin from these paths
415
+ * Excludes the plugin from these paths
372
416
  */
373
417
  excludePaths?: string[];
374
418
  /**
375
- * Include the plugin on these paths (overrides excludePaths)
419
+ * The unique plugin ID
420
+ */
421
+ id: string;
422
+ /**
423
+ * Includes the plugin on these paths (overrides excludePaths)
376
424
  */
377
425
  includePaths?: string[];
378
426
  /**
379
- * Turns the plugin into a container for other plugins
427
+ * Renders the plugin as a badge
428
+ */
429
+ isBadge?: boolean;
430
+ /**
431
+ * Renders the plugin as a container for other plugins
380
432
  */
381
433
  isContainer?: boolean;
382
434
  /**
@@ -384,17 +436,33 @@ export interface SidekickPlugin {
384
436
  */
385
437
  isPalette?: boolean;
386
438
  /**
387
- * he dimensions and position of a palette box
439
+ * Opens the URL in a popover instead of a new tab
440
+ */
441
+ isPopover?: boolean;
442
+ /**
443
+ * The dimensions and position of the palette (top, left, bottom, right, width, height)
388
444
  */
389
445
  paletteRect?: string;
390
446
  /**
391
- * Opens the URL in a popover instead of a new tab
447
+ * Append ref, repo, owner, host, and project as query params to the URL
392
448
  */
393
- isPopover?: boolean;
449
+ passConfig?: boolean;
450
+ /**
451
+ * Append the referrer URL as a query param to the URL
452
+ */
453
+ passReferrer?: boolean;
454
+ /**
455
+ * Renders the plugin in the bar (true, default) or the menu (false)
456
+ */
457
+ pinned?: boolean;
394
458
  /**
395
- * The dimensions of a popover, delimited by a semicolon (width, height)
459
+ * The dimensions of the popover (width, height)
396
460
  */
397
461
  popoverRect?: string;
462
+ /**
463
+ * The button text
464
+ */
465
+ title?: string;
398
466
  /**
399
467
  * The button text in other supported languages
400
468
  */
@@ -408,35 +476,28 @@ export interface SidekickPlugin {
408
476
  [k: string]: string;
409
477
  };
410
478
  /**
411
- * Append ref, repo, owner, host, and project as query params on new URL button click
479
+ * The URL to open when the button is clicked
412
480
  */
413
- passConfig?: boolean;
481
+ url?: string;
482
+ [k: string]: unknown;
483
+ }
484
+ export interface SidekickSpecialView {
414
485
  /**
415
- * Append the referrer URL as a query param on new URL button click
486
+ * The unique view ID
416
487
  */
417
- passReferrer?: boolean;
488
+ id: string;
418
489
  /**
419
- * Opens the URL in a palette instead of a new tab
490
+ * Open the special view on this path
420
491
  */
421
- isBadge?: boolean;
492
+ path: string;
422
493
  /**
423
- * The variant of the badge following the Adobe Spectrum badge variants
494
+ * Title of the special view
424
495
  */
425
- badgeVariant?:
426
- | 'gray'
427
- | 'red'
428
- | 'orange'
429
- | 'yellow'
430
- | 'chartreuse'
431
- | 'celery'
432
- | 'green'
433
- | 'seafoam'
434
- | 'cyan'
435
- | 'blue'
436
- | 'indigo'
437
- | 'purple'
438
- | 'fuchsia'
439
- | 'magenta';
496
+ title?: string;
497
+ /**
498
+ * The URL of the special view. The resource path will be passed to it via 'path' parameter
499
+ */
500
+ viewer: string;
440
501
  [k: string]: unknown;
441
502
  }
442
503
  export interface Metadata {
@@ -42,6 +42,7 @@ export interface HelixSiteConfig {
42
42
  access?: Access;
43
43
  tokens?: Tokens;
44
44
  secrets?: Secrets;
45
+ apiKeys?: ApiKeys;
45
46
  groups?: Groups;
46
47
  sidekick?: SidekickConfig;
47
48
  metadata?: Metadata;
@@ -141,13 +142,19 @@ export interface CDNConfig {
141
142
  prod?: FastlyCDNConfig | CloudflareCDNConfig | AkamaiCDNConfig | ManagedCDNConfig | CloudfrontCDNConfig | EmptyConfig;
142
143
  live?: {
143
144
  /**
144
- * Sidekick config to override the default preview host. it supports parameters $owner and $repo
145
+ * Sidekick config to override the default previewHost. it supports parameters $owner and $repo
145
146
  */
146
147
  host: string;
147
148
  };
148
149
  preview?: {
149
150
  /**
150
- * Sidekick config to override the default live host. it supports parameters $owner and $repo
151
+ * Sidekick config to override the default liveHost. it supports parameters $owner and $repo
152
+ */
153
+ host: string;
154
+ };
155
+ review?: {
156
+ /**
157
+ * Sidekick config to override the default reviewHost. it supports parameters $owner and $repo
151
158
  */
152
159
  host: string;
153
160
  };
@@ -329,6 +336,29 @@ export interface Secrets {
329
336
  description?: string;
330
337
  };
331
338
  }
339
+ /**
340
+ * Stores information about generated admin API keys. The keys listed here have no operational meaning, but are used to track the keys that have been generated.
341
+ */
342
+ export interface ApiKeys {
343
+ /**
344
+ * This interface was referenced by `ApiKeys`'s JSON-Schema definition
345
+ * via the `patternProperty` "^[a-zA-Z0-9-_]+$".
346
+ */
347
+ [k: string]: {
348
+ /**
349
+ * the API token id (jti)
350
+ */
351
+ id: string;
352
+ created: string;
353
+ expiration: string;
354
+ roles: string[];
355
+ /**
356
+ * the subject of the API token (sub)
357
+ */
358
+ subject: string;
359
+ description?: string;
360
+ };
361
+ }
332
362
  export interface Groups {
333
363
  [k: string]: Group;
334
364
  }
@@ -346,22 +376,60 @@ export interface Group {
346
376
  }[];
347
377
  }
348
378
  export interface SidekickConfig {
379
+ /**
380
+ * The label of the custom editing environment.
381
+ */
382
+ editUrlLabel?: string;
383
+ /**
384
+ * The URL pattern for the custom editing environment. Supports placeholders like {{contentSourceUrl}} or {{pathname}}.
385
+ */
386
+ editUrlPattern?: string;
387
+ /**
388
+ * The host name of the production website (overrides cdn.prod.host)
389
+ */
390
+ host?: string;
391
+ /**
392
+ * The host name of the live environment (overrides cdn.live.host, defaults to *.aem.live)
393
+ */
394
+ liveHost?: string;
349
395
  plugins?: SidekickPlugin[];
350
- [k: string]: unknown;
351
- }
352
- export interface SidekickPlugin {
353
396
  /**
354
- * The unique plugin ID
397
+ * The host name of the preview environment (overrides cdn.preview.host, defaults to *.aem.page)
355
398
  */
356
- id: string;
399
+ previewHost?: string;
357
400
  /**
358
- * The button text
401
+ * The name of the project to display in the sidekick
359
402
  */
360
- title?: string;
403
+ project?: string;
361
404
  /**
362
- * The URL to open when the button is clicked
405
+ * The host name of the review environment (overrides cdn.review.host, defaults to *.aem.reviews)
363
406
  */
364
- url?: string;
407
+ reviewHost?: string;
408
+ specialViews?: SidekickSpecialView[];
409
+ /**
410
+ * Additional hosts that are trusted to use the sidekick authentication
411
+ */
412
+ trustedHosts?: string[];
413
+ }
414
+ export interface SidekickPlugin {
415
+ /**
416
+ * The variant of the badge following the Adobe Spectrum badge variants
417
+ */
418
+ badgeVariant?:
419
+ | 'gray'
420
+ | 'red'
421
+ | 'orange'
422
+ | 'yellow'
423
+ | 'chartreuse'
424
+ | 'celery'
425
+ | 'green'
426
+ | 'seafoam'
427
+ | 'cyan'
428
+ | 'blue'
429
+ | 'indigo'
430
+ | 'purple'
431
+ | 'fuchsia'
432
+ | 'magenta';
365
433
  /**
366
434
  * The ID of the container to add this plugin to
367
435
  */
@@ -369,21 +437,29 @@ export interface SidekickPlugin {
369
437
  /**
370
438
  * The environments to display this plugin in
371
439
  */
372
- environments?: string & ('any' | 'dev' | 'admin' | 'edit' | 'preview' | 'live' | 'prod' | 'review')[];
440
+ environments?: string & ('any' | 'dev' | 'admin' | 'edit' | 'preview' | 'review' | 'live' | 'prod')[];
373
441
  /**
374
442
  * The name of a custom event to fire when the button is clicked (defaults to id)
375
443
  */
376
444
  event?: string;
377
445
  /**
378
- * Exclude the plugin from these paths
446
+ * Excludes the plugin from these paths
379
447
  */
380
448
  excludePaths?: string[];
381
449
  /**
382
- * Include the plugin on these paths (overrides excludePaths)
450
+ * The unique plugin ID
451
+ */
452
+ id: string;
453
+ /**
454
+ * Includes the plugin on these paths (overrides excludePaths)
383
455
  */
384
456
  includePaths?: string[];
385
457
  /**
386
- * Turns the plugin into a container for other plugins
458
+ * Renders the plugin as a badge
459
+ */
460
+ isBadge?: boolean;
461
+ /**
462
+ * Renders the plugin as a container for other plugins
387
463
  */
388
464
  isContainer?: boolean;
389
465
  /**
@@ -391,17 +467,33 @@ export interface SidekickPlugin {
391
467
  */
392
468
  isPalette?: boolean;
393
469
  /**
394
- * he dimensions and position of a palette box
470
+ * Opens the URL in a popover instead of a new tab
471
+ */
472
+ isPopover?: boolean;
473
+ /**
474
+ * The dimensions and position of the palette (top, left, bottom, right, width, height)
395
475
  */
396
476
  paletteRect?: string;
397
477
  /**
398
- * Opens the URL in a popover instead of a new tab
478
+ * Append ref, repo, owner, host, and project as query params to the URL
399
479
  */
400
- isPopover?: boolean;
480
+ passConfig?: boolean;
481
+ /**
482
+ * Append the referrer URL as a query param to the URL
483
+ */
484
+ passReferrer?: boolean;
485
+ /**
486
+ * Renders the plugin in the bar (true, default) or the menu (false)
487
+ */
488
+ pinned?: boolean;
401
489
  /**
402
- * The dimensions of a popover, delimited by a semicolon (width, height)
490
+ * The dimensions of the popover (width, height)
403
491
  */
404
492
  popoverRect?: string;
493
+ /**
494
+ * The button text
495
+ */
496
+ title?: string;
405
497
  /**
406
498
  * The button text in other supported languages
407
499
  */
@@ -415,35 +507,28 @@ export interface SidekickPlugin {
415
507
  [k: string]: string;
416
508
  };
417
509
  /**
418
- * Append ref, repo, owner, host, and project as query params on new URL button click
510
+ * The URL to open when the button is clicked
419
511
  */
420
- passConfig?: boolean;
512
+ url?: string;
513
+ [k: string]: unknown;
514
+ }
515
+ export interface SidekickSpecialView {
421
516
  /**
422
- * Append the referrer URL as a query param on new URL button click
517
+ * The unique view ID
423
518
  */
424
- passReferrer?: boolean;
519
+ id: string;
425
520
  /**
426
- * Opens the URL in a palette instead of a new tab
521
+ * Open the special view on this path
427
522
  */
428
- isBadge?: boolean;
523
+ path: string;
429
524
  /**
430
- * The variant of the badge following the Adobe Spectrum badge variants
525
+ * Title of the special view
431
526
  */
432
- badgeVariant?:
433
- | 'gray'
434
- | 'red'
435
- | 'orange'
436
- | 'yellow'
437
- | 'chartreuse'
438
- | 'celery'
439
- | 'green'
440
- | 'seafoam'
441
- | 'cyan'
442
- | 'blue'
443
- | 'indigo'
444
- | 'purple'
445
- | 'fuchsia'
446
- | 'magenta';
527
+ title?: string;
528
+ /**
529
+ * The URL of the special view. The resource path will be passed to it via 'path' parameter
530
+ */
531
+ viewer: string;
447
532
  [k: string]: unknown;
448
533
  }
449
534
  export interface Metadata {