@lighthouse/common 6.10.0 → 6.10.1-canary.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 (229) hide show
  1. package/.mise.toml +6 -6
  2. package/CHANGELOG.md +758 -758
  3. package/README.md +1 -1
  4. package/dist/errors/FetchImageError.js +3 -3
  5. package/dist/helpers/fetch-image-for-pdf-generator-service/index.js +7 -7
  6. package/dist/helpers/floatify/index.js +6 -6
  7. package/dist/helpers/get-audit-items-data/index.js +47 -36
  8. package/dist/helpers/validate-url/index.js +4 -4
  9. package/dist/pdf/activity-report/index.js +32 -32
  10. package/dist/pdf/audit/index.js +23 -23
  11. package/dist/pdf/helpers/fields/index.js +47 -27
  12. package/dist/pdf/issue/index.js +23 -23
  13. package/dist/pdf/job/index.js +22 -22
  14. package/dist/pdf/shift-report/index.js +28 -28
  15. package/dist/pdf/task/index.js +23 -23
  16. package/dist/scheduling/generators/occurrenceIntervalsGenerator.js +2 -2
  17. package/dist/scheduling/generators/scheduleIntervalsGenerator.js +2 -2
  18. package/dist/scheduling/generators/serviceIntervalsGenerator.js +2 -2
  19. package/dist/scheduling/helpers/convertToTimezone.js +6 -6
  20. package/dist/scheduling/helpers/generateNonRepeatingSchedule.js +2 -2
  21. package/dist/scheduling/helpers/generateRepeatingSchedule.js +2 -2
  22. package/dist/scheduling/helpers/generateScheduleEnd.js +2 -2
  23. package/dist/scheduling/helpers/hasValidStartAndEnd.js +5 -5
  24. package/dist/scheduling/helpers/intervalCovers.js +6 -6
  25. package/dist/scheduling/helpers/intervalIntersectsEnd.js +6 -6
  26. package/dist/scheduling/helpers/intervalIntersectsStart.js +6 -6
  27. package/dist/scheduling/helpers/intervalOnlyIntersectsEnd.js +6 -6
  28. package/dist/scheduling/helpers/intervalOnlyIntersectsStart.js +6 -6
  29. package/dist/scheduling/helpers/intervalOutside.js +6 -6
  30. package/dist/scheduling/helpers/intervalWithin.js +6 -6
  31. package/dist/scheduling/helpers/mergeIntervals.js +6 -6
  32. package/dist/scheduling/helpers/splitIntervals.js +6 -6
  33. package/dist/scheduling/strategies/getNext.js +2 -2
  34. package/dist/scheduling/strategies/getNextExactDateOfMonth.js +2 -2
  35. package/dist/scheduling/strategies/getNextLastDayOfMonth.js +2 -2
  36. package/dist/scheduling/strategies/getNextLastWeekdayOfMonth.js +2 -2
  37. package/dist/scheduling/strategies/getNextNoRepeat.js +2 -2
  38. package/dist/scheduling/strategies/getNextWeekday.js +2 -2
  39. package/dist/scheduling/strategies/getNextXDayOfXWeekOfMonth.js +2 -2
  40. package/dist/service-hours/__helpers__/calculate-hours.js +4 -4
  41. package/dist/service-hours/__helpers__/isOpen.js +2 -2
  42. package/dist/service-hours/schema.js +4 -4
  43. package/lib/constants.js +12 -6
  44. package/lib/constants.js.map +1 -1
  45. package/lib/errors/DomainError.js +14 -21
  46. package/lib/errors/DomainError.js.map +1 -1
  47. package/lib/errors/FetchImageError.js +17 -24
  48. package/lib/errors/FetchImageError.js.map +1 -1
  49. package/lib/errors/ValidationError.js +30 -36
  50. package/lib/errors/ValidationError.js.map +1 -1
  51. package/lib/errors/index.js +23 -5
  52. package/lib/errors/index.js.map +1 -1
  53. package/lib/helpers/build-fetch-url/index.js +43 -47
  54. package/lib/helpers/build-fetch-url/index.js.map +1 -1
  55. package/lib/helpers/fetch-image/index.js +83 -82
  56. package/lib/helpers/fetch-image/index.js.map +1 -1
  57. package/lib/helpers/fetch-image-for-pdf-generator-service/index.js +168 -243
  58. package/lib/helpers/fetch-image-for-pdf-generator-service/index.js.map +1 -1
  59. package/lib/helpers/fetch-image-for-web/index.js +71 -94
  60. package/lib/helpers/fetch-image-for-web/index.js.map +1 -1
  61. package/lib/helpers/fetch-lighthouse-logo/index.js +36 -61
  62. package/lib/helpers/fetch-lighthouse-logo/index.js.map +1 -1
  63. package/lib/helpers/floatify/index.js +13 -7
  64. package/lib/helpers/floatify/index.js.map +1 -1
  65. package/lib/helpers/get-assignees-full-names/index.js +11 -7
  66. package/lib/helpers/get-assignees-full-names/index.js.map +1 -1
  67. package/lib/helpers/get-audit-entry-details/index.js +42 -32
  68. package/lib/helpers/get-audit-entry-details/index.js.map +1 -1
  69. package/lib/helpers/get-audit-items-data/index.js +104 -83
  70. package/lib/helpers/get-audit-items-data/index.js.map +1 -1
  71. package/lib/helpers/get-geometry-geocoded-string/index.js +10 -5
  72. package/lib/helpers/get-geometry-geocoded-string/index.js.map +1 -1
  73. package/lib/helpers/get-issue-details/index.js +53 -43
  74. package/lib/helpers/get-issue-details/index.js.map +1 -1
  75. package/lib/helpers/get-job-details/index.js +49 -41
  76. package/lib/helpers/get-job-details/index.js.map +1 -1
  77. package/lib/helpers/get-location-reference/index.js +32 -34
  78. package/lib/helpers/get-location-reference/index.js.map +1 -1
  79. package/lib/helpers/get-pretty-duration/index.js +16 -10
  80. package/lib/helpers/get-pretty-duration/index.js.map +1 -1
  81. package/lib/helpers/get-reference-details/index.js +20 -10
  82. package/lib/helpers/get-reference-details/index.js.map +1 -1
  83. package/lib/helpers/get-status-details/index.js +8 -2
  84. package/lib/helpers/get-status-details/index.js.map +1 -1
  85. package/lib/helpers/get-task-entry-details/index.js +32 -23
  86. package/lib/helpers/get-task-entry-details/index.js.map +1 -1
  87. package/lib/helpers/get-timezone-abbr/index.js +11 -4
  88. package/lib/helpers/get-timezone-abbr/index.js.map +1 -1
  89. package/lib/helpers/get-timezone-datetime/index.js +20 -13
  90. package/lib/helpers/get-timezone-datetime/index.js.map +1 -1
  91. package/lib/helpers/get-user-full-name/index.js +9 -3
  92. package/lib/helpers/get-user-full-name/index.js.map +1 -1
  93. package/lib/helpers/get-value-as-percentage/index.js +9 -4
  94. package/lib/helpers/get-value-as-percentage/index.js.map +1 -1
  95. package/lib/helpers/image-validators/index.js +18 -12
  96. package/lib/helpers/image-validators/index.js.map +1 -1
  97. package/lib/helpers/index.js +130 -18
  98. package/lib/helpers/index.js.map +1 -1
  99. package/lib/helpers/validate-url/index.js +11 -5
  100. package/lib/helpers/validate-url/index.js.map +1 -1
  101. package/lib/images/index.js +10 -4
  102. package/lib/images/index.js.map +1 -1
  103. package/lib/index.js +66 -10
  104. package/lib/index.js.map +1 -1
  105. package/lib/pdf/activity-report/index.js +407 -537
  106. package/lib/pdf/activity-report/index.js.map +1 -1
  107. package/lib/pdf/audit/index.js +137 -134
  108. package/lib/pdf/audit/index.js.map +1 -1
  109. package/lib/pdf/fonts/index.js +4 -2
  110. package/lib/pdf/fonts/index.js.map +1 -1
  111. package/lib/pdf/helpers/build-audit-content/index.js +57 -51
  112. package/lib/pdf/helpers/build-audit-content/index.js.map +1 -1
  113. package/lib/pdf/helpers/build-audit-follow-ups/index.js +52 -50
  114. package/lib/pdf/helpers/build-audit-follow-ups/index.js.map +1 -1
  115. package/lib/pdf/helpers/build-location-scans-content/index.js +22 -16
  116. package/lib/pdf/helpers/build-location-scans-content/index.js.map +1 -1
  117. package/lib/pdf/helpers/build-template-content/index.js +52 -51
  118. package/lib/pdf/helpers/build-template-content/index.js.map +1 -1
  119. package/lib/pdf/helpers/default-footer/index.js +38 -35
  120. package/lib/pdf/helpers/default-footer/index.js.map +1 -1
  121. package/lib/pdf/helpers/default-header/index.js +40 -35
  122. package/lib/pdf/helpers/default-header/index.js.map +1 -1
  123. package/lib/pdf/helpers/default-styles/index.js +7 -1
  124. package/lib/pdf/helpers/default-styles/index.js.map +1 -1
  125. package/lib/pdf/helpers/fields/index.js +225 -214
  126. package/lib/pdf/helpers/fields/index.js.map +1 -1
  127. package/lib/pdf/helpers/format-location-address/index.js +14 -8
  128. package/lib/pdf/helpers/format-location-address/index.js.map +1 -1
  129. package/lib/pdf/helpers/generate-definition/index.js +60 -65
  130. package/lib/pdf/helpers/generate-definition/index.js.map +1 -1
  131. package/lib/pdf/helpers/horizontal-line/index.js +14 -14
  132. package/lib/pdf/helpers/horizontal-line/index.js.map +1 -1
  133. package/lib/pdf/helpers/html-transformer/index.js +45 -35
  134. package/lib/pdf/helpers/html-transformer/index.js.map +1 -1
  135. package/lib/pdf/helpers/index.js +194 -15
  136. package/lib/pdf/helpers/index.js.map +1 -1
  137. package/lib/pdf/helpers/parse-value/index.js +10 -4
  138. package/lib/pdf/helpers/parse-value/index.js.map +1 -1
  139. package/lib/pdf/helpers/table/index.js +136 -205
  140. package/lib/pdf/helpers/table/index.js.map +1 -1
  141. package/lib/pdf/helpers/text/index.js +11 -8
  142. package/lib/pdf/helpers/text/index.js.map +1 -1
  143. package/lib/pdf/icons/index.js +8 -2
  144. package/lib/pdf/icons/index.js.map +1 -1
  145. package/lib/pdf/index.js +47 -6
  146. package/lib/pdf/index.js.map +1 -1
  147. package/lib/pdf/issue/index.js +141 -135
  148. package/lib/pdf/issue/index.js.map +1 -1
  149. package/lib/pdf/job/index.js +95 -81
  150. package/lib/pdf/job/index.js.map +1 -1
  151. package/lib/pdf/shift-report/emptyFixtures.js +8 -2
  152. package/lib/pdf/shift-report/emptyFixtures.js.map +1 -1
  153. package/lib/pdf/shift-report/index.js +399 -521
  154. package/lib/pdf/shift-report/index.js.map +1 -1
  155. package/lib/pdf/task/index.js +89 -83
  156. package/lib/pdf/task/index.js.map +1 -1
  157. package/lib/scheduling/generators/index.js +38 -3
  158. package/lib/scheduling/generators/index.js.map +1 -1
  159. package/lib/scheduling/generators/occurrenceIntervalsGenerator.js +44 -37
  160. package/lib/scheduling/generators/occurrenceIntervalsGenerator.js.map +1 -1
  161. package/lib/scheduling/generators/scheduleIntervalsGenerator.js +20 -28
  162. package/lib/scheduling/generators/scheduleIntervalsGenerator.js.map +1 -1
  163. package/lib/scheduling/generators/serviceIntervalsGenerator.js +120 -150
  164. package/lib/scheduling/generators/serviceIntervalsGenerator.js.map +1 -1
  165. package/lib/scheduling/helpers/convertToTimezone.js +18 -11
  166. package/lib/scheduling/helpers/convertToTimezone.js.map +1 -1
  167. package/lib/scheduling/helpers/generateNonRepeatingSchedule.js +57 -95
  168. package/lib/scheduling/helpers/generateNonRepeatingSchedule.js.map +1 -1
  169. package/lib/scheduling/helpers/generateRepeatingSchedule.js +80 -119
  170. package/lib/scheduling/helpers/generateRepeatingSchedule.js.map +1 -1
  171. package/lib/scheduling/helpers/generateScheduleEnd.js +24 -14
  172. package/lib/scheduling/helpers/generateScheduleEnd.js.map +1 -1
  173. package/lib/scheduling/helpers/hasValidStartAndEnd.js +19 -11
  174. package/lib/scheduling/helpers/hasValidStartAndEnd.js.map +1 -1
  175. package/lib/scheduling/helpers/index.js +159 -14
  176. package/lib/scheduling/helpers/index.js.map +1 -1
  177. package/lib/scheduling/helpers/intervalCovers.js +13 -7
  178. package/lib/scheduling/helpers/intervalCovers.js.map +1 -1
  179. package/lib/scheduling/helpers/intervalIntersectsEnd.js +13 -7
  180. package/lib/scheduling/helpers/intervalIntersectsEnd.js.map +1 -1
  181. package/lib/scheduling/helpers/intervalIntersectsStart.js +13 -7
  182. package/lib/scheduling/helpers/intervalIntersectsStart.js.map +1 -1
  183. package/lib/scheduling/helpers/intervalOnlyIntersectsEnd.js +15 -10
  184. package/lib/scheduling/helpers/intervalOnlyIntersectsEnd.js.map +1 -1
  185. package/lib/scheduling/helpers/intervalOnlyIntersectsStart.js +15 -10
  186. package/lib/scheduling/helpers/intervalOnlyIntersectsStart.js.map +1 -1
  187. package/lib/scheduling/helpers/intervalOutside.js +15 -9
  188. package/lib/scheduling/helpers/intervalOutside.js.map +1 -1
  189. package/lib/scheduling/helpers/intervalWithin.js +13 -7
  190. package/lib/scheduling/helpers/intervalWithin.js.map +1 -1
  191. package/lib/scheduling/helpers/mergeIntervals.js +21 -17
  192. package/lib/scheduling/helpers/mergeIntervals.js.map +1 -1
  193. package/lib/scheduling/helpers/splitIntervals.js +24 -23
  194. package/lib/scheduling/helpers/splitIntervals.js.map +1 -1
  195. package/lib/scheduling/index.js +38 -3
  196. package/lib/scheduling/index.js.map +1 -1
  197. package/lib/scheduling/scheduling.types.js +9 -3
  198. package/lib/scheduling/scheduling.types.js.map +1 -1
  199. package/lib/scheduling/strategies/getNext.js +57 -63
  200. package/lib/scheduling/strategies/getNext.js.map +1 -1
  201. package/lib/scheduling/strategies/getNextExactDateOfMonth.js +47 -56
  202. package/lib/scheduling/strategies/getNextExactDateOfMonth.js.map +1 -1
  203. package/lib/scheduling/strategies/getNextLastDayOfMonth.js +43 -51
  204. package/lib/scheduling/strategies/getNextLastDayOfMonth.js.map +1 -1
  205. package/lib/scheduling/strategies/getNextLastWeekdayOfMonth.js +49 -56
  206. package/lib/scheduling/strategies/getNextLastWeekdayOfMonth.js.map +1 -1
  207. package/lib/scheduling/strategies/getNextNoRepeat.js +25 -36
  208. package/lib/scheduling/strategies/getNextNoRepeat.js.map +1 -1
  209. package/lib/scheduling/strategies/getNextWeekday.js +47 -79
  210. package/lib/scheduling/strategies/getNextWeekday.js.map +1 -1
  211. package/lib/scheduling/strategies/getNextXDayOfXWeekOfMonth.js +52 -58
  212. package/lib/scheduling/strategies/getNextXDayOfXWeekOfMonth.js.map +1 -1
  213. package/lib/scheduling/strategies/index.js +82 -7
  214. package/lib/scheduling/strategies/index.js.map +1 -1
  215. package/lib/schema/index.js +16 -1
  216. package/lib/schema/index.js.map +1 -1
  217. package/lib/schema/schema.js +28 -34
  218. package/lib/schema/schema.js.map +1 -1
  219. package/lib/service-hours/__helpers__/calculate-hours.js +24 -22
  220. package/lib/service-hours/__helpers__/calculate-hours.js.map +1 -1
  221. package/lib/service-hours/__helpers__/isOpen.js +25 -24
  222. package/lib/service-hours/__helpers__/isOpen.js.map +1 -1
  223. package/lib/service-hours/index.js +27 -2
  224. package/lib/service-hours/index.js.map +1 -1
  225. package/lib/service-hours/schema.js +68 -55
  226. package/lib/service-hours/schema.js.map +1 -1
  227. package/package.json +86 -86
  228. package/vitest.config.ts +23 -23
  229. package/vitest.setup.js +7 -7
@@ -1,263 +1,188 @@
1
- import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
- import _regeneratorRuntime from "@babel/runtime/regenerator";
3
- import { validateBase64Image } from '../image-validators';
4
- import AWS from 'aws-sdk';
1
+ "use strict";
5
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.fetchImageForPdfGeneratorService = void 0;
8
+ exports.fetchResourceFromS3 = fetchResourceFromS3;
9
+ exports.formatBase64Image = formatBase64Image;
10
+ exports.requestImageTransformation = requestImageTransformation;
11
+ var _imageValidators = require("../image-validators");
12
+ var _awsSdk = _interopRequireDefault(require("aws-sdk"));
6
13
  // Image transformer and cache are always in us-east-1 (shared across all regions)
7
14
  // The image-optimisation-image-processing Lambda only exists in us-east-1
8
- var IMAGE_CACHE_REGION = 'us-east-1';
9
- var lambda = new AWS.Lambda({
15
+ const IMAGE_CACHE_REGION = 'us-east-1';
16
+ const lambda = new _awsSdk.default.Lambda({
10
17
  region: IMAGE_CACHE_REGION
11
18
  });
12
- var s3 = new AWS.S3({
19
+ const s3 = new _awsSdk.default.S3({
13
20
  region: IMAGE_CACHE_REGION
14
21
  });
15
- export var fetchImageForPdfGeneratorService = /*#__PURE__*/function () {
16
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(url) {
17
- var _transformerResponse$;
18
- var urlMatch, applicationId, _parseUrlString, path, queryString, searchParamsObject, transformedBucketImagePath, alreadyTransformedImage, fullDataUrl, transformerResponse, statusCode, redirectLocation, _fullDataUrl, response, buffer, _t, _t2, _t3;
19
- return _regeneratorRuntime.wrap(function (_context) {
20
- while (1) switch (_context.prev = _context.next) {
21
- case 0:
22
- console.debug('Fetching image via CloudFront For Serverless Pdf Generator Service');
23
- if (url) {
24
- _context.next = 1;
25
- break;
26
- }
27
- throw new Error('URL is required to fetch image for PDF generator service');
28
- case 1:
29
- urlMatch = url && url.match(/([a-f0-9]{24})\//);
30
- applicationId = urlMatch && urlMatch[1];
31
- if (applicationId) {
32
- _context.next = 2;
33
- break;
34
- }
35
- throw new Error('Requestor has insufficient permissions');
36
- case 2:
37
- _parseUrlString = parseUrlString(url), path = _parseUrlString.path, queryString = _parseUrlString.queryString, searchParamsObject = _parseUrlString.searchParamsObject;
38
- transformedBucketImagePath = path + (queryString ? "/".concat(queryString) : '');
39
- _context.next = 3;
40
- return fetchResourceFromS3({
41
- bucketName: process.env.S3_BUCKET_IMAGE_TRANSFORMER_CACHE,
42
- key: transformedBucketImagePath
43
- });
44
- case 3:
45
- alreadyTransformedImage = _context.sent;
46
- if (!(alreadyTransformedImage !== null && alreadyTransformedImage !== void 0 && alreadyTransformedImage.body)) {
47
- _context.next = 4;
48
- break;
49
- }
50
- fullDataUrl = formatBase64Image({
51
- base64String: alreadyTransformedImage.body.toString('base64'),
52
- key: transformedBucketImagePath
53
- });
54
- return _context.abrupt("return", fullDataUrl);
55
- case 4:
56
- _context.next = 5;
57
- return requestImageTransformation("/".concat(path), searchParamsObject);
58
- case 5:
59
- transformerResponse = _context.sent;
60
- statusCode = transformerResponse.statusCode;
61
- redirectLocation = (_transformerResponse$ = transformerResponse.headers) === null || _transformerResponse$ === void 0 ? void 0 : _transformerResponse$.Location;
62
- _t = statusCode;
63
- _context.next = _t === 200 ? 6 : _t === 302 ? 7 : _t === 400 ? 14 : _t === 403 ? 15 : _t === 404 ? 16 : _t === 500 ? 17 : 18;
64
- break;
65
- case 6:
66
- console.debug('Image transformation successful');
67
- _fullDataUrl = formatBase64Image({
68
- base64String: transformerResponse.body.toString('base64'),
69
- key: url
70
- });
71
- return _context.abrupt("return", _fullDataUrl);
72
- case 7:
73
- console.debug('Image transformation successful but image is too big for lambda delivery, fetching directly via redirect URL');
74
- if (redirectLocation) {
75
- _context.next = 8;
76
- break;
77
- }
22
+ const fetchImageForPdfGeneratorService = async function (url) {
23
+ console.debug('Fetching image via CloudFront For Serverless Pdf Generator Service');
24
+ if (!url) {
25
+ throw new Error('URL is required to fetch image for PDF generator service');
26
+ }
27
+ const urlMatch = url && url.match(/([a-f0-9]{24})\//);
28
+ const applicationId = urlMatch && urlMatch[1];
29
+ if (!applicationId) {
30
+ throw new Error('Requestor has insufficient permissions');
31
+ }
32
+ const {
33
+ path,
34
+ queryString,
35
+ searchParamsObject
36
+ } = parseUrlString(url);
37
+ const transformedBucketImagePath = path + (queryString ? `/${queryString}` : '');
38
+ const alreadyTransformedImage = await fetchResourceFromS3({
39
+ bucketName: process.env.S3_BUCKET_IMAGE_TRANSFORMER_CACHE,
40
+ key: transformedBucketImagePath
41
+ });
42
+ if (alreadyTransformedImage?.body) {
43
+ const fullDataUrl = formatBase64Image({
44
+ base64String: alreadyTransformedImage.body.toString('base64'),
45
+ key: transformedBucketImagePath
46
+ });
47
+ return fullDataUrl;
48
+ }
49
+ const transformerResponse = await requestImageTransformation(`/${path}`, searchParamsObject);
50
+ const statusCode = transformerResponse.statusCode;
51
+ const redirectLocation = transformerResponse.headers?.Location;
52
+ switch (statusCode) {
53
+ case 200:
54
+ {
55
+ console.debug('Image transformation successful');
56
+ const fullDataUrl = formatBase64Image({
57
+ base64String: transformerResponse.body.toString('base64'),
58
+ key: url
59
+ });
60
+ return fullDataUrl;
61
+ }
62
+ case 302:
63
+ {
64
+ console.debug('Image transformation successful but image is too big for lambda delivery, fetching directly via redirect URL');
65
+ if (!redirectLocation) {
78
66
  throw new Error('Redirect response received but no location provided');
79
- case 8:
80
- _context.prev = 8;
81
- _context.next = 9;
82
- return fetch(redirectLocation);
83
- case 9:
84
- response = _context.sent;
85
- _context.next = 11;
86
- break;
87
- case 10:
88
- _context.prev = 10;
89
- _t2 = _context["catch"](8);
90
- throw new Error("Failed to fetch image from redirect URL: ".concat(_t2.message));
91
- case 11:
92
- if (response.ok) {
93
- _context.next = 12;
94
- break;
95
- }
96
- throw new Error("Failed to fetch image from redirect: ".concat(response.status));
97
- case 12:
98
- _t3 = Buffer;
99
- _context.next = 13;
100
- return response.arrayBuffer();
101
- case 13:
102
- buffer = _t3.from.call(_t3, _context.sent);
103
- return _context.abrupt("return", formatBase64Image({
104
- base64String: buffer.toString('base64'),
105
- key: transformedBucketImagePath
106
- }));
107
- case 14:
108
- throw new Error("Bad request to image transformer: ".concat(transformerResponse.body));
109
- case 15:
110
- throw new Error('Requested transformed image is too big');
111
- case 16:
112
- throw new Error('The requested image does not exist');
113
- case 17:
114
- throw new Error("Image transformation failed: ".concat(transformerResponse.body));
115
- case 18:
116
- throw new Error("Unexpected response from image transformer: ".concat(statusCode, " - ").concat(transformerResponse.body));
117
- case 19:
118
- case "end":
119
- return _context.stop();
67
+ }
68
+ let response;
69
+ try {
70
+ response = await fetch(redirectLocation);
71
+ } catch (error) {
72
+ throw new Error(`Failed to fetch image from redirect URL: ${error.message}`);
73
+ }
74
+ if (!response.ok) {
75
+ throw new Error(`Failed to fetch image from redirect: ${response.status}`);
76
+ }
77
+ const buffer = Buffer.from(await response.arrayBuffer());
78
+ return formatBase64Image({
79
+ base64String: buffer.toString('base64'),
80
+ key: transformedBucketImagePath
81
+ });
120
82
  }
121
- }, _callee, null, [[8, 10]]);
122
- }));
123
- return function fetchImageForPdfGeneratorService(_x) {
124
- return _ref.apply(this, arguments);
125
- };
126
- }();
127
- export function requestImageTransformation(_x2, _x3) {
128
- return _requestImageTransformation.apply(this, arguments);
129
- }
130
- function _requestImageTransformation() {
131
- _requestImageTransformation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(path, searchParamsObject) {
132
- var lambdaEvent, params, result, response, errorMessage, _t4;
133
- return _regeneratorRuntime.wrap(function (_context2) {
134
- while (1) switch (_context2.prev = _context2.next) {
135
- case 0:
136
- if (path) {
137
- _context2.next = 1;
138
- break;
139
- }
140
- throw new Error('Image Path is required for image transformation');
141
- case 1:
142
- console.debug('ImageTransformation: Invoking image transformer lambda for path:', {
143
- path: path,
144
- searchParamsObject: searchParamsObject
145
- });
146
- lambdaEvent = {
147
- queryStringParameters: searchParamsObject,
148
- requestContext: {
149
- http: {
150
- method: 'GET',
151
- path: path
152
- }
153
- }
154
- };
155
- params = {
156
- FunctionName: process.env.IMAGE_TRANSFORMER_ARN,
157
- InvocationType: 'RequestResponse',
158
- Payload: JSON.stringify(lambdaEvent)
159
- };
160
- _context2.prev = 2;
161
- _context2.next = 3;
162
- return lambda.invoke(params).promise();
163
- case 3:
164
- result = _context2.sent;
165
- response = JSON.parse(result.Payload);
166
- return _context2.abrupt("return", response);
167
- case 4:
168
- _context2.prev = 4;
169
- _t4 = _context2["catch"](2);
170
- errorMessage = "Failed to invoke image transformer lambda: ".concat(_t4.message);
171
- console.error(errorMessage, _t4);
172
- throw new Error(errorMessage);
173
- case 5:
174
- case "end":
175
- return _context2.stop();
83
+ case 400:
84
+ throw new Error(`Bad request to image transformer: ${transformerResponse.body}`);
85
+ case 403:
86
+ throw new Error('Requested transformed image is too big');
87
+ case 404:
88
+ throw new Error('The requested image does not exist');
89
+ case 500:
90
+ throw new Error(`Image transformation failed: ${transformerResponse.body}`);
91
+ default:
92
+ throw new Error(`Unexpected response from image transformer: ${statusCode} - ${transformerResponse.body}`);
93
+ }
94
+ };
95
+ exports.fetchImageForPdfGeneratorService = fetchImageForPdfGeneratorService;
96
+ async function requestImageTransformation(path, searchParamsObject) {
97
+ if (!path) {
98
+ throw new Error('Image Path is required for image transformation');
99
+ }
100
+ console.debug('ImageTransformation: Invoking image transformer lambda for path:', {
101
+ path,
102
+ searchParamsObject
103
+ });
104
+ const lambdaEvent = {
105
+ queryStringParameters: searchParamsObject,
106
+ requestContext: {
107
+ http: {
108
+ method: 'GET',
109
+ path
176
110
  }
177
- }, _callee2, null, [[2, 4]]);
178
- }));
179
- return _requestImageTransformation.apply(this, arguments);
180
- }
181
- export function fetchResourceFromS3(_x4) {
182
- return _fetchResourceFromS.apply(this, arguments);
111
+ }
112
+ };
113
+ const params = {
114
+ FunctionName: process.env.IMAGE_TRANSFORMER_ARN,
115
+ InvocationType: 'RequestResponse',
116
+ Payload: JSON.stringify(lambdaEvent)
117
+ };
118
+ try {
119
+ const result = await lambda.invoke(params).promise();
120
+ const response = JSON.parse(result.Payload);
121
+ return response;
122
+ } catch (error) {
123
+ const errorMessage = `Failed to invoke image transformer lambda: ${error.message}`;
124
+ console.error(errorMessage, error);
125
+ throw new Error(errorMessage);
126
+ }
183
127
  }
184
- function _fetchResourceFromS() {
185
- _fetchResourceFromS = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref2) {
186
- var bucketName, key, params, result, _t5;
187
- return _regeneratorRuntime.wrap(function (_context3) {
188
- while (1) switch (_context3.prev = _context3.next) {
189
- case 0:
190
- bucketName = _ref2.bucketName, key = _ref2.key;
191
- console.debug("Fetching resource from S3 Bucket: '".concat(bucketName, "' at path: '").concat(key, "'"));
192
- if (!(!bucketName || !key)) {
193
- _context3.next = 1;
194
- break;
195
- }
196
- throw new Error('bucketName and key are required for S3 resource fetch ' + JSON.stringify({
197
- bucketName: bucketName,
198
- key: key
199
- }));
200
- case 1:
201
- params = {
202
- Bucket: bucketName,
203
- Key: key
204
- };
205
- _context3.prev = 2;
206
- _context3.next = 3;
207
- return s3.getObject(params).promise();
208
- case 3:
209
- result = _context3.sent;
210
- return _context3.abrupt("return", {
211
- body: result.Body,
212
- contentType: result.ContentType,
213
- contentLength: result.ContentLength,
214
- lastModified: result.LastModified,
215
- etag: result.ETag
216
- });
217
- case 4:
218
- _context3.prev = 4;
219
- _t5 = _context3["catch"](2);
220
- if (!(_t5.code !== 'NoSuchKey')) {
221
- _context3.next = 5;
222
- break;
223
- }
224
- console.error('Failed to fetch image:', _t5);
225
- throw new Error("Failed to fetch image: ".concat(bucketName, "/").concat(key));
226
- case 5:
227
- console.debug('Image not found in transformed bucket, invoking transformer');
228
- case 6:
229
- case "end":
230
- return _context3.stop();
231
- }
232
- }, _callee3, null, [[2, 4]]);
233
- }));
234
- return _fetchResourceFromS.apply(this, arguments);
128
+ async function fetchResourceFromS3({
129
+ bucketName,
130
+ key
131
+ }) {
132
+ console.debug(`Fetching resource from S3 Bucket: '${bucketName}' at path: '${key}'`);
133
+ if (!bucketName || !key) {
134
+ throw new Error('bucketName and key are required for S3 resource fetch ' + JSON.stringify({
135
+ bucketName,
136
+ key
137
+ }));
138
+ }
139
+ const params = {
140
+ Bucket: bucketName,
141
+ Key: key
142
+ };
143
+ try {
144
+ const result = await s3.getObject(params).promise();
145
+ return {
146
+ body: result.Body,
147
+ contentType: result.ContentType,
148
+ contentLength: result.ContentLength,
149
+ lastModified: result.LastModified,
150
+ etag: result.ETag
151
+ };
152
+ } catch (error) {
153
+ if (error.code !== 'NoSuchKey') {
154
+ console.error('Failed to fetch image:', error);
155
+ throw new Error(`Failed to fetch image: ${bucketName}/${key}`);
156
+ }
157
+ console.debug('Image not found in transformed bucket, invoking transformer');
158
+ }
235
159
  }
236
- export function formatBase64Image(_ref3) {
237
- var base64String = _ref3.base64String,
238
- key = _ref3.key;
160
+ function formatBase64Image({
161
+ base64String,
162
+ key
163
+ }) {
239
164
  if (!key) {
240
165
  throw new Error('Key is required for image formatting');
241
166
  }
242
- var imageType = key.toLowerCase().includes('.png') ? 'png' : 'jpeg';
243
- var base64Flag = "data:image/".concat(imageType, ";base64,");
244
- var fullDataUrl = "".concat(base64Flag).concat(base64String);
167
+ const imageType = key.toLowerCase().includes('.png') ? 'png' : 'jpeg';
168
+ const base64Flag = `data:image/${imageType};base64,`;
169
+ const fullDataUrl = `${base64Flag}${base64String}`;
245
170
 
246
171
  // Validate the formatted data URL
247
- var isValid = validateBase64Image(fullDataUrl);
172
+ const isValid = (0, _imageValidators.validateBase64Image)(fullDataUrl);
248
173
  if (!isValid) {
249
174
  throw new Error('InvalidImageError');
250
175
  }
251
176
  return fullDataUrl;
252
177
  }
253
178
 
254
- /**
255
- * Parses a URL-like string into path and query parameters
256
- * @param {string} urlString - String like "https://example.cloudfront.net/<applicationId>/<path>/filename.jpeg?width=100&height=100"
257
- * @returns {Object} - Object with { path: string, queryString: string, searchParamsObject: Object }
258
- * @example
259
- * parseUrlString("https://example.cloudfront.net/abc123/folder/image.jpeg?width=100&height=100")
260
- * // Returns: { path: "abc123/folder/image.jpeg", queryString: "width=100,t=456", searchParamsObject: { width: "100", height: "100" } }
179
+ /**
180
+ * Parses a URL-like string into path and query parameters
181
+ * @param {string} urlString - String like "https://example.cloudfront.net/<applicationId>/<path>/filename.jpeg?width=100&height=100"
182
+ * @returns {Object} - Object with { path: string, queryString: string, searchParamsObject: Object }
183
+ * @example
184
+ * parseUrlString("https://example.cloudfront.net/abc123/folder/image.jpeg?width=100&height=100")
185
+ * // Returns: { path: "abc123/folder/image.jpeg", queryString: "width=100,t=456", searchParamsObject: { width: "100", height: "100" } }
261
186
  */
262
187
  function parseUrlString(urlString) {
263
188
  if (!urlString || typeof urlString !== 'string') {
@@ -265,18 +190,18 @@ function parseUrlString(urlString) {
265
190
  }
266
191
 
267
192
  // Extract the path after the domain
268
- var url = new URL(urlString);
269
- var searchParamsObject = {};
270
- url.searchParams.forEach(function (value, key) {
193
+ const url = new URL(urlString);
194
+ let searchParamsObject = {};
195
+ url.searchParams.forEach((value, key) => {
271
196
  searchParamsObject[key] = value;
272
197
  });
273
- var queryString = url.searchParams.toString();
198
+ let queryString = url.searchParams.toString();
274
199
  queryString = queryString ? queryString.replace(/&/g, ',') : '';
275
200
  return {
276
201
  path: url.pathname.substring(1),
277
202
  // Remove leading '/'
278
- queryString: queryString,
279
- searchParamsObject: searchParamsObject
203
+ queryString,
204
+ searchParamsObject
280
205
  };
281
206
  }
282
207
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["validateBase64Image","AWS","IMAGE_CACHE_REGION","lambda","Lambda","region","s3","S3","fetchImageForPdfGeneratorService","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","url","_transformerResponse$","urlMatch","applicationId","_parseUrlString","path","queryString","searchParamsObject","transformedBucketImagePath","alreadyTransformedImage","fullDataUrl","transformerResponse","statusCode","redirectLocation","_fullDataUrl","response","buffer","_t","_t2","_t3","wrap","_context","prev","next","console","debug","Error","match","parseUrlString","concat","fetchResourceFromS3","bucketName","process","env","S3_BUCKET_IMAGE_TRANSFORMER_CACHE","key","sent","body","formatBase64Image","base64String","toString","abrupt","requestImageTransformation","headers","Location","fetch","message","ok","status","Buffer","arrayBuffer","from","call","stop","_x","apply","arguments","_x2","_x3","_requestImageTransformation","_callee2","lambdaEvent","params","result","errorMessage","_t4","_context2","queryStringParameters","requestContext","http","method","FunctionName","IMAGE_TRANSFORMER_ARN","InvocationType","Payload","JSON","stringify","invoke","promise","parse","error","_x4","_fetchResourceFromS","_callee3","_ref2","_t5","_context3","Bucket","Key","getObject","Body","contentType","ContentType","contentLength","ContentLength","lastModified","LastModified","etag","ETag","code","_ref3","imageType","toLowerCase","includes","base64Flag","isValid","urlString","URL","searchParams","forEach","value","replace","pathname","substring"],"sources":["../../../src/helpers/fetch-image-for-pdf-generator-service/index.js"],"sourcesContent":["import { validateBase64Image } from '../image-validators'\nimport AWS from 'aws-sdk'\n\n// Image transformer and cache are always in us-east-1 (shared across all regions)\n// The image-optimisation-image-processing Lambda only exists in us-east-1\nconst IMAGE_CACHE_REGION = 'us-east-1'\n\nconst lambda = new AWS.Lambda({\n region: IMAGE_CACHE_REGION,\n})\n\nconst s3 = new AWS.S3({\n region: IMAGE_CACHE_REGION,\n})\n\nexport const fetchImageForPdfGeneratorService = async function (url) {\n console.debug(\n 'Fetching image via CloudFront For Serverless Pdf Generator Service'\n )\n\n if (!url) {\n throw new Error('URL is required to fetch image for PDF generator service')\n }\n\n const urlMatch = url && url.match(/([a-f0-9]{24})\\//)\n const applicationId = urlMatch && urlMatch[1]\n\n if (!applicationId) {\n throw new Error('Requestor has insufficient permissions')\n }\n\n const { path, queryString, searchParamsObject } = parseUrlString(url)\n\n const transformedBucketImagePath =\n path + (queryString ? `/${queryString}` : '')\n\n const alreadyTransformedImage = await fetchResourceFromS3({\n bucketName: process.env.S3_BUCKET_IMAGE_TRANSFORMER_CACHE,\n key: transformedBucketImagePath,\n })\n\n if (alreadyTransformedImage?.body) {\n const fullDataUrl = formatBase64Image({\n base64String: alreadyTransformedImage.body.toString('base64'),\n key: transformedBucketImagePath,\n })\n return fullDataUrl\n }\n\n const transformerResponse = await requestImageTransformation(\n `/${path}`,\n searchParamsObject\n )\n\n const statusCode = transformerResponse.statusCode\n const redirectLocation = transformerResponse.headers?.Location\n\n switch (statusCode) {\n case 200: {\n console.debug('Image transformation successful')\n\n const fullDataUrl = formatBase64Image({\n base64String: transformerResponse.body.toString('base64'),\n key: url,\n })\n\n return fullDataUrl\n }\n case 302: {\n console.debug(\n 'Image transformation successful but image is too big for lambda delivery, fetching directly via redirect URL'\n )\n\n if (!redirectLocation) {\n throw new Error('Redirect response received but no location provided')\n }\n\n let response\n try {\n response = await fetch(redirectLocation)\n } catch (error) {\n throw new Error(\n `Failed to fetch image from redirect URL: ${error.message}`\n )\n }\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch image from redirect: ${response.status}`\n )\n }\n\n const buffer = Buffer.from(await response.arrayBuffer())\n\n return formatBase64Image({\n base64String: buffer.toString('base64'),\n key: transformedBucketImagePath,\n })\n }\n case 400:\n throw new Error(\n `Bad request to image transformer: ${transformerResponse.body}`\n )\n case 403:\n throw new Error('Requested transformed image is too big')\n case 404:\n throw new Error('The requested image does not exist')\n case 500:\n throw new Error(\n `Image transformation failed: ${transformerResponse.body}`\n )\n default:\n throw new Error(\n `Unexpected response from image transformer: ${statusCode} - ${transformerResponse.body}`\n )\n }\n}\n\nexport async function requestImageTransformation(path, searchParamsObject) {\n if (!path) {\n throw new Error('Image Path is required for image transformation')\n }\n\n console.debug(\n 'ImageTransformation: Invoking image transformer lambda for path:',\n { path, searchParamsObject }\n )\n\n const lambdaEvent = {\n queryStringParameters: searchParamsObject,\n requestContext: {\n http: {\n method: 'GET',\n path,\n },\n },\n }\n\n const params = {\n FunctionName: process.env.IMAGE_TRANSFORMER_ARN,\n InvocationType: 'RequestResponse',\n Payload: JSON.stringify(lambdaEvent),\n }\n\n try {\n const result = await lambda.invoke(params).promise()\n\n const response = JSON.parse(result.Payload)\n\n return response\n } catch (error) {\n const errorMessage = `Failed to invoke image transformer lambda: ${error.message}`\n console.error(errorMessage, error)\n throw new Error(errorMessage)\n }\n}\n\nexport async function fetchResourceFromS3({ bucketName, key }) {\n console.debug(\n `Fetching resource from S3 Bucket: '${bucketName}' at path: '${key}'`\n )\n if (!bucketName || !key) {\n throw new Error(\n 'bucketName and key are required for S3 resource fetch ' +\n JSON.stringify({ bucketName, key })\n )\n }\n\n const params = {\n Bucket: bucketName,\n Key: key,\n }\n\n try {\n const result = await s3.getObject(params).promise()\n\n return {\n body: result.Body,\n contentType: result.ContentType,\n contentLength: result.ContentLength,\n lastModified: result.LastModified,\n etag: result.ETag,\n }\n } catch (error) {\n if (error.code !== 'NoSuchKey') {\n console.error('Failed to fetch image:', error)\n throw new Error(`Failed to fetch image: ${bucketName}/${key}`)\n }\n\n console.debug('Image not found in transformed bucket, invoking transformer')\n }\n}\n\nexport function formatBase64Image({ base64String, key }) {\n if (!key) {\n throw new Error('Key is required for image formatting')\n }\n\n const imageType = key.toLowerCase().includes('.png') ? 'png' : 'jpeg'\n const base64Flag = `data:image/${imageType};base64,`\n const fullDataUrl = `${base64Flag}${base64String}`\n\n // Validate the formatted data URL\n const isValid = validateBase64Image(fullDataUrl)\n if (!isValid) {\n throw new Error('InvalidImageError')\n }\n\n return fullDataUrl\n}\n\n/**\n * Parses a URL-like string into path and query parameters\n * @param {string} urlString - String like \"https://example.cloudfront.net/<applicationId>/<path>/filename.jpeg?width=100&height=100\"\n * @returns {Object} - Object with { path: string, queryString: string, searchParamsObject: Object }\n * @example\n * parseUrlString(\"https://example.cloudfront.net/abc123/folder/image.jpeg?width=100&height=100\")\n * // Returns: { path: \"abc123/folder/image.jpeg\", queryString: \"width=100,t=456\", searchParamsObject: { width: \"100\", height: \"100\" } }\n */\nfunction parseUrlString(urlString) {\n if (!urlString || typeof urlString !== 'string') {\n throw new Error('URL string is required and must be a string')\n }\n\n // Extract the path after the domain\n const url = new URL(urlString)\n\n let searchParamsObject = {}\n url.searchParams.forEach((value, key) => {\n searchParamsObject[key] = value\n })\n\n let queryString = url.searchParams.toString()\n queryString = queryString ? queryString.replace(/&/g, ',') : ''\n\n return {\n path: url.pathname.substring(1), // Remove leading '/'\n queryString,\n searchParamsObject,\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_imageValidators","require","_awsSdk","_interopRequireDefault","IMAGE_CACHE_REGION","lambda","AWS","Lambda","region","s3","S3","fetchImageForPdfGeneratorService","url","console","debug","Error","urlMatch","match","applicationId","path","queryString","searchParamsObject","parseUrlString","transformedBucketImagePath","alreadyTransformedImage","fetchResourceFromS3","bucketName","process","env","S3_BUCKET_IMAGE_TRANSFORMER_CACHE","key","body","fullDataUrl","formatBase64Image","base64String","toString","transformerResponse","requestImageTransformation","statusCode","redirectLocation","headers","Location","response","fetch","error","message","ok","status","buffer","Buffer","from","arrayBuffer","exports","lambdaEvent","queryStringParameters","requestContext","http","method","params","FunctionName","IMAGE_TRANSFORMER_ARN","InvocationType","Payload","JSON","stringify","result","invoke","promise","parse","errorMessage","Bucket","Key","getObject","Body","contentType","ContentType","contentLength","ContentLength","lastModified","LastModified","etag","ETag","code","imageType","toLowerCase","includes","base64Flag","isValid","validateBase64Image","urlString","URL","searchParams","forEach","value","replace","pathname","substring"],"sources":["../../../src/helpers/fetch-image-for-pdf-generator-service/index.js"],"sourcesContent":["import { validateBase64Image } from '../image-validators'\r\nimport AWS from 'aws-sdk'\r\n\r\n// Image transformer and cache are always in us-east-1 (shared across all regions)\r\n// The image-optimisation-image-processing Lambda only exists in us-east-1\r\nconst IMAGE_CACHE_REGION = 'us-east-1'\r\n\r\nconst lambda = new AWS.Lambda({\r\n region: IMAGE_CACHE_REGION,\r\n})\r\n\r\nconst s3 = new AWS.S3({\r\n region: IMAGE_CACHE_REGION,\r\n})\r\n\r\nexport const fetchImageForPdfGeneratorService = async function (url) {\r\n console.debug(\r\n 'Fetching image via CloudFront For Serverless Pdf Generator Service'\r\n )\r\n\r\n if (!url) {\r\n throw new Error('URL is required to fetch image for PDF generator service')\r\n }\r\n\r\n const urlMatch = url && url.match(/([a-f0-9]{24})\\//)\r\n const applicationId = urlMatch && urlMatch[1]\r\n\r\n if (!applicationId) {\r\n throw new Error('Requestor has insufficient permissions')\r\n }\r\n\r\n const { path, queryString, searchParamsObject } = parseUrlString(url)\r\n\r\n const transformedBucketImagePath =\r\n path + (queryString ? `/${queryString}` : '')\r\n\r\n const alreadyTransformedImage = await fetchResourceFromS3({\r\n bucketName: process.env.S3_BUCKET_IMAGE_TRANSFORMER_CACHE,\r\n key: transformedBucketImagePath,\r\n })\r\n\r\n if (alreadyTransformedImage?.body) {\r\n const fullDataUrl = formatBase64Image({\r\n base64String: alreadyTransformedImage.body.toString('base64'),\r\n key: transformedBucketImagePath,\r\n })\r\n return fullDataUrl\r\n }\r\n\r\n const transformerResponse = await requestImageTransformation(\r\n `/${path}`,\r\n searchParamsObject\r\n )\r\n\r\n const statusCode = transformerResponse.statusCode\r\n const redirectLocation = transformerResponse.headers?.Location\r\n\r\n switch (statusCode) {\r\n case 200: {\r\n console.debug('Image transformation successful')\r\n\r\n const fullDataUrl = formatBase64Image({\r\n base64String: transformerResponse.body.toString('base64'),\r\n key: url,\r\n })\r\n\r\n return fullDataUrl\r\n }\r\n case 302: {\r\n console.debug(\r\n 'Image transformation successful but image is too big for lambda delivery, fetching directly via redirect URL'\r\n )\r\n\r\n if (!redirectLocation) {\r\n throw new Error('Redirect response received but no location provided')\r\n }\r\n\r\n let response\r\n try {\r\n response = await fetch(redirectLocation)\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to fetch image from redirect URL: ${error.message}`\r\n )\r\n }\r\n\r\n if (!response.ok) {\r\n throw new Error(\r\n `Failed to fetch image from redirect: ${response.status}`\r\n )\r\n }\r\n\r\n const buffer = Buffer.from(await response.arrayBuffer())\r\n\r\n return formatBase64Image({\r\n base64String: buffer.toString('base64'),\r\n key: transformedBucketImagePath,\r\n })\r\n }\r\n case 400:\r\n throw new Error(\r\n `Bad request to image transformer: ${transformerResponse.body}`\r\n )\r\n case 403:\r\n throw new Error('Requested transformed image is too big')\r\n case 404:\r\n throw new Error('The requested image does not exist')\r\n case 500:\r\n throw new Error(\r\n `Image transformation failed: ${transformerResponse.body}`\r\n )\r\n default:\r\n throw new Error(\r\n `Unexpected response from image transformer: ${statusCode} - ${transformerResponse.body}`\r\n )\r\n }\r\n}\r\n\r\nexport async function requestImageTransformation(path, searchParamsObject) {\r\n if (!path) {\r\n throw new Error('Image Path is required for image transformation')\r\n }\r\n\r\n console.debug(\r\n 'ImageTransformation: Invoking image transformer lambda for path:',\r\n { path, searchParamsObject }\r\n )\r\n\r\n const lambdaEvent = {\r\n queryStringParameters: searchParamsObject,\r\n requestContext: {\r\n http: {\r\n method: 'GET',\r\n path,\r\n },\r\n },\r\n }\r\n\r\n const params = {\r\n FunctionName: process.env.IMAGE_TRANSFORMER_ARN,\r\n InvocationType: 'RequestResponse',\r\n Payload: JSON.stringify(lambdaEvent),\r\n }\r\n\r\n try {\r\n const result = await lambda.invoke(params).promise()\r\n\r\n const response = JSON.parse(result.Payload)\r\n\r\n return response\r\n } catch (error) {\r\n const errorMessage = `Failed to invoke image transformer lambda: ${error.message}`\r\n console.error(errorMessage, error)\r\n throw new Error(errorMessage)\r\n }\r\n}\r\n\r\nexport async function fetchResourceFromS3({ bucketName, key }) {\r\n console.debug(\r\n `Fetching resource from S3 Bucket: '${bucketName}' at path: '${key}'`\r\n )\r\n if (!bucketName || !key) {\r\n throw new Error(\r\n 'bucketName and key are required for S3 resource fetch ' +\r\n JSON.stringify({ bucketName, key })\r\n )\r\n }\r\n\r\n const params = {\r\n Bucket: bucketName,\r\n Key: key,\r\n }\r\n\r\n try {\r\n const result = await s3.getObject(params).promise()\r\n\r\n return {\r\n body: result.Body,\r\n contentType: result.ContentType,\r\n contentLength: result.ContentLength,\r\n lastModified: result.LastModified,\r\n etag: result.ETag,\r\n }\r\n } catch (error) {\r\n if (error.code !== 'NoSuchKey') {\r\n console.error('Failed to fetch image:', error)\r\n throw new Error(`Failed to fetch image: ${bucketName}/${key}`)\r\n }\r\n\r\n console.debug('Image not found in transformed bucket, invoking transformer')\r\n }\r\n}\r\n\r\nexport function formatBase64Image({ base64String, key }) {\r\n if (!key) {\r\n throw new Error('Key is required for image formatting')\r\n }\r\n\r\n const imageType = key.toLowerCase().includes('.png') ? 'png' : 'jpeg'\r\n const base64Flag = `data:image/${imageType};base64,`\r\n const fullDataUrl = `${base64Flag}${base64String}`\r\n\r\n // Validate the formatted data URL\r\n const isValid = validateBase64Image(fullDataUrl)\r\n if (!isValid) {\r\n throw new Error('InvalidImageError')\r\n }\r\n\r\n return fullDataUrl\r\n}\r\n\r\n/**\r\n * Parses a URL-like string into path and query parameters\r\n * @param {string} urlString - String like \"https://example.cloudfront.net/<applicationId>/<path>/filename.jpeg?width=100&height=100\"\r\n * @returns {Object} - Object with { path: string, queryString: string, searchParamsObject: Object }\r\n * @example\r\n * parseUrlString(\"https://example.cloudfront.net/abc123/folder/image.jpeg?width=100&height=100\")\r\n * // Returns: { path: \"abc123/folder/image.jpeg\", queryString: \"width=100,t=456\", searchParamsObject: { width: \"100\", height: \"100\" } }\r\n */\r\nfunction parseUrlString(urlString) {\r\n if (!urlString || typeof urlString !== 'string') {\r\n throw new Error('URL string is required and must be a string')\r\n }\r\n\r\n // Extract the path after the domain\r\n const url = new URL(urlString)\r\n\r\n let searchParamsObject = {}\r\n url.searchParams.forEach((value, key) => {\r\n searchParamsObject[key] = value\r\n })\r\n\r\n let queryString = url.searchParams.toString()\r\n queryString = queryString ? queryString.replace(/&/g, ',') : ''\r\n\r\n return {\r\n path: url.pathname.substring(1), // Remove leading '/'\r\n queryString,\r\n searchParamsObject,\r\n }\r\n}\r\n"],"mappings":"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","ignoreList":[]}