headroom-cms 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/README.md +282 -0
  2. package/admin/assets/AdminsPage-CnrQqwKA.js +1 -0
  3. package/admin/assets/AllContentPage-ByN1h3PP.js +1 -0
  4. package/admin/assets/ApiKeysPage-FgNHZPBS.js +1 -0
  5. package/admin/assets/AuditPage-DAPpo-sj.js +1 -0
  6. package/admin/assets/BlockEditor-CZTwex-o.js +179 -0
  7. package/admin/assets/BlockEditor-Cp_wZ2xN.css +1 -0
  8. package/admin/assets/BlockTypeEditPage-Buuwbx1P.js +1 -0
  9. package/admin/assets/BlockTypesPage-Dj0qmsqX.js +1 -0
  10. package/admin/assets/BulkActionBar-BMcUBJSH.js +1 -0
  11. package/admin/assets/CollectionEditPage-CLgQu2HS.js +1 -0
  12. package/admin/assets/CollectionsPage-BnCaxALz.js +1 -0
  13. package/admin/assets/ContentCreatePage-CJI326o-.js +1 -0
  14. package/admin/assets/ContentEditPage-A4i8P2Jd.js +3 -0
  15. package/admin/assets/ContentListPage-Bc4mBIkB.js +1 -0
  16. package/admin/assets/CustomBlockPreview-CCssn6vF.js +479 -0
  17. package/admin/assets/FieldBuilder-YJGSk0nY.js +3 -0
  18. package/admin/assets/LoginPage-Jrne8-Wr.js +1 -0
  19. package/admin/assets/MediaPage-DfPQBmNf.css +1 -0
  20. package/admin/assets/MediaPage-_qNXqsZg.js +1 -0
  21. package/admin/assets/SiteSettingsPage-CoZnavij.js +1 -0
  22. package/admin/assets/SitesPage-ETqFT3nO.js +1 -0
  23. package/admin/assets/TagsPage-BGpp0XZM.js +1 -0
  24. package/admin/assets/UsersPage-CKRJpAb6.js +1 -0
  25. package/admin/assets/WebhookEditPage-BOcLe5OJ.js +1 -0
  26. package/admin/assets/WebhooksPage-Czco583Y.js +1 -0
  27. package/admin/assets/badge-0Z1nL6DI.js +1 -0
  28. package/admin/assets/card-D1-S-QZ6.js +1 -0
  29. package/admin/assets/check-BGA0ADyt.js +1 -0
  30. package/admin/assets/checkbox-BPqrj_XS.js +1 -0
  31. package/admin/assets/command-ChD319uJ.js +1 -0
  32. package/admin/assets/contentStatus-DfWHjFVB.js +1 -0
  33. package/admin/assets/copy-BqH9rXYM.js +1 -0
  34. package/admin/assets/core.esm-Csvubn5Q.js +5 -0
  35. package/admin/assets/format-CZ9bpk32.js +1 -0
  36. package/admin/assets/index-DOqKbrpW.css +1 -0
  37. package/admin/assets/index-Ds50UTAc.js +18 -0
  38. package/admin/assets/lib-BrI1UB_t.js +38 -0
  39. package/admin/assets/media-url-DIg_vSyf.js +1 -0
  40. package/admin/assets/module-RjUF93sV.js +716 -0
  41. package/admin/assets/native-48B9X9Wg.js +1 -0
  42. package/admin/assets/plus-BgHSYWJN.js +1 -0
  43. package/admin/assets/radix-DQ3amgxj.js +51 -0
  44. package/admin/assets/react-vendor-DNVhVxD7.js +4 -0
  45. package/admin/assets/search-DIzcfCVh.js +1 -0
  46. package/admin/assets/select-CJXZv4wv.js +1 -0
  47. package/admin/assets/sortable.esm-Zh-9QRSf.js +1 -0
  48. package/admin/assets/table-B3EHrN_H.js +1 -0
  49. package/admin/assets/tanstack-BO6c-AOu.js +1 -0
  50. package/admin/assets/trash-2-Gny2Upn-.js +1 -0
  51. package/admin/assets/useAdminResolver-BsQc_N4z.js +1 -0
  52. package/admin/assets/useContent-CSobIico.js +1 -0
  53. package/admin/assets/useDebouncedValue-Bf8UizjU.js +1 -0
  54. package/admin/assets/useMedia-CQnmMz4N.js +1 -0
  55. package/admin/assets/useTags-CYqbj5cK.js +1 -0
  56. package/admin/assets/useWebhooks-DXgtQ3aU.js +1 -0
  57. package/admin/index.html +21 -0
  58. package/admin/vite.svg +1 -0
  59. package/dist/admin-site.d.ts +30 -0
  60. package/dist/admin-site.d.ts.map +1 -0
  61. package/dist/admin-site.js +80 -0
  62. package/dist/admin-site.js.map +1 -0
  63. package/dist/api.d.ts +26 -0
  64. package/dist/api.d.ts.map +1 -0
  65. package/dist/api.js +91 -0
  66. package/dist/api.js.map +1 -0
  67. package/dist/auth.d.ts +27 -0
  68. package/dist/auth.d.ts.map +1 -0
  69. package/dist/auth.js +86 -0
  70. package/dist/auth.js.map +1 -0
  71. package/dist/cdn.d.ts +27 -0
  72. package/dist/cdn.d.ts.map +1 -0
  73. package/dist/cdn.js +382 -0
  74. package/dist/cdn.js.map +1 -0
  75. package/dist/image.d.ts +21 -0
  76. package/dist/image.d.ts.map +1 -0
  77. package/dist/image.js +48 -0
  78. package/dist/image.js.map +1 -0
  79. package/dist/index.d.ts +85 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +124 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/storage.d.ts +21 -0
  84. package/dist/storage.d.ts.map +1 -0
  85. package/dist/storage.js +125 -0
  86. package/dist/storage.js.map +1 -0
  87. package/dist/webhooks.d.ts +23 -0
  88. package/dist/webhooks.d.ts.map +1 -0
  89. package/dist/webhooks.js +91 -0
  90. package/dist/webhooks.js.map +1 -0
  91. package/lambda/api/bootstrap +0 -0
  92. package/lambda/api/resource.enc +0 -0
  93. package/lambda/functions/custom-message/index.mjs +112 -0
  94. package/lambda/functions/custom-message/resource.enc +1 -0
  95. package/lambda/image-lambda/index.mjs +188 -0
  96. package/lambda/image-lambda/node_modules/.package-lock.json +160 -0
  97. package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/README.md +46 -0
  98. package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/lib/glib-2.0/include/glibconfig.h +220 -0
  99. package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/lib/index.js +1 -0
  100. package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/lib/libvips-cpp.so.42 +0 -0
  101. package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/package.json +42 -0
  102. package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/versions.json +30 -0
  103. package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/LICENSE +191 -0
  104. package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/README.md +18 -0
  105. package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/lib/sharp-linux-arm64.node +0 -0
  106. package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/package.json +46 -0
  107. package/lambda/image-lambda/node_modules/color/LICENSE +21 -0
  108. package/lambda/image-lambda/node_modules/color/README.md +123 -0
  109. package/lambda/image-lambda/node_modules/color/index.js +496 -0
  110. package/lambda/image-lambda/node_modules/color/package.json +47 -0
  111. package/lambda/image-lambda/node_modules/color-convert/CHANGELOG.md +54 -0
  112. package/lambda/image-lambda/node_modules/color-convert/LICENSE +21 -0
  113. package/lambda/image-lambda/node_modules/color-convert/README.md +68 -0
  114. package/lambda/image-lambda/node_modules/color-convert/conversions.js +839 -0
  115. package/lambda/image-lambda/node_modules/color-convert/index.js +81 -0
  116. package/lambda/image-lambda/node_modules/color-convert/package.json +48 -0
  117. package/lambda/image-lambda/node_modules/color-convert/route.js +97 -0
  118. package/lambda/image-lambda/node_modules/color-name/LICENSE +8 -0
  119. package/lambda/image-lambda/node_modules/color-name/README.md +11 -0
  120. package/lambda/image-lambda/node_modules/color-name/index.js +152 -0
  121. package/lambda/image-lambda/node_modules/color-name/package.json +28 -0
  122. package/lambda/image-lambda/node_modules/color-string/LICENSE +21 -0
  123. package/lambda/image-lambda/node_modules/color-string/README.md +62 -0
  124. package/lambda/image-lambda/node_modules/color-string/index.js +242 -0
  125. package/lambda/image-lambda/node_modules/color-string/package.json +39 -0
  126. package/lambda/image-lambda/node_modules/detect-libc/LICENSE +201 -0
  127. package/lambda/image-lambda/node_modules/detect-libc/README.md +163 -0
  128. package/lambda/image-lambda/node_modules/detect-libc/index.d.ts +14 -0
  129. package/lambda/image-lambda/node_modules/detect-libc/lib/detect-libc.js +313 -0
  130. package/lambda/image-lambda/node_modules/detect-libc/lib/elf.js +39 -0
  131. package/lambda/image-lambda/node_modules/detect-libc/lib/filesystem.js +51 -0
  132. package/lambda/image-lambda/node_modules/detect-libc/lib/process.js +24 -0
  133. package/lambda/image-lambda/node_modules/detect-libc/package.json +44 -0
  134. package/lambda/image-lambda/node_modules/is-arrayish/LICENSE +21 -0
  135. package/lambda/image-lambda/node_modules/is-arrayish/README.md +16 -0
  136. package/lambda/image-lambda/node_modules/is-arrayish/index.js +9 -0
  137. package/lambda/image-lambda/node_modules/is-arrayish/package.json +45 -0
  138. package/lambda/image-lambda/node_modules/semver/LICENSE +15 -0
  139. package/lambda/image-lambda/node_modules/semver/README.md +665 -0
  140. package/lambda/image-lambda/node_modules/semver/bin/semver.js +191 -0
  141. package/lambda/image-lambda/node_modules/semver/classes/comparator.js +143 -0
  142. package/lambda/image-lambda/node_modules/semver/classes/index.js +7 -0
  143. package/lambda/image-lambda/node_modules/semver/classes/range.js +557 -0
  144. package/lambda/image-lambda/node_modules/semver/classes/semver.js +333 -0
  145. package/lambda/image-lambda/node_modules/semver/functions/clean.js +8 -0
  146. package/lambda/image-lambda/node_modules/semver/functions/cmp.js +54 -0
  147. package/lambda/image-lambda/node_modules/semver/functions/coerce.js +62 -0
  148. package/lambda/image-lambda/node_modules/semver/functions/compare-build.js +9 -0
  149. package/lambda/image-lambda/node_modules/semver/functions/compare-loose.js +5 -0
  150. package/lambda/image-lambda/node_modules/semver/functions/compare.js +7 -0
  151. package/lambda/image-lambda/node_modules/semver/functions/diff.js +60 -0
  152. package/lambda/image-lambda/node_modules/semver/functions/eq.js +5 -0
  153. package/lambda/image-lambda/node_modules/semver/functions/gt.js +5 -0
  154. package/lambda/image-lambda/node_modules/semver/functions/gte.js +5 -0
  155. package/lambda/image-lambda/node_modules/semver/functions/inc.js +21 -0
  156. package/lambda/image-lambda/node_modules/semver/functions/lt.js +5 -0
  157. package/lambda/image-lambda/node_modules/semver/functions/lte.js +5 -0
  158. package/lambda/image-lambda/node_modules/semver/functions/major.js +5 -0
  159. package/lambda/image-lambda/node_modules/semver/functions/minor.js +5 -0
  160. package/lambda/image-lambda/node_modules/semver/functions/neq.js +5 -0
  161. package/lambda/image-lambda/node_modules/semver/functions/parse.js +18 -0
  162. package/lambda/image-lambda/node_modules/semver/functions/patch.js +5 -0
  163. package/lambda/image-lambda/node_modules/semver/functions/prerelease.js +8 -0
  164. package/lambda/image-lambda/node_modules/semver/functions/rcompare.js +5 -0
  165. package/lambda/image-lambda/node_modules/semver/functions/rsort.js +5 -0
  166. package/lambda/image-lambda/node_modules/semver/functions/satisfies.js +12 -0
  167. package/lambda/image-lambda/node_modules/semver/functions/sort.js +5 -0
  168. package/lambda/image-lambda/node_modules/semver/functions/valid.js +8 -0
  169. package/lambda/image-lambda/node_modules/semver/index.js +91 -0
  170. package/lambda/image-lambda/node_modules/semver/internal/constants.js +37 -0
  171. package/lambda/image-lambda/node_modules/semver/internal/debug.js +11 -0
  172. package/lambda/image-lambda/node_modules/semver/internal/identifiers.js +29 -0
  173. package/lambda/image-lambda/node_modules/semver/internal/lrucache.js +42 -0
  174. package/lambda/image-lambda/node_modules/semver/internal/parse-options.js +17 -0
  175. package/lambda/image-lambda/node_modules/semver/internal/re.js +223 -0
  176. package/lambda/image-lambda/node_modules/semver/package.json +78 -0
  177. package/lambda/image-lambda/node_modules/semver/preload.js +4 -0
  178. package/lambda/image-lambda/node_modules/semver/range.bnf +16 -0
  179. package/lambda/image-lambda/node_modules/semver/ranges/gtr.js +6 -0
  180. package/lambda/image-lambda/node_modules/semver/ranges/intersects.js +9 -0
  181. package/lambda/image-lambda/node_modules/semver/ranges/ltr.js +6 -0
  182. package/lambda/image-lambda/node_modules/semver/ranges/max-satisfying.js +27 -0
  183. package/lambda/image-lambda/node_modules/semver/ranges/min-satisfying.js +26 -0
  184. package/lambda/image-lambda/node_modules/semver/ranges/min-version.js +63 -0
  185. package/lambda/image-lambda/node_modules/semver/ranges/outside.js +82 -0
  186. package/lambda/image-lambda/node_modules/semver/ranges/simplify.js +49 -0
  187. package/lambda/image-lambda/node_modules/semver/ranges/subset.js +249 -0
  188. package/lambda/image-lambda/node_modules/semver/ranges/to-comparators.js +10 -0
  189. package/lambda/image-lambda/node_modules/semver/ranges/valid.js +13 -0
  190. package/lambda/image-lambda/node_modules/sharp/LICENSE +191 -0
  191. package/lambda/image-lambda/node_modules/sharp/README.md +118 -0
  192. package/lambda/image-lambda/node_modules/sharp/install/check.js +41 -0
  193. package/lambda/image-lambda/node_modules/sharp/lib/channel.js +174 -0
  194. package/lambda/image-lambda/node_modules/sharp/lib/colour.js +180 -0
  195. package/lambda/image-lambda/node_modules/sharp/lib/composite.js +210 -0
  196. package/lambda/image-lambda/node_modules/sharp/lib/constructor.js +452 -0
  197. package/lambda/image-lambda/node_modules/sharp/lib/index.d.ts +1754 -0
  198. package/lambda/image-lambda/node_modules/sharp/lib/index.js +16 -0
  199. package/lambda/image-lambda/node_modules/sharp/lib/input.js +658 -0
  200. package/lambda/image-lambda/node_modules/sharp/lib/is.js +169 -0
  201. package/lambda/image-lambda/node_modules/sharp/lib/libvips.js +203 -0
  202. package/lambda/image-lambda/node_modules/sharp/lib/operation.js +958 -0
  203. package/lambda/image-lambda/node_modules/sharp/lib/output.js +1587 -0
  204. package/lambda/image-lambda/node_modules/sharp/lib/resize.js +587 -0
  205. package/lambda/image-lambda/node_modules/sharp/lib/sharp.js +114 -0
  206. package/lambda/image-lambda/node_modules/sharp/lib/utility.js +296 -0
  207. package/lambda/image-lambda/node_modules/sharp/package.json +222 -0
  208. package/lambda/image-lambda/node_modules/sharp/src/binding.gyp +280 -0
  209. package/lambda/image-lambda/node_modules/sharp/src/common.cc +1091 -0
  210. package/lambda/image-lambda/node_modules/sharp/src/common.h +393 -0
  211. package/lambda/image-lambda/node_modules/sharp/src/metadata.cc +320 -0
  212. package/lambda/image-lambda/node_modules/sharp/src/metadata.h +85 -0
  213. package/lambda/image-lambda/node_modules/sharp/src/operations.cc +475 -0
  214. package/lambda/image-lambda/node_modules/sharp/src/operations.h +125 -0
  215. package/lambda/image-lambda/node_modules/sharp/src/pipeline.cc +1758 -0
  216. package/lambda/image-lambda/node_modules/sharp/src/pipeline.h +393 -0
  217. package/lambda/image-lambda/node_modules/sharp/src/sharp.cc +40 -0
  218. package/lambda/image-lambda/node_modules/sharp/src/stats.cc +183 -0
  219. package/lambda/image-lambda/node_modules/sharp/src/stats.h +59 -0
  220. package/lambda/image-lambda/node_modules/sharp/src/utilities.cc +269 -0
  221. package/lambda/image-lambda/node_modules/sharp/src/utilities.h +19 -0
  222. package/lambda/image-lambda/node_modules/simple-swizzle/LICENSE +21 -0
  223. package/lambda/image-lambda/node_modules/simple-swizzle/README.md +43 -0
  224. package/lambda/image-lambda/node_modules/simple-swizzle/index.js +29 -0
  225. package/lambda/image-lambda/node_modules/simple-swizzle/package.json +36 -0
  226. package/lambda/webhook-worker/bootstrap +0 -0
  227. package/lambda/webhook-worker/resource.enc +0 -0
  228. package/package.json +50 -0
  229. package/src/admin-site.ts +108 -0
  230. package/src/api.ts +113 -0
  231. package/src/auth.ts +110 -0
  232. package/src/cdn.ts +449 -0
  233. package/src/image.ts +62 -0
  234. package/src/index.ts +216 -0
  235. package/src/sst-env.d.ts +143 -0
  236. package/src/storage.ts +138 -0
  237. package/src/webhooks.ts +114 -0
@@ -0,0 +1,112 @@
1
+ // ../functions/custom-message.ts
2
+ function escapeHtml(str) {
3
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4
+ }
5
+ async function handler(event) {
6
+ if (event.triggerSource !== "CustomMessage_AdminCreateUser") {
7
+ return event;
8
+ }
9
+ const inviterEmail = event.request.clientMetadata?.inviterEmail ?? "an administrator";
10
+ const adminUrl = event.request.clientMetadata?.adminUrl ?? "";
11
+ const siteHost = event.request.clientMetadata?.siteHost ?? "";
12
+ const tempPassword = event.request.codeParameter;
13
+ const userEmail = event.request.usernameParameter;
14
+ const loginLink = adminUrl ? `${adminUrl}/login` : "";
15
+ event.response.emailSubject = "You've been invited to Headroom CMS";
16
+ event.response.emailMessage = buildEmailHtml({
17
+ userEmail,
18
+ inviterEmail,
19
+ tempPassword,
20
+ loginLink,
21
+ siteHost
22
+ });
23
+ return event;
24
+ }
25
+ function buildEmailHtml(params) {
26
+ const { userEmail, tempPassword } = params;
27
+ const safeInviterEmail = escapeHtml(params.inviterEmail);
28
+ const safeSiteHost = escapeHtml(params.siteHost);
29
+ const safeLoginLink = escapeHtml(params.loginLink);
30
+ const loginSection = safeLoginLink ? `<tr>
31
+ <td style="padding: 0 0 16px 0;">
32
+ <a href="${safeLoginLink}" style="display: inline-block; background-color: #18181b; color: #ffffff; padding: 12px 24px; border-radius: 6px; text-decoration: none; font-weight: 500; font-size: 14px;">Sign in to Headroom</a>
33
+ </td>
34
+ </tr>
35
+ <tr>
36
+ <td style="padding: 0 0 24px 0;">
37
+ <p style="margin: 0; font-size: 13px; color: #71717a;">Or copy this link:</p>
38
+ <p style="margin: 4px 0 0 0; font-size: 13px; color: #3f3f46; word-break: break-all;">
39
+ <a href="${safeLoginLink}" style="color: #2563eb; text-decoration: underline;">${safeLoginLink}</a>
40
+ </p>
41
+ </td>
42
+ </tr>` : "";
43
+ return `<!DOCTYPE html>
44
+ <html>
45
+ <head>
46
+ <meta charset="utf-8">
47
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
48
+ </head>
49
+ <body style="margin: 0; padding: 0; background-color: #f4f4f5; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
50
+ <table role="presentation" style="width: 100%; border-collapse: collapse;">
51
+ <tr>
52
+ <td style="padding: 40px 20px;">
53
+ <table role="presentation" style="max-width: 480px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
54
+
55
+ <!-- Header -->
56
+ <tr>
57
+ <td style="padding: 32px 32px 0 32px;">
58
+ <h1 style="margin: 0 0 4px 0; font-size: 20px; font-weight: 600; color: #18181b;">Headroom CMS</h1>
59
+ <p style="margin: 0; font-size: 13px; color: #71717a;">Content Management System</p>
60
+ </td>
61
+ </tr>
62
+
63
+ <!-- Body -->
64
+ <tr>
65
+ <td style="padding: 24px 32px;">
66
+ <p style="margin: 0 0 16px 0; font-size: 14px; line-height: 1.6; color: #3f3f46;">
67
+ <strong>${safeInviterEmail}</strong> has invited you to ${safeSiteHost ? `manage content on <strong>${safeSiteHost}</strong> using Headroom CMS` : "join Headroom CMS"}.
68
+ </p>
69
+ <p style="margin: 0 0 16px 0; font-size: 14px; line-height: 1.6; color: #3f3f46;">
70
+ Your account has been created with the following credentials:
71
+ </p>
72
+
73
+ <!-- Credentials -->
74
+ <table role="presentation" style="width: 100%; border-collapse: collapse; margin: 0 0 24px 0; background-color: #f4f4f5; border-radius: 6px;">
75
+ <tr>
76
+ <td style="padding: 16px;">
77
+ <p style="margin: 0 0 8px 0; font-size: 13px; color: #71717a;">Email</p>
78
+ <p style="margin: 0 0 12px 0; font-size: 14px; font-weight: 500; color: #18181b;">${userEmail}</p>
79
+ <p style="margin: 0 0 8px 0; font-size: 13px; color: #71717a;">Temporary password</p>
80
+ <p style="margin: 0; font-size: 14px; font-weight: 500; font-family: 'SFMono-Regular', Consolas, monospace; color: #18181b; word-break: break-all;">${tempPassword}</p>
81
+ </td>
82
+ </tr>
83
+ </table>
84
+
85
+ ${loginSection}
86
+
87
+ <p style="margin: 0; font-size: 13px; line-height: 1.5; color: #71717a;">
88
+ You will be asked to set a new password when you sign in for the first time.
89
+ This temporary password expires in 7 days.
90
+ </p>
91
+ </td>
92
+ </tr>
93
+
94
+ <!-- Footer -->
95
+ <tr>
96
+ <td style="padding: 16px 32px; border-top: 1px solid #e4e4e7;">
97
+ <p style="margin: 0; font-size: 12px; color: #a1a1aa;">
98
+ This is an automated message from Headroom CMS. If you didn't expect this invitation, you can ignore this email.
99
+ </p>
100
+ </td>
101
+ </tr>
102
+
103
+ </table>
104
+ </td>
105
+ </tr>
106
+ </table>
107
+ </body>
108
+ </html>`;
109
+ }
110
+ export {
111
+ handler
112
+ };
@@ -0,0 +1 @@
1
+ ب�ׄ":X�b����
@@ -0,0 +1,188 @@
1
+ // ../image-lambda/index.mjs
2
+ import sharp from "sharp";
3
+ import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
4
+ import { createHmac, timingSafeEqual } from "crypto";
5
+ var s3 = new S3Client({});
6
+ var BUCKET = process.env.CONTENT_BUCKET;
7
+ var SIGNING_SECRET = process.env.IMAGE_SIGNING_SECRET;
8
+ var MAX_WIDTH = 2048;
9
+ var MAX_HEIGHT = 2048;
10
+ var MAX_PIXELS = 4e6;
11
+ var ALLOWED_FORMATS = ["jpeg", "png", "webp", "avif", "gif"];
12
+ var ALLOWED_FIT = ["cover", "contain", "fill", "inside", "outside"];
13
+ var DEFAULT_QUALITY = 80;
14
+ var SHARP_MIME_TYPES = /* @__PURE__ */ new Set([
15
+ "image/jpeg",
16
+ "image/png",
17
+ "image/gif",
18
+ "image/webp",
19
+ "image/avif",
20
+ "image/tiff"
21
+ ]);
22
+ var PATH_REGEX = /^\/img\/([a-zA-Z0-9._-]+)\/([A-Z0-9]+)\/original(\.[a-z0-9]+)$/i;
23
+ async function handler(event) {
24
+ const method = event.requestContext?.http?.method ?? event.httpMethod;
25
+ if (method !== "GET" && method !== "HEAD") {
26
+ return { statusCode: 405, body: "Method not allowed" };
27
+ }
28
+ const rawPath = event.rawPath ?? event.path;
29
+ const rawQuery = event.rawQueryString ?? "";
30
+ const match = rawPath.match(PATH_REGEX);
31
+ if (!match) {
32
+ return { statusCode: 400, body: "Invalid image path" };
33
+ }
34
+ const params = new URLSearchParams(rawQuery);
35
+ const sig = params.get("sig");
36
+ if (!sig) {
37
+ return { statusCode: 403, body: "Missing signature" };
38
+ }
39
+ if (sig.length !== 32) {
40
+ return { statusCode: 403, body: "Invalid signature" };
41
+ }
42
+ params.delete("sig");
43
+ const hasTransform = params.has("w") || params.has("h") || params.has("format") || params.has("fit") || params.has("q") || params.has("cx");
44
+ if (!hasTransform) {
45
+ return { statusCode: 400, body: "No transform requested. Use /media/ path for originals." };
46
+ }
47
+ const expectedSig = computeSignature(rawPath, params);
48
+ if (!timingSafeEqual(Buffer.from(sig), Buffer.from(expectedSig))) {
49
+ return { statusCode: 403, body: "Invalid signature" };
50
+ }
51
+ const [, site, mediaId, ext] = match;
52
+ const s3Key = `sites/${site}/media/${mediaId}/original${ext}`;
53
+ const w = clamp(parseInt(params.get("w")) || null, 1, MAX_WIDTH);
54
+ const h = clamp(parseInt(params.get("h")) || null, 1, MAX_HEIGHT);
55
+ const fit = ALLOWED_FIT.includes(params.get("fit")) ? params.get("fit") : "cover";
56
+ const format = ALLOWED_FORMATS.includes(params.get("format")) ? params.get("format") : null;
57
+ const quality = clamp(
58
+ parseInt(params.get("q")) || DEFAULT_QUALITY,
59
+ 1,
60
+ 100
61
+ );
62
+ const cxRaw = params.get("cx");
63
+ const cyRaw = params.get("cy");
64
+ const cwRaw = params.get("cw");
65
+ const chRaw = params.get("ch");
66
+ const cx = cxRaw != null ? clamp(parseInt(cxRaw), 0, MAX_WIDTH) : null;
67
+ const cy = cyRaw != null ? clamp(parseInt(cyRaw), 0, MAX_HEIGHT) : null;
68
+ const cw = cwRaw != null ? clamp(parseInt(cwRaw), 1, MAX_WIDTH) : null;
69
+ const ch = chRaw != null ? clamp(parseInt(chRaw), 1, MAX_HEIGHT) : null;
70
+ const cropCount = [cx, cy, cw, ch].filter((v) => v != null).length;
71
+ if (cropCount > 0 && cropCount < 4) {
72
+ return { statusCode: 400, body: "All crop parameters (cx, cy, cw, ch) must be provided together" };
73
+ }
74
+ const hasCrop = cropCount === 4;
75
+ const outputKey = params.get("output");
76
+ const effectiveW = w || (hasCrop ? cw : null);
77
+ const effectiveH = h || (hasCrop ? ch : null);
78
+ if (effectiveW && effectiveH && effectiveW * effectiveH > MAX_PIXELS) {
79
+ return { statusCode: 400, body: "Requested dimensions too large" };
80
+ }
81
+ try {
82
+ const s3Response = await s3.send(
83
+ new GetObjectCommand({ Bucket: BUCKET, Key: s3Key })
84
+ );
85
+ if (!SHARP_MIME_TYPES.has(s3Response.ContentType)) {
86
+ return { statusCode: 400, body: "Unsupported content type for transformation" };
87
+ }
88
+ const inputBuffer = Buffer.from(
89
+ await s3Response.Body.transformToByteArray()
90
+ );
91
+ let pipeline = sharp(inputBuffer);
92
+ if (hasCrop) {
93
+ pipeline = pipeline.extract({ left: cx, top: cy, width: cw, height: ch });
94
+ }
95
+ if (w || h) {
96
+ pipeline = pipeline.resize(w, h, {
97
+ fit,
98
+ withoutEnlargement: true
99
+ });
100
+ }
101
+ const outputFormat = format ?? extToFormat(ext);
102
+ pipeline = pipeline.toFormat(outputFormat, { quality });
103
+ if (outputKey) {
104
+ const result = await pipeline.toBuffer({ resolveWithObject: true });
105
+ await s3.send(new PutObjectCommand({
106
+ Bucket: BUCKET,
107
+ Key: outputKey,
108
+ Body: result.data,
109
+ ContentType: formatToMime(result.info.format)
110
+ }));
111
+ return {
112
+ statusCode: 200,
113
+ headers: { "Content-Type": "application/json" },
114
+ body: JSON.stringify({
115
+ key: outputKey,
116
+ width: result.info.width,
117
+ height: result.info.height,
118
+ size: result.info.size,
119
+ format: result.info.format
120
+ })
121
+ };
122
+ }
123
+ const outputBuffer = await pipeline.toBuffer();
124
+ return {
125
+ statusCode: 200,
126
+ headers: {
127
+ "content-type": formatToMime(outputFormat),
128
+ "cache-control": "public, max-age=31536000, immutable",
129
+ "content-length": String(outputBuffer.length)
130
+ },
131
+ body: outputBuffer.toString("base64"),
132
+ isBase64Encoded: true
133
+ };
134
+ } catch (err) {
135
+ if (err.name === "NoSuchKey") {
136
+ return { statusCode: 404, body: "Image not found" };
137
+ }
138
+ console.error("Image processing error:", err);
139
+ return { statusCode: 500, body: "Image processing failed" };
140
+ }
141
+ }
142
+ function computeSignature(path, params) {
143
+ const sorted = new URLSearchParams([...params.entries()].sort());
144
+ const qs = sorted.toString();
145
+ const canonical = qs ? `${path}?${qs}` : path;
146
+ return createHmac("sha256", SIGNING_SECRET).update(canonical).digest("hex").substring(0, 32);
147
+ }
148
+ function clamp(val, min, max) {
149
+ if (val == null) return null;
150
+ return Math.min(Math.max(val, min), max);
151
+ }
152
+ function extToFormat(ext) {
153
+ const map = {
154
+ ".jpg": "jpeg",
155
+ ".jpeg": "jpeg",
156
+ ".png": "png",
157
+ ".gif": "gif",
158
+ ".webp": "webp",
159
+ ".avif": "avif",
160
+ ".tiff": "tiff"
161
+ };
162
+ return map[ext.toLowerCase()] ?? "jpeg";
163
+ }
164
+ function formatToMime(format) {
165
+ const map = {
166
+ jpeg: "image/jpeg",
167
+ png: "image/png",
168
+ gif: "image/gif",
169
+ webp: "image/webp",
170
+ avif: "image/avif",
171
+ tiff: "image/tiff"
172
+ };
173
+ return map[format] ?? "application/octet-stream";
174
+ }
175
+ export {
176
+ ALLOWED_FIT,
177
+ ALLOWED_FORMATS,
178
+ MAX_HEIGHT,
179
+ MAX_PIXELS,
180
+ MAX_WIDTH,
181
+ PATH_REGEX,
182
+ SHARP_MIME_TYPES,
183
+ clamp,
184
+ computeSignature,
185
+ extToFormat,
186
+ formatToMime,
187
+ handler
188
+ };
@@ -0,0 +1,160 @@
1
+ {
2
+ "lockfileVersion": 3,
3
+ "requires": true,
4
+ "packages": {
5
+ "node_modules/@img/sharp-libvips-linux-arm64": {
6
+ "version": "1.0.4",
7
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
8
+ "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
9
+ "cpu": [
10
+ "arm64"
11
+ ],
12
+ "license": "LGPL-3.0-or-later",
13
+ "optional": true,
14
+ "os": [
15
+ "linux"
16
+ ],
17
+ "funding": {
18
+ "url": "https://opencollective.com/libvips"
19
+ }
20
+ },
21
+ "node_modules/@img/sharp-linux-arm64": {
22
+ "version": "0.33.5",
23
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
24
+ "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
25
+ "cpu": [
26
+ "arm64"
27
+ ],
28
+ "license": "Apache-2.0",
29
+ "optional": true,
30
+ "os": [
31
+ "linux"
32
+ ],
33
+ "engines": {
34
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
35
+ },
36
+ "funding": {
37
+ "url": "https://opencollective.com/libvips"
38
+ },
39
+ "optionalDependencies": {
40
+ "@img/sharp-libvips-linux-arm64": "1.0.4"
41
+ }
42
+ },
43
+ "node_modules/color": {
44
+ "version": "4.2.3",
45
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
46
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
47
+ "license": "MIT",
48
+ "dependencies": {
49
+ "color-convert": "^2.0.1",
50
+ "color-string": "^1.9.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=12.5.0"
54
+ }
55
+ },
56
+ "node_modules/color-convert": {
57
+ "version": "2.0.1",
58
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
59
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
60
+ "license": "MIT",
61
+ "dependencies": {
62
+ "color-name": "~1.1.4"
63
+ },
64
+ "engines": {
65
+ "node": ">=7.0.0"
66
+ }
67
+ },
68
+ "node_modules/color-name": {
69
+ "version": "1.1.4",
70
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
71
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
72
+ "license": "MIT"
73
+ },
74
+ "node_modules/color-string": {
75
+ "version": "1.9.1",
76
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
77
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
78
+ "license": "MIT",
79
+ "dependencies": {
80
+ "color-name": "^1.0.0",
81
+ "simple-swizzle": "^0.2.2"
82
+ }
83
+ },
84
+ "node_modules/detect-libc": {
85
+ "version": "2.1.2",
86
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
87
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
88
+ "license": "Apache-2.0",
89
+ "engines": {
90
+ "node": ">=8"
91
+ }
92
+ },
93
+ "node_modules/is-arrayish": {
94
+ "version": "0.3.4",
95
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
96
+ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
97
+ "license": "MIT"
98
+ },
99
+ "node_modules/semver": {
100
+ "version": "7.7.4",
101
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
102
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
103
+ "license": "ISC",
104
+ "bin": {
105
+ "semver": "bin/semver.js"
106
+ },
107
+ "engines": {
108
+ "node": ">=10"
109
+ }
110
+ },
111
+ "node_modules/sharp": {
112
+ "version": "0.33.5",
113
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
114
+ "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
115
+ "hasInstallScript": true,
116
+ "license": "Apache-2.0",
117
+ "dependencies": {
118
+ "color": "^4.2.3",
119
+ "detect-libc": "^2.0.3",
120
+ "semver": "^7.6.3"
121
+ },
122
+ "engines": {
123
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
124
+ },
125
+ "funding": {
126
+ "url": "https://opencollective.com/libvips"
127
+ },
128
+ "optionalDependencies": {
129
+ "@img/sharp-darwin-arm64": "0.33.5",
130
+ "@img/sharp-darwin-x64": "0.33.5",
131
+ "@img/sharp-libvips-darwin-arm64": "1.0.4",
132
+ "@img/sharp-libvips-darwin-x64": "1.0.4",
133
+ "@img/sharp-libvips-linux-arm": "1.0.5",
134
+ "@img/sharp-libvips-linux-arm64": "1.0.4",
135
+ "@img/sharp-libvips-linux-s390x": "1.0.4",
136
+ "@img/sharp-libvips-linux-x64": "1.0.4",
137
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
138
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
139
+ "@img/sharp-linux-arm": "0.33.5",
140
+ "@img/sharp-linux-arm64": "0.33.5",
141
+ "@img/sharp-linux-s390x": "0.33.5",
142
+ "@img/sharp-linux-x64": "0.33.5",
143
+ "@img/sharp-linuxmusl-arm64": "0.33.5",
144
+ "@img/sharp-linuxmusl-x64": "0.33.5",
145
+ "@img/sharp-wasm32": "0.33.5",
146
+ "@img/sharp-win32-ia32": "0.33.5",
147
+ "@img/sharp-win32-x64": "0.33.5"
148
+ }
149
+ },
150
+ "node_modules/simple-swizzle": {
151
+ "version": "0.2.4",
152
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
153
+ "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==",
154
+ "license": "MIT",
155
+ "dependencies": {
156
+ "is-arrayish": "^0.3.1"
157
+ }
158
+ }
159
+ }
160
+ }
@@ -0,0 +1,46 @@
1
+ # `@img/sharp-libvips-linux-arm64`
2
+
3
+ Prebuilt libvips and dependencies for use with sharp on Linux (glibc) 64-bit ARM.
4
+
5
+ ## Licensing
6
+
7
+ This software contains third-party libraries
8
+ used under the terms of the following licences:
9
+
10
+ | Library | Used under the terms of |
11
+ |---------------|-----------------------------------------------------------------------------------------------------------|
12
+ | aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
13
+ | cairo | Mozilla Public License 2.0 |
14
+ | cgif | MIT Licence |
15
+ | expat | MIT Licence |
16
+ | fontconfig | [fontconfig Licence](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
17
+ | freetype | [freetype Licence](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
18
+ | fribidi | LGPLv3 |
19
+ | glib | LGPLv3 |
20
+ | harfbuzz | MIT Licence |
21
+ | highway | Apache-2.0 License, BSD 3-Clause |
22
+ | lcms | MIT Licence |
23
+ | libarchive | BSD 2-Clause |
24
+ | libexif | LGPLv3 |
25
+ | libffi | MIT Licence |
26
+ | libheif | LGPLv3 |
27
+ | libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
28
+ | libnsgif | MIT Licence |
29
+ | libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
30
+ | librsvg | LGPLv3 |
31
+ | libspng | [BSD 2-Clause, libpng License](https://github.com/randy408/libspng/blob/master/LICENSE) |
32
+ | libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
33
+ | libvips | LGPLv3 |
34
+ | libwebp | New BSD License |
35
+ | libxml2 | MIT Licence |
36
+ | mozjpeg | [zlib License, IJG License, BSD-3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
37
+ | pango | LGPLv3 |
38
+ | pixman | MIT Licence |
39
+ | proxy-libintl | LGPLv3 |
40
+ | zlib-ng | [zlib Licence](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
41
+
42
+ Use of libraries under the terms of the LGPLv3 is via the
43
+ "any later version" clause of the LGPLv2 or LGPLv2.1.
44
+
45
+ Please report any errors or omissions via
46
+ https://github.com/lovell/sharp-libvips/issues/new