@intentius/chant-lexicon-aws 0.0.11 → 0.0.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/src/index.ts CHANGED
@@ -77,12 +77,12 @@ export {
77
77
  LambdaApi,
78
78
  LambdaScheduled, ScheduledLambda,
79
79
  LambdaSqs, LambdaEventBridge, LambdaDynamoDB, LambdaS3, LambdaSns,
80
- VpcDefault, FargateAlb, AlbShared, FargateService,
80
+ VpcDefault, FargateAlb, AlbShared, FargateService, RdsInstance, RdsPostgres,
81
81
  } from "./composites/index";
82
82
  export type {
83
83
  LambdaFunctionProps, LambdaApiProps, ScheduledLambdaProps,
84
84
  LambdaSqsProps, LambdaEventBridgeProps, LambdaDynamoDBProps, LambdaS3Props, LambdaSnsProps,
85
- VpcDefaultProps, FargateAlbProps, AlbSharedProps, FargateServiceProps,
85
+ VpcDefaultProps, FargateAlbProps, AlbSharedProps, FargateServiceProps, RdsInstanceProps, RdsPostgresProps,
86
86
  } from "./composites/index";
87
87
 
88
88
  // Code generation pipeline
@@ -275,6 +275,56 @@ describe("parseCFNSchema", () => {
275
275
  const result = parseCFNSchema(schema);
276
276
  expect(result.resource.conditionalCreateOnly).toEqual([]);
277
277
  });
278
+
279
+ // --- Nested readOnlyProperties ---
280
+
281
+ test("parses nested readOnlyProperties as flattened dot-separated attrs", () => {
282
+ const schema = JSON.stringify({
283
+ typeName: "AWS::RDS::DBInstance",
284
+ properties: {
285
+ DBInstanceIdentifier: { type: "string" },
286
+ Endpoint: { $ref: "#/definitions/Endpoint" },
287
+ },
288
+ definitions: {
289
+ Endpoint: {
290
+ type: "object",
291
+ properties: {
292
+ Address: { type: "string" },
293
+ Port: { type: "string" },
294
+ HostedZoneId: { type: "string" },
295
+ },
296
+ additionalProperties: false,
297
+ },
298
+ },
299
+ readOnlyProperties: [
300
+ "/properties/Endpoint",
301
+ "/properties/Endpoint/Address",
302
+ "/properties/Endpoint/Port",
303
+ "/properties/Endpoint/HostedZoneId",
304
+ "/properties/DBInstanceIdentifier",
305
+ ],
306
+ additionalProperties: false,
307
+ });
308
+ const result = parseCFNSchema(schema);
309
+
310
+ // Should have both top-level and nested attrs
311
+ const attrNames = result.resource.attributes.map((a) => a.name);
312
+ expect(attrNames).toContain("Endpoint");
313
+ expect(attrNames).toContain("Endpoint.Address");
314
+ expect(attrNames).toContain("Endpoint.Port");
315
+ expect(attrNames).toContain("Endpoint.HostedZoneId");
316
+ expect(attrNames).toContain("DBInstanceIdentifier");
317
+
318
+ // Top-level Endpoint gets its resolved type from properties
319
+ const endpoint = result.resource.attributes.find((a) => a.name === "Endpoint");
320
+ expect(endpoint!.tsType).not.toBe("string"); // Should be a $ref type
321
+
322
+ // Nested attrs are always string
323
+ const address = result.resource.attributes.find((a) => a.name === "Endpoint.Address");
324
+ expect(address!.tsType).toBe("string");
325
+ const port = result.resource.attributes.find((a) => a.name === "Endpoint.Port");
326
+ expect(port!.tsType).toBe("string");
327
+ });
278
328
  });
279
329
 
280
330
  describe("cfnShortName", () => {
package/src/spec/parse.ts CHANGED
@@ -93,15 +93,18 @@ export function parseCFNSchema(data: string | Buffer): SchemaParseResult {
93
93
  const attrs: ParsedAttribute[] = [];
94
94
  for (const path of schema.readOnlyProperties ?? []) {
95
95
  const attrName = stripPointerPath(path);
96
- // Skip nested paths (contain "/" after stripping prefix, or ".")
97
- if (attrName.includes("/") || attrName.includes(".")) continue;
98
96
 
99
- // Try to find type from properties, default to string
97
+ // Flatten nested paths: "Endpoint/Address" attr name "Endpoint.Address"
98
+ const cfnAttr = attrName.replace(/\//g, ".");
99
+
100
100
  let tsType = "string";
101
- if (schema.properties?.[attrName]) {
102
- tsType = resolvePropertyType(schema.properties[attrName], schema);
101
+ // For top-level attrs, look up type from properties
102
+ if (!cfnAttr.includes(".") && schema.properties?.[cfnAttr]) {
103
+ tsType = resolvePropertyType(schema.properties[cfnAttr], schema);
103
104
  }
104
- attrs.push({ name: attrName, tsType });
105
+ // For nested attrs, type is always string (CF GetAtt returns strings for leaf values)
106
+
107
+ attrs.push({ name: cfnAttr, tsType });
105
108
  }
106
109
 
107
110
  // Parse definitions into property types and enums
@@ -0,0 +1,34 @@
1
+ import { describe, test, expect } from "bun:test";
2
+ import { validate } from "./validate";
3
+ import { dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+
6
+ const basePath = dirname(dirname(fileURLToPath(import.meta.url)));
7
+
8
+ describe("validate", () => {
9
+ test("runs validation checks on current generated artifacts", async () => {
10
+ const result = await validate({ basePath });
11
+ expect(result.checks.length).toBeGreaterThan(0);
12
+ });
13
+
14
+ test("checks lexicon JSON exists and parses", async () => {
15
+ const result = await validate({ basePath });
16
+ const jsonCheck = result.checks.find((c) => c.name === "lexicon-json-exists");
17
+ expect(jsonCheck).toBeDefined();
18
+ expect(jsonCheck?.ok).toBe(true);
19
+ });
20
+
21
+ test("checks types exist", async () => {
22
+ const result = await validate({ basePath });
23
+ const typesCheck = result.checks.find((c) => c.name === "types-exist");
24
+ expect(typesCheck).toBeDefined();
25
+ expect(typesCheck?.ok).toBe(true);
26
+ });
27
+
28
+ test("checks required names are present", async () => {
29
+ const result = await validate({ basePath });
30
+ const requiredCheck = result.checks.find((c) => c.name === "required-names");
31
+ expect(requiredCheck).toBeDefined();
32
+ expect(requiredCheck?.ok).toBe(true);
33
+ });
34
+ });