@squiz/dx-common-lib 1.69.1 → 1.71.0

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.
Files changed (116) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/api-key-validation/ApiKeyValidationService.d.ts +1 -0
  3. package/lib/api-key-validation/CloudflareApiKeyService.d.ts +2 -0
  4. package/lib/api-key-validation/CloudflareApiKeyService.js +15 -6
  5. package/lib/api-key-validation/CloudflareApiKeyService.js.map +1 -1
  6. package/lib/api-key-validation/CloudflareApiKeyService.spec.js +29 -5
  7. package/lib/api-key-validation/CloudflareApiKeyService.spec.js.map +1 -1
  8. package/lib/api-key-validation/DevelopmentApiKeyService.d.ts +2 -1
  9. package/lib/api-key-validation/DevelopmentApiKeyService.js +5 -1
  10. package/lib/api-key-validation/DevelopmentApiKeyService.js.map +1 -1
  11. package/lib/api-key-validation/DevelopmentApiKeyService.spec.js +11 -0
  12. package/lib/api-key-validation/DevelopmentApiKeyService.spec.js.map +1 -1
  13. package/lib/api-key-validation/getApiKeyService.js +1 -2
  14. package/lib/api-key-validation/getApiKeyService.js.map +1 -1
  15. package/lib/assertions/assertAssign.js +1 -2
  16. package/lib/assertions/assertAssign.js.map +1 -1
  17. package/lib/assertions/assertAssignWithDefaultUndefinedValue.js +1 -2
  18. package/lib/assertions/assertAssignWithDefaultUndefinedValue.js.map +1 -1
  19. package/lib/assertions/assertIsArray.js +1 -2
  20. package/lib/assertions/assertIsArray.js.map +1 -1
  21. package/lib/assertions/assertIsBoolean.js +1 -2
  22. package/lib/assertions/assertIsBoolean.js.map +1 -1
  23. package/lib/assertions/assertIsDefined.js +1 -2
  24. package/lib/assertions/assertIsDefined.js.map +1 -1
  25. package/lib/assertions/assertIsEnumValue.js +1 -2
  26. package/lib/assertions/assertIsEnumValue.js.map +1 -1
  27. package/lib/assertions/assertIsMapOfStringAny.js +1 -2
  28. package/lib/assertions/assertIsMapOfStringAny.js.map +1 -1
  29. package/lib/assertions/assertIsMapOfStringString.js +1 -2
  30. package/lib/assertions/assertIsMapOfStringString.js.map +1 -1
  31. package/lib/assertions/assertIsNotAnEmptyString.js +1 -2
  32. package/lib/assertions/assertIsNotAnEmptyString.js.map +1 -1
  33. package/lib/assertions/assertIsObject.js +1 -2
  34. package/lib/assertions/assertIsObject.js.map +1 -1
  35. package/lib/assertions/assertIsString.js +1 -2
  36. package/lib/assertions/assertIsString.js.map +1 -1
  37. package/lib/cache/applyDefaultRulesToCacheControlObject.d.ts +15 -15
  38. package/lib/cache/applyDefaultRulesToCacheControlObject.js +1 -2
  39. package/lib/cache/applyDefaultRulesToCacheControlObject.js.map +1 -1
  40. package/lib/cache/cacheControlToString.js +1 -2
  41. package/lib/cache/cacheControlToString.js.map +1 -1
  42. package/lib/cache/parseAndSanitiseCacheControlHeader.js +3 -3
  43. package/lib/cache/parseAndSanitiseCacheControlHeader.js.map +1 -1
  44. package/lib/cache/parseCacheControl.js +1 -2
  45. package/lib/cache/parseCacheControl.js.map +1 -1
  46. package/lib/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.d.ts +7 -0
  47. package/lib/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.js +16 -0
  48. package/lib/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.js.map +1 -0
  49. package/lib/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.spec.d.ts +1 -0
  50. package/lib/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.spec.js +13 -0
  51. package/lib/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.spec.js.map +1 -0
  52. package/lib/edge-components-secret-key-service/EdgeComponentsSecretKeyService.d.ts +4 -0
  53. package/lib/edge-components-secret-key-service/EdgeComponentsSecretKeyService.js +3 -0
  54. package/lib/edge-components-secret-key-service/EdgeComponentsSecretKeyService.js.map +1 -0
  55. package/lib/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.d.ts +16 -0
  56. package/lib/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.js +49 -0
  57. package/lib/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.js.map +1 -0
  58. package/lib/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.spec.d.ts +1 -0
  59. package/lib/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.spec.js +34 -0
  60. package/lib/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.spec.js.map +1 -0
  61. package/lib/edge-components-secret-key-service/getEdgeComponentsSecretService.d.ts +5 -0
  62. package/lib/edge-components-secret-key-service/getEdgeComponentsSecretService.js +20 -0
  63. package/lib/edge-components-secret-key-service/getEdgeComponentsSecretService.js.map +1 -0
  64. package/lib/edge-components-secret-key-service/getEdgeComponentsSecretService.spec.d.ts +1 -0
  65. package/lib/edge-components-secret-key-service/getEdgeComponentsSecretService.spec.js +28 -0
  66. package/lib/edge-components-secret-key-service/getEdgeComponentsSecretService.spec.js.map +1 -0
  67. package/lib/esi-mac-token-generator/EsiMacTokenGenerator.d.ts +8 -0
  68. package/lib/esi-mac-token-generator/EsiMacTokenGenerator.js +24 -0
  69. package/lib/esi-mac-token-generator/EsiMacTokenGenerator.js.map +1 -0
  70. package/lib/esi-mac-token-generator/EsiMacTokenGenerator.spec.d.ts +1 -0
  71. package/lib/esi-mac-token-generator/EsiMacTokenGenerator.spec.js +23 -0
  72. package/lib/esi-mac-token-generator/EsiMacTokenGenerator.spec.js.map +1 -0
  73. package/lib/index.d.ts +5 -0
  74. package/lib/index.js +5 -0
  75. package/lib/index.js.map +1 -1
  76. package/lib/json-order/index.d.ts +2 -2
  77. package/lib/json-order/key.js.map +1 -1
  78. package/lib/json-order/order.js.map +1 -1
  79. package/lib/json-order/parse.js.map +1 -1
  80. package/lib/server-utils/errorMiddleware.js +1 -2
  81. package/lib/server-utils/errorMiddleware.js.map +1 -1
  82. package/lib/server-utils/requestLogger.js +2 -3
  83. package/lib/server-utils/requestLogger.js.map +1 -1
  84. package/lib/util/getNodeEnv.js +1 -2
  85. package/lib/util/getNodeEnv.js.map +1 -1
  86. package/lib/util/getPageInfo.js +1 -2
  87. package/lib/util/getPageInfo.js.map +1 -1
  88. package/lib/util/isPathTryingToAccessOutsideOfRoot.js +1 -2
  89. package/lib/util/isPathTryingToAccessOutsideOfRoot.js.map +1 -1
  90. package/lib/util/isReadable.js +1 -2
  91. package/lib/util/isReadable.js.map +1 -1
  92. package/lib/util/joinAbsoluteUrlPath.js +1 -2
  93. package/lib/util/joinAbsoluteUrlPath.js.map +1 -1
  94. package/lib/util/never.js +1 -2
  95. package/lib/util/never.js.map +1 -1
  96. package/lib/util/parseEnvVarForVar.js +1 -2
  97. package/lib/util/parseEnvVarForVar.js.map +1 -1
  98. package/lib/zip/zipDirectory.js +1 -2
  99. package/lib/zip/zipDirectory.js.map +1 -1
  100. package/package.json +3 -3
  101. package/src/api-key-validation/ApiKeyValidationService.ts +2 -0
  102. package/src/api-key-validation/CloudflareApiKeyService.spec.ts +52 -5
  103. package/src/api-key-validation/CloudflareApiKeyService.ts +16 -8
  104. package/src/api-key-validation/DevelopmentApiKeyService.spec.ts +13 -0
  105. package/src/api-key-validation/DevelopmentApiKeyService.ts +6 -0
  106. package/src/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.spec.ts +11 -0
  107. package/src/edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService.ts +13 -0
  108. package/src/edge-components-secret-key-service/EdgeComponentsSecretKeyService.ts +4 -0
  109. package/src/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.spec.ts +47 -0
  110. package/src/edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService.ts +63 -0
  111. package/src/edge-components-secret-key-service/getEdgeComponentsSecretService.spec.ts +39 -0
  112. package/src/edge-components-secret-key-service/getEdgeComponentsSecretService.ts +21 -0
  113. package/src/esi-mac-token-generator/EsiMacTokenGenerator.spec.ts +25 -0
  114. package/src/esi-mac-token-generator/EsiMacTokenGenerator.ts +28 -0
  115. package/src/index.ts +5 -0
  116. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"isReadable.js","sourceRoot":"","sources":["../../src/util/isReadable.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,wDAA2B;AAC3B,2BAA+B;AAExB,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,IAAY;IAC7D,IAAI;QACF,MAAM,kBAAG,CAAC,MAAM,CAAC,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,cAAS,CAAC,IAAI,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC;KACb;IAAC,MAAM;QACN,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAPD,gCAOC"}
1
+ {"version":3,"file":"isReadable.js","sourceRoot":"","sources":["../../src/util/isReadable.ts"],"names":[],"mappings":";;;;;AAIA,gCAOC;AAXD,gDAAwB;AACxB,wDAA2B;AAC3B,2BAA+B;AAExB,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,IAAY;IAC7D,IAAI,CAAC;QACH,MAAM,kBAAG,CAAC,MAAM,CAAC,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,cAAS,CAAC,IAAI,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.joinAbsoluteUrlPath = void 0;
3
+ exports.joinAbsoluteUrlPath = joinAbsoluteUrlPath;
4
4
  function joinAbsoluteUrlPath(...args) {
5
5
  const [rootUrl] = args;
6
6
  /**
@@ -16,7 +16,6 @@ function joinAbsoluteUrlPath(...args) {
16
16
  return url.pathname.replace(/(^\/|\/$)/g, '');
17
17
  }
18
18
  }
19
- exports.joinAbsoluteUrlPath = joinAbsoluteUrlPath;
20
19
  function getSanitisedString(subdirs) {
21
20
  return subdirs.map((dir) => dir.replace(/(^\.\/+)|(^\/+|\/+$)/g, '')).join('/');
22
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"joinAbsoluteUrlPath.js","sourceRoot":"","sources":["../../src/util/joinAbsoluteUrlPath.ts"],"names":[],"mappings":";;;AAAA,SAAgB,mBAAmB,CAAC,GAAG,IAAc;IACnD,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAEpE,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE;QAC1B,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;KACvB;SAAM;QACL,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;KAC/C;AACH,CAAC;AAdD,kDAcC;AAED,SAAS,kBAAkB,CAAC,OAAiB;IAC3C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"joinAbsoluteUrlPath.js","sourceRoot":"","sources":["../../src/util/joinAbsoluteUrlPath.ts"],"names":[],"mappings":";;AAAA,kDAcC;AAdD,SAAgB,mBAAmB,CAAC,GAAG,IAAc;IACnD,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAEpE,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAiB;IAC3C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;AACrC,CAAC"}
package/lib/util/never.js CHANGED
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.never = void 0;
3
+ exports.never = never;
4
4
  function never(a) {
5
5
  // this should never be executed. This is a compile time check
6
6
  throw new Error(`value ${a} is not valid`);
7
7
  }
8
- exports.never = never;
9
8
  //# sourceMappingURL=never.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"never.js","sourceRoot":"","sources":["../../src/util/never.ts"],"names":[],"mappings":";;;AAAA,SAAgB,KAAK,CAAC,CAAQ;IAC5B,8DAA8D;IAC9D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;AAC7C,CAAC;AAHD,sBAGC"}
1
+ {"version":3,"file":"never.js","sourceRoot":"","sources":["../../src/util/never.ts"],"names":[],"mappings":";;AAAA,sBAGC;AAHD,SAAgB,KAAK,CAAC,CAAQ;IAC5B,8DAA8D;IAC9D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;AAC7C,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseEnvVarForVar = void 0;
3
+ exports.parseEnvVarForVar = parseEnvVarForVar;
4
4
  function parseEnvVarForVar(varName, defaultValue = undefined) {
5
5
  if (process.env[varName] === undefined) {
6
6
  if (defaultValue !== undefined) {
@@ -11,5 +11,4 @@ function parseEnvVarForVar(varName, defaultValue = undefined) {
11
11
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
12
12
  return process.env[varName];
13
13
  }
14
- exports.parseEnvVarForVar = parseEnvVarForVar;
15
14
  //# sourceMappingURL=parseEnvVarForVar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseEnvVarForVar.js","sourceRoot":"","sources":["../../src/util/parseEnvVarForVar.ts"],"names":[],"mappings":";;;AAAA,SAAgB,iBAAiB,CAAC,OAAe,EAAE,eAAmC,SAAS;IAC7F,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE;QACtC,IAAI,YAAY,KAAK,SAAS,EAAE;YAC9B,OAAO,YAAY,CAAC;SACrB;QAED,MAAM,IAAI,KAAK,CAAC,gBAAgB,OAAO,cAAc,CAAC,CAAC;KACxD;IAED,oEAAoE;IACpE,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;AAC/B,CAAC;AAXD,8CAWC"}
1
+ {"version":3,"file":"parseEnvVarForVar.js","sourceRoot":"","sources":["../../src/util/parseEnvVarForVar.ts"],"names":[],"mappings":";;AAAA,8CAWC;AAXD,SAAgB,iBAAiB,CAAC,OAAe,EAAE,eAAmC,SAAS;IAC7F,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,gBAAgB,OAAO,cAAc,CAAC,CAAC;IACzD,CAAC;IAED,oEAAoE;IACpE,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;AAC/B,CAAC"}
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.zipDirectory = void 0;
6
+ exports.zipDirectory = zipDirectory;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const archiver_1 = __importDefault(require("archiver"));
@@ -28,5 +28,4 @@ function zipDirectory(sourceDirectory, outputDirectory) {
28
28
  archive.finalize();
29
29
  });
30
30
  }
31
- exports.zipDirectory = zipDirectory;
32
31
  //# sourceMappingURL=zipDirectory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zipDirectory.js","sourceRoot":"","sources":["../../src/zip/zipDirectory.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,4CAAoB;AAEpB,wDAAgC;AAEhC,SAAgB,YAAY,CAAC,eAAuB,EAAE,eAAuB;IAC3E,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,YAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,IAAA,kBAAQ,EAAC,KAAK,EAAE;YAC9B,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,8BAA8B;SACnD,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;YACjB,OAAO,CAAC,aAAa,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,GAAG;YACjC,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG;YAC/B,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,CAAC,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAzBD,oCAyBC"}
1
+ {"version":3,"file":"zipDirectory.js","sourceRoot":"","sources":["../../src/zip/zipDirectory.ts"],"names":[],"mappings":";;;;;AAKA,oCAyBC;AA9BD,gDAAwB;AACxB,4CAAoB;AAEpB,wDAAgC;AAEhC,SAAgB,YAAY,CAAC,eAAuB,EAAE,eAAuB;IAC3E,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,YAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,IAAA,kBAAQ,EAAC,KAAK,EAAE;YAC9B,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,8BAA8B;SACnD,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;YACjB,OAAO,CAAC,aAAa,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,GAAG;YACjC,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG;YAC/B,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,CAAC,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/dx-common-lib",
3
- "version": "1.69.1",
3
+ "version": "1.71.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "private": false,
@@ -30,10 +30,10 @@
30
30
  "@types/fs-extra": "11.0.1",
31
31
  "@types/jest": "28.1.8",
32
32
  "@types/lodash.clonedeep": "4.5.7",
33
- "@types/node": "20.12.4",
33
+ "@types/node": "22.10.5",
34
34
  "dotenv": "16.0.3",
35
35
  "jest": "29.4.1",
36
36
  "ts-jest": "29.0.5",
37
- "typescript": "4.9.4"
37
+ "typescript": "^5.7.2"
38
38
  }
39
39
  }
@@ -5,4 +5,6 @@ export interface ApiKeyValidationService {
5
5
  * @deprecated Suggest moving towards using JWT authentication.
6
6
  */
7
7
  getInterServiceKeys(): string[];
8
+
9
+ getEsiSecretToken(): string;
8
10
  }
@@ -15,13 +15,31 @@ describe('CloudflareApiKeyService', () => {
15
15
  sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: 'bad json' }));
16
16
 
17
17
  await expect(service.refreshApiKeys()).rejects.toThrowError(
18
- new Error('failed to decode cloudflare api key values'),
18
+ new Error('Failed to decode cloudflare api key values: Invalid JSON'),
19
+ );
20
+ });
21
+
22
+ it('should throw an error if the secret value missing "inter-service-keys" value', async () => {
23
+ sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: '{"esi-secret-token": "foo"}' }));
24
+
25
+ await expect(service.refreshApiKeys()).rejects.toThrowError(
26
+ new Error('Failed to decode cloudflare api key values: Missing all required keys'),
27
+ );
28
+ });
29
+
30
+ it('should throw an error if the secret value missing "esi-secret-token" value', async () => {
31
+ sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: '{"inter-service-keys": []}' }));
32
+
33
+ await expect(service.refreshApiKeys()).rejects.toThrowError(
34
+ new Error('Failed to decode cloudflare api key values: Missing all required keys'),
19
35
  );
20
36
  });
21
37
 
22
38
  it('should make a request to the aws secrets manager when refreshing the keys', async () => {
23
39
  sendSpy.mockClear();
24
- sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: '{"inter-service-keys":[]}' }));
40
+ sendSpy.mockImplementationOnce(() =>
41
+ Promise.resolve({ SecretString: '{"inter-service-keys":[], "esi-secret-token": "foo"}' }),
42
+ );
25
43
  await service.refreshApiKeys();
26
44
 
27
45
  expect(sendSpy.mock.lastCall[0].input).toEqual({ SecretId: 'my-secret-name' });
@@ -30,7 +48,9 @@ describe('CloudflareApiKeyService', () => {
30
48
 
31
49
  it('should start a refresh timer once called, but only once', (done) => {
32
50
  sendSpy.mockClear();
33
- sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: '{"inter-service-keys":["my-new-key"]}' }));
51
+ sendSpy.mockImplementationOnce(() =>
52
+ Promise.resolve({ SecretString: '{"inter-service-keys":["my-new-key"], "esi-secret-token": "foo"}' }),
53
+ );
34
54
  const spy = jest.spyOn(service, 'refreshApiKeys');
35
55
 
36
56
  expect(spy).not.toBeCalled();
@@ -50,7 +70,9 @@ describe('CloudflareApiKeyService', () => {
50
70
  describe('interServiceKeyIsValid', () => {
51
71
  describe('when there are no api keys', () => {
52
72
  beforeAll(async () => {
53
- sendSpy.mockImplementation(() => Promise.resolve({ SecretString: '{"inter-service-keys":[]}' }));
73
+ sendSpy.mockImplementation(() =>
74
+ Promise.resolve({ SecretString: '{"inter-service-keys":[], "esi-secret-token": "foo"}' }),
75
+ );
54
76
  await service.refreshApiKeys();
55
77
  });
56
78
 
@@ -65,7 +87,8 @@ describe('CloudflareApiKeyService', () => {
65
87
  beforeAll(async () => {
66
88
  sendSpy.mockImplementation(() =>
67
89
  Promise.resolve({
68
- SecretString: '{"keys":["my-key", "my-other-key"], "inter-service-keys":["my-inter-service-key"]}',
90
+ SecretString:
91
+ '{"keys":["my-key", "my-other-key"], "inter-service-keys":["my-inter-service-key"], "esi-secret-token": "foo"}',
69
92
  }),
70
93
  );
71
94
  await service.refreshApiKeys();
@@ -76,4 +99,28 @@ describe('CloudflareApiKeyService', () => {
76
99
  });
77
100
  });
78
101
  });
102
+
103
+ describe('getInterServiceKeys', () => {
104
+ it('should return "esi-secret-token" from the secret manager', async () => {
105
+ sendSpy.mockClear();
106
+ sendSpy.mockImplementationOnce(() =>
107
+ Promise.resolve({ SecretString: '{"inter-service-keys":["some-key"], "esi-secret-token": "foo"}' }),
108
+ );
109
+ await service.refreshApiKeys();
110
+
111
+ expect(service.getInterServiceKeys()).toEqual(['some-key']);
112
+ });
113
+ });
114
+
115
+ describe('getEsiSecretToken', () => {
116
+ it('should return "esi-secret-token" from the secret manager', async () => {
117
+ sendSpy.mockClear();
118
+ sendSpy.mockImplementationOnce(() =>
119
+ Promise.resolve({ SecretString: '{"inter-service-keys":[], "esi-secret-token": "foo"}' }),
120
+ );
121
+ await service.refreshApiKeys();
122
+
123
+ expect(service.getEsiSecretToken()).toEqual('foo');
124
+ });
125
+ });
79
126
  });
@@ -9,10 +9,12 @@ import { getLogger, Logger } from '@squiz/dx-logger-lib';
9
9
 
10
10
  export interface CloudFlareKeys {
11
11
  'inter-service-keys': string[];
12
+ 'esi-secret-token': string;
12
13
  }
13
14
 
14
15
  let validKeys: CloudFlareKeys = {
15
16
  'inter-service-keys': [],
17
+ 'esi-secret-token': '',
16
18
  };
17
19
 
18
20
  let refreshInterval: ReturnType<typeof setInterval>;
@@ -61,17 +63,19 @@ export class CloudflareApiKeyService implements ApiKeyValidationService {
61
63
 
62
64
  try {
63
65
  if (!secretValue.SecretString) {
64
- throw new Error('cloudflare api key SecretString undefined');
66
+ throw new Error('Cloudflare api key SecretString undefined');
65
67
  }
66
- const secret = JSON.parse(secretValue.SecretString);
67
-
68
- if (secret['inter-service-keys']) {
69
- return secret;
68
+ try {
69
+ const secret = JSON.parse(secretValue.SecretString) as CloudFlareKeys;
70
+ if (secret['inter-service-keys'] && secret['esi-secret-token']) {
71
+ return secret;
72
+ }
73
+ } catch (e) {
74
+ throw new Error('Invalid JSON');
70
75
  }
71
-
72
- throw new Error('api keys retrieved and decoded successfully but contained no values');
76
+ throw new Error('Missing all required keys');
73
77
  } catch (e) {
74
- throw new Error('failed to decode cloudflare api key values');
78
+ throw new Error(`Failed to decode cloudflare api key values: ${(e as Error).message}`);
75
79
  }
76
80
  }
77
81
 
@@ -92,4 +96,8 @@ export class CloudflareApiKeyService implements ApiKeyValidationService {
92
96
  public getInterServiceKeys(): string[] {
93
97
  return validKeys['inter-service-keys'];
94
98
  }
99
+
100
+ public getEsiSecretToken(): string {
101
+ return validKeys['esi-secret-token'];
102
+ }
95
103
  }
@@ -20,4 +20,17 @@ describe('DevelopmentApiKeyService', () => {
20
20
  expect(service.interServiceKeyIsValid('invalid-api-key')).toEqual(false);
21
21
  });
22
22
  });
23
+
24
+ describe('getInterServiceKeys', () => {
25
+ it('should return a fixed value', async () => {
26
+ console.log(service.getInterServiceKeys());
27
+ expect(service.getInterServiceKeys()).toEqual(['inter-service-api-key']);
28
+ });
29
+ });
30
+
31
+ describe('getEsiSecretToken', () => {
32
+ it('should return a fixed value', async () => {
33
+ expect(service.getEsiSecretToken()).toEqual('cf-secret-token');
34
+ });
35
+ });
23
36
  });
@@ -2,6 +2,8 @@ import { getLogger, Logger } from '@squiz/dx-logger-lib';
2
2
  import { ApiKeyValidationService } from './ApiKeyValidationService';
3
3
  import { IncomingMessage } from 'http';
4
4
 
5
+ export const DEVELOPMENT_ESI_SECRET = `cf-secret-token`;
6
+
5
7
  export class DevelopmentApiKeyService implements ApiKeyValidationService {
6
8
  private logger: Logger;
7
9
 
@@ -22,4 +24,8 @@ export class DevelopmentApiKeyService implements ApiKeyValidationService {
22
24
  public getInterServiceKeys(): string[] {
23
25
  return ['inter-service-api-key'];
24
26
  }
27
+
28
+ public getEsiSecretToken(): string {
29
+ return DEVELOPMENT_ESI_SECRET;
30
+ }
25
31
  }
@@ -0,0 +1,11 @@
1
+ import { DevelopmentEdgeComponentsSecretKeyService } from './DevelopmentEdgeComponentsSecretKeyService';
2
+
3
+ describe('DevelopmentEdgeComponentsSecretKeyService', () => {
4
+ describe('getSecretKey', () => {
5
+ it('should return secret key set', async () => {
6
+ const service = new DevelopmentEdgeComponentsSecretKeyService('secret-key-value');
7
+ await service.loadSecretKey();
8
+ expect(service.getSecretKey()).toBe('secret-key-value');
9
+ });
10
+ });
11
+ });
@@ -0,0 +1,13 @@
1
+ import { EdgeComponentsSecretKeyService } from './EdgeComponentsSecretKeyService';
2
+
3
+ export class DevelopmentEdgeComponentsSecretKeyService implements EdgeComponentsSecretKeyService {
4
+ constructor(protected secretValue: string) {}
5
+
6
+ public async loadSecretKey() {
7
+ // no-op
8
+ }
9
+
10
+ public getSecretKey(): string {
11
+ return this.secretValue;
12
+ }
13
+ }
@@ -0,0 +1,4 @@
1
+ export interface EdgeComponentsSecretKeyService {
2
+ loadSecretKey(): Promise<void>;
3
+ getSecretKey(): string | undefined;
4
+ }
@@ -0,0 +1,47 @@
1
+ import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
2
+ import { ProductionEdgeComponentsSecretKeyService } from './ProductionEdgeComponentsSecretKeyService';
3
+
4
+ const sendSpy = jest.spyOn(SecretsManagerClient.prototype, 'send');
5
+
6
+ describe('ProductionEdgeComponentsSecretKeyService', () => {
7
+ const service = new ProductionEdgeComponentsSecretKeyService('my-secret-name');
8
+
9
+ describe('loadSecretKey', () => {
10
+ it('should throw an error if the secret value is not in the expected format', async () => {
11
+ sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: '{"foo":"key-val"}' }));
12
+
13
+ await expect(service.loadSecretKey()).rejects.toThrowError(
14
+ new Error(`Invalid secret my-secret-name: Property 'key' missing in the object`),
15
+ );
16
+ expect(service.getSecretKey()).toBe(undefined);
17
+ });
18
+
19
+ it('should throw an error if the secret value is invalid JSON', async () => {
20
+ sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: 'bad json' }));
21
+
22
+ await expect(service.loadSecretKey()).rejects.toThrowError(
23
+ new Error(`Invalid secret my-secret-name: Unexpected token 'b', "bad json" is not valid JSON`),
24
+ );
25
+ expect(service.getSecretKey()).toBe(undefined);
26
+ });
27
+
28
+ it('should throw an error if the secret value is undefined', async () => {
29
+ sendSpy.mockImplementationOnce(() => Promise.resolve({}));
30
+
31
+ await expect(service.loadSecretKey()).rejects.toThrowError(
32
+ new Error(`Failed to fetch secret key my-secret-name: Secret key my-secret-name is not defined`),
33
+ );
34
+ expect(service.getSecretKey()).toBe(undefined);
35
+ });
36
+
37
+ it('should make a request to the aws secrets manager when loading the keys', async () => {
38
+ sendSpy.mockClear();
39
+ sendSpy.mockImplementationOnce(() => Promise.resolve({ SecretString: '{"key":"key-val"}' }));
40
+ await service.loadSecretKey();
41
+
42
+ expect(sendSpy.mock.lastCall[0].input).toEqual({ SecretId: 'my-secret-name' });
43
+ expect(sendSpy.mock.lastCall[0]).toBeInstanceOf(GetSecretValueCommand);
44
+ expect(service.getSecretKey()).toBe('key-val');
45
+ });
46
+ });
47
+ });
@@ -0,0 +1,63 @@
1
+ import {
2
+ GetSecretValueCommand,
3
+ GetSecretValueCommandOutput,
4
+ SecretsManagerClient,
5
+ } from '@aws-sdk/client-secrets-manager';
6
+ import { getLogger, Logger } from '@squiz/dx-logger-lib';
7
+ import { EdgeComponentsSecretKeyService } from './EdgeComponentsSecretKeyService';
8
+
9
+ export type EdgeComponentsSecretKeyType = {
10
+ key: string;
11
+ };
12
+
13
+ export class ProductionEdgeComponentsSecretKeyService implements EdgeComponentsSecretKeyService {
14
+ protected secretsClient: SecretsManagerClient;
15
+ protected logger: Logger;
16
+ protected secretKey?: string;
17
+
18
+ constructor(protected secretName: string, logger?: Logger) {
19
+ this.secretsClient = new SecretsManagerClient({});
20
+
21
+ if (!logger) {
22
+ logger = getLogger({ name: 'SecretKeyService' });
23
+ }
24
+
25
+ this.logger = logger;
26
+ }
27
+
28
+ protected async fetchSecret(): Promise<string> {
29
+ let secretValue: GetSecretValueCommandOutput;
30
+ try {
31
+ secretValue = await this.secretsClient.send(
32
+ new GetSecretValueCommand({
33
+ SecretId: this.secretName,
34
+ }),
35
+ );
36
+ if (secretValue.SecretString === undefined) {
37
+ throw new Error(`Secret key ${this.secretName} is not defined`);
38
+ }
39
+ } catch (e: any) {
40
+ throw new Error(`Failed to fetch secret key ${this.secretName}: ${e.message}`);
41
+ }
42
+
43
+ try {
44
+ const secret = JSON.parse(secretValue.SecretString) as EdgeComponentsSecretKeyType;
45
+ if (secret.key === undefined) {
46
+ throw new Error(`Property 'key' missing in the object`);
47
+ }
48
+ return secret.key;
49
+ } catch (e) {
50
+ throw new Error(`Invalid secret ${this.secretName}: ${(e as Error).message}`);
51
+ }
52
+ }
53
+
54
+ public async loadSecretKey() {
55
+ this.logger.info(`Fetching secret ${this.secretName}`);
56
+ this.secretKey = await this.fetchSecret();
57
+ this.logger.info(`Found secret ${this.secretName}`);
58
+ }
59
+
60
+ public getSecretKey(): string | undefined {
61
+ return this.secretKey;
62
+ }
63
+ }
@@ -0,0 +1,39 @@
1
+ import { ProductionEdgeComponentsSecretKeyService } from './ProductionEdgeComponentsSecretKeyService';
2
+ import { DevelopmentEdgeComponentsSecretKeyService } from './DevelopmentEdgeComponentsSecretKeyService';
3
+ import { getEdgeComponentsSecretService } from './getEdgeComponentsSecretService';
4
+
5
+ describe('getEdgeComponentsSecretService', () => {
6
+ it('should return an instance of DevelopmentEdgeComponentsSecretKeyService when NODE_ENV is development', () => {
7
+ process.env.NODE_ENV = 'development';
8
+ expect(getEdgeComponentsSecretService({})).toBeInstanceOf(DevelopmentEdgeComponentsSecretKeyService);
9
+ });
10
+
11
+ it('should return an instance of DevelopmentEdgeComponentsSecretKeyService when NODE_ENV is development - secret supplied', () => {
12
+ process.env.NODE_ENV = 'development';
13
+ expect(getEdgeComponentsSecretService({ secretValue: 'some-val' })).toBeInstanceOf(
14
+ DevelopmentEdgeComponentsSecretKeyService,
15
+ );
16
+ });
17
+
18
+ it('should return an instance of ProductionEdgeComponentsSecretKeyService when NODE_ENV is production', () => {
19
+ process.env.NODE_ENV = 'production';
20
+ expect(getEdgeComponentsSecretService({ secretName: 'foo' })).toBeInstanceOf(
21
+ ProductionEdgeComponentsSecretKeyService,
22
+ );
23
+ });
24
+
25
+ it('should throw an error if no prodEnv values available', () => {
26
+ process.env.NODE_ENV = 'production';
27
+ expect(() => getEdgeComponentsSecretService({})).toThrow(
28
+ new Error(`Need to specify 'secretName' for production env`),
29
+ );
30
+ });
31
+
32
+ it('should throw an error if NODE_ENV is anything other than development or production', () => {
33
+ process.env.NODE_ENV = 'something invalid';
34
+
35
+ expect(() => getEdgeComponentsSecretService({})).toThrow(
36
+ new Error(`NODE_ENV env var can only be values "production" or "development"`),
37
+ );
38
+ });
39
+ });
@@ -0,0 +1,21 @@
1
+ import { getNodeEnv } from '../util';
2
+ import { DevelopmentEdgeComponentsSecretKeyService } from './DevelopmentEdgeComponentsSecretKeyService';
3
+ import { ProductionEdgeComponentsSecretKeyService } from './ProductionEdgeComponentsSecretKeyService';
4
+ import { EdgeComponentsSecretKeyService } from './EdgeComponentsSecretKeyService';
5
+
6
+ export function getEdgeComponentsSecretService(config: {
7
+ secretName?: string;
8
+ secretValue?: string;
9
+ }): EdgeComponentsSecretKeyService {
10
+ const env = getNodeEnv();
11
+
12
+ switch (env) {
13
+ case 'development':
14
+ return new DevelopmentEdgeComponentsSecretKeyService(config.secretValue ?? '');
15
+ case 'production':
16
+ if (config.secretName === undefined) {
17
+ throw new Error(`Need to specify 'secretName' for production env`);
18
+ }
19
+ return new ProductionEdgeComponentsSecretKeyService(config.secretName);
20
+ }
21
+ }
@@ -0,0 +1,25 @@
1
+ import { EsiMacTokenGenerator } from './EsiMacTokenGenerator';
2
+
3
+ describe('EsiMacTokenGenerator', () => {
4
+ it('should return an valid MAC', async () => {
5
+ const secret = 'some-secret';
6
+ const service = new EsiMacTokenGenerator(secret);
7
+
8
+ const requestUrl = 'http://some.url';
9
+ const esiUrl = 'http://some.esi.url';
10
+ const mac = await service.generateMac(requestUrl, esiUrl);
11
+
12
+ expect(mac).toEqual('NvARK6dlXV0dnVlnTSxTbGaT+VuDDIVY8FFdzBsf2c4=');
13
+
14
+ // verify the code
15
+ const encoder = new TextEncoder();
16
+ const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, [
17
+ 'sign',
18
+ 'verify',
19
+ ]);
20
+
21
+ const signature = `${requestUrl}|${esiUrl}`;
22
+ const verify = await crypto.subtle.verify('HMAC', key, Buffer.from(mac, 'base64'), encoder.encode(signature));
23
+ expect(verify).toEqual(true);
24
+ });
25
+ });
@@ -0,0 +1,28 @@
1
+ export class EsiMacTokenGenerator {
2
+ private key: CryptoKey | undefined = undefined;
3
+ private encoder: TextEncoder;
4
+
5
+ constructor(private secret: string) {
6
+ this.encoder = new TextEncoder();
7
+ }
8
+
9
+ public async generateMac(requestUrl: string, esiUrl: string): Promise<string> {
10
+ const signatureString = `${requestUrl}|${esiUrl}`;
11
+ const key = await this.getKey();
12
+ const mac = await crypto.subtle.sign('HMAC', key, this.encoder.encode(signatureString));
13
+ return Buffer.from(mac).toString('base64');
14
+ }
15
+
16
+ private async getKey() {
17
+ if (this.key === undefined) {
18
+ this.key = await crypto.subtle.importKey(
19
+ 'raw',
20
+ this.encoder.encode(this.secret),
21
+ { name: 'HMAC', hash: 'SHA-256' },
22
+ false,
23
+ ['sign', 'verify'],
24
+ );
25
+ }
26
+ return this.key;
27
+ }
28
+ }
package/src/index.ts CHANGED
@@ -10,3 +10,8 @@ export * from './api-key-validation/DevelopmentApiKeyService';
10
10
  export * from './api-key-validation/getApiKeyService';
11
11
  export * from './cache';
12
12
  export * from './json-order';
13
+ export * from './edge-components-secret-key-service/DevelopmentEdgeComponentsSecretKeyService';
14
+ export * from './edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService';
15
+ export * from './edge-components-secret-key-service/EdgeComponentsSecretKeyService';
16
+ export * from './edge-components-secret-key-service/getEdgeComponentsSecretService';
17
+ export * from './esi-mac-token-generator/EsiMacTokenGenerator';