@jaypie/constructs 1.2.6 → 1.2.8

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.
@@ -1,4 +1,4 @@
1
- import { RemovalPolicy, Stack } from "aws-cdk-lib";
1
+ import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
2
2
  import * as acm from "aws-cdk-lib/aws-certificatemanager";
3
3
  import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
4
4
  import * as lambda from "aws-cdk-lib/aws-lambda";
@@ -35,10 +35,19 @@ export interface JaypieDistributionProps extends Omit<cloudfront.DistributionPro
35
35
  */
36
36
  host?: string;
37
37
  /**
38
- * Invoke mode for Lambda Function URLs
39
- * @default InvokeMode.BUFFERED
38
+ * Invoke mode for Lambda Function URLs.
39
+ * If not provided, auto-detects from handler if it has an invokeMode property
40
+ * (e.g., JaypieStreamingLambda).
41
+ * @default InvokeMode.BUFFERED (or auto-detected from handler)
40
42
  */
41
43
  invokeMode?: lambda.InvokeMode;
44
+ /**
45
+ * Origin read timeout - how long CloudFront waits for a response from the origin.
46
+ * This is the maximum time allowed for the origin to respond.
47
+ * @default CDK.DURATION.CLOUDFRONT_API (180 seconds)
48
+ * @max Duration.seconds(180)
49
+ */
50
+ originReadTimeout?: Duration;
42
51
  /**
43
52
  * Role tag for tagging resources
44
53
  * @default CDK.ROLE.HOSTING
@@ -64,6 +73,7 @@ export declare class JaypieDistribution extends Construct implements cloudfront.
64
73
  private isIOrigin;
65
74
  private isIFunctionUrl;
66
75
  private isIFunction;
76
+ private hasInvokeMode;
67
77
  get env(): {
68
78
  account: string;
69
79
  region: string;
@@ -0,0 +1,44 @@
1
+ import { Construct } from "constructs";
2
+ import * as lambda from "aws-cdk-lib/aws-lambda";
3
+ import { JaypieLambda, JaypieLambdaProps } from "./JaypieLambda.js";
4
+ export interface JaypieStreamingLambdaProps extends JaypieLambdaProps {
5
+ /**
6
+ * The port your application listens on.
7
+ * @default 8000
8
+ */
9
+ port?: number;
10
+ /**
11
+ * Enable response streaming mode.
12
+ * When true, uses RESPONSE_STREAM invoke mode.
13
+ * When false, uses BUFFERED invoke mode.
14
+ * @default false
15
+ */
16
+ streaming?: boolean;
17
+ }
18
+ /**
19
+ * A Lambda construct that uses AWS Lambda Web Adapter for streaming support.
20
+ * This allows running web applications (Express, Fastify, etc.) with streaming responses.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const streamingLambda = new JaypieStreamingLambda(this, "StreamingApi", {
25
+ * code: "dist/api",
26
+ * handler: "run.sh",
27
+ * streaming: true,
28
+ * });
29
+ *
30
+ * // Use with JaypieDistribution
31
+ * new JaypieDistribution(this, "Distribution", {
32
+ * handler: streamingLambda,
33
+ * invokeMode: streamingLambda.invokeMode,
34
+ * });
35
+ * ```
36
+ */
37
+ export declare class JaypieStreamingLambda extends JaypieLambda {
38
+ /**
39
+ * The invoke mode for this Lambda function.
40
+ * Use this when configuring JaypieDistribution.
41
+ */
42
+ readonly invokeMode: lambda.InvokeMode;
43
+ constructor(scope: Construct, id: string, props: JaypieStreamingLambdaProps);
44
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,17 @@
1
+ export declare const LAMBDA_WEB_ADAPTER: {
2
+ ACCOUNT: string;
3
+ DEFAULT_PORT: number;
4
+ EXEC_WRAPPER: string;
5
+ INVOKE_MODE: {
6
+ BUFFERED: string;
7
+ RESPONSE_STREAM: string;
8
+ };
9
+ LAYER: {
10
+ ARM64: string;
11
+ X86: string;
12
+ };
13
+ VERSION: number;
14
+ };
1
15
  export declare const CDK: {
2
16
  ACCOUNT: {
3
17
  DEVELOPMENT: string;
@@ -55,6 +69,7 @@ export declare const CDK: {
55
69
  };
56
70
  DURATION: {
57
71
  EXPRESS_API: number;
72
+ CLOUDFRONT_API: number;
58
73
  LAMBDA_MAXIMUM: number;
59
74
  LAMBDA_WORKER: number;
60
75
  };
@@ -63,6 +63,20 @@ var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
63
63
  var dynamodb__namespace = /*#__PURE__*/_interopNamespaceDefault(dynamodb);
64
64
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
65
65
 
66
+ const LAMBDA_WEB_ADAPTER = {
67
+ ACCOUNT: "753240598075",
68
+ DEFAULT_PORT: 8000,
69
+ EXEC_WRAPPER: "/opt/bootstrap",
70
+ INVOKE_MODE: {
71
+ BUFFERED: "BUFFERED",
72
+ RESPONSE_STREAM: "RESPONSE_STREAM",
73
+ },
74
+ LAYER: {
75
+ ARM64: "LambdaAdapterLayerArm64",
76
+ X86: "LambdaAdapterLayerX86",
77
+ },
78
+ VERSION: 25,
79
+ };
66
80
  const CDK$2 = {
67
81
  ACCOUNT: {
68
82
  DEVELOPMENT: "development",
@@ -121,6 +135,7 @@ const CDK$2 = {
121
135
  },
122
136
  DURATION: {
123
137
  EXPRESS_API: 30,
138
+ CLOUDFRONT_API: 180,
124
139
  LAMBDA_MAXIMUM: 900,
125
140
  LAMBDA_WORKER: 900,
126
141
  },
@@ -1994,10 +2009,22 @@ class JaypieDatadogForwarder extends constructs.Construct {
1994
2009
  }
1995
2010
  }
1996
2011
 
2012
+ class JaypieDatadogSecret extends JaypieEnvSecret {
2013
+ constructor(scope, id = "MongoConnectionString", props) {
2014
+ const defaultProps = {
2015
+ envKey: "DATADOG_API_KEY",
2016
+ roleTag: CDK$2.ROLE.MONITORING,
2017
+ vendorTag: CDK$2.VENDOR.DATADOG,
2018
+ ...props,
2019
+ };
2020
+ super(scope, id, defaultProps);
2021
+ }
2022
+ }
2023
+
1997
2024
  class JaypieDistribution extends constructs.Construct {
1998
2025
  constructor(scope, id, props) {
1999
2026
  super(scope, id);
2000
- const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, invokeMode = lambda__namespace.InvokeMode.BUFFERED, roleTag = CDK$2.ROLE.API, zone: propsZone, ...distributionProps } = props;
2027
+ const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, invokeMode = lambda__namespace.InvokeMode.BUFFERED, originReadTimeout = cdk.Duration.seconds(CDK$2.DURATION.CLOUDFRONT_API), roleTag = CDK$2.ROLE.API, zone: propsZone, ...distributionProps } = props;
2001
2028
  // Validate environment variables
2002
2029
  if (process.env.CDK_ENV_API_SUBDOMAIN &&
2003
2030
  !isValidSubdomain(process.env.CDK_ENV_API_SUBDOMAIN)) {
@@ -2039,18 +2066,29 @@ class JaypieDistribution extends constructs.Construct {
2039
2066
  // IFunction before IFunctionUrl (IFunction doesn't have functionUrlId)
2040
2067
  let origin;
2041
2068
  if (handler) {
2069
+ // Auto-detect invoke mode from handler (e.g., JaypieStreamingLambda)
2070
+ // Explicit invokeMode prop takes precedence over auto-detection
2071
+ const resolvedInvokeMode = invokeMode !== lambda__namespace.InvokeMode.BUFFERED
2072
+ ? invokeMode // Explicit non-default value, use it
2073
+ : this.hasInvokeMode(handler)
2074
+ ? handler.invokeMode // Auto-detect from handler
2075
+ : invokeMode; // Use default BUFFERED
2042
2076
  if (this.isIFunction(handler)) {
2043
2077
  // Create FunctionUrl for the Lambda function
2044
2078
  const functionUrl = new lambda__namespace.FunctionUrl(this, "FunctionUrl", {
2045
2079
  function: handler,
2046
2080
  authType: lambda__namespace.FunctionUrlAuthType.NONE,
2047
- invokeMode,
2081
+ invokeMode: resolvedInvokeMode,
2048
2082
  });
2049
2083
  this.functionUrl = functionUrl;
2050
- origin = new origins__namespace.FunctionUrlOrigin(functionUrl);
2084
+ origin = new origins__namespace.FunctionUrlOrigin(functionUrl, {
2085
+ readTimeout: originReadTimeout,
2086
+ });
2051
2087
  }
2052
2088
  else if (this.isIFunctionUrl(handler)) {
2053
- origin = new origins__namespace.FunctionUrlOrigin(handler);
2089
+ origin = new origins__namespace.FunctionUrlOrigin(handler, {
2090
+ readTimeout: originReadTimeout,
2091
+ });
2054
2092
  }
2055
2093
  else if (this.isIOrigin(handler)) {
2056
2094
  origin = handler;
@@ -2181,6 +2219,13 @@ class JaypieDistribution extends constructs.Construct {
2181
2219
  "functionName" in handler &&
2182
2220
  !("url" in handler));
2183
2221
  }
2222
+ hasInvokeMode(handler) {
2223
+ // Check if handler has an invokeMode property (e.g., JaypieStreamingLambda)
2224
+ return (typeof handler === "object" &&
2225
+ handler !== null &&
2226
+ "invokeMode" in handler &&
2227
+ typeof handler.invokeMode === "string");
2228
+ }
2184
2229
  // Implement IDistribution interface
2185
2230
  get env() {
2186
2231
  return {
@@ -2207,18 +2252,6 @@ class JaypieDistribution extends constructs.Construct {
2207
2252
  }
2208
2253
  }
2209
2254
 
2210
- class JaypieDatadogSecret extends JaypieEnvSecret {
2211
- constructor(scope, id = "MongoConnectionString", props) {
2212
- const defaultProps = {
2213
- envKey: "DATADOG_API_KEY",
2214
- roleTag: CDK$2.ROLE.MONITORING,
2215
- vendorTag: CDK$2.VENDOR.DATADOG,
2216
- ...props,
2217
- };
2218
- super(scope, id, defaultProps);
2219
- }
2220
- }
2221
-
2222
2255
  class JaypieDnsRecord extends constructs.Construct {
2223
2256
  constructor(scope, id, props) {
2224
2257
  super(scope, id);
@@ -2618,6 +2651,16 @@ class JaypieEventsRule extends constructs.Construct {
2618
2651
  }
2619
2652
  }
2620
2653
 
2654
+ class JaypieExpressLambda extends JaypieLambda {
2655
+ constructor(scope, id, props) {
2656
+ super(scope, id, {
2657
+ timeout: cdk.Duration.seconds(CDK$2.DURATION.EXPRESS_API),
2658
+ roleTag: CDK$2.ROLE.API,
2659
+ ...props,
2660
+ });
2661
+ }
2662
+ }
2663
+
2621
2664
  class JaypieGitHubDeployRole extends constructs.Construct {
2622
2665
  constructor(scope, id = "GitHubDeployRole", props = {}) {
2623
2666
  super(scope, id);
@@ -2700,16 +2743,6 @@ class JaypieGitHubDeployRole extends constructs.Construct {
2700
2743
  }
2701
2744
  }
2702
2745
 
2703
- class JaypieExpressLambda extends JaypieLambda {
2704
- constructor(scope, id, props) {
2705
- super(scope, id, {
2706
- timeout: cdk.Duration.seconds(CDK$2.DURATION.EXPRESS_API),
2707
- roleTag: CDK$2.ROLE.API,
2708
- ...props,
2709
- });
2710
- }
2711
- }
2712
-
2713
2746
  const SERVICE = {
2714
2747
  ROUTE53: "route53.amazonaws.com",
2715
2748
  };
@@ -3754,6 +3787,75 @@ class JaypieStaticWebBucket extends JaypieWebDeploymentBucket {
3754
3787
  }
3755
3788
  }
3756
3789
 
3790
+ /**
3791
+ * A Lambda construct that uses AWS Lambda Web Adapter for streaming support.
3792
+ * This allows running web applications (Express, Fastify, etc.) with streaming responses.
3793
+ *
3794
+ * @example
3795
+ * ```typescript
3796
+ * const streamingLambda = new JaypieStreamingLambda(this, "StreamingApi", {
3797
+ * code: "dist/api",
3798
+ * handler: "run.sh",
3799
+ * streaming: true,
3800
+ * });
3801
+ *
3802
+ * // Use with JaypieDistribution
3803
+ * new JaypieDistribution(this, "Distribution", {
3804
+ * handler: streamingLambda,
3805
+ * invokeMode: streamingLambda.invokeMode,
3806
+ * });
3807
+ * ```
3808
+ */
3809
+ class JaypieStreamingLambda extends JaypieLambda {
3810
+ constructor(scope, id, props) {
3811
+ const { architecture = lambda__namespace.Architecture.X86_64, environment: propsEnvironment, layers: propsLayers = [], port = LAMBDA_WEB_ADAPTER.DEFAULT_PORT, streaming = false, ...restProps } = props;
3812
+ // Determine the Lambda Web Adapter layer ARN based on architecture
3813
+ const region = cdk.Stack.of(scope).region;
3814
+ const layerArn = architecture === lambda__namespace.Architecture.ARM_64
3815
+ ? `arn:aws:lambda:${region}:${LAMBDA_WEB_ADAPTER.ACCOUNT}:layer:${LAMBDA_WEB_ADAPTER.LAYER.ARM64}:${LAMBDA_WEB_ADAPTER.VERSION}`
3816
+ : `arn:aws:lambda:${region}:${LAMBDA_WEB_ADAPTER.ACCOUNT}:layer:${LAMBDA_WEB_ADAPTER.LAYER.X86}:${LAMBDA_WEB_ADAPTER.VERSION}`;
3817
+ // Create the Lambda Web Adapter layer
3818
+ const webAdapterLayer = lambda__namespace.LayerVersion.fromLayerVersionArn(scope, `${id}WebAdapterLayer`, layerArn);
3819
+ // Build environment variables with Lambda Web Adapter configuration
3820
+ const lwaInvokeMode = streaming
3821
+ ? LAMBDA_WEB_ADAPTER.INVOKE_MODE.RESPONSE_STREAM
3822
+ : LAMBDA_WEB_ADAPTER.INVOKE_MODE.BUFFERED;
3823
+ const webAdapterEnvironment = {
3824
+ AWS_LAMBDA_EXEC_WRAPPER: LAMBDA_WEB_ADAPTER.EXEC_WRAPPER,
3825
+ AWS_LWA_INVOKE_MODE: lwaInvokeMode,
3826
+ PORT: String(port),
3827
+ };
3828
+ // Merge environment variables - props environment takes precedence
3829
+ let mergedEnvironment;
3830
+ if (Array.isArray(propsEnvironment)) {
3831
+ // Array syntax: prepend our object to the array
3832
+ mergedEnvironment = [webAdapterEnvironment, ...propsEnvironment];
3833
+ }
3834
+ else if (propsEnvironment && typeof propsEnvironment === "object") {
3835
+ // Object syntax: merge objects
3836
+ mergedEnvironment = {
3837
+ ...webAdapterEnvironment,
3838
+ ...propsEnvironment,
3839
+ };
3840
+ }
3841
+ else {
3842
+ mergedEnvironment = webAdapterEnvironment;
3843
+ }
3844
+ super(scope, id, {
3845
+ architecture,
3846
+ environment: mergedEnvironment,
3847
+ layers: [webAdapterLayer, ...propsLayers],
3848
+ roleTag: CDK$2.ROLE.API,
3849
+ timeout: cdk.Duration.seconds(CDK$2.DURATION.EXPRESS_API),
3850
+ ...restProps,
3851
+ });
3852
+ // Set invoke mode for use with JaypieDistribution
3853
+ this.invokeMode = streaming
3854
+ ? lambda__namespace.InvokeMode.RESPONSE_STREAM
3855
+ : lambda__namespace.InvokeMode.BUFFERED;
3856
+ }
3857
+ }
3858
+
3757
3859
  class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
3758
3860
  constructor(scope, id = "TraceSigningKey", props) {
3759
3861
  const defaultProps = {
@@ -3793,8 +3895,10 @@ exports.JaypieSsoPermissions = JaypieSsoPermissions;
3793
3895
  exports.JaypieSsoSyncApplication = JaypieSsoSyncApplication;
3794
3896
  exports.JaypieStack = JaypieStack;
3795
3897
  exports.JaypieStaticWebBucket = JaypieStaticWebBucket;
3898
+ exports.JaypieStreamingLambda = JaypieStreamingLambda;
3796
3899
  exports.JaypieTraceSigningKeySecret = JaypieTraceSigningKeySecret;
3797
3900
  exports.JaypieWebDeploymentBucket = JaypieWebDeploymentBucket;
3901
+ exports.LAMBDA_WEB_ADAPTER = LAMBDA_WEB_ADAPTER;
3798
3902
  exports.addDatadogLayers = addDatadogLayers;
3799
3903
  exports.clearAllSecretsCaches = clearAllSecretsCaches;
3800
3904
  exports.clearSecretsCache = clearSecretsCache;