@jaypie/constructs 1.2.42 → 1.2.44

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.
@@ -10,7 +10,7 @@ export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
10
10
  export { JaypieDistribution, JaypieDistributionProps, JaypieWafConfig, SecurityHeadersOverrides, } from "./JaypieDistribution";
11
11
  export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
12
12
  export { JaypieDynamoDb, JaypieDynamoDbProps } from "./JaypieDynamoDb";
13
- export type { IndexDefinition } from "@jaypie/fabric";
13
+ export type { IndexDefinition } from "./types/IndexDefinition";
14
14
  export { JaypieEnvSecret } from "./JaypieEnvSecret";
15
15
  export { JaypieEventsRule, JaypieEventsRuleProps } from "./JaypieEventsRule";
16
16
  export { JaypieExpressLambda } from "./JaypieExpressLambda";
@@ -0,0 +1,22 @@
1
+ /**
2
+ * GSI index definition for JaypieDynamoDb.
3
+ *
4
+ * Shape mirrors `@jaypie/fabric`'s IndexDefinition so a single object can be
5
+ * shared between CDK provisioning (here) and runtime model code (fabric).
6
+ * The type is owned locally so `@jaypie/constructs` does not take a runtime
7
+ * dependency on the pre-1.0 `@jaypie/fabric` package.
8
+ *
9
+ * - `pk` fields are combined with a separator to form the partition key attribute
10
+ * - `sk` with one field uses that field directly as the GSI sort key
11
+ * - `sk` with multiple fields produces a composite `{indexName}Sk` attribute
12
+ */
13
+ export interface IndexDefinition {
14
+ /** Name of the index (auto-generated from pk fields if not provided) */
15
+ name?: string;
16
+ /** Partition key fields - combined with separator */
17
+ pk: string[];
18
+ /** Sort key fields - combined with separator when composite */
19
+ sk?: string[];
20
+ /** Advisory: index key is only written when all pk/sk fields are present */
21
+ sparse?: boolean;
22
+ }
@@ -1,10 +1,10 @@
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
+ import type { IndexDefinition } from "./types/IndexDefinition";
5
5
  export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "globalSecondaryIndexes" | "partitionKey" | "sortKey"> {
6
6
  /**
7
- * Configure GSIs for the table using @jaypie/fabric IndexDefinition format.
7
+ * Configure GSIs for the table using the IndexDefinition format.
8
8
  * - `undefined`: No GSIs (default)
9
9
  * - Array of IndexDefinition: Use the specified indexes
10
10
  *
@@ -13,18 +13,18 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
13
13
  * new JaypieDynamoDb(this, "myTable");
14
14
  *
15
15
  * @example
16
- * // With custom indexes
16
+ * // Inline indexes
17
17
  * new JaypieDynamoDb(this, "myTable", {
18
18
  * indexes: [
19
- * { pk: ["scope", "model"], sk: ["sequence"] },
20
- * { pk: ["scope", "model", "type"], sk: ["sequence"], sparse: true },
19
+ * { name: "indexModel", pk: ["model"], sk: ["scope", "updatedAt"] },
20
+ * { name: "indexModelAlias", pk: ["model", "alias"], sk: ["scope", "updatedAt"], sparse: true },
21
21
  * ],
22
22
  * });
23
23
  */
24
24
  indexes?: IndexDefinition[];
25
25
  /**
26
26
  * Partition key attribute definition.
27
- * @default { name: "model", type: AttributeType.STRING }
27
+ * @default { name: "id", type: AttributeType.STRING }
28
28
  */
29
29
  partitionKey?: dynamodb.Attribute;
30
30
  /**
@@ -40,8 +40,8 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
40
40
  */
41
41
  service?: string;
42
42
  /**
43
- * Sort key attribute definition.
44
- * @default { name: "id", type: AttributeType.STRING }
43
+ * Sort key attribute definition. Defaults to `undefined` (no sort key) —
44
+ * the Jaypie single-table pattern uses `id` as a unique partition key.
45
45
  */
46
46
  sortKey?: dynamodb.Attribute;
47
47
  /**
@@ -53,8 +53,7 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
53
53
  * DynamoDB table with Jaypie single-table design patterns.
54
54
  *
55
55
  * Creates a table with:
56
- * - Partition key: `model` (String)
57
- * - Sort key: `id` (String)
56
+ * - Partition key: `id` (String), no sort key
58
57
  * - Billing: PAY_PER_REQUEST (on-demand)
59
58
  * - Removal policy: RETAIN in production, DESTROY otherwise
60
59
  * - No GSIs by default (use `indexes` prop to add them)
@@ -65,12 +64,12 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
65
64
  * const table = new JaypieDynamoDb(this, "myApp");
66
65
  *
67
66
  * @example
68
- * // With explicit table name (overrides CDK-generated name)
67
+ * // With inline IndexDefinition for GSIs
69
68
  * const table = new JaypieDynamoDb(this, "MyTable", {
70
69
  * tableName: "custom-table-name",
71
70
  * indexes: [
72
- * { pk: ["scope", "model"] },
73
- * { pk: ["scope", "model", "type"], sparse: true },
71
+ * { name: "indexModel", pk: ["model"], sk: ["scope", "updatedAt"] },
72
+ * { name: "indexModelAlias", pk: ["model", "alias"], sk: ["scope", "updatedAt"], sparse: true },
74
73
  * ],
75
74
  * });
76
75
  */
@@ -10,7 +10,7 @@ export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
10
10
  export { JaypieDistribution, JaypieDistributionProps, JaypieWafConfig, SecurityHeadersOverrides, } from "./JaypieDistribution";
11
11
  export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
12
12
  export { JaypieDynamoDb, JaypieDynamoDbProps } from "./JaypieDynamoDb";
13
- export type { IndexDefinition } from "@jaypie/fabric";
13
+ export type { IndexDefinition } from "./types/IndexDefinition";
14
14
  export { JaypieEnvSecret } from "./JaypieEnvSecret";
15
15
  export { JaypieEventsRule, JaypieEventsRuleProps } from "./JaypieEventsRule";
16
16
  export { JaypieExpressLambda } from "./JaypieExpressLambda";
package/dist/esm/index.js CHANGED
@@ -26,7 +26,6 @@ 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 wafv2 from 'aws-cdk-lib/aws-wafv2';
28
28
  import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
29
- import { generateIndexName, DEFAULT_SORT_KEY } from '@jaypie/fabric';
30
29
  import * as cr from 'aws-cdk-lib/custom-resources';
31
30
  import { Nextjs } from 'cdk-nextjs-standalone';
32
31
  import * as path from 'path';
@@ -2895,41 +2894,65 @@ class JaypieDnsRecord extends Construct {
2895
2894
  }
2896
2895
  }
2897
2896
 
2898
- //
2899
- //
2900
- // Constants
2901
- //
2902
- /** Composite key separator used in GSI partition keys */
2903
- const SEPARATOR = "#";
2904
2897
  //
2905
2898
  //
2906
2899
  // Helper Functions
2907
2900
  //
2908
2901
  /**
2909
- * Convert IndexDefinition[] from @jaypie/fabric to CDK GlobalSecondaryIndexPropsV2[]
2902
+ * Derive GSI attribute names for an index definition.
2903
+ *
2904
+ * Mirrors `@jaypie/fabric`'s `getGsiAttributeNames` so CDK provisioning and
2905
+ * any runtime write path agree on the attribute names. Kept local to avoid
2906
+ * a runtime dependency on the pre-1.0 `@jaypie/fabric` package.
2910
2907
  *
2911
- * @param indexes - Array of IndexDefinition from @jaypie/fabric
2912
- * @returns Array of CDK GlobalSecondaryIndexPropsV2
2908
+ * - `pk` is always the index name (`index.name` or generated from `index.pk`)
2909
+ * - `sk` is the single sk field name when `sk.length === 1`, or
2910
+ * `{indexName}Sk` when `sk.length > 1` (composite sk attribute)
2911
+ */
2912
+ function getGsiAttributeNames(index) {
2913
+ const name = index.name ?? generateIndexName(index.pk);
2914
+ let sk;
2915
+ if (index.sk && index.sk.length > 1) {
2916
+ sk = `${name}Sk`;
2917
+ }
2918
+ else if (index.sk && index.sk.length === 1) {
2919
+ sk = index.sk[0];
2920
+ }
2921
+ return { pk: name, sk };
2922
+ }
2923
+ function generateIndexName(pk) {
2924
+ const suffix = pk
2925
+ .map((field) => field.charAt(0).toUpperCase() + field.slice(1))
2926
+ .join("");
2927
+ return `index${suffix}`;
2928
+ }
2929
+ /**
2930
+ * Convert IndexDefinition[] to CDK GlobalSecondaryIndexPropsV2[].
2931
+ *
2932
+ * Composite sk indexes (sk.length > 1) get a dedicated STRING `{indexName}Sk`
2933
+ * attribute; single-field sk indexes reference the field directly (STRING in
2934
+ * the general case, NUMBER for the legacy `sequence` name).
2913
2935
  */
2914
2936
  function indexesToGsi(indexes) {
2915
2937
  return indexes.map((index) => {
2916
- // Generate index name from pk fields if not provided
2917
- const indexName = index.name ?? generateIndexName(index.pk);
2918
- // Sort key defaults to ["sequence"] if not provided
2919
- const skFields = index.sk ?? DEFAULT_SORT_KEY;
2938
+ const { pk, sk } = getGsiAttributeNames(index);
2939
+ let sortKey;
2940
+ if (sk) {
2941
+ if (sk === "sequence") {
2942
+ sortKey = { name: "sequence", type: dynamodb.AttributeType.NUMBER };
2943
+ }
2944
+ else {
2945
+ sortKey = { name: sk, type: dynamodb.AttributeType.STRING };
2946
+ }
2947
+ }
2920
2948
  return {
2921
- indexName,
2949
+ indexName: pk,
2922
2950
  partitionKey: {
2923
- name: indexName,
2951
+ name: pk,
2924
2952
  type: dynamodb.AttributeType.STRING,
2925
2953
  },
2926
2954
  projectionType: dynamodb.ProjectionType.ALL,
2927
- sortKey: skFields.length === 1 && skFields[0] === "sequence"
2928
- ? { name: "sequence", type: dynamodb.AttributeType.NUMBER }
2929
- : {
2930
- name: skFields.join(SEPARATOR),
2931
- type: dynamodb.AttributeType.STRING,
2932
- },
2955
+ ...(sortKey && { sortKey }),
2933
2956
  };
2934
2957
  });
2935
2958
  }
@@ -2941,8 +2964,7 @@ function indexesToGsi(indexes) {
2941
2964
  * DynamoDB table with Jaypie single-table design patterns.
2942
2965
  *
2943
2966
  * Creates a table with:
2944
- * - Partition key: `model` (String)
2945
- * - Sort key: `id` (String)
2967
+ * - Partition key: `id` (String), no sort key
2946
2968
  * - Billing: PAY_PER_REQUEST (on-demand)
2947
2969
  * - Removal policy: RETAIN in production, DESTROY otherwise
2948
2970
  * - No GSIs by default (use `indexes` prop to add them)
@@ -2953,12 +2975,12 @@ function indexesToGsi(indexes) {
2953
2975
  * const table = new JaypieDynamoDb(this, "myApp");
2954
2976
  *
2955
2977
  * @example
2956
- * // With explicit table name (overrides CDK-generated name)
2978
+ * // With inline IndexDefinition for GSIs
2957
2979
  * const table = new JaypieDynamoDb(this, "MyTable", {
2958
2980
  * tableName: "custom-table-name",
2959
2981
  * indexes: [
2960
- * { pk: ["scope", "model"] },
2961
- * { pk: ["scope", "model", "type"], sparse: true },
2982
+ * { name: "indexModel", pk: ["model"], sk: ["scope", "updatedAt"] },
2983
+ * { name: "indexModelAlias", pk: ["model", "alias"], sk: ["scope", "updatedAt"], sparse: true },
2962
2984
  * ],
2963
2985
  * });
2964
2986
  */
@@ -2971,11 +2993,11 @@ class JaypieDynamoDb extends Construct {
2971
2993
  const constructId = isShorthand ? `JaypieDynamoDb-${id}` : id;
2972
2994
  super(scope, constructId);
2973
2995
  const { billing = dynamodb.Billing.onDemand(), indexes, partitionKey = {
2974
- name: "model",
2996
+ name: "id",
2975
2997
  type: dynamodb.AttributeType.STRING,
2976
2998
  }, project, removalPolicy = isProductionEnv()
2977
2999
  ? RemovalPolicy.RETAIN
2978
- : RemovalPolicy.DESTROY, roleTag = CDK$2.ROLE.STORAGE, service, sortKey = { name: "id", type: dynamodb.AttributeType.STRING }, vendorTag, ...restProps } = props;
3000
+ : RemovalPolicy.DESTROY, roleTag = CDK$2.ROLE.STORAGE, service, sortKey, vendorTag, ...restProps } = props;
2979
3001
  // Convert IndexDefinition[] to CDK GSI props
2980
3002
  const globalSecondaryIndexes = indexes ? indexesToGsi(indexes) : undefined;
2981
3003
  this._table = new dynamodb.TableV2(this, "Table", {
@@ -2983,7 +3005,7 @@ class JaypieDynamoDb extends Construct {
2983
3005
  globalSecondaryIndexes,
2984
3006
  partitionKey,
2985
3007
  removalPolicy,
2986
- sortKey,
3008
+ ...(sortKey && { sortKey }),
2987
3009
  ...restProps,
2988
3010
  });
2989
3011
  // Apply tags