Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .projenrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,7 @@ const cli = configureProject(
'wrap-ansi@^7', // Last non-ESM version
'yaml@^1',
'yargs@^15',
'jsonschema',
],
tsconfig: {
compilerOptions: {
Expand Down
26 changes: 26 additions & 0 deletions packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES
Original file line number Diff line number Diff line change
Expand Up @@ -22580,6 +22580,32 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


----------------

** jsonschema@1.5.0 - https://www.npmjs.com/package/jsonschema/v/1.5.0 | MIT
jsonschema is licensed under MIT license.

Copyright (C) 2012-2015 Tom de Grunt <tom@degrunt.nl>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


----------------

** lazystream@1.0.1 - https://www.npmjs.com/package/lazystream/v/1.0.1 | MIT
Expand Down
4 changes: 4 additions & 0 deletions packages/aws-cdk/.projen/deps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/aws-cdk/.projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions packages/aws-cdk/THIRD_PARTY_LICENSES
Original file line number Diff line number Diff line change
Expand Up @@ -22373,6 +22373,32 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


----------------

** jsonschema@1.5.0 - https://www.npmjs.com/package/jsonschema/v/1.5.0 | MIT
jsonschema is licensed under MIT license.

Copyright (C) 2012-2015 Tom de Grunt <tom@degrunt.nl>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


----------------

** lazystream@1.0.1 - https://www.npmjs.com/package/lazystream/v/1.0.1 | MIT
Expand Down
98 changes: 98 additions & 0 deletions packages/aws-cdk/lib/cli/user-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import * as os from 'os';
import * as fs_path from 'path';
import { ToolkitError } from '@aws-cdk/toolkit-lib';
import * as fs from 'fs-extra';
import { validate } from 'jsonschema';
import { Context, PROJECT_CONTEXT } from '../api/context';
import { Settings } from '../api/settings';
import type { Tag } from '../api/tags';
import type { IoHelper } from '../api-private';
import { cdkConfigSchema } from '../schema';

export const PROJECT_CONFIG = 'cdk.json';
export { PROJECT_CONTEXT } from '../api/context';
Expand Down Expand Up @@ -210,6 +212,9 @@ async function settingsFromFile(ioHelper: IoHelper, fileName: string): Promise<S
const expanded = expandHomeDir(fileName);
if (await fs.pathExists(expanded)) {
const data = await fs.readJson(expanded);

await validateConfigurationFile(data, fileName, ioHelper);

settings = new Settings(data);
} else {
settings = new Settings();
Expand Down Expand Up @@ -408,3 +413,96 @@ async function parseStringTagsListToObject(
}
return tags.length > 0 ? tags : undefined;
}

/**
* Find similar property names to suggest corrections for typos
*/
function getTypeCorrectionHint(expectedType: string, actualValue: any): string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 is there a better way to do this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 is there a better way to do this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 is there a better way to do this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 is there a better way to do this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 what do you think? is there a better way to do this

Copy link
Copy Markdown

@we-are-the-hive we-are-the-hive May 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 The Hive Has Spoken

Question: "what do you think? is there a better way to do this"

Options considered:

  • Manual JSON Schema — Keep the current approach of manually maintaining a JSON schema file with validation logic. This provides full control over schema structure and validation messages, and the schema can be versioned alongside the codebase. It's straightforward to understand and doesn't require additional build tooling.
  • TypeScript-to-Schema Generation — Use libraries like typescript-json-schema or ts-json-schema-generator to automatically generate the JSON schema from TypeScript interfaces. Define the configuration types in TypeScript and generate the schema as a build step, ensuring type definitions and schema stay synchronized.
  • Zod Schema as Source of Truth — Define configuration using Zod schemas which provide both runtime validation and TypeScript type inference. Use zod-to-json-schema to generate JSON schema for IDE support and documentation. This keeps validation logic, types, and schema in a single source of truth with excellent error messages.
  • JSON Schema with Ajv Compilation — Use the manual JSON schema but leverage Ajv's standalone code generation to compile the schema into optimized JavaScript validation code at build time. This provides fast runtime validation without parsing the schema at startup and enables better error formatting.
  • TypeBox Schema Definition — Use TypeBox to define schemas that simultaneously generate JSON Schema and TypeScript types from a single definition. TypeBox schemas are JSON Schema compliant at runtime, eliminating the generation step while maintaining type safety. Validation can use Ajv directly with the TypeBox schemas.

Winner: Zod Schema as Source of Truth (1 round)

The hive chose Zod Schema as Source of Truth because it eliminates the maintenance burden of keeping separate JSON schema and TypeScript types in sync, while providing runtime validation, automatic type inference, and the ability to generate JSON schema on demand—all from a single authoritative source.

Debate details

Round 1: Zod Schema as Source of Truth(3) · Manual JSON Schema(1) · TypeScript-to-Schema Generation(0) · JSON Schema with Ajv Compilation(0) · TypeBox Schema Definition(0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 what do you think? is there a better way to do this

Copy link
Copy Markdown

@we-are-the-hive we-are-the-hive May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 The Hive Has Spoken

Question: "what do you think? is there a better way to do this"

Options considered:

  • Manual JSON Schema — Keep the current approach of a hand-crafted JSON schema file with validation logic in user-configuration.ts. This gives full control over the schema structure, custom error messages, and allows incremental additions without tooling dependencies. Validation is performed at config load time using a standard JSON Schema validator like ajv.
  • TypeScript-Generated Schema — Define the configuration as TypeScript interfaces/types and use a tool like ts-json-schema-generator or zod-to-json-schema to auto-generate the JSON schema from the source of truth. The generated schema is committed or produced at build time and used for runtime validation. This ensures the schema always matches the TypeScript types developers already maintain.
  • Zod Runtime Validation — Replace the JSON schema with Zod schemas defined in TypeScript that serve as both the type definition and the runtime validator. Zod provides excellent error messages, composability, and TypeScript type inference without needing a separate schema file. The .toJsonSchema() export can still produce a JSON schema for IDE autocompletion if needed.
  • Projen Schema Integration — Leverage projen's existing configuration management to generate and validate the schema as part of the project synthesis step. Define config shape in .projenrc.ts and have projen produce both the schema JSON and TypeScript validation code during npx projen, treating the schema as a managed project artifact rather than manually authored code.
  • JSON Schema from JSII — Since CDK already uses JSII for cross-language type information, extract the configuration interface from the JSII assembly or use the existing type model to generate the JSON schema automatically. This reuses the project's existing type reflection infrastructure and ensures config types stay aligned with the public API surface.

Winner: Zod Runtime Validation (1 round)

The hive chose Zod runtime validation because it allows defining the schema once in code and deriving both the JSON schema and TypeScript types from it, eliminating the maintenance burden of keeping a manually written JSON schema in sync with the validation logic and type definitions.

Debate details

Round 1: Zod Runtime Validation(9) · TypeScript-Generated Schema(3) · Projen Schema Integration(1) · Manual JSON Schema(0) · JSON Schema from JSII(0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 what do you think? is there a better way to do thi

Copy link
Copy Markdown

@we-are-the-hive we-are-the-hive May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝 The Hive Has Spoken

Question: "what do you think? is there a better way to do thi"

Options considered:

  • Manual JSON Schema — Keep the current approach of a hand-crafted JSON Schema file checked into the repository with manual validation logic. This gives full control over the schema shape, custom error messages, and allows incremental additions without tooling dependencies. Validation is implemented directly using a library like ajv against the static schema file.
  • TypeScript-Generated Schema — Use a tool like ts-json-schema-generator or typescript-json-schema to automatically derive the JSON Schema from TypeScript interfaces/types that define the CDK config structure. The schema generation becomes a build step, ensuring the schema always reflects the actual type definitions. Validation still uses ajv or similar at runtime.
  • Zod Runtime Validation — Define the config schema using Zod, which provides both runtime validation and TypeScript type inference from a single source of truth. Zod schemas can be exported as JSON Schema via zod-to-json-schema for IDE autocompletion, while the runtime validation provides rich, structured error messages out of the box.
  • JSON Schema with Codegen — Treat the JSON Schema as the canonical source and use json-schema-to-typescript (or similar) to generate TypeScript interfaces from it. This inverts the typical flow—schema-first design ensures the validation contract is always authoritative, and generated types keep code in sync. The schema file remains manually authored but is the single source of truth.
  • Projen Structured Config — Leverage projen's existing configuration management patterns to define the CDK config schema declaratively within .projenrc.ts, generating both the JSON Schema and validation code as synthesized project artifacts. This keeps schema management consistent with how the rest of the monorepo handles generated files and ensures the schema is always regenerated on npx projen.

Winner: Zod Runtime Validation (1 round)

The hive chose Zod runtime validation because it provides type-safe schema definition with automatic TypeScript type inference, eliminates the need to manually maintain a separate JSON schema file, and offers robust runtime validation with clear error messages—all while being a well-established library that reduces the risk of the hand-written schema drifting out of sync with the actual configuration interface.

Debate details

Round 1: Zod Runtime Validation(7) · JSON Schema with Codegen(3) · Projen Structured Config(2) · TypeScript-Generated Schema(1) · Manual JSON Schema(0)

if (expectedType === 'boolean' && (actualValue === 'true' || actualValue === 'false')) {
return ` (use ${actualValue} without quotes)`;
}
if (expectedType === 'string' && typeof actualValue === 'number') {
return ` (use "${actualValue}" with quotes)`;
}
return '';
}

/**
* Validates configuration data against the CDK JSON Schema and emits warnings for issues
*
* @param data - The configuration object to validate
* @param fileName - The file name for error reporting
* @param ioHelper - IoHelper for logging warnings
*/
async function validateConfigurationFile(data: any, fileName: string, ioHelper: IoHelper): Promise<void> {
try {
const schema = cdkConfigSchema;
const result = validate(data, schema);

await handleSchemaErrors(result.errors, fileName, ioHelper);

await handleUnknownProperties(data, schema, fileName, ioHelper);
} catch (error) {
await ioHelper.defaults.debug(`Schema validation failed for ${fileName}: ${error}`);
}
}

/**
* Handles schema validation errors and emits appropriate warnings
*/
async function handleSchemaErrors(errors: any[], fileName: string, ioHelper: IoHelper): Promise<void> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐝

if (!errors || errors.length === 0) {
return;
}

for (const error of errors) {
const propertyPath = error.property?.replace('instance.', '') || 'root';
const propertyName = propertyPath || 'property';

if (error.name === 'type') {
const errorSchema = error.schema as any;
const expectedType = Array.isArray(errorSchema.type)
? errorSchema.type.join(' or ')
: errorSchema.type || 'unknown';
const actualType = typeof error.instance;
const hint = getTypeCorrectionHint(expectedType, error.instance);

await ioHelper.defaults.warn(
`${fileName}: '${propertyName}' should be ${expectedType}, got ${actualType}${hint}`,
);
} else if (error.name === 'enum') {
const allowedValues = (error.schema as any).enum?.join(', ') || 'unknown';
await ioHelper.defaults.warn(
`${fileName}: '${propertyName}' must be one of: ${allowedValues}`,
);
} else if (error.name !== 'additionalProperties') {
// Generic fallback for other validation errors (skip additionalProperties as we handle those separately)
await ioHelper.defaults.warn(
`${fileName}: ${error.message}`,
);
}
}
}

/**
* Handles unknown properties
*/
async function handleUnknownProperties(
data: any,
schema: any,
fileName: string,
ioHelper: IoHelper,
): Promise<void> {
if (!data || typeof data !== 'object' || Array.isArray(data)) {
return;
}

const knownProperties = Object.keys(schema.properties || {});
const unknownProperties = Object.keys(data).filter(prop => !knownProperties.includes(prop));

for (const prop of unknownProperties) {
await ioHelper.defaults.warn(
`${fileName}: Unknown property '${prop}' (not a standard CDK property)`,
);
}
}
Loading
Loading