@jaypie/constructs 1.2.3 → 1.2.5

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.
@@ -0,0 +1,115 @@
1
+ import { Construct } from "constructs";
2
+ import { RemovalPolicy } from "aws-cdk-lib";
3
+ import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
4
+ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "globalSecondaryIndexes" | "partitionKey" | "sortKey"> {
5
+ /**
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
10
+ */
11
+ globalSecondaryIndexes?: boolean | dynamodb.GlobalSecondaryIndexPropsV2[];
12
+ /**
13
+ * Partition key attribute definition.
14
+ * @default { name: "model", type: AttributeType.STRING }
15
+ */
16
+ partitionKey?: dynamodb.Attribute;
17
+ /**
18
+ * Optional project identifier for tagging
19
+ */
20
+ project?: string;
21
+ /**
22
+ * Optional role tag for the table
23
+ */
24
+ roleTag?: string;
25
+ /**
26
+ * Optional service identifier for tagging
27
+ */
28
+ service?: string;
29
+ /**
30
+ * Sort key attribute definition.
31
+ * @default { name: "id", type: AttributeType.STRING }
32
+ */
33
+ sortKey?: dynamodb.Attribute;
34
+ /**
35
+ * Optional vendor tag for the table
36
+ */
37
+ vendorTag?: string;
38
+ }
39
+ /**
40
+ * DynamoDB table with Jaypie single-table design patterns.
41
+ *
42
+ * Creates a table with:
43
+ * - Partition key: `model` (String)
44
+ * - Sort key: `id` (String)
45
+ * - Billing: PAY_PER_REQUEST (on-demand)
46
+ * - Removal policy: RETAIN in production, DESTROY otherwise
47
+ * - Five GSIs for different access patterns (can be overridden)
48
+ *
49
+ * @example
50
+ * // Shorthand: tableName becomes "myApp", construct id is "JaypieDynamoDb-myApp"
51
+ * const table = new JaypieDynamoDb(this, "myApp");
52
+ *
53
+ * @example
54
+ * // Full configuration
55
+ * const table = new JaypieDynamoDb(this, "MyTable", {
56
+ * tableName: "custom-table-name",
57
+ * globalSecondaryIndexes: [], // Disable GSIs
58
+ * });
59
+ *
60
+ * @example
61
+ * // Use only specific GSIs
62
+ * const table = new JaypieDynamoDb(this, "MyTable", {
63
+ * globalSecondaryIndexes: [
64
+ * JaypieDynamoDb.GlobalSecondaryIndex.Ou,
65
+ * JaypieDynamoDb.GlobalSecondaryIndex.Type,
66
+ * ],
67
+ * });
68
+ */
69
+ export declare class JaypieDynamoDb extends Construct implements dynamodb.ITableV2 {
70
+ /**
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
82
+ */
83
+ static readonly GlobalSecondaryIndexes: dynamodb.GlobalSecondaryIndexPropsV2[];
84
+ private readonly _table;
85
+ constructor(scope: Construct, id: string, props?: JaypieDynamoDbProps);
86
+ /**
87
+ * The underlying DynamoDB TableV2 construct
88
+ */
89
+ get table(): dynamodb.TableV2;
90
+ get env(): import("aws-cdk-lib").ResourceEnvironment;
91
+ get stack(): import("aws-cdk-lib").Stack;
92
+ get tableArn(): string;
93
+ get tableId(): string | undefined;
94
+ get tableName(): string;
95
+ get tableStreamArn(): string | undefined;
96
+ get encryptionKey(): import("aws-cdk-lib/aws-kms").IKey | undefined;
97
+ applyRemovalPolicy(policy: RemovalPolicy): void;
98
+ grant(grantee: import("aws-cdk-lib/aws-iam").IGrantable, ...actions: string[]): import("aws-cdk-lib/aws-iam").Grant;
99
+ grantFullAccess(grantee: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
100
+ grantReadData(grantee: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
101
+ grantReadWriteData(grantee: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
102
+ grantStream(grantee: import("aws-cdk-lib/aws-iam").IGrantable, ...actions: string[]): import("aws-cdk-lib/aws-iam").Grant;
103
+ grantStreamRead(grantee: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
104
+ grantTableListStreams(grantee: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
105
+ grantWriteData(grantee: import("aws-cdk-lib/aws-iam").IGrantable): import("aws-cdk-lib/aws-iam").Grant;
106
+ metric(metricName: string, props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
107
+ metricConditionalCheckFailedRequests(props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
108
+ metricConsumedReadCapacityUnits(props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
109
+ metricConsumedWriteCapacityUnits(props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
110
+ metricSuccessfulRequestLatency(props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
111
+ metricSystemErrorsForOperations(props?: dynamodb.SystemErrorsForOperationsMetricOptions): import("aws-cdk-lib/aws-cloudwatch").IMetric;
112
+ metricThrottledRequests(props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
113
+ metricThrottledRequestsForOperations(props?: dynamodb.OperationsMetricOptions): import("aws-cdk-lib/aws-cloudwatch").IMetric;
114
+ metricUserErrors(props?: import("aws-cdk-lib/aws-cloudwatch").MetricOptions): import("aws-cdk-lib/aws-cloudwatch").Metric;
115
+ }
@@ -20,8 +20,10 @@ export interface JaypieLambdaProps {
20
20
  description?: string;
21
21
  /**
22
22
  * DynamoDB tables to grant read/write access to the Lambda function.
23
+ * Each table is granted read/write access and if exactly one table is provided,
24
+ * the CDK_ENV_DYNAMO_TABLE environment variable is set to the table name.
23
25
  */
24
- dynamoTables?: dynamodb.ITable[];
26
+ tables?: dynamodb.ITable[];
25
27
  /**
26
28
  * Environment variables for the Lambda function.
27
29
  *
@@ -22,8 +22,10 @@ export interface JaypieNextjsProps {
22
22
  domainName?: string | DomainNameConfig;
23
23
  /**
24
24
  * DynamoDB tables to grant read/write access to the Next.js server function.
25
+ * Each table is granted read/write access and if exactly one table is provided,
26
+ * the CDK_ENV_DYNAMO_TABLE environment variable is set to the table name.
25
27
  */
26
- dynamoTables?: dynamodb.ITable[];
28
+ tables?: dynamodb.ITable[];
27
29
  /**
28
30
  * Environment variables for the Next.js application.
29
31
  *
@@ -0,0 +1 @@
1
+ export {};
@@ -21,6 +21,7 @@ var awsEvents = require('aws-cdk-lib/aws-events');
21
21
  var awsEventsTargets = require('aws-cdk-lib/aws-events-targets');
22
22
  var cloudfront = require('aws-cdk-lib/aws-cloudfront');
23
23
  var origins = require('aws-cdk-lib/aws-cloudfront-origins');
24
+ var dynamodb = require('aws-cdk-lib/aws-dynamodb');
24
25
  var cdkNextjsStandalone = require('cdk-nextjs-standalone');
25
26
  var path = require('path');
26
27
  var awsCloudtrail = require('aws-cdk-lib/aws-cloudtrail');
@@ -59,6 +60,7 @@ var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda
59
60
  var logs__namespace = /*#__PURE__*/_interopNamespaceDefault(logs);
60
61
  var cloudfront__namespace = /*#__PURE__*/_interopNamespaceDefault(cloudfront);
61
62
  var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
63
+ var dynamodb__namespace = /*#__PURE__*/_interopNamespaceDefault(dynamodb);
62
64
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
63
65
 
64
66
  const CDK$2 = {
@@ -394,10 +396,17 @@ function envHostname({ component, domain, env, subdomain, } = {}) {
394
396
  const resolvedSubdomain = providedSubdomain || process.env.CDK_ENV_SUBDOMAIN;
395
397
  const resolvedEnv = env || process.env.PROJECT_ENV;
396
398
  const filteredEnv = resolvedEnv === CDK$2.ENV.PRODUCTION ? undefined : resolvedEnv;
399
+ // Check if parts are already contained in the domain to avoid duplication
400
+ const domainParts = resolvedDomain.split(".");
401
+ const isPartInDomain = (part) => {
402
+ if (!part)
403
+ return false;
404
+ return domainParts.includes(part);
405
+ };
397
406
  const parts = [
398
- resolvedComponent,
399
- resolvedSubdomain,
400
- filteredEnv,
407
+ isPartInDomain(resolvedComponent) ? undefined : resolvedComponent,
408
+ isPartInDomain(resolvedSubdomain) ? undefined : resolvedSubdomain,
409
+ isPartInDomain(filteredEnv) ? undefined : filteredEnv,
401
410
  resolvedDomain,
402
411
  ].filter((part) => part);
403
412
  return parts.join(".");
@@ -1201,7 +1210,7 @@ class JaypieAppStack extends JaypieStack {
1201
1210
  class JaypieLambda extends constructs.Construct {
1202
1211
  constructor(scope, id, props) {
1203
1212
  super(scope, id);
1204
- const { allowAllOutbound, allowPublicSubnet, architecture = lambda__namespace.Architecture.X86_64, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, dynamoTables = [], environment: environmentInput, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], logGroup, logRetention = CDK$2.LAMBDA.LOG_RETENTION, maxEventAge, memorySize = CDK$2.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag = CDK$2.ROLE.PROCESSING, runtime = new lambda__namespace.Runtime("nodejs24.x", lambda__namespace.RuntimeFamily.NODEJS, {
1213
+ const { allowAllOutbound, allowPublicSubnet, architecture = lambda__namespace.Architecture.X86_64, code, datadogApiKeyArn, deadLetterQueue, deadLetterQueueEnabled, deadLetterTopic, description, tables = [], environment: environmentInput, envSecrets = {}, ephemeralStorageSize, filesystem, handler = "index.handler", initialPolicy, layers = [], logGroup, logRetention = CDK$2.LAMBDA.LOG_RETENTION, maxEventAge, memorySize = CDK$2.LAMBDA.MEMORY_SIZE, paramsAndSecrets, paramsAndSecretsOptions, profiling, profilingGroup, provisionedConcurrentExecutions, reservedConcurrentExecutions, retryAttempts, roleTag = CDK$2.ROLE.PROCESSING, runtime = new lambda__namespace.Runtime("nodejs24.x", lambda__namespace.RuntimeFamily.NODEJS, {
1205
1214
  supportsInlineCode: true,
1206
1215
  }), runtimeManagementMode, secrets: secretsInput = [], securityGroups, timeout = cdk.Duration.seconds(CDK$2.DURATION.LAMBDA_WORKER), tracing, vendorTag, vpc, vpcSubnets, } = props;
1207
1216
  // Resolve environment from array or object syntax
@@ -1293,12 +1302,12 @@ class JaypieLambda extends constructs.Construct {
1293
1302
  secret.grantRead(this._lambda);
1294
1303
  });
1295
1304
  // Grant read/write permissions for DynamoDB tables
1296
- dynamoTables.forEach((table) => {
1305
+ tables.forEach((table) => {
1297
1306
  table.grantReadWriteData(this._lambda);
1298
1307
  });
1299
1308
  // Add table name to environment if there's exactly one table
1300
- if (dynamoTables.length === 1) {
1301
- this._lambda.addEnvironment("CDK_ENV_DYNAMO_TABLE", dynamoTables[0].tableName);
1309
+ if (tables.length === 1) {
1310
+ this._lambda.addEnvironment("CDK_ENV_DYNAMO_TABLE", tables[0].tableName);
1302
1311
  }
1303
1312
  // Configure provisioned concurrency if specified
1304
1313
  if (provisionedConcurrentExecutions !== undefined) {
@@ -2288,6 +2297,247 @@ class JaypieDnsRecord extends constructs.Construct {
2288
2297
  }
2289
2298
  }
2290
2299
 
2300
+ //
2301
+ //
2302
+ // Constants
2303
+ //
2304
+ /**
2305
+ * GSI attribute names used in Jaypie single-table design
2306
+ */
2307
+ const GSI_NAMES = {
2308
+ ALIAS: "indexAlias",
2309
+ CLASS: "indexClass",
2310
+ OU: "indexOu",
2311
+ TYPE: "indexType",
2312
+ XID: "indexXid",
2313
+ };
2314
+ /**
2315
+ * Individual GSI definitions for Jaypie single-table design.
2316
+ * All GSIs use a string partition key and numeric sort key (sequence).
2317
+ */
2318
+ const GlobalSecondaryIndex = {
2319
+ Alias: {
2320
+ indexName: GSI_NAMES.ALIAS,
2321
+ partitionKey: {
2322
+ name: GSI_NAMES.ALIAS,
2323
+ type: dynamodb__namespace.AttributeType.STRING,
2324
+ },
2325
+ projectionType: dynamodb__namespace.ProjectionType.ALL,
2326
+ sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
2327
+ },
2328
+ Class: {
2329
+ indexName: GSI_NAMES.CLASS,
2330
+ partitionKey: {
2331
+ name: GSI_NAMES.CLASS,
2332
+ type: dynamodb__namespace.AttributeType.STRING,
2333
+ },
2334
+ projectionType: dynamodb__namespace.ProjectionType.ALL,
2335
+ sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
2336
+ },
2337
+ Ou: {
2338
+ indexName: GSI_NAMES.OU,
2339
+ partitionKey: { name: GSI_NAMES.OU, type: dynamodb__namespace.AttributeType.STRING },
2340
+ projectionType: dynamodb__namespace.ProjectionType.ALL,
2341
+ sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
2342
+ },
2343
+ Type: {
2344
+ indexName: GSI_NAMES.TYPE,
2345
+ partitionKey: { name: GSI_NAMES.TYPE, type: dynamodb__namespace.AttributeType.STRING },
2346
+ projectionType: dynamodb__namespace.ProjectionType.ALL,
2347
+ sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
2348
+ },
2349
+ Xid: {
2350
+ indexName: GSI_NAMES.XID,
2351
+ partitionKey: { name: GSI_NAMES.XID, type: dynamodb__namespace.AttributeType.STRING },
2352
+ projectionType: dynamodb__namespace.ProjectionType.ALL,
2353
+ sortKey: { name: "sequence", type: dynamodb__namespace.AttributeType.NUMBER },
2354
+ },
2355
+ };
2356
+ /**
2357
+ * Array of all default Jaypie GSI definitions.
2358
+ * Used when no globalSecondaryIndexes are provided.
2359
+ */
2360
+ const GlobalSecondaryIndexes = [
2361
+ GlobalSecondaryIndex.Alias,
2362
+ GlobalSecondaryIndex.Class,
2363
+ GlobalSecondaryIndex.Ou,
2364
+ GlobalSecondaryIndex.Type,
2365
+ GlobalSecondaryIndex.Xid,
2366
+ ];
2367
+ //
2368
+ //
2369
+ // Main
2370
+ //
2371
+ /**
2372
+ * DynamoDB table with Jaypie single-table design patterns.
2373
+ *
2374
+ * Creates a table with:
2375
+ * - Partition key: `model` (String)
2376
+ * - Sort key: `id` (String)
2377
+ * - Billing: PAY_PER_REQUEST (on-demand)
2378
+ * - Removal policy: RETAIN in production, DESTROY otherwise
2379
+ * - Five GSIs for different access patterns (can be overridden)
2380
+ *
2381
+ * @example
2382
+ * // Shorthand: tableName becomes "myApp", construct id is "JaypieDynamoDb-myApp"
2383
+ * const table = new JaypieDynamoDb(this, "myApp");
2384
+ *
2385
+ * @example
2386
+ * // Full configuration
2387
+ * const table = new JaypieDynamoDb(this, "MyTable", {
2388
+ * tableName: "custom-table-name",
2389
+ * globalSecondaryIndexes: [], // Disable GSIs
2390
+ * });
2391
+ *
2392
+ * @example
2393
+ * // Use only specific GSIs
2394
+ * const table = new JaypieDynamoDb(this, "MyTable", {
2395
+ * globalSecondaryIndexes: [
2396
+ * JaypieDynamoDb.GlobalSecondaryIndex.Ou,
2397
+ * JaypieDynamoDb.GlobalSecondaryIndex.Type,
2398
+ * ],
2399
+ * });
2400
+ */
2401
+ class JaypieDynamoDb extends constructs.Construct {
2402
+ constructor(scope, id, props = {}) {
2403
+ // Determine if this is shorthand usage: new JaypieDynamoDb(this, "myApp")
2404
+ // In shorthand, id becomes the tableName and construct id is prefixed
2405
+ const isShorthand = !props.tableName && !id.includes("-");
2406
+ const constructId = isShorthand ? `JaypieDynamoDb-${id}` : id;
2407
+ const tableName = props.tableName ?? (isShorthand ? id : undefined);
2408
+ super(scope, constructId);
2409
+ const { billing = dynamodb__namespace.Billing.onDemand(), globalSecondaryIndexes: gsiInput, partitionKey = {
2410
+ name: "model",
2411
+ type: dynamodb__namespace.AttributeType.STRING,
2412
+ }, project, removalPolicy = isProductionEnv()
2413
+ ? cdk.RemovalPolicy.RETAIN
2414
+ : cdk.RemovalPolicy.DESTROY, roleTag = CDK$2.ROLE.STORAGE, service, sortKey = { name: "id", type: dynamodb__namespace.AttributeType.STRING }, vendorTag, ...restProps } = props;
2415
+ // Resolve GSI configuration: undefined/true = all, false = none, array = use as-is
2416
+ const globalSecondaryIndexes = gsiInput === false
2417
+ ? undefined
2418
+ : Array.isArray(gsiInput)
2419
+ ? gsiInput
2420
+ : GlobalSecondaryIndexes;
2421
+ this._table = new dynamodb__namespace.TableV2(this, "Table", {
2422
+ billing,
2423
+ globalSecondaryIndexes,
2424
+ partitionKey,
2425
+ removalPolicy,
2426
+ sortKey,
2427
+ tableName,
2428
+ ...restProps,
2429
+ });
2430
+ // Apply tags
2431
+ if (project) {
2432
+ cdk.Tags.of(this._table).add(CDK$2.TAG.PROJECT, project);
2433
+ }
2434
+ cdk.Tags.of(this._table).add(CDK$2.TAG.ROLE, roleTag);
2435
+ if (service) {
2436
+ cdk.Tags.of(this._table).add(CDK$2.TAG.SERVICE, service);
2437
+ }
2438
+ if (vendorTag) {
2439
+ cdk.Tags.of(this._table).add(CDK$2.TAG.VENDOR, vendorTag);
2440
+ }
2441
+ }
2442
+ //
2443
+ //
2444
+ // Public accessors
2445
+ //
2446
+ /**
2447
+ * The underlying DynamoDB TableV2 construct
2448
+ */
2449
+ get table() {
2450
+ return this._table;
2451
+ }
2452
+ //
2453
+ //
2454
+ // ITableV2 implementation
2455
+ //
2456
+ get env() {
2457
+ return this._table.env;
2458
+ }
2459
+ get stack() {
2460
+ return this._table.stack;
2461
+ }
2462
+ get tableArn() {
2463
+ return this._table.tableArn;
2464
+ }
2465
+ get tableId() {
2466
+ return this._table.tableId;
2467
+ }
2468
+ get tableName() {
2469
+ return this._table.tableName;
2470
+ }
2471
+ get tableStreamArn() {
2472
+ return this._table.tableStreamArn;
2473
+ }
2474
+ get encryptionKey() {
2475
+ return this._table.encryptionKey;
2476
+ }
2477
+ applyRemovalPolicy(policy) {
2478
+ this._table.applyRemovalPolicy(policy);
2479
+ }
2480
+ grant(grantee, ...actions) {
2481
+ return this._table.grant(grantee, ...actions);
2482
+ }
2483
+ grantFullAccess(grantee) {
2484
+ return this._table.grantFullAccess(grantee);
2485
+ }
2486
+ grantReadData(grantee) {
2487
+ return this._table.grantReadData(grantee);
2488
+ }
2489
+ grantReadWriteData(grantee) {
2490
+ return this._table.grantReadWriteData(grantee);
2491
+ }
2492
+ grantStream(grantee, ...actions) {
2493
+ return this._table.grantStream(grantee, ...actions);
2494
+ }
2495
+ grantStreamRead(grantee) {
2496
+ return this._table.grantStreamRead(grantee);
2497
+ }
2498
+ grantTableListStreams(grantee) {
2499
+ return this._table.grantTableListStreams(grantee);
2500
+ }
2501
+ grantWriteData(grantee) {
2502
+ return this._table.grantWriteData(grantee);
2503
+ }
2504
+ metric(metricName, props) {
2505
+ return this._table.metric(metricName, props);
2506
+ }
2507
+ metricConditionalCheckFailedRequests(props) {
2508
+ return this._table.metricConditionalCheckFailedRequests(props);
2509
+ }
2510
+ metricConsumedReadCapacityUnits(props) {
2511
+ return this._table.metricConsumedReadCapacityUnits(props);
2512
+ }
2513
+ metricConsumedWriteCapacityUnits(props) {
2514
+ return this._table.metricConsumedWriteCapacityUnits(props);
2515
+ }
2516
+ metricSuccessfulRequestLatency(props) {
2517
+ return this._table.metricSuccessfulRequestLatency(props);
2518
+ }
2519
+ metricSystemErrorsForOperations(props) {
2520
+ return this._table.metricSystemErrorsForOperations(props);
2521
+ }
2522
+ metricThrottledRequests(props) {
2523
+ return this._table.metricThrottledRequests(props);
2524
+ }
2525
+ metricThrottledRequestsForOperations(props) {
2526
+ return this._table.metricThrottledRequestsForOperations(props);
2527
+ }
2528
+ metricUserErrors(props) {
2529
+ return this._table.metricUserErrors(props);
2530
+ }
2531
+ }
2532
+ /**
2533
+ * Individual GSI definitions for Jaypie single-table design
2534
+ */
2535
+ JaypieDynamoDb.GlobalSecondaryIndex = GlobalSecondaryIndex;
2536
+ /**
2537
+ * Array of all default Jaypie GSI definitions
2538
+ */
2539
+ JaypieDynamoDb.GlobalSecondaryIndexes = GlobalSecondaryIndexes;
2540
+
2291
2541
  class JaypieEventsRule extends constructs.Construct {
2292
2542
  /**
2293
2543
  * Create a new EventBridge rule that targets a Lambda function
@@ -2693,13 +2943,13 @@ class JaypieNextJs extends constructs.Construct {
2693
2943
  secret.grantRead(nextjs.serverFunction.lambdaFunction);
2694
2944
  });
2695
2945
  // Grant read/write permissions for DynamoDB tables
2696
- const dynamoTables = props?.dynamoTables || [];
2697
- dynamoTables.forEach((table) => {
2946
+ const tables = props?.tables || [];
2947
+ tables.forEach((table) => {
2698
2948
  table.grantReadWriteData(nextjs.serverFunction.lambdaFunction);
2699
2949
  });
2700
2950
  // Add table name to environment if there's exactly one table
2701
- if (dynamoTables.length === 1) {
2702
- nextjs.serverFunction.lambdaFunction.addEnvironment("CDK_ENV_DYNAMO_TABLE", dynamoTables[0].tableName);
2951
+ if (tables.length === 1) {
2952
+ nextjs.serverFunction.lambdaFunction.addEnvironment("CDK_ENV_DYNAMO_TABLE", tables[0].tableName);
2703
2953
  }
2704
2954
  // Store reference to nextjs for property exposure
2705
2955
  this._nextjs = nextjs;
@@ -3526,6 +3776,7 @@ exports.JaypieDatadogForwarder = JaypieDatadogForwarder;
3526
3776
  exports.JaypieDatadogSecret = JaypieDatadogSecret;
3527
3777
  exports.JaypieDistribution = JaypieDistribution;
3528
3778
  exports.JaypieDnsRecord = JaypieDnsRecord;
3779
+ exports.JaypieDynamoDb = JaypieDynamoDb;
3529
3780
  exports.JaypieEnvSecret = JaypieEnvSecret;
3530
3781
  exports.JaypieEventsRule = JaypieEventsRule;
3531
3782
  exports.JaypieExpressLambda = JaypieExpressLambda;