@jaypie/constructs 1.2.11 → 1.2.13
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.
- package/dist/cjs/JaypieApiGateway.d.ts +18 -1
- package/dist/cjs/JaypieDistribution.d.ts +32 -4
- package/dist/cjs/JaypieDynamoDb.d.ts +3 -3
- package/dist/cjs/JaypieNextJs.d.ts +5 -7
- package/dist/cjs/helpers/envHostname.d.ts +7 -2
- package/dist/cjs/helpers/index.d.ts +1 -1
- package/dist/cjs/index.cjs +77 -26
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/esm/JaypieApiGateway.d.ts +18 -1
- package/dist/esm/JaypieDistribution.d.ts +32 -4
- package/dist/esm/JaypieDynamoDb.d.ts +3 -3
- package/dist/esm/JaypieNextJs.d.ts +5 -7
- package/dist/esm/helpers/envHostname.d.ts +7 -2
- package/dist/esm/helpers/index.d.ts +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +77 -26
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,9 +3,26 @@ import { RemovalPolicy, Stack } from "aws-cdk-lib";
|
|
|
3
3
|
import * as acm from "aws-cdk-lib/aws-certificatemanager";
|
|
4
4
|
import * as apiGateway from "aws-cdk-lib/aws-apigateway";
|
|
5
5
|
import * as route53 from "aws-cdk-lib/aws-route53";
|
|
6
|
+
import { HostConfig } from "./helpers";
|
|
6
7
|
export interface JaypieApiGatewayProps extends apiGateway.LambdaRestApiProps {
|
|
7
8
|
certificate?: boolean | acm.ICertificate;
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The domain name for the API Gateway.
|
|
11
|
+
*
|
|
12
|
+
* Supports both string and config object:
|
|
13
|
+
* - String: used directly as the domain name (e.g., "api.example.com")
|
|
14
|
+
* - Object: passed to envHostname() to construct the domain name
|
|
15
|
+
* - { subdomain, domain, env, component }
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Direct string
|
|
19
|
+
* host: "api.example.com"
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Config object - resolves using envHostname()
|
|
23
|
+
* host: { subdomain: "api" }
|
|
24
|
+
*/
|
|
25
|
+
host?: string | HostConfig;
|
|
9
26
|
name?: string;
|
|
10
27
|
roleTag?: string;
|
|
11
28
|
zone?: string | route53.IHostedZone;
|
|
@@ -6,7 +6,8 @@ import * as route53 from "aws-cdk-lib/aws-route53";
|
|
|
6
6
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
7
7
|
import { LambdaDestination } from "aws-cdk-lib/aws-s3-notifications";
|
|
8
8
|
import { Construct } from "constructs";
|
|
9
|
-
|
|
9
|
+
import { HostConfig } from "./helpers";
|
|
10
|
+
export interface JaypieDistributionProps extends Omit<cloudfront.DistributionProps, "certificate" | "defaultBehavior" | "logBucket"> {
|
|
10
11
|
/**
|
|
11
12
|
* SSL certificate for the CloudFront distribution
|
|
12
13
|
* @default true (creates a new certificate)
|
|
@@ -20,20 +21,45 @@ export interface JaypieDistributionProps extends Omit<cloudfront.DistributionPro
|
|
|
20
21
|
* Log destination configuration for CloudFront access logs
|
|
21
22
|
* - LambdaDestination: Use a specific Lambda destination for S3 notifications
|
|
22
23
|
* - true: Use Datadog forwarder for S3 notifications (default)
|
|
23
|
-
* - false: Disable logging
|
|
24
|
+
* - false: Disable S3 notifications (logging still occurs if logBucket is set)
|
|
24
25
|
* @default true
|
|
25
26
|
*/
|
|
26
27
|
destination?: LambdaDestination | boolean;
|
|
28
|
+
/**
|
|
29
|
+
* External log bucket for CloudFront access logs.
|
|
30
|
+
* - IBucket: Use existing bucket directly
|
|
31
|
+
* - string: Bucket name to import
|
|
32
|
+
* - { exportName: string }: CloudFormation export name to import
|
|
33
|
+
* - true: Use account logging bucket (CDK.IMPORT.LOG_BUCKET)
|
|
34
|
+
* @default undefined (creates new bucket if destination !== false)
|
|
35
|
+
*/
|
|
36
|
+
logBucket?: s3.IBucket | string | {
|
|
37
|
+
exportName: string;
|
|
38
|
+
} | true;
|
|
27
39
|
/**
|
|
28
40
|
* The origin handler - can be an IOrigin, IFunctionUrl, or IFunction
|
|
29
41
|
* If IFunction, a FunctionUrl will be created with auth NONE
|
|
30
42
|
*/
|
|
31
43
|
handler?: cloudfront.IOrigin | lambda.IFunctionUrl | lambda.IFunction;
|
|
32
44
|
/**
|
|
33
|
-
* The domain name for the distribution
|
|
45
|
+
* The domain name for the distribution.
|
|
46
|
+
*
|
|
47
|
+
* Supports both string and config object:
|
|
48
|
+
* - String: used directly as the domain name (e.g., "api.example.com")
|
|
49
|
+
* - Object: passed to envHostname() to construct the domain name
|
|
50
|
+
* - { subdomain, domain, env, component }
|
|
51
|
+
*
|
|
34
52
|
* @default mergeDomain(CDK_ENV_API_SUBDOMAIN, CDK_ENV_API_HOSTED_ZONE || CDK_ENV_HOSTED_ZONE)
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Direct string
|
|
56
|
+
* host: "api.example.com"
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Config object - resolves using envHostname()
|
|
60
|
+
* host: { subdomain: "api" }
|
|
35
61
|
*/
|
|
36
|
-
host?: string;
|
|
62
|
+
host?: string | HostConfig;
|
|
37
63
|
/**
|
|
38
64
|
* Invoke mode for Lambda Function URLs.
|
|
39
65
|
* If not provided, auto-detects from handler if it has an invokeMode property
|
|
@@ -74,6 +100,8 @@ export declare class JaypieDistribution extends Construct implements cloudfront.
|
|
|
74
100
|
private isIFunctionUrl;
|
|
75
101
|
private isIFunction;
|
|
76
102
|
private hasInvokeMode;
|
|
103
|
+
private isExportNameObject;
|
|
104
|
+
private resolveLogBucket;
|
|
77
105
|
get env(): {
|
|
78
106
|
account: string;
|
|
79
107
|
region: string;
|
|
@@ -4,7 +4,7 @@ import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
|
|
|
4
4
|
export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "globalSecondaryIndexes" | "partitionKey" | "sortKey"> {
|
|
5
5
|
/**
|
|
6
6
|
* Configure GSIs for the table.
|
|
7
|
-
* - `undefined` or `true`: Creates all five Jaypie GSIs (Alias, Class,
|
|
7
|
+
* - `undefined` or `true`: Creates all five Jaypie GSIs (Alias, Class, Scope, Type, Xid)
|
|
8
8
|
* - `false`: No GSIs
|
|
9
9
|
* - Array: Use the specified GSIs
|
|
10
10
|
*/
|
|
@@ -61,7 +61,7 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
|
|
|
61
61
|
* // Use only specific GSIs
|
|
62
62
|
* const table = new JaypieDynamoDb(this, "MyTable", {
|
|
63
63
|
* globalSecondaryIndexes: [
|
|
64
|
-
* JaypieDynamoDb.GlobalSecondaryIndex.
|
|
64
|
+
* JaypieDynamoDb.GlobalSecondaryIndex.Scope,
|
|
65
65
|
* JaypieDynamoDb.GlobalSecondaryIndex.Type,
|
|
66
66
|
* ],
|
|
67
67
|
* });
|
|
@@ -73,7 +73,7 @@ export declare class JaypieDynamoDb extends Construct implements dynamodb.ITable
|
|
|
73
73
|
static readonly GlobalSecondaryIndex: {
|
|
74
74
|
readonly Alias: dynamodb.GlobalSecondaryIndexPropsV2;
|
|
75
75
|
readonly Class: dynamodb.GlobalSecondaryIndexPropsV2;
|
|
76
|
-
readonly
|
|
76
|
+
readonly Scope: dynamodb.GlobalSecondaryIndexPropsV2;
|
|
77
77
|
readonly Type: dynamodb.GlobalSecondaryIndexPropsV2;
|
|
78
78
|
readonly Xid: dynamodb.GlobalSecondaryIndexPropsV2;
|
|
79
79
|
};
|
|
@@ -2,13 +2,11 @@ import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
|
|
|
2
2
|
import { IHostedZone } from "aws-cdk-lib/aws-route53";
|
|
3
3
|
import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
|
|
4
4
|
import { Construct } from "constructs";
|
|
5
|
-
import { EnvironmentInput, SecretsArrayItem } from "./helpers";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
subdomain?: string;
|
|
11
|
-
}
|
|
5
|
+
import { EnvironmentInput, HostConfig, SecretsArrayItem } from "./helpers";
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Use HostConfig instead. This alias is kept for backwards compatibility.
|
|
8
|
+
*/
|
|
9
|
+
export type DomainNameConfig = HostConfig;
|
|
12
10
|
export interface JaypieNextjsProps {
|
|
13
11
|
datadogApiKeyArn?: string;
|
|
14
12
|
/**
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for resolving a hostname from parts.
|
|
3
|
+
* Used by envHostname() to construct domain names from environment and config.
|
|
4
|
+
*/
|
|
5
|
+
export interface HostConfig {
|
|
2
6
|
component?: string;
|
|
3
7
|
domain?: string;
|
|
4
8
|
env?: string;
|
|
5
9
|
subdomain?: string;
|
|
6
|
-
}
|
|
10
|
+
}
|
|
11
|
+
export declare function envHostname({ component, domain, env, subdomain, }?: HostConfig): string;
|
|
@@ -2,7 +2,7 @@ export { addDatadogLayers } from "./addDatadogLayers";
|
|
|
2
2
|
export { constructEnvName } from "./constructEnvName";
|
|
3
3
|
export { constructStackName } from "./constructStackName";
|
|
4
4
|
export { constructTagger } from "./constructTagger";
|
|
5
|
-
export { envHostname } from "./envHostname";
|
|
5
|
+
export { envHostname, HostConfig } from "./envHostname";
|
|
6
6
|
export { extendDatadogRole, ExtendDatadogRoleOptions, } from "./extendDatadogRole";
|
|
7
7
|
export { clearAllCertificateCaches, clearCertificateCache, resolveCertificate, ResolveCertificateOptions, } from "./resolveCertificate";
|
|
8
8
|
export { isEnv, isProductionEnv, isSandboxEnv } from "./isEnv";
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1159,15 +1159,20 @@ class JaypieApiGateway extends constructs.Construct {
|
|
|
1159
1159
|
zone = process.env.CDK_ENV_API_HOSTED_ZONE;
|
|
1160
1160
|
}
|
|
1161
1161
|
// Determine host from props or environment
|
|
1162
|
-
let host
|
|
1163
|
-
if (
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1162
|
+
let host;
|
|
1163
|
+
if (typeof propsHost === "string") {
|
|
1164
|
+
host = propsHost;
|
|
1165
|
+
}
|
|
1166
|
+
else if (typeof propsHost === "object") {
|
|
1167
|
+
// Resolve host from HostConfig using envHostname()
|
|
1168
|
+
host = envHostname(propsHost);
|
|
1169
|
+
}
|
|
1170
|
+
else if (process.env.CDK_ENV_API_HOST_NAME) {
|
|
1171
|
+
host = process.env.CDK_ENV_API_HOST_NAME;
|
|
1172
|
+
}
|
|
1173
|
+
else if (process.env.CDK_ENV_API_SUBDOMAIN &&
|
|
1174
|
+
process.env.CDK_ENV_API_HOSTED_ZONE) {
|
|
1175
|
+
host = mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE);
|
|
1171
1176
|
}
|
|
1172
1177
|
const apiGatewayName = name || constructEnvName("ApiGateway");
|
|
1173
1178
|
const apiDomainName = constructEnvName("ApiDomainName");
|
|
@@ -2357,7 +2362,7 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
|
|
|
2357
2362
|
class JaypieDistribution extends constructs.Construct {
|
|
2358
2363
|
constructor(scope, id, props) {
|
|
2359
2364
|
super(scope, id);
|
|
2360
|
-
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;
|
|
2365
|
+
const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, invokeMode = lambda__namespace.InvokeMode.BUFFERED, logBucket: logBucketProp, originReadTimeout = cdk.Duration.seconds(CDK$2.DURATION.CLOUDFRONT_API), roleTag = CDK$2.ROLE.API, zone: propsZone, ...distributionProps } = props;
|
|
2361
2366
|
// Validate environment variables
|
|
2362
2367
|
if (process.env.CDK_ENV_API_SUBDOMAIN &&
|
|
2363
2368
|
!isValidSubdomain(process.env.CDK_ENV_API_SUBDOMAIN)) {
|
|
@@ -2372,8 +2377,20 @@ class JaypieDistribution extends constructs.Construct {
|
|
|
2372
2377
|
throw new Error("CDK_ENV_HOSTED_ZONE is not a valid hostname");
|
|
2373
2378
|
}
|
|
2374
2379
|
// Determine host from props or environment
|
|
2375
|
-
let host
|
|
2376
|
-
if (
|
|
2380
|
+
let host;
|
|
2381
|
+
if (typeof propsHost === "string") {
|
|
2382
|
+
host = propsHost;
|
|
2383
|
+
}
|
|
2384
|
+
else if (typeof propsHost === "object") {
|
|
2385
|
+
// Resolve host from HostConfig using envHostname()
|
|
2386
|
+
try {
|
|
2387
|
+
host = envHostname(propsHost);
|
|
2388
|
+
}
|
|
2389
|
+
catch {
|
|
2390
|
+
host = undefined;
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
else {
|
|
2377
2394
|
try {
|
|
2378
2395
|
if (process.env.CDK_ENV_API_HOST_NAME) {
|
|
2379
2396
|
host = process.env.CDK_ENV_API_HOST_NAME;
|
|
@@ -2459,12 +2476,16 @@ class JaypieDistribution extends constructs.Construct {
|
|
|
2459
2476
|
});
|
|
2460
2477
|
this.certificate = certificateToUse;
|
|
2461
2478
|
}
|
|
2462
|
-
//
|
|
2479
|
+
// Resolve or create log bucket
|
|
2463
2480
|
let logBucket;
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2481
|
+
const isExternalBucket = logBucketProp !== undefined;
|
|
2482
|
+
if (logBucketProp !== undefined) {
|
|
2483
|
+
// Use external bucket
|
|
2484
|
+
logBucket = this.resolveLogBucket(logBucketProp);
|
|
2485
|
+
}
|
|
2486
|
+
else if (destinationProp !== false) {
|
|
2487
|
+
// Create new bucket (original behavior)
|
|
2488
|
+
const createdBucket = new s3__namespace.Bucket(this, constructEnvName("LogBucket"), {
|
|
2468
2489
|
autoDeleteObjects: true,
|
|
2469
2490
|
lifecycleRules: [
|
|
2470
2491
|
{
|
|
@@ -2477,15 +2498,21 @@ class JaypieDistribution extends constructs.Construct {
|
|
|
2477
2498
|
],
|
|
2478
2499
|
},
|
|
2479
2500
|
],
|
|
2501
|
+
objectOwnership: s3__namespace.ObjectOwnership.OBJECT_WRITER,
|
|
2502
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
2480
2503
|
});
|
|
2481
|
-
cdk.Tags.of(
|
|
2482
|
-
|
|
2504
|
+
cdk.Tags.of(createdBucket).add(CDK$2.TAG.ROLE, CDK$2.ROLE.STORAGE);
|
|
2505
|
+
logBucket = createdBucket;
|
|
2506
|
+
}
|
|
2507
|
+
// Add S3 notifications if we have a bucket and destination is not false
|
|
2508
|
+
if (logBucket && destinationProp !== false && !isExternalBucket) {
|
|
2509
|
+
// Only add notifications to buckets we created (not external buckets)
|
|
2483
2510
|
const lambdaDestination = destinationProp === true
|
|
2484
2511
|
? new s3n.LambdaDestination(resolveDatadogForwarderFunction(this))
|
|
2485
2512
|
: destinationProp;
|
|
2486
2513
|
logBucket.addEventNotification(s3__namespace.EventType.OBJECT_CREATED, lambdaDestination);
|
|
2487
|
-
this.logBucket = logBucket;
|
|
2488
2514
|
}
|
|
2515
|
+
this.logBucket = logBucket;
|
|
2489
2516
|
// Create the CloudFront distribution
|
|
2490
2517
|
this.distribution = new cloudfront__namespace.Distribution(this, constructEnvName("Distribution"), {
|
|
2491
2518
|
defaultBehavior,
|
|
@@ -2556,6 +2583,30 @@ class JaypieDistribution extends constructs.Construct {
|
|
|
2556
2583
|
"invokeMode" in handler &&
|
|
2557
2584
|
typeof handler.invokeMode === "string");
|
|
2558
2585
|
}
|
|
2586
|
+
isExportNameObject(value) {
|
|
2587
|
+
return (typeof value === "object" &&
|
|
2588
|
+
value !== null &&
|
|
2589
|
+
"exportName" in value &&
|
|
2590
|
+
typeof value.exportName === "string");
|
|
2591
|
+
}
|
|
2592
|
+
resolveLogBucket(logBucketProp) {
|
|
2593
|
+
// true = use account logging bucket
|
|
2594
|
+
if (logBucketProp === true) {
|
|
2595
|
+
const bucketName = cdk.Fn.importValue(CDK$2.IMPORT.LOG_BUCKET);
|
|
2596
|
+
return s3__namespace.Bucket.fromBucketName(this, "ImportedLogBucket", bucketName);
|
|
2597
|
+
}
|
|
2598
|
+
// { exportName: string } = import from CloudFormation export
|
|
2599
|
+
if (this.isExportNameObject(logBucketProp)) {
|
|
2600
|
+
const bucketName = cdk.Fn.importValue(logBucketProp.exportName);
|
|
2601
|
+
return s3__namespace.Bucket.fromBucketName(this, "ImportedLogBucket", bucketName);
|
|
2602
|
+
}
|
|
2603
|
+
// string = bucket name
|
|
2604
|
+
if (typeof logBucketProp === "string") {
|
|
2605
|
+
return s3__namespace.Bucket.fromBucketName(this, "ImportedLogBucket", logBucketProp);
|
|
2606
|
+
}
|
|
2607
|
+
// IBucket = use directly
|
|
2608
|
+
return logBucketProp;
|
|
2609
|
+
}
|
|
2559
2610
|
// Implement IDistribution interface
|
|
2560
2611
|
get env() {
|
|
2561
2612
|
return {
|
|
@@ -2670,7 +2721,7 @@ class JaypieDnsRecord extends constructs.Construct {
|
|
|
2670
2721
|
const GSI_NAMES = {
|
|
2671
2722
|
ALIAS: "indexAlias",
|
|
2672
2723
|
CLASS: "indexClass",
|
|
2673
|
-
|
|
2724
|
+
SCOPE: "indexScope",
|
|
2674
2725
|
TYPE: "indexType",
|
|
2675
2726
|
XID: "indexXid",
|
|
2676
2727
|
};
|
|
@@ -2697,9 +2748,9 @@ const GlobalSecondaryIndex = {
|
|
|
2697
2748
|
projectionType: dynamodb__namespace.ProjectionType.ALL,
|
|
2698
2749
|
sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
|
|
2699
2750
|
},
|
|
2700
|
-
|
|
2701
|
-
indexName: GSI_NAMES.
|
|
2702
|
-
partitionKey: { name: GSI_NAMES.
|
|
2751
|
+
Scope: {
|
|
2752
|
+
indexName: GSI_NAMES.SCOPE,
|
|
2753
|
+
partitionKey: { name: GSI_NAMES.SCOPE, type: dynamodb__namespace.AttributeType.STRING },
|
|
2703
2754
|
projectionType: dynamodb__namespace.ProjectionType.ALL,
|
|
2704
2755
|
sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
|
|
2705
2756
|
},
|
|
@@ -2723,7 +2774,7 @@ const GlobalSecondaryIndex = {
|
|
|
2723
2774
|
const GlobalSecondaryIndexes = [
|
|
2724
2775
|
GlobalSecondaryIndex.Alias,
|
|
2725
2776
|
GlobalSecondaryIndex.Class,
|
|
2726
|
-
GlobalSecondaryIndex.
|
|
2777
|
+
GlobalSecondaryIndex.Scope,
|
|
2727
2778
|
GlobalSecondaryIndex.Type,
|
|
2728
2779
|
GlobalSecondaryIndex.Xid,
|
|
2729
2780
|
];
|
|
@@ -2756,7 +2807,7 @@ const GlobalSecondaryIndexes = [
|
|
|
2756
2807
|
* // Use only specific GSIs
|
|
2757
2808
|
* const table = new JaypieDynamoDb(this, "MyTable", {
|
|
2758
2809
|
* globalSecondaryIndexes: [
|
|
2759
|
-
* JaypieDynamoDb.GlobalSecondaryIndex.
|
|
2810
|
+
* JaypieDynamoDb.GlobalSecondaryIndex.Scope,
|
|
2760
2811
|
* JaypieDynamoDb.GlobalSecondaryIndex.Type,
|
|
2761
2812
|
* ],
|
|
2762
2813
|
* });
|