@jaypie/constructs 1.2.12 → 1.2.14

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,6 +1,6 @@
1
- export { CDK, LAMBDA_WEB_ADAPTER } from "./constants";
1
+ export { CDK } from "./constants";
2
2
  export { JaypieAccountLoggingBucket, JaypieAccountLoggingBucketProps, } from "./JaypieAccountLoggingBucket";
3
- export { JaypieApiGateway } from "./JaypieApiGateway";
3
+ export { JaypieApiGateway, JaypieApiGatewayProps, } from "./JaypieApiGateway";
4
4
  export { JaypieAppStack } from "./JaypieAppStack";
5
5
  export { JaypieBucketQueuedLambda } from "./JaypieBucketQueuedLambda";
6
6
  export { JaypieCertificate, JaypieCertificateProps, } from "./JaypieCertificate";
@@ -10,6 +10,7 @@ export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
10
10
  export { JaypieDistribution, JaypieDistributionProps, } from "./JaypieDistribution";
11
11
  export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
12
12
  export { JaypieDynamoDb, JaypieDynamoDbProps } from "./JaypieDynamoDb";
13
+ export type { IndexDefinition } from "@jaypie/fabric";
13
14
  export { JaypieEnvSecret } from "./JaypieEnvSecret";
14
15
  export { JaypieEventsRule, JaypieEventsRuleProps } from "./JaypieEventsRule";
15
16
  export { JaypieExpressLambda } from "./JaypieExpressLambda";
@@ -26,7 +27,6 @@ export { AccountAssignments, JaypieSsoPermissions, JaypieSsoPermissionsProps, }
26
27
  export { JaypieSsoSyncApplication, JaypieSsoSyncApplicationProps, } from "./JaypieSsoSyncApplication";
27
28
  export { JaypieStack, JaypieStackProps } from "./JaypieStack";
28
29
  export { JaypieStaticWebBucket, JaypieStaticWebBucketProps, } from "./JaypieStaticWebBucket";
29
- export { JaypieStreamingLambda, JaypieStreamingLambdaProps, } from "./JaypieStreamingLambda";
30
30
  export { JaypieTraceSigningKeySecret } from "./JaypieTraceSigningKeySecret";
31
31
  export { JaypieWebDeploymentBucket } from "./JaypieWebDeploymentBucket";
32
32
  export * from "./helpers";
@@ -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
- host?: string;
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,6 +6,7 @@ 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
+ import { HostConfig } from "./helpers";
9
10
  export interface JaypieDistributionProps extends Omit<cloudfront.DistributionProps, "certificate" | "defaultBehavior" | "logBucket"> {
10
11
  /**
11
12
  * SSL certificate for the CloudFront distribution
@@ -41,15 +42,28 @@ export interface JaypieDistributionProps extends Omit<cloudfront.DistributionPro
41
42
  */
42
43
  handler?: cloudfront.IOrigin | lambda.IFunctionUrl | lambda.IFunction;
43
44
  /**
44
- * 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
+ *
45
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" }
46
61
  */
47
- host?: string;
62
+ host?: string | HostConfig;
48
63
  /**
49
64
  * Invoke mode for Lambda Function URLs.
50
- * If not provided, auto-detects from handler if it has an invokeMode property
51
- * (e.g., JaypieStreamingLambda).
52
- * @default InvokeMode.BUFFERED (or auto-detected from handler)
65
+ * Use RESPONSE_STREAM for streaming responses with createLambdaStreamHandler.
66
+ * @default InvokeMode.BUFFERED
53
67
  */
54
68
  invokeMode?: lambda.InvokeMode;
55
69
  /**
@@ -1,14 +1,35 @@
1
1
  import { Construct } from "constructs";
2
2
  import { RemovalPolicy } from "aws-cdk-lib";
3
3
  import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
4
+ import { type IndexDefinition } from "@jaypie/fabric";
4
5
  export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "globalSecondaryIndexes" | "partitionKey" | "sortKey"> {
5
6
  /**
6
- * Configure GSIs for the table.
7
- * - `undefined` or `true`: Creates all five Jaypie GSIs (Alias, Class, Ou, Type, Xid)
8
- * - `false`: No GSIs
9
- * - Array: Use the specified GSIs
7
+ * Configure GSIs for the table using @jaypie/fabric IndexDefinition format.
8
+ * - `undefined`: No GSIs (default)
9
+ * - Array of IndexDefinition: Use the specified indexes
10
+ *
11
+ * Use `JaypieDynamoDb.DEFAULT_INDEXES` for the standard Jaypie GSIs.
12
+ *
13
+ * @example
14
+ * // No GSIs (default)
15
+ * new JaypieDynamoDb(this, "myTable");
16
+ *
17
+ * @example
18
+ * // With default Jaypie indexes
19
+ * new JaypieDynamoDb(this, "myTable", {
20
+ * indexes: JaypieDynamoDb.DEFAULT_INDEXES,
21
+ * });
22
+ *
23
+ * @example
24
+ * // With custom indexes
25
+ * new JaypieDynamoDb(this, "myTable", {
26
+ * indexes: [
27
+ * { pk: ["scope", "model"], sk: ["sequence"] },
28
+ * { pk: ["scope", "model", "type"], sk: ["sequence"], sparse: true },
29
+ * ],
30
+ * });
10
31
  */
11
- globalSecondaryIndexes?: boolean | dynamodb.GlobalSecondaryIndexPropsV2[];
32
+ indexes?: IndexDefinition[];
12
33
  /**
13
34
  * Partition key attribute definition.
14
35
  * @default { name: "model", type: AttributeType.STRING }
@@ -44,43 +65,34 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
44
65
  * - Sort key: `id` (String)
45
66
  * - Billing: PAY_PER_REQUEST (on-demand)
46
67
  * - Removal policy: RETAIN in production, DESTROY otherwise
47
- * - Five GSIs for different access patterns (can be overridden)
68
+ * - No GSIs by default (use `indexes` prop to add them)
48
69
  *
49
70
  * @example
50
71
  * // Shorthand: tableName becomes "myApp", construct id is "JaypieDynamoDb-myApp"
51
72
  * const table = new JaypieDynamoDb(this, "myApp");
52
73
  *
53
74
  * @example
54
- * // Full configuration
55
- * const table = new JaypieDynamoDb(this, "MyTable", {
56
- * tableName: "custom-table-name",
57
- * globalSecondaryIndexes: [], // Disable GSIs
75
+ * // With default Jaypie indexes
76
+ * const table = new JaypieDynamoDb(this, "myApp", {
77
+ * indexes: JaypieDynamoDb.DEFAULT_INDEXES,
58
78
  * });
59
79
  *
60
80
  * @example
61
- * // Use only specific GSIs
81
+ * // With custom indexes
62
82
  * const table = new JaypieDynamoDb(this, "MyTable", {
63
- * globalSecondaryIndexes: [
64
- * JaypieDynamoDb.GlobalSecondaryIndex.Ou,
65
- * JaypieDynamoDb.GlobalSecondaryIndex.Type,
83
+ * tableName: "custom-table-name",
84
+ * indexes: [
85
+ * { pk: ["scope", "model"] },
86
+ * { pk: ["scope", "model", "type"], sparse: true },
66
87
  * ],
67
88
  * });
68
89
  */
69
90
  export declare class JaypieDynamoDb extends Construct implements dynamodb.ITableV2 {
70
91
  /**
71
- * Individual GSI definitions for Jaypie single-table design
72
- */
73
- static readonly GlobalSecondaryIndex: {
74
- readonly Alias: dynamodb.GlobalSecondaryIndexPropsV2;
75
- readonly Class: dynamodb.GlobalSecondaryIndexPropsV2;
76
- readonly Ou: dynamodb.GlobalSecondaryIndexPropsV2;
77
- readonly Type: dynamodb.GlobalSecondaryIndexPropsV2;
78
- readonly Xid: dynamodb.GlobalSecondaryIndexPropsV2;
79
- };
80
- /**
81
- * Array of all default Jaypie GSI definitions
92
+ * Default Jaypie GSI definitions from @jaypie/fabric.
93
+ * Pass to `indexes` prop to create all standard GSIs.
82
94
  */
83
- static readonly GlobalSecondaryIndexes: dynamodb.GlobalSecondaryIndexPropsV2[];
95
+ static readonly DEFAULT_INDEXES: any;
84
96
  private readonly _table;
85
97
  constructor(scope: Construct, id: string, props?: JaypieDynamoDbProps);
86
98
  /**
@@ -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
- export interface DomainNameConfig {
7
- component?: string;
8
- domain?: string;
9
- env?: string;
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,17 +1,3 @@
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
- };
15
1
  export declare const CDK: {
16
2
  ACCOUNT: {
17
3
  DEVELOPMENT: string;
@@ -1,6 +1,11 @@
1
- export declare function envHostname({ component, domain, env, subdomain, }?: {
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
- }): string;
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";
@@ -1,6 +1,6 @@
1
- export { CDK, LAMBDA_WEB_ADAPTER } from "./constants";
1
+ export { CDK } from "./constants";
2
2
  export { JaypieAccountLoggingBucket, JaypieAccountLoggingBucketProps, } from "./JaypieAccountLoggingBucket";
3
- export { JaypieApiGateway } from "./JaypieApiGateway";
3
+ export { JaypieApiGateway, JaypieApiGatewayProps, } from "./JaypieApiGateway";
4
4
  export { JaypieAppStack } from "./JaypieAppStack";
5
5
  export { JaypieBucketQueuedLambda } from "./JaypieBucketQueuedLambda";
6
6
  export { JaypieCertificate, JaypieCertificateProps, } from "./JaypieCertificate";
@@ -10,6 +10,7 @@ export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
10
10
  export { JaypieDistribution, JaypieDistributionProps, } from "./JaypieDistribution";
11
11
  export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
12
12
  export { JaypieDynamoDb, JaypieDynamoDbProps } from "./JaypieDynamoDb";
13
+ export type { IndexDefinition } from "@jaypie/fabric";
13
14
  export { JaypieEnvSecret } from "./JaypieEnvSecret";
14
15
  export { JaypieEventsRule, JaypieEventsRuleProps } from "./JaypieEventsRule";
15
16
  export { JaypieExpressLambda } from "./JaypieExpressLambda";
@@ -26,7 +27,6 @@ export { AccountAssignments, JaypieSsoPermissions, JaypieSsoPermissionsProps, }
26
27
  export { JaypieSsoSyncApplication, JaypieSsoSyncApplicationProps, } from "./JaypieSsoSyncApplication";
27
28
  export { JaypieStack, JaypieStackProps } from "./JaypieStack";
28
29
  export { JaypieStaticWebBucket, JaypieStaticWebBucketProps, } from "./JaypieStaticWebBucket";
29
- export { JaypieStreamingLambda, JaypieStreamingLambdaProps, } from "./JaypieStreamingLambda";
30
30
  export { JaypieTraceSigningKeySecret } from "./JaypieTraceSigningKeySecret";
31
31
  export { JaypieWebDeploymentBucket } from "./JaypieWebDeploymentBucket";
32
32
  export * from "./helpers";
package/dist/esm/index.js CHANGED
@@ -25,26 +25,13 @@ import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets';
25
25
  import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
26
26
  import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
27
27
  import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
28
+ import { DEFAULT_INDEXES, generateIndexName, DEFAULT_SORT_KEY } from '@jaypie/fabric';
28
29
  import { Nextjs } from 'cdk-nextjs-standalone';
29
30
  import * as path from 'path';
30
31
  import { Trail, ReadWriteType } from 'aws-cdk-lib/aws-cloudtrail';
31
32
  import { CfnPermissionSet, CfnAssignment } from 'aws-cdk-lib/aws-sso';
32
33
  import { CfnApplication } from 'aws-cdk-lib/aws-sam';
33
34
 
34
- const LAMBDA_WEB_ADAPTER = {
35
- ACCOUNT: "753240598075",
36
- DEFAULT_PORT: 8000,
37
- EXEC_WRAPPER: "/opt/bootstrap",
38
- INVOKE_MODE: {
39
- BUFFERED: "BUFFERED",
40
- RESPONSE_STREAM: "RESPONSE_STREAM",
41
- },
42
- LAYER: {
43
- ARM64: "LambdaAdapterLayerArm64",
44
- X86: "LambdaAdapterLayerX86",
45
- },
46
- VERSION: 25,
47
- };
48
35
  const CDK$2 = {
49
36
  ACCOUNT: {
50
37
  DEVELOPMENT: "development",
@@ -750,7 +737,7 @@ function resolveDatadogLayers(scope, options = {}) {
750
737
  }
751
738
  const layerIdSuffix = uniqueId || process.env.PROJECT_NONCE || Date.now().toString();
752
739
  // Create Datadog Node.js layer
753
- const datadogNodeLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `DatadogNodeLayer-${layerIdSuffix}`, `arn:aws:lambda:${resolvedRegion}:464622532012:layer:Datadog-Node20-x:${CDK$2.DATADOG.LAYER.NODE}`);
740
+ const datadogNodeLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `DatadogNodeLayer-${layerIdSuffix}`, `arn:aws:lambda:${resolvedRegion}:464622532012:layer:Datadog-Node24-x:${CDK$2.DATADOG.LAYER.NODE}`);
754
741
  // Create Datadog Extension layer
755
742
  const datadogExtensionLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `DatadogExtensionLayer-${layerIdSuffix}`, `arn:aws:lambda:${resolvedRegion}:464622532012:layer:Datadog-Extension:${CDK$2.DATADOG.LAYER.EXTENSION}`);
756
743
  return [datadogNodeLayer, datadogExtensionLayer];
@@ -1127,15 +1114,20 @@ class JaypieApiGateway extends Construct {
1127
1114
  zone = process.env.CDK_ENV_API_HOSTED_ZONE;
1128
1115
  }
1129
1116
  // Determine host from props or environment
1130
- let host = propsHost;
1131
- if (!host) {
1132
- if (process.env.CDK_ENV_API_HOST_NAME) {
1133
- host = process.env.CDK_ENV_API_HOST_NAME;
1134
- }
1135
- else if (process.env.CDK_ENV_API_SUBDOMAIN &&
1136
- process.env.CDK_ENV_API_HOSTED_ZONE) {
1137
- host = mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE);
1138
- }
1117
+ let host;
1118
+ if (typeof propsHost === "string") {
1119
+ host = propsHost;
1120
+ }
1121
+ else if (typeof propsHost === "object") {
1122
+ // Resolve host from HostConfig using envHostname()
1123
+ host = envHostname(propsHost);
1124
+ }
1125
+ else if (process.env.CDK_ENV_API_HOST_NAME) {
1126
+ host = process.env.CDK_ENV_API_HOST_NAME;
1127
+ }
1128
+ else if (process.env.CDK_ENV_API_SUBDOMAIN &&
1129
+ process.env.CDK_ENV_API_HOSTED_ZONE) {
1130
+ host = mergeDomain(process.env.CDK_ENV_API_SUBDOMAIN, process.env.CDK_ENV_API_HOSTED_ZONE);
1139
1131
  }
1140
1132
  const apiGatewayName = name || constructEnvName("ApiGateway");
1141
1133
  const apiDomainName = constructEnvName("ApiDomainName");
@@ -2340,8 +2332,20 @@ class JaypieDistribution extends Construct {
2340
2332
  throw new Error("CDK_ENV_HOSTED_ZONE is not a valid hostname");
2341
2333
  }
2342
2334
  // Determine host from props or environment
2343
- let host = propsHost;
2344
- if (!host) {
2335
+ let host;
2336
+ if (typeof propsHost === "string") {
2337
+ host = propsHost;
2338
+ }
2339
+ else if (typeof propsHost === "object") {
2340
+ // Resolve host from HostConfig using envHostname()
2341
+ try {
2342
+ host = envHostname(propsHost);
2343
+ }
2344
+ catch {
2345
+ host = undefined;
2346
+ }
2347
+ }
2348
+ else {
2345
2349
  try {
2346
2350
  if (process.env.CDK_ENV_API_HOST_NAME) {
2347
2351
  host = process.env.CDK_ENV_API_HOST_NAME;
@@ -2367,7 +2371,7 @@ class JaypieDistribution extends Construct {
2367
2371
  // IFunction before IFunctionUrl (IFunction doesn't have functionUrlId)
2368
2372
  let origin;
2369
2373
  if (handler) {
2370
- // Auto-detect invoke mode from handler (e.g., JaypieStreamingLambda)
2374
+ // Auto-detect invoke mode from handler if it has an invokeMode property
2371
2375
  // Explicit invokeMode prop takes precedence over auto-detection
2372
2376
  const resolvedInvokeMode = invokeMode !== lambda.InvokeMode.BUFFERED
2373
2377
  ? invokeMode // Explicit non-default value, use it
@@ -2528,7 +2532,7 @@ class JaypieDistribution extends Construct {
2528
2532
  !("url" in handler));
2529
2533
  }
2530
2534
  hasInvokeMode(handler) {
2531
- // Check if handler has an invokeMode property (e.g., JaypieStreamingLambda)
2535
+ // Check if handler has an invokeMode property for streaming support
2532
2536
  return (typeof handler === "object" &&
2533
2537
  handler !== null &&
2534
2538
  "invokeMode" in handler &&
@@ -2666,69 +2670,40 @@ class JaypieDnsRecord extends Construct {
2666
2670
  //
2667
2671
  // Constants
2668
2672
  //
2673
+ /** Composite key separator used in GSI partition keys */
2674
+ const SEPARATOR = "#";
2675
+ //
2676
+ //
2677
+ // Helper Functions
2678
+ //
2669
2679
  /**
2670
- * GSI attribute names used in Jaypie single-table design
2671
- */
2672
- const GSI_NAMES = {
2673
- ALIAS: "indexAlias",
2674
- CLASS: "indexClass",
2675
- OU: "indexOu",
2676
- TYPE: "indexType",
2677
- XID: "indexXid",
2678
- };
2679
- /**
2680
- * Individual GSI definitions for Jaypie single-table design.
2681
- * All GSIs use a string partition key and numeric sort key (sequence).
2682
- */
2683
- const GlobalSecondaryIndex = {
2684
- Alias: {
2685
- indexName: GSI_NAMES.ALIAS,
2686
- partitionKey: {
2687
- name: GSI_NAMES.ALIAS,
2688
- type: dynamodb.AttributeType.STRING,
2689
- },
2690
- projectionType: dynamodb.ProjectionType.ALL,
2691
- sortKey: { name: "sequence", type: dynamodb.AttributeType.NUMBER },
2692
- },
2693
- Class: {
2694
- indexName: GSI_NAMES.CLASS,
2695
- partitionKey: {
2696
- name: GSI_NAMES.CLASS,
2697
- type: dynamodb.AttributeType.STRING,
2698
- },
2699
- projectionType: dynamodb.ProjectionType.ALL,
2700
- sortKey: { name: "sequence", type: dynamodb.AttributeType.NUMBER },
2701
- },
2702
- Ou: {
2703
- indexName: GSI_NAMES.OU,
2704
- partitionKey: { name: GSI_NAMES.OU, type: dynamodb.AttributeType.STRING },
2705
- projectionType: dynamodb.ProjectionType.ALL,
2706
- sortKey: { name: "sequence", type: dynamodb.AttributeType.NUMBER },
2707
- },
2708
- Type: {
2709
- indexName: GSI_NAMES.TYPE,
2710
- partitionKey: { name: GSI_NAMES.TYPE, type: dynamodb.AttributeType.STRING },
2711
- projectionType: dynamodb.ProjectionType.ALL,
2712
- sortKey: { name: "sequence", type: dynamodb.AttributeType.NUMBER },
2713
- },
2714
- Xid: {
2715
- indexName: GSI_NAMES.XID,
2716
- partitionKey: { name: GSI_NAMES.XID, type: dynamodb.AttributeType.STRING },
2717
- projectionType: dynamodb.ProjectionType.ALL,
2718
- sortKey: { name: "sequence", type: dynamodb.AttributeType.NUMBER },
2719
- },
2720
- };
2721
- /**
2722
- * Array of all default Jaypie GSI definitions.
2723
- * Used when no globalSecondaryIndexes are provided.
2680
+ * Convert IndexDefinition[] from @jaypie/fabric to CDK GlobalSecondaryIndexPropsV2[]
2681
+ *
2682
+ * @param indexes - Array of IndexDefinition from @jaypie/fabric
2683
+ * @returns Array of CDK GlobalSecondaryIndexPropsV2
2724
2684
  */
2725
- const GlobalSecondaryIndexes = [
2726
- GlobalSecondaryIndex.Alias,
2727
- GlobalSecondaryIndex.Class,
2728
- GlobalSecondaryIndex.Ou,
2729
- GlobalSecondaryIndex.Type,
2730
- GlobalSecondaryIndex.Xid,
2731
- ];
2685
+ function indexesToGsi(indexes) {
2686
+ return indexes.map((index) => {
2687
+ // Generate index name from pk fields if not provided
2688
+ const indexName = index.name ?? generateIndexName(index.pk);
2689
+ // Sort key defaults to ["sequence"] if not provided
2690
+ const skFields = index.sk ?? DEFAULT_SORT_KEY;
2691
+ return {
2692
+ indexName,
2693
+ partitionKey: {
2694
+ name: indexName,
2695
+ type: dynamodb.AttributeType.STRING,
2696
+ },
2697
+ projectionType: dynamodb.ProjectionType.ALL,
2698
+ sortKey: skFields.length === 1 && skFields[0] === "sequence"
2699
+ ? { name: "sequence", type: dynamodb.AttributeType.NUMBER }
2700
+ : {
2701
+ name: skFields.join(SEPARATOR),
2702
+ type: dynamodb.AttributeType.STRING,
2703
+ },
2704
+ };
2705
+ });
2706
+ }
2732
2707
  //
2733
2708
  //
2734
2709
  // Main
@@ -2741,25 +2716,25 @@ const GlobalSecondaryIndexes = [
2741
2716
  * - Sort key: `id` (String)
2742
2717
  * - Billing: PAY_PER_REQUEST (on-demand)
2743
2718
  * - Removal policy: RETAIN in production, DESTROY otherwise
2744
- * - Five GSIs for different access patterns (can be overridden)
2719
+ * - No GSIs by default (use `indexes` prop to add them)
2745
2720
  *
2746
2721
  * @example
2747
2722
  * // Shorthand: tableName becomes "myApp", construct id is "JaypieDynamoDb-myApp"
2748
2723
  * const table = new JaypieDynamoDb(this, "myApp");
2749
2724
  *
2750
2725
  * @example
2751
- * // Full configuration
2752
- * const table = new JaypieDynamoDb(this, "MyTable", {
2753
- * tableName: "custom-table-name",
2754
- * globalSecondaryIndexes: [], // Disable GSIs
2726
+ * // With default Jaypie indexes
2727
+ * const table = new JaypieDynamoDb(this, "myApp", {
2728
+ * indexes: JaypieDynamoDb.DEFAULT_INDEXES,
2755
2729
  * });
2756
2730
  *
2757
2731
  * @example
2758
- * // Use only specific GSIs
2732
+ * // With custom indexes
2759
2733
  * const table = new JaypieDynamoDb(this, "MyTable", {
2760
- * globalSecondaryIndexes: [
2761
- * JaypieDynamoDb.GlobalSecondaryIndex.Ou,
2762
- * JaypieDynamoDb.GlobalSecondaryIndex.Type,
2734
+ * tableName: "custom-table-name",
2735
+ * indexes: [
2736
+ * { pk: ["scope", "model"] },
2737
+ * { pk: ["scope", "model", "type"], sparse: true },
2763
2738
  * ],
2764
2739
  * });
2765
2740
  */
@@ -2771,18 +2746,14 @@ class JaypieDynamoDb extends Construct {
2771
2746
  const constructId = isShorthand ? `JaypieDynamoDb-${id}` : id;
2772
2747
  const tableName = props.tableName ?? (isShorthand ? id : undefined);
2773
2748
  super(scope, constructId);
2774
- const { billing = dynamodb.Billing.onDemand(), globalSecondaryIndexes: gsiInput, partitionKey = {
2749
+ const { billing = dynamodb.Billing.onDemand(), indexes, partitionKey = {
2775
2750
  name: "model",
2776
2751
  type: dynamodb.AttributeType.STRING,
2777
2752
  }, project, removalPolicy = isProductionEnv()
2778
2753
  ? RemovalPolicy.RETAIN
2779
2754
  : RemovalPolicy.DESTROY, roleTag = CDK$2.ROLE.STORAGE, service, sortKey = { name: "id", type: dynamodb.AttributeType.STRING }, vendorTag, ...restProps } = props;
2780
- // Resolve GSI configuration: undefined/true = all, false = none, array = use as-is
2781
- const globalSecondaryIndexes = gsiInput === false
2782
- ? undefined
2783
- : Array.isArray(gsiInput)
2784
- ? gsiInput
2785
- : GlobalSecondaryIndexes;
2755
+ // Convert IndexDefinition[] to CDK GSI props
2756
+ const globalSecondaryIndexes = indexes ? indexesToGsi(indexes) : undefined;
2786
2757
  this._table = new dynamodb.TableV2(this, "Table", {
2787
2758
  billing,
2788
2759
  globalSecondaryIndexes,
@@ -2895,13 +2866,10 @@ class JaypieDynamoDb extends Construct {
2895
2866
  }
2896
2867
  }
2897
2868
  /**
2898
- * Individual GSI definitions for Jaypie single-table design
2869
+ * Default Jaypie GSI definitions from @jaypie/fabric.
2870
+ * Pass to `indexes` prop to create all standard GSIs.
2899
2871
  */
2900
- JaypieDynamoDb.GlobalSecondaryIndex = GlobalSecondaryIndex;
2901
- /**
2902
- * Array of all default Jaypie GSI definitions
2903
- */
2904
- JaypieDynamoDb.GlobalSecondaryIndexes = GlobalSecondaryIndexes;
2872
+ JaypieDynamoDb.DEFAULT_INDEXES = DEFAULT_INDEXES;
2905
2873
 
2906
2874
  class JaypieEventsRule extends Construct {
2907
2875
  /**
@@ -4117,75 +4085,6 @@ class JaypieStaticWebBucket extends JaypieWebDeploymentBucket {
4117
4085
  }
4118
4086
  }
4119
4087
 
4120
- /**
4121
- * A Lambda construct that uses AWS Lambda Web Adapter for streaming support.
4122
- * This allows running web applications (Express, Fastify, etc.) with streaming responses.
4123
- *
4124
- * @example
4125
- * ```typescript
4126
- * const streamingLambda = new JaypieStreamingLambda(this, "StreamingApi", {
4127
- * code: "dist/api",
4128
- * handler: "run.sh",
4129
- * streaming: true,
4130
- * });
4131
- *
4132
- * // Use with JaypieDistribution
4133
- * new JaypieDistribution(this, "Distribution", {
4134
- * handler: streamingLambda,
4135
- * invokeMode: streamingLambda.invokeMode,
4136
- * });
4137
- * ```
4138
- */
4139
- class JaypieStreamingLambda extends JaypieLambda {
4140
- constructor(scope, id, props) {
4141
- const { architecture = lambda.Architecture.X86_64, environment: propsEnvironment, layers: propsLayers = [], port = LAMBDA_WEB_ADAPTER.DEFAULT_PORT, streaming = false, ...restProps } = props;
4142
- // Determine the Lambda Web Adapter layer ARN based on architecture
4143
- const region = Stack.of(scope).region;
4144
- const layerArn = architecture === lambda.Architecture.ARM_64
4145
- ? `arn:aws:lambda:${region}:${LAMBDA_WEB_ADAPTER.ACCOUNT}:layer:${LAMBDA_WEB_ADAPTER.LAYER.ARM64}:${LAMBDA_WEB_ADAPTER.VERSION}`
4146
- : `arn:aws:lambda:${region}:${LAMBDA_WEB_ADAPTER.ACCOUNT}:layer:${LAMBDA_WEB_ADAPTER.LAYER.X86}:${LAMBDA_WEB_ADAPTER.VERSION}`;
4147
- // Create the Lambda Web Adapter layer
4148
- const webAdapterLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `${id}WebAdapterLayer`, layerArn);
4149
- // Build environment variables with Lambda Web Adapter configuration
4150
- const lwaInvokeMode = streaming
4151
- ? LAMBDA_WEB_ADAPTER.INVOKE_MODE.RESPONSE_STREAM
4152
- : LAMBDA_WEB_ADAPTER.INVOKE_MODE.BUFFERED;
4153
- const webAdapterEnvironment = {
4154
- AWS_LAMBDA_EXEC_WRAPPER: LAMBDA_WEB_ADAPTER.EXEC_WRAPPER,
4155
- AWS_LWA_INVOKE_MODE: lwaInvokeMode,
4156
- PORT: String(port),
4157
- };
4158
- // Merge environment variables - props environment takes precedence
4159
- let mergedEnvironment;
4160
- if (Array.isArray(propsEnvironment)) {
4161
- // Array syntax: prepend our object to the array
4162
- mergedEnvironment = [webAdapterEnvironment, ...propsEnvironment];
4163
- }
4164
- else if (propsEnvironment && typeof propsEnvironment === "object") {
4165
- // Object syntax: merge objects
4166
- mergedEnvironment = {
4167
- ...webAdapterEnvironment,
4168
- ...propsEnvironment,
4169
- };
4170
- }
4171
- else {
4172
- mergedEnvironment = webAdapterEnvironment;
4173
- }
4174
- super(scope, id, {
4175
- architecture,
4176
- environment: mergedEnvironment,
4177
- layers: [webAdapterLayer, ...propsLayers],
4178
- roleTag: CDK$2.ROLE.API,
4179
- timeout: Duration.seconds(CDK$2.DURATION.EXPRESS_API),
4180
- ...restProps,
4181
- });
4182
- // Set invoke mode for use with JaypieDistribution
4183
- this.invokeMode = streaming
4184
- ? lambda.InvokeMode.RESPONSE_STREAM
4185
- : lambda.InvokeMode.BUFFERED;
4186
- }
4187
- }
4188
-
4189
4088
  class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
4190
4089
  constructor(scope, id = "TraceSigningKey", props) {
4191
4090
  const defaultProps = {
@@ -4198,5 +4097,5 @@ class JaypieTraceSigningKeySecret extends JaypieEnvSecret {
4198
4097
  }
4199
4098
  }
4200
4099
 
4201
- export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieCertificate, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieDynamoDb, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieStaticWebBucket, JaypieStreamingLambda, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, LAMBDA_WEB_ADAPTER, addDatadogLayers, clearAllCertificateCaches, clearAllSecretsCaches, clearCertificateCache, clearSecretsCache, constructEnvName, constructStackName, constructTagger, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveCertificate, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveEnvironment, resolveHostedZone, resolveParamsAndSecrets, resolveSecrets };
4100
+ export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieCertificate, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieDynamoDb, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieStaticWebBucket, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, addDatadogLayers, clearAllCertificateCaches, clearAllSecretsCaches, clearCertificateCache, clearSecretsCache, constructEnvName, constructStackName, constructTagger, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveCertificate, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveEnvironment, resolveHostedZone, resolveParamsAndSecrets, resolveSecrets };
4202
4101
  //# sourceMappingURL=index.js.map