@infoxchange/make-it-so-sst-v2 3.0.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 (99) hide show
  1. package/.editorconfig +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +377 -0
  4. package/commitlint.config.ts +14 -0
  5. package/dist/cdk-constructs/IxApi.d.ts +12 -0
  6. package/dist/cdk-constructs/IxApi.d.ts.map +1 -0
  7. package/dist/cdk-constructs/IxApi.js +56 -0
  8. package/dist/cdk-constructs/IxBucket.d.ts +9 -0
  9. package/dist/cdk-constructs/IxBucket.d.ts.map +1 -0
  10. package/dist/cdk-constructs/IxBucket.js +22 -0
  11. package/dist/cdk-constructs/IxCertificate.d.ts +16 -0
  12. package/dist/cdk-constructs/IxCertificate.d.ts.map +1 -0
  13. package/dist/cdk-constructs/IxCertificate.js +26 -0
  14. package/dist/cdk-constructs/IxDnsRecord.d.ts +23 -0
  15. package/dist/cdk-constructs/IxDnsRecord.d.ts.map +1 -0
  16. package/dist/cdk-constructs/IxDnsRecord.js +43 -0
  17. package/dist/cdk-constructs/IxElasticache.d.ts +17 -0
  18. package/dist/cdk-constructs/IxElasticache.d.ts.map +1 -0
  19. package/dist/cdk-constructs/IxElasticache.js +70 -0
  20. package/dist/cdk-constructs/IxNextjsSite.d.ts +16 -0
  21. package/dist/cdk-constructs/IxNextjsSite.d.ts.map +1 -0
  22. package/dist/cdk-constructs/IxNextjsSite.js +38 -0
  23. package/dist/cdk-constructs/IxQuicksightWorkspace.d.ts +17 -0
  24. package/dist/cdk-constructs/IxQuicksightWorkspace.d.ts.map +1 -0
  25. package/dist/cdk-constructs/IxQuicksightWorkspace.js +29 -0
  26. package/dist/cdk-constructs/IxSESIdentity.d.ts +12 -0
  27. package/dist/cdk-constructs/IxSESIdentity.d.ts.map +1 -0
  28. package/dist/cdk-constructs/IxSESIdentity.js +45 -0
  29. package/dist/cdk-constructs/IxStaticSite.d.ts +17 -0
  30. package/dist/cdk-constructs/IxStaticSite.d.ts.map +1 -0
  31. package/dist/cdk-constructs/IxStaticSite.js +38 -0
  32. package/dist/cdk-constructs/IxVpcDetails.d.ts +12 -0
  33. package/dist/cdk-constructs/IxVpcDetails.d.ts.map +1 -0
  34. package/dist/cdk-constructs/IxVpcDetails.js +26 -0
  35. package/dist/cdk-constructs/IxWebsiteRedirect.d.ts +35 -0
  36. package/dist/cdk-constructs/IxWebsiteRedirect.d.ts.map +1 -0
  37. package/dist/cdk-constructs/IxWebsiteRedirect.js +72 -0
  38. package/dist/cdk-constructs/SiteOidcAuth/auth-check-handler-body.d.ts +2 -0
  39. package/dist/cdk-constructs/SiteOidcAuth/auth-check-handler-body.d.ts.map +1 -0
  40. package/dist/cdk-constructs/SiteOidcAuth/auth-check-handler-body.js +130 -0
  41. package/dist/cdk-constructs/SiteOidcAuth/auth-route.d.ts +2 -0
  42. package/dist/cdk-constructs/SiteOidcAuth/auth-route.d.ts.map +1 -0
  43. package/dist/cdk-constructs/SiteOidcAuth/auth-route.js +59 -0
  44. package/dist/cdk-constructs/SiteOidcAuth/index.d.ts +197 -0
  45. package/dist/cdk-constructs/SiteOidcAuth/index.d.ts.map +1 -0
  46. package/dist/cdk-constructs/SiteOidcAuth/index.js +188 -0
  47. package/dist/cdk-constructs/index.d.ts +11 -0
  48. package/dist/cdk-constructs/index.d.ts.map +1 -0
  49. package/dist/cdk-constructs/index.js +10 -0
  50. package/dist/deployConfig.d.ts +72 -0
  51. package/dist/deployConfig.d.ts.map +1 -0
  52. package/dist/deployConfig.js +78 -0
  53. package/dist/lib/auth/index.d.ts +2 -0
  54. package/dist/lib/auth/index.d.ts.map +1 -0
  55. package/dist/lib/auth/index.js +1 -0
  56. package/dist/lib/auth/oidc.d.ts +26 -0
  57. package/dist/lib/auth/oidc.d.ts.map +1 -0
  58. package/dist/lib/auth/oidc.js +48 -0
  59. package/dist/lib/proxy/fetch.d.ts +4 -0
  60. package/dist/lib/proxy/fetch.d.ts.map +1 -0
  61. package/dist/lib/proxy/fetch.js +31 -0
  62. package/dist/lib/proxy/index.d.ts +2 -0
  63. package/dist/lib/proxy/index.d.ts.map +1 -0
  64. package/dist/lib/proxy/index.js +1 -0
  65. package/dist/lib/site/support.d.ts +71 -0
  66. package/dist/lib/site/support.d.ts.map +1 -0
  67. package/dist/lib/site/support.js +262 -0
  68. package/dist/lib/utils/hash.d.ts +2 -0
  69. package/dist/lib/utils/hash.d.ts.map +1 -0
  70. package/dist/lib/utils/hash.js +13 -0
  71. package/dist/lib/utils/objects.d.ts +4 -0
  72. package/dist/lib/utils/objects.d.ts.map +1 -0
  73. package/dist/lib/utils/objects.js +7 -0
  74. package/eslint.config.js +11 -0
  75. package/package.json +66 -0
  76. package/src/cdk-constructs/IxApi.ts +81 -0
  77. package/src/cdk-constructs/IxBucket.ts +35 -0
  78. package/src/cdk-constructs/IxCertificate.ts +54 -0
  79. package/src/cdk-constructs/IxDnsRecord.ts +79 -0
  80. package/src/cdk-constructs/IxElasticache.ts +106 -0
  81. package/src/cdk-constructs/IxNextjsSite.ts +72 -0
  82. package/src/cdk-constructs/IxQuicksightWorkspace.ts +54 -0
  83. package/src/cdk-constructs/IxSESIdentity.ts +70 -0
  84. package/src/cdk-constructs/IxStaticSite.ts +69 -0
  85. package/src/cdk-constructs/IxVpcDetails.ts +38 -0
  86. package/src/cdk-constructs/IxWebsiteRedirect.ts +133 -0
  87. package/src/cdk-constructs/SiteOidcAuth/auth-check-handler-body.ts +168 -0
  88. package/src/cdk-constructs/SiteOidcAuth/auth-route.ts +71 -0
  89. package/src/cdk-constructs/SiteOidcAuth/index.ts +299 -0
  90. package/src/cdk-constructs/index.ts +10 -0
  91. package/src/deployConfig.ts +87 -0
  92. package/src/lib/auth/index.ts +1 -0
  93. package/src/lib/auth/oidc.ts +73 -0
  94. package/src/lib/proxy/fetch.ts +41 -0
  95. package/src/lib/proxy/index.ts +1 -0
  96. package/src/lib/site/support.ts +439 -0
  97. package/src/lib/utils/hash.ts +14 -0
  98. package/src/lib/utils/objects.ts +19 -0
  99. package/tsconfig.json +9 -0
@@ -0,0 +1,439 @@
1
+ import { Construct } from "constructs";
2
+ import {
3
+ NextjsSite,
4
+ NextjsSiteProps,
5
+ Stack,
6
+ StaticSite,
7
+ StaticSiteProps,
8
+ } from "sst/constructs";
9
+ import ixDeployConfig from "../../deployConfig.js";
10
+ import { IxCertificate } from "../../cdk-constructs/IxCertificate.js";
11
+ import { IxWebsiteRedirect } from "../../cdk-constructs/IxWebsiteRedirect.js";
12
+ import { IxVpcDetails } from "../../cdk-constructs/IxVpcDetails.js";
13
+ import { IxDnsRecord } from "../../cdk-constructs/IxDnsRecord.js";
14
+ import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
15
+ import { convertToBase62Hash } from "../utils/hash.js";
16
+ import { type DistributionDomainProps } from "sst/constructs/Distribution.js";
17
+ import type { Plan as SSTPlan } from "sst/constructs/SsrSite.js";
18
+ import {
19
+ SiteOidcAuth,
20
+ type AddToSiteProps as SiteOidcAuthAddToSiteProps,
21
+ } from "../../cdk-constructs/SiteOidcAuth/index.js";
22
+
23
+ type SharedExtendedSiteProps = {
24
+ customDomain?: string | ExtendedCustomDomains;
25
+ auth?: {
26
+ oidc: {
27
+ issuerUrl: string;
28
+ clientId: string;
29
+ scope: string;
30
+ };
31
+ } & SiteOidcAuthAddToSiteProps;
32
+ };
33
+
34
+ export type ExtendedCustomDomains = DistributionDomainProps & {
35
+ isIxManagedDomain?: boolean;
36
+ additionalDomainAliases?: string[];
37
+ };
38
+ export type ExtendedNextjsSiteProps = Omit<
39
+ NextjsSiteProps,
40
+ "customDomain" | "environment"
41
+ > &
42
+ SharedExtendedSiteProps & {
43
+ /**
44
+ * An object with the key being the environment variable name. The value can either be the environment variable value
45
+ * as a string or as an object with `buildtime` and/or `runtime` properties where the values of `buildtime` and
46
+ * `runtime` is the environment variable value that will be used during that step.
47
+ *
48
+ * @example
49
+ * ```js
50
+ * environment: {
51
+ * USER_POOL_CLIENT: auth.cognitoUserPoolClient.userPoolClientId,
52
+ * NODE_OPTIONS: {
53
+ * buildtime: "--max-old-space-size=4096",
54
+ * },
55
+ * API_URL: {
56
+ * buildtime: "https://external.domain",
57
+ * runtime: "https://internal.domain",
58
+ * },
59
+ * },
60
+ * ```
61
+ */
62
+ environment?: Record<
63
+ string,
64
+ string | { buildtime?: string; runtime?: string }
65
+ >;
66
+ };
67
+
68
+ export type ExtendedStaticSiteProps = Omit<StaticSiteProps, "customDomain"> &
69
+ SharedExtendedSiteProps;
70
+
71
+ export function setupCustomDomain<
72
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
73
+ >(scope: Construct, id: string, props: Readonly<Props>): Props {
74
+ let updatedProps = props;
75
+ // Default to using domains names passed in by the pipeline as the custom domain
76
+ if (ixDeployConfig.isIxDeploy && !("customDomain" in updatedProps)) {
77
+ updatedProps = {
78
+ ...updatedProps,
79
+ customDomain: {
80
+ isIxManagedDomain: true,
81
+ isExternalDomain: true,
82
+ domainName: ixDeployConfig.siteDomains[0],
83
+ alternateNames: ixDeployConfig.siteDomains.slice(1),
84
+ domainAlias: ixDeployConfig.siteDomainAliases[0],
85
+ additionalDomainAliases: ixDeployConfig.siteDomainAliases.slice(1),
86
+ },
87
+ };
88
+ }
89
+ return updatedProps;
90
+ }
91
+
92
+ export function setupCertificate<
93
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
94
+ >(scope: Construct, id: string, props: Readonly<Props>): Props {
95
+ const updatedProps: Props = { ...props };
96
+ if (!updatedProps?.customDomain) return updatedProps;
97
+
98
+ if (typeof updatedProps.customDomain === "string") {
99
+ updatedProps.customDomain = { domainName: updatedProps.customDomain };
100
+ }
101
+
102
+ // No cert creation required if isIxManagedDomain is false or a cert is already provided
103
+ if (
104
+ !updatedProps.customDomain.isIxManagedDomain &&
105
+ updatedProps.customDomain.cdk?.certificate
106
+ ) {
107
+ return updatedProps;
108
+ }
109
+
110
+ const domainCert = new IxCertificate(scope, id + "-IxCertificate", {
111
+ domainName: updatedProps.customDomain.domainName,
112
+ subjectAlternativeNames: updatedProps.customDomain.alternateNames,
113
+ region: "us-east-1", // CloudFront will only use certificates in us-east-1
114
+ });
115
+ updatedProps.customDomain.cdk = updatedProps.customDomain.cdk ?? {};
116
+ updatedProps.customDomain.cdk.certificate = domainCert.acmCertificate;
117
+
118
+ return updatedProps;
119
+ }
120
+
121
+ export function setupDomainAliasRedirect<
122
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
123
+ >(scope: Construct, id: string, props: Readonly<Props>): Props {
124
+ if (
125
+ typeof props.customDomain !== "object" ||
126
+ !(
127
+ props.customDomain.domainAlias ||
128
+ props.customDomain.additionalDomainAliases?.length
129
+ ) ||
130
+ !props.customDomain.isIxManagedDomain ||
131
+ !props.customDomain.cdk?.certificate
132
+ ) {
133
+ return props;
134
+ }
135
+ const domainsToRedirectFrom = [
136
+ ...(props.customDomain.domainAlias ? [props.customDomain.domainAlias] : []),
137
+ ...(props.customDomain.additionalDomainAliases ?? []),
138
+ ];
139
+ new IxWebsiteRedirect(scope, id + "-IxWebsiteRedirect", {
140
+ recordNames: domainsToRedirectFrom,
141
+ targetDomain: props.customDomain.domainName,
142
+ });
143
+ return {
144
+ ...props,
145
+ customDomain: {
146
+ ...props.customDomain,
147
+ domainAlias: undefined, // SST's site constructs will complain if domainAlias is set while isExternalDomain is true
148
+ },
149
+ };
150
+ }
151
+
152
+ export function setupVpcDetails<Props extends ExtendedNextjsSiteProps>(
153
+ scope: Construct,
154
+ id: string,
155
+ props: Readonly<Props>,
156
+ ): Props {
157
+ const updatedProps: Props = { ...props };
158
+
159
+ // Don't make any changes if the user has set the VPC manually in any place
160
+ if (
161
+ "vpc" in (updatedProps.cdk?.server || {}) ||
162
+ "vpc" in (updatedProps.cdk?.revalidation || {})
163
+ ) {
164
+ return updatedProps;
165
+ }
166
+
167
+ const vpcDetails = new IxVpcDetails(scope, id + "-IxVpcDetails");
168
+
169
+ updatedProps.cdk = updatedProps.cdk ?? {};
170
+ updatedProps.cdk.server = {
171
+ ...updatedProps.cdk.server,
172
+ vpc: vpcDetails.vpc,
173
+ };
174
+ updatedProps.cdk.revalidation = {
175
+ ...updatedProps.cdk.revalidation,
176
+ vpc: vpcDetails.vpc,
177
+ };
178
+
179
+ if (!ixDeployConfig.vpcHttpProxy) {
180
+ console.warn(
181
+ `Attempting to add HTTP proxy environment variables to ${id} but the VPC_HTTP_PROXY env var is not configured.`,
182
+ );
183
+ }
184
+ // If we're using the AWS runner then the build stage will already be inside the VPC and required the proxy but
185
+ // the HTTP proxy environment variables will be already set in the environment by the pipeline and so the build
186
+ // stage will inherit that.
187
+ updatedProps.environment = {
188
+ HTTP_PROXY: { runtime: ixDeployConfig.vpcHttpProxy },
189
+ HTTPS_PROXY: { runtime: ixDeployConfig.vpcHttpProxy },
190
+ http_proxy: { runtime: ixDeployConfig.vpcHttpProxy },
191
+ https_proxy: { runtime: ixDeployConfig.vpcHttpProxy },
192
+ ...updatedProps.environment,
193
+ };
194
+
195
+ return updatedProps;
196
+ }
197
+
198
+ /**
199
+ * Ensures environment variables that are conditionally included for buildtime or runtime are only used during the
200
+ * appropriate phase.
201
+ */
202
+ export function applyConditionalEnvironmentVariables<
203
+ Props extends ExtendedNextjsSiteProps,
204
+ >(scope: Construct, id: string, props: Readonly<Props>): Props {
205
+ const updatedProps: Props = { ...props };
206
+
207
+ if (!updatedProps.environment) return updatedProps;
208
+
209
+ const buildtimeSpecificEnvVars = Object.fromEntries(
210
+ Object.entries(updatedProps.environment)
211
+ .filter(([, value]) => typeof value === "object")
212
+ .map(([varName, value]) => [
213
+ varName,
214
+ typeof value === "object" && "buildtime" in value
215
+ ? value.buildtime
216
+ : undefined,
217
+ ]),
218
+ );
219
+
220
+ const runtimeSpecificEnvVars = Object.fromEntries(
221
+ Object.entries(updatedProps.environment)
222
+ .filter(([, value]) => typeof value === "object")
223
+ .map(([varName, value]) => [
224
+ varName,
225
+ typeof value === "object" && "runtime" in value
226
+ ? value.runtime
227
+ : undefined,
228
+ ]),
229
+ );
230
+
231
+ // Remove runtime excluded env vars from lambda
232
+ updatedProps.cdk = updatedProps.cdk ?? {};
233
+ const oldTransform = updatedProps.cdk.transform;
234
+ updatedProps.cdk.transform = (plan: SSTPlan) => {
235
+ oldTransform?.(plan);
236
+
237
+ for (const origin of Object.values(plan.origins)) {
238
+ if (!("function" in origin) || !origin.function.environment) {
239
+ continue;
240
+ }
241
+ for (const [envVarName, envVarValue] of Object.entries(
242
+ runtimeSpecificEnvVars,
243
+ )) {
244
+ if (envVarValue !== undefined) {
245
+ origin.function.environment[envVarName] = envVarValue;
246
+ } else {
247
+ // @ts-expect-error - Environment values should generally only be strings but we need to set it to undefined
248
+ // as a workaround to override any environment variables that are mixed in during function creation which are
249
+ // only meant to be included at build time.
250
+ // https://github.com/sst/v2/blob/d0c9d5c1cbf8016b2a2b7ed2e247c27546b40387/packages/sst/src/constructs/SsrSite.ts#L1029
251
+ origin.function.environment[envVarName] = undefined;
252
+ }
253
+ }
254
+ }
255
+ };
256
+
257
+ // Remove buildtime excluded env vars from environment object which is used during build
258
+ for (const [envVarName, envVarValue] of Object.entries(
259
+ buildtimeSpecificEnvVars,
260
+ )) {
261
+ if (envVarValue !== undefined) {
262
+ updatedProps.environment[envVarName] = envVarValue;
263
+ } else {
264
+ delete updatedProps.environment[envVarName];
265
+ }
266
+ }
267
+
268
+ return updatedProps;
269
+ }
270
+
271
+ /**
272
+ * Before props reach this function they should have already been converted into something compatible with the parent
273
+ * SST construct. This function verifies that's the case and updates the type if so.
274
+ */
275
+ export function parentCompatibleSsrProps<
276
+ Props extends ExtendedNextjsSiteProps,
277
+ ResultProps = Omit<Props, "environment"> & {
278
+ environment?: Record<string, string>;
279
+ },
280
+ >(props: Readonly<Props>): ResultProps {
281
+ for (const value of Object.values(props.environment ?? {})) {
282
+ if (typeof value !== "string") {
283
+ throw new Error(
284
+ "Internal make-it-so error: The environment prop contains buildtime/runtime specific environment variables which cannot be passed to the parent NextjsSite construct. Please use the applyConditionalEnvironmentVariables function to ensure only appropriate environment variables are included.",
285
+ );
286
+ }
287
+ }
288
+ return props as ResultProps;
289
+ }
290
+
291
+ export function setupDefaultEnvVars<Props extends ExtendedNextjsSiteProps>(
292
+ scope: Construct | Stack,
293
+ id: string,
294
+ props: Readonly<Props>,
295
+ ): Props {
296
+ const updatedProps: Props = { ...props };
297
+ // NextjsSite functions to not use default env var unfortunately so we have to
298
+ // explicitly set them ourselves https://github.com/sst/sst/issues/2359
299
+ if ("defaultFunctionProps" in scope) {
300
+ for (const funcProps of scope.defaultFunctionProps) {
301
+ const defaultFunctionEnvVars = { ...funcProps.environment };
302
+
303
+ updatedProps.environment = {
304
+ ...defaultFunctionEnvVars,
305
+ ...updatedProps.environment,
306
+ };
307
+ }
308
+ }
309
+ return updatedProps;
310
+ }
311
+
312
+ export function setupDnsRecords<
313
+ Instance extends NextjsSite | StaticSite,
314
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
315
+ >(
316
+ instance: Instance,
317
+ scope: Construct,
318
+ id: string,
319
+ props: Readonly<Props>,
320
+ ): void {
321
+ if (
322
+ !instance.cdk?.distribution ||
323
+ typeof props.customDomain !== "object" ||
324
+ !props.customDomain.isIxManagedDomain
325
+ )
326
+ return;
327
+
328
+ for (const domainName of getCustomDomains(props)) {
329
+ const domainNameLogicalId = convertToBase62Hash(domainName);
330
+
331
+ new IxDnsRecord(scope, `DnsRecord-${domainNameLogicalId}`, {
332
+ type: "ALIAS",
333
+ name: domainName,
334
+ value: instance.cdk.distribution.distributionDomainName,
335
+ aliasZoneId: CloudFrontTarget.getHostedZoneId(scope),
336
+ ttl: 900,
337
+ });
338
+ }
339
+ }
340
+
341
+ export function getCustomDomains<
342
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
343
+ >(props: Readonly<Props>): string[] {
344
+ const domainNames = new Set<string>();
345
+
346
+ const primaryCustomDomain = getPrimaryCustomDomain(props);
347
+ const alternativeDomains = getAlternativeDomains(props);
348
+
349
+ if (primaryCustomDomain) domainNames.add(primaryCustomDomain);
350
+ if (alternativeDomains.length)
351
+ alternativeDomains.forEach((domain) => domainNames.add(domain));
352
+
353
+ return Array.from(domainNames);
354
+ }
355
+
356
+ export function getPrimaryDomain<
357
+ Instance extends NextjsSite | StaticSite,
358
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
359
+ >(instance: Instance, props: Readonly<Props>): string | null {
360
+ return (
361
+ getPrimaryCustomDomain(props) ??
362
+ instance.cdk?.distribution?.distributionDomainName ??
363
+ null
364
+ );
365
+ }
366
+
367
+ export function getPrimaryOrigin<
368
+ Instance extends NextjsSite | StaticSite,
369
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
370
+ >(instance: Instance, props: Readonly<Props>): string | null {
371
+ const primaryDomain = getPrimaryDomain(instance, props);
372
+ return primaryDomain ? `https://${primaryDomain}` : null;
373
+ }
374
+
375
+ export function getPrimaryCustomDomain<
376
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
377
+ >(props: Readonly<Props>): string | null {
378
+ if (typeof props.customDomain === "string") {
379
+ return props.customDomain;
380
+ } else if (typeof props.customDomain === "object") {
381
+ return props.customDomain.domainName ?? null;
382
+ }
383
+ return null;
384
+ }
385
+
386
+ export function getAliasDomain<
387
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
388
+ >(props: Readonly<Props>): string | null {
389
+ if (typeof props.customDomain === "object") {
390
+ return props.customDomain.domainAlias ?? null;
391
+ }
392
+ return null;
393
+ }
394
+
395
+ export function getAlternativeDomains<
396
+ Props extends ExtendedStaticSiteProps | ExtendedNextjsSiteProps,
397
+ >(props: Readonly<Props>): string[] {
398
+ if (typeof props.customDomain === "object") {
399
+ return props.customDomain.alternateNames ?? [];
400
+ }
401
+ return [];
402
+ }
403
+
404
+ export function processAuthProps<
405
+ SiteType extends "StaticSite" | "SsrSite",
406
+ Props extends SiteType extends "StaticSite"
407
+ ? ExtendedStaticSiteProps
408
+ : ExtendedNextjsSiteProps,
409
+ >(
410
+ scope: Construct,
411
+ id: string,
412
+ siteType: SiteType,
413
+ props: Readonly<Props>,
414
+ ): Props {
415
+ if (!props.auth) return props;
416
+ const { oidc, ...otherAuthProps } = props.auth;
417
+ const auth = new SiteOidcAuth(scope, `${id}-SiteOidcAuth`, {
418
+ oidcIssuerUrl: oidc.issuerUrl,
419
+ oidcClientId: oidc.clientId,
420
+ oidcScope: oidc.scope,
421
+ });
422
+ if (siteType === "StaticSite") {
423
+ return auth.addToStaticSiteProps(
424
+ scope,
425
+ props as ExtendedStaticSiteProps,
426
+ otherAuthProps,
427
+ ) as Props;
428
+ } else if (siteType === "SsrSite") {
429
+ return auth.addToSsrSiteProps(
430
+ scope,
431
+ props as ExtendedNextjsSiteProps,
432
+ otherAuthProps,
433
+ ) as Props;
434
+ }
435
+ siteType satisfies never;
436
+ throw new Error(
437
+ `Unsupported site type ${siteType} when processing auth prop.`,
438
+ );
439
+ }
@@ -0,0 +1,14 @@
1
+ export function convertToBase62Hash(string: string): string {
2
+ const base62Chars =
3
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
4
+ let hash = "";
5
+ let num = 0;
6
+ for (let i = 0; i < string.length; i++) {
7
+ num += string.charCodeAt(i);
8
+ }
9
+ while (num > 0) {
10
+ hash = base62Chars[num % 62] + hash;
11
+ num = Math.floor(num / 62);
12
+ }
13
+ return hash;
14
+ }
@@ -0,0 +1,19 @@
1
+ export function remapKeys<
2
+ SourceObject extends object,
3
+ MapObject extends Record<keyof SourceObject, string>,
4
+ >(
5
+ object: SourceObject,
6
+ keyMap: Readonly<MapObject>,
7
+ ): {
8
+ [k in keyof SourceObject as k extends keyof MapObject
9
+ ? MapObject[k]
10
+ : k]: SourceObject[k];
11
+ } {
12
+ return Object.fromEntries(
13
+ Object.entries(object).map(([key, value]) => {
14
+ // @ts-expect-error the typing for map() reduces keys to general string
15
+ const newKey = keyMap[key] ?? key;
16
+ return [newKey, value];
17
+ }),
18
+ );
19
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "declarationMap": true,
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src/**/*.ts"],
8
+ "extends": "@tsconfig/node21/tsconfig.json"
9
+ }