### Example: Getting Struct FQN Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Demonstrates how to create an empty struct and retrieve its fully-qualified name. ```typescript const builder = Struct.empty('org.pkg.MyStruct'); console.log(builder.fqn); // 'org.pkg.MyStruct' ``` -------------------------------- ### Complete Example: Building and Rendering TypeScript Interfaces Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/types.md Demonstrates how to use jsii-struct-builder to create custom interface specifications, build them using Struct and ProjenStruct, and render them into TypeScript code using TypeScriptRenderer. Includes setup with necessary imports and file system operations. ```typescript import { Struct, ProjenStruct, TypeScriptRenderer, TypeScriptInterfaceFile, } from '@mrgrain/jsii-struct-builder'; import { Docs, InterfaceType, Property, TypeKind, PrimitiveType, CollectionKind, } from '@jsii/spec'; import { typescript } from 'projen'; import fs from 'fs'; // Create a custom interface spec const spec: InterfaceType = { kind: TypeKind.Interface, assembly: 'my_org', fqn: 'my_org.CustomOptions', name: 'CustomOptions', docs: { summary: 'Custom options', remarks: 'These are our custom options.', }, properties: [ { name: 'enabled', type: { primitive: PrimitiveType.Boolean }, optional: true, docs: { summary: 'Enable the feature', default: 'true', }, } as Property, ], }; // Method 1: Use the builder directly const builder = Struct.fromSpec(spec) .add({ name: 'timeout', type: { primitive: PrimitiveType.Number }, optional: true, }); // Method 2: Render with TypeScriptRenderer const renderer = new TypeScriptRenderer({ indent: 2, useTypeImports: true, importLocations: { 'my_org': './', }, }); const code = renderer.renderStruct(builder); fs.writeFileSync('custom-options.ts', code); // Method 3: Use with ProjenStruct const project = new typescript.TypeScriptProject({ name: 'my-project', }); const projenStruct = new ProjenStruct(project, { name: 'ProjenOptions', docs: { summary: 'Projen-integrated options', } as Docs, fqn: 'my_org.ProjenOptions', }); projenStruct.add({ name: 'setting', type: { primitive: PrimitiveType.String }, }); ``` -------------------------------- ### Instantiate TypeScriptInterfaceFile Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Example of creating a TypeScriptInterfaceFile instance with specific rendering and file management options. ```typescript import { TypeScriptInterfaceFile } from '@mrgrain/jsii-struct-builder'; import { TypeScriptProject } from 'projen'; import type { InterfaceType } from '@jsii/spec'; const project = new TypeScriptProject({ name: 'my-project' }); const spec: InterfaceType = { /* ... */ }; new TypeScriptInterfaceFile(project, 'src/my-interface.ts', spec, { indent: 2, useTypeImports: true, importLocations: { 'my_pkg': './' }, readonly: false, }); ``` -------------------------------- ### Example Usage of Docs with ProjenStruct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/types.md Demonstrates how to use the `docs` field when creating a `ProjenStruct`. This example shows how to populate various documentation fields, including custom tags. ```typescript import { ProjenStruct } from '@mrgrain/jsii-struct-builder'; import { typescript } from 'projen'; const project = new typescript.TypeScriptProject({ name: 'my-project', }); new ProjenStruct(project, { name: 'MyOptions', docs: { summary: 'Options for MyClass', remarks: 'This is a custom options object with several configuration options.', default: 'An empty object {}', stability: 'stable', custom: { 'example': 'const opts: MyOptions = { enabled: true };', 'see': 'https://example.com/docs', }, }, }); ``` -------------------------------- ### Example: Configuring TypeScriptInterfaceFile Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/typescript-interface-file.md Demonstrates how to instantiate TypeScriptInterfaceFile with custom options for import locations, indentation, type imports, and file control. ```typescript new TypeScriptInterfaceFile(project, 'src/my-interface.ts', spec, { importLocations: { 'aws-cdk-lib': 'aws-cdk-lib', 'my_pkg': './', }, indent: 2, useTypeImports: true, readonly: false, editGithubWorkflow: true, }); ``` -------------------------------- ### Install jsii-struct-builder Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/README.md Install the package as a dev dependency using npm. ```console npm install --save-dev @mrgrain/jsii-struct-builder ``` -------------------------------- ### Minimal ProjenStruct Configuration Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Basic setup for ProjenStruct with only a name. Auto-detected imports and file path are used. ```typescript new ProjenStruct(project, { name: 'MyOptions', }); // Generated FQN: @myorg/my-project.MyOptions // Generated path: src/my-options.ts // Imports: Auto-detected ``` -------------------------------- ### Example: Iterating Struct Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Shows how to iterate over the properties of a struct and log their names and types. ```typescript const builder = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps'); builder.properties.forEach((prop) => { console.log(`${prop.name}: ${prop.type}`); }); ``` -------------------------------- ### Property and Struct Creation Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/types.md Demonstrates creating a Property object and adding it to a jsii struct using Struct.fromSpec(). ```typescript import { PrimitiveType, Property, } from '@jsii/spec'; import { Struct } from '@mrgrain/jsii-struct-builder'; const myProp: Property = { name: 'timeout', type: { primitive: PrimitiveType.Number }, optional: true, docs: { summary: 'Timeout in milliseconds', default: '5000', }, }; const struct = Struct.empty('my_pkg.Options') .add(myProp); ``` -------------------------------- ### Full Configuration for Projen Structs Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Configure a `ProjenStruct` with advanced options like description, fully qualified name (fqn), file path, and import locations. This example also demonstrates mixing in properties from another struct and applying transformations. ```typescript new ProjenStruct(project, { name: 'CustomFunctionProps', description: 'Custom Lambda function properties', fqn: 'my_org.constructs.CustomFunctionProps', filePath: 'src/constructs/custom-function-props.ts', importLocations: { 'aws-cdk-lib': 'aws-cdk-lib', 'my_org': './', }, }) .mixin(Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps')) .allOptional() .omit('code'); ``` -------------------------------- ### Example: Accessing Struct Spec Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Demonstrates how to get the InterfaceType object for a struct and access its properties like name and the count of its properties. ```typescript const builder = Struct.fromFqn('projen.typescript.TypeScriptProjectOptions'); const spec = builder.spec; console.log(spec.name); // 'TypeScriptProjectOptions' console.log(spec.properties?.length); // number of properties ``` -------------------------------- ### Fluent API Reusability Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Shows how to create multiple distinct builder chains from a single base builder instance. This promotes reusability and leverages caching for efficiency. ```typescript struct1 = base.omit(...); struct2 = base.only(...) ``` -------------------------------- ### Example: Mixing Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Demonstrates mixing properties from two existing struct definitions ('TypeScriptProjectOptions' and 'ProjectOptions') into a new struct named 'MergedOptions'. ```typescript import { Struct } from '@mrgrain/jsii-struct-builder'; const baseOptions = Struct.fromFqn('projen.typescript.TypeScriptProjectOptions'); const base2 = Struct.fromFqn('projen.ProjectOptions'); const merged = Struct.empty('my_pkg.MergedOptions') .mixin(baseOptions, base2); ``` -------------------------------- ### Example: Generated TypeScript Interface File Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/typescript-interface-file.md Shows the typical output of a generated TypeScript interface file, including a marker comment, sorted imports, and the interface definition with JSDoc. ```typescript // ~~ Generated by @mrgrain/jsii-struct-builder - DO NOT EDIT MANUALLY ~~ import type { FunctionProps } from 'aws-cdk-lib/aws-lambda'; /** * Lambda function properties with automatic code handling. * * This is a restricted version of FunctionProps where code is always provided by the construct. */ export interface MyFunctionProps { /** * The function timeout in seconds. * * @default 60 */ readonly timeout?: number; /** * Environment variables. */ readonly environment?: Record; } ``` -------------------------------- ### Project Directory Structure Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/DELIVERY_SUMMARY.md This snippet shows the directory structure of the jsii-struct-builder project's documentation output. It highlights the main README.md as the starting point and lists other key documentation files and directories. ```plaintext /workspace/home/output/ ├── README.md ← Start here ├── INDEX.md ← Navigation hub ├── quick-start.md ← Quick reference ├── module-overview.md ← Architecture ├── types.md ← Type definitions ├── configuration.md ← Configuration ├── exports.md ← All symbols ├── feature-matrix.md ← Feature reference ├── MANIFEST.txt ← Inventory ├── DELIVERY_SUMMARY.md ← This file └── api-reference/ ├── struct.md ← Core builder ├── projen-struct.md ← Projen integration ├── typescript-renderer.md ← Code generator └── typescript-interface-file.md ← File component ``` -------------------------------- ### Custom Renderer Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md Extends the TypeScriptRenderer class to implement custom logic for rendering properties. ```typescript class CustomRenderer extends TypeScriptRenderer { protected renderProperty(p: Property, containingFqn: string) { // Custom logic here super.renderProperty(p, containingFqn); } } ``` -------------------------------- ### TypeScript Renderer Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/typescript-renderer.md Demonstrates how to use the TypeScriptRenderer to create a struct and render it as a TypeScript interface. This includes adding various property types like strings, arrays, maps, and imported types. ```typescript import { TypeScriptRenderer, Struct } from '@mrgrain/jsii-struct-builder'; import { CollectionKind, PrimitiveType } from '@jsii/spec'; const struct = Struct.empty('my_pkg.ComplexExample'); struct.add( { name: 'simpleString', type: { primitive: PrimitiveType.String }, }, { name: 'arrayOfNumbers', type: { collection: { kind: CollectionKind.Array, elementtype: { primitive: PrimitiveType.Number }, }, }, }, { name: 'mapOfStrings', type: { collection: { kind: CollectionKind.Map, elementtype: { primitive: PrimitiveType.String }, }, }, }, { name: 'lambdaFunction', type: { fqn: 'aws-cdk-lib.aws_lambda.Function' }, } ); const renderer = new TypeScriptRenderer(); console.log(renderer.renderStruct(struct)); ``` -------------------------------- ### Example: Making Properties Immutable Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Demonstrates using the `map` method to iterate over all properties of a struct and set their `immutable` attribute to `true`. ```typescript const builder = Struct.fromFqn('projen.typescript.TypeScriptProjectOptions'); // Make all properties immutable builder.map((prop) => ({ ...prop, immutable: true, })); ``` -------------------------------- ### Add JSDoc to a Property Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Add documentation to individual properties, including summary, default value, remarks, and custom tags like 'example'. ```typescript builder.add({ name: 'timeout', type: { primitive: PrimitiveType.Number }, optional: true, docs: { summary: 'Timeout in milliseconds', default: '5000', remarks: 'If not specified, defaults to 5 seconds', custom: { 'example': 'timeout: 10000', }, }, }); ``` -------------------------------- ### Fluent API Chaining Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Demonstrates method chaining where all methods return `this` for a fluent interface. This allows for sequential composition of operations like adding and omitting properties. ```typescript struct.add(...).omit(...).update(...) ``` -------------------------------- ### Use Custom Props in Construct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Example of using the generated custom props interface within a construct class. It demonstrates how to import and apply the custom props. ```typescript // lib/MyFunction.ts import { Code, Function, Runtime } from 'aws-cdk-lib/aws-lambda'; import { Construct } from 'constructs'; import { join } from 'path'; import { MyFunctionProps } from './my-function-props'; export class MyFunction extends Construct { constructor(scope: Construct, id: string, props: MyFunctionProps = {}) { super(scope, id); new Function(this, 'Function', { runtime: Runtime.NODEJS_18_X, handler: 'index.handler', ...props, code: Code.fromAsset(join(__dirname, 'lambda-handler')), }); } } ``` -------------------------------- ### Custom Struct Builder Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md Extends the Struct class to create domain-specific builders with custom filtering logic. ```typescript class CdkStruct extends Struct { withoutDeprecatedAndInternal() { return this .withoutDeprecated() .filter(p => p.docs?.custom?.internal !== 'true'); } } ``` -------------------------------- ### Example: Replacing a Property Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Shows how to replace the 'timeout' property in 'FunctionProps' with a new property named 'customTimeout', changing its type and documentation. ```typescript const builder = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps'); builder.replace('timeout', { name: 'customTimeout', type: { primitive: PrimitiveType.Number }, optional: true, docs: { summary: 'Custom timeout override' }, }); ``` -------------------------------- ### TypeReference Usage Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/types.md Illustrates defining various type references for struct properties, including primitive, array, custom named, and union types. ```typescript import { CollectionKind, PrimitiveType, } from '@jsii/spec'; import { Struct } from '@mrgrain/jsii-struct-builder'; const struct = Struct.empty('my_pkg.Example'); struct.add( { name: 'simpleType', type: { primitive: PrimitiveType.String }, }, { name: 'arrayType', type: { collection: { kind: CollectionKind.Array, elementtype: { primitive: PrimitiveType.Number }, }, }, }, { name: 'customType', type: { fqn: 'my_org.CustomClass' }, }, { name: 'unionType', type: { union: { types: [ { primitive: PrimitiveType.String }, { primitive: PrimitiveType.Number }, ], }, }, } ); ``` -------------------------------- ### Resolving Assembly Not Found Errors Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Explains how to fix errors where a Fully Qualified Name (FQN) references a package that is not installed or not found in `node_modules`. ```typescript Struct.fromFqn('nonexistent_package.SomeType') // ❌ Error // Solution: Install the package // npm install nonexistent_package ``` -------------------------------- ### Example: Adding Multiple Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Illustrates adding two properties, 'timeout' and 'retries', to a new struct builder. The 'timeout' property is optional, while 'retries' is required. ```typescript import { Struct } from '@mrgrain/jsii-struct-builder'; import { PrimitiveType } from '@jsii/spec'; const builder = Struct.empty('my_pkg.MyOptions'); builder .add({ name: 'timeout', type: { primitive: PrimitiveType.Number }, optional: true, docs: { summary: 'Timeout in milliseconds' }, }) .add({ name: 'retries', type: { primitive: PrimitiveType.Number }, optional: false, docs: { summary: 'Number of retries' }, }); ``` -------------------------------- ### Custom TypeScript Code Generation with TypeScriptRenderer Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/typescript-renderer.md Shows how to use the TypeScriptRenderer directly for custom workflows, such as generating TypeScript interfaces with specific configurations like indentation, type imports, and custom import locations. This example generates a struct from a FQN and omits a specific property. ```typescript import { Struct, TypeScriptRenderer } from '@mrgrain/jsii-struct-builder'; import fs from 'fs'; const myStruct = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps') .allOptional() .omit('code'); const renderer = new TypeScriptRenderer({ indent: 2, useTypeImports: true, importLocations: { 'aws-cdk-lib': 'aws-cdk-lib', }, }); const output = renderer.renderStruct(myStruct); fs.writeFileSync('my-function-props.ts', output); ``` -------------------------------- ### Fluent API Order Independence Example Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Illustrates that the order of method calls in the fluent API does not affect the final result. Methods like `omit()` and `add()` can be composed in any sequence. ```typescript omit().add() ``` ```typescript add().omit() ``` -------------------------------- ### Instantiate ProjenStruct with Full Options Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Instantiate ProjenStruct with all available options for advanced configuration. This allows customization of documentation, FQN, file path, and import mappings. ```typescript new ProjenStruct(project, { name: 'CustomFargateServiceProps', docs: { summary: 'Props for CustomFargateService', remarks: 'This is a restricted version of aws-cdk-lib.aws_ecs.FargateServiceProps', custom: { 'internal': 'true', }, }, fqn: 'my_org.services.CustomFargateServiceProps', filePath: 'src/services/custom-fargate-service-props.ts', importLocations: { 'my_org': './', 'aws-cdk-lib': 'aws-cdk-lib', }, outputFileOptions: { readonly: false, }, }); ``` -------------------------------- ### Access Fully-Qualified Name Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Get the fully-qualified name (FQN) of the struct. ```typescript readonly fqn: string ``` -------------------------------- ### Create a Struct from Scratch Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Define a new struct with a custom FQN and add properties with specified types and optionality. This is useful for creating new configuration objects. ```typescript import { Struct } from '@mrgrain/jsii-struct-builder'; import { PrimitiveType } from '@jsii/spec'; const custom = Struct.empty('my_org.CustomOptions') .add( { name: 'enabled', type: { primitive: PrimitiveType.Boolean }, optional: true, }, { name: 'timeout', type: { primitive: PrimitiveType.Number }, optional: true, } ); ``` -------------------------------- ### Instantiate ProjenStruct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Instantiate ProjenStruct with a project and basic options. This sets up the struct file generation within the projen project. ```typescript import { ProjenStruct, } from '@mrgrain/jsii-struct-builder'; import { typescript } from 'projen'; const project = new typescript.TypeScriptProject({ name: 'my-project', // ... other config }); new ProjenStruct(project, { name: 'MyOptions', description: 'Options for MyClass', }); ``` -------------------------------- ### Minimal Projen Integration for Structs Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Set up a basic Projen project and define a jsii struct using `ProjenStruct`. This is the simplest way to integrate struct building into your Projen workflow. ```typescript import { ProjenStruct } from '@mrgrain/jsii-struct-builder'; import { typescript } from 'projen'; const project = new typescript.TypeScriptProject({ name: 'my-project', }); new ProjenStruct(project, { name: 'MyOptions', }); ``` -------------------------------- ### Transform Struct Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/INDEX.md Conditionally update properties of a jsii struct. This example adds documentation remarks based on whether a property is optional. ```typescript const transformed = Struct .fromFqn('aws-cdk-lib.aws_lambda.FunctionProps') .updateEvery((prop) => ({ docs: { remarks: prop.optional ? undefined : 'This property is required.', }, })); ``` -------------------------------- ### Configure jsii Interface Generation Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/README.md Illustrates how to configure the generation of jsii interfaces with custom fully qualified names (fqn), file paths, and import locations for complex scenarios. ```typescript new JsiiInterface(project, { name: 'MyProjectOptions', fqn: 'my_project.nested.location.MyProjectOptions', filePath: 'src/nested/my-project-options.ts', importLocations: { my_project: '../enums', }, }).add({ name: 'complexSetting', type: { fqn: 'my_project.SomeEnum' }, }); ``` -------------------------------- ### jsii-struct-builder Package Configuration Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/exports.md Defines the main entry point, type declarations, and export paths for the package. This configuration is essential for module resolution and type checking. ```json { "name": "@mrgrain/jsii-struct-builder", "main": "lib/index.js", "types": "lib/index.d.ts", "exports": { ".": { "import": "./lib/index.js", "types": "./lib/index.d.ts" } } } ``` -------------------------------- ### ProjenStructOptions Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/exports.md Configuration options for creating a ProjenStruct. ```APIDOC ## Interface: ProjenStructOptions ### Description Configuration for `ProjenStruct`. ### Fields - `name: string` - Required - The name of the struct. - `description?: string` - Optional - A description for the struct. - `docs?: Docs` - Optional - Documentation settings. - `fqn?: string` - Optional - The fully-qualified name for the struct. - `filePath?: string` - Optional - The file path where the struct definition will be placed. - `importLocations?: Record` - Optional - Custom import locations. - `outputFileOptions?: Omit` - Optional - Options for the output TypeScript file, excluding import locations. ``` -------------------------------- ### File Generation with Projen Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md This flow illustrates how the jsii-struct-builder integrates with Projen to generate TypeScript interface files. It shows the lifecycle from creating a ProjenStruct to the final file being written to disk during the Projen synthesis process. ```plaintext 1. User creates new ProjenStruct(project, options) ↓ 2. ProjenStruct.constructor() creates internal Struct ↓ 3. User calls .add(), .mixin(), etc. → delegates to internal Struct ↓ 4. projen.preSynthesize() hook triggers ProjenStruct.preSynthesize() ↓ 5. Creates TypeScriptInterfaceFile with current spec ↓ 6. TypeScriptInterfaceFile creates TextFile with rendered code ↓ 7. Projen writes file to disk during synthesis ``` -------------------------------- ### ProjenStruct with Full Docs Configuration Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Configures ProjenStruct using the 'docs' object for comprehensive JSDoc, overriding the 'description' option. ```typescript new ProjenStruct(project, { name: 'CustomFargateServiceProps', docs: { summary: 'Props for CustomFargateService', remarks: `This is a restricted version of aws-cdk-lib.aws_ecs.FargateServiceProps. The taskDefinition and desiredCount are not customizable.`, stability: 'stable', custom: { 'internal': 'true', // Renders as @internal true 'see': 'https://example.com/docs', }, }, }); ``` -------------------------------- ### Error Handling: Assembly Not Found Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Illustrates the `AggregateError` type that occurs when an assembly is not found, typically due to a missing npm package. The fix involves installing the required package. ```typescript Struct.fromFqn('nonexistent.Type') ``` -------------------------------- ### Optimization Tip: Reuse Builders Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Advises reusing builder instances that have been loaded once. This strategy leverages the caching mechanism for improved performance by avoiding repeated loading. ```typescript Load once, use multiple times ``` -------------------------------- ### Projen Integration Diagram Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md This diagram illustrates the integration of the Struct builder with Projen. It shows how Projen's TypeScriptProject utilizes ProjenStruct, which in turn wraps and uses a Struct builder. The flow extends to TypeScriptInterfaceFile and TypeScriptRenderer, highlighting the rendering process and dependencies. ```plaintext ┌──────────────────────────┐ │ TypeScriptProject │ │ (projen) │ └──────────────┬───────────┘ │ ┌────────────▼──────────┐ │ ProjenStruct │ │ (extends Component) │ └────────────┬──────────┘ │ │ wraps & uses ┌────────────▼──────────┐ │ TypeScriptInterfaceFile │ (extends TextFile) │ └────────────┬──────────┘ │ │ uses ┌────────────▼──────────┐ │ TypeScriptRenderer │ └────────────┬──────────┘ │ │ renders ┌────────────▼──────────┐ │ Struct │ │ (IStructBuilder) │ └─────────────────────┘ ``` -------------------------------- ### Complex Struct Transformation Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Perform complex transformations on a struct definition. This example removes deprecated properties, omits a specific property, and then maps over the remaining properties to make them immutable and optional. ```typescript const custom = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps') .withoutDeprecated() .omit('code') .map((prop) => ({ ...prop, immutable: true, optional: true, })); ``` -------------------------------- ### Configure Output File Options Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Use `outputFileOptions` to control the generation and management of output files. Options like `readonly` and `editGithubWorkflow` allow for integration with version control and CI/CD pipelines. ```typescript new ProjenStruct(project, { name: 'MyOptions', outputFileOptions: { readonly: false, // Allow editing editGithubWorkflow: true, // Include in workflows }, }); ``` -------------------------------- ### allOptional() Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Marks all properties as optional by setting `optional: true` on each. Returns `this` for chaining. ```APIDOC ## allOptional() ### Description Marks all properties as optional by setting `optional: true` on each. ### Method (Not specified, assumed to be a method call) ### Parameters (None) ### Request Example ```typescript const builder = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps'); builder.allOptional(); ``` ### Response #### Success Response - **this** - Returns `this` for chaining. #### Response Example (None specified) ``` -------------------------------- ### Struct.fromFqn Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Loads a jsii struct from its fully-qualified name (FQN) and creates a builder from it, optionally merging parent interface properties. ```APIDOC ## Struct.fromFqn(fqn: string, mergeParents?: boolean) ### Description Load a jsii struct from an existing fully-qualified name and create a builder from it. Automatically resolves the jsii assembly metadata. ### Method `static fromFqn` ### Parameters #### Path Parameters - **fqn** (`string`) - Required - The fully-qualified name of the jsii interface (e.g., `'projen.typescript.TypeScriptProjectOptions'`) - **mergeParents** (`boolean`) - Optional - Defaults to `true`. If `true`, inherit and merge properties from parent interfaces up the inheritance chain. ### Returns A new `Struct` instance with the loaded specification. ### Throws Aggregates errors if the assembly cannot be found in installed packages or the current working directory, or if the FQN does not resolve to an interface. ### Example ```typescript import { Struct } from '@mrgrain/jsii-struct-builder'; // Load from projen package const tsProjectOptions = Struct.fromFqn( 'projen.typescript.TypeScriptProjectOptions' ); // Load without merging parent interfaces const onlyDirect = Struct.fromFqn( 'aws-cdk-lib.aws_lambda.FunctionProps', false ); ``` ``` -------------------------------- ### Define Custom Lambda Props Struct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Example of creating a custom Lambda function props struct using ProjenStruct. It mixes in existing props, omits specific fields, and sets others to be optional. ```typescript import { ProjenStruct, Struct } from '@mrgrain/jsii-struct-builder'; import { awscdk } from 'projen'; const project = new awscdk.AwsCdkConstructLibrary({ name: 'my-constructs', // ... more config }); // Create a custom Lambda function props struct new ProjenStruct(project, { name: 'MyFunctionProps' }) .mixin(Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps')) .withoutDeprecated() .allOptional() .omit('code'); // our construct always provides code ``` -------------------------------- ### Define Custom ECS Service Props Struct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Example of creating a custom ECS service props struct. It mixes in existing props, omits specific fields, and adds a new custom field with detailed documentation. ```typescript new ProjenStruct(project, { name: 'CustomFargateServiceProps', docs: { summary: 'Props for CustomFargateService', remarks: 'FargateServiceProps without taskDefinition and desiredCount', custom: { 'internal': 'true' }, }, }) .mixin(Struct.fromFqn('aws-cdk-lib.aws_ecs.FargateServiceProps')) .omit('taskDefinition', 'desiredCount') .add({ name: 'logMappings', type: { collection: { elementtype: { fqn: 'my_constructs.LogMapping' }, kind: CollectionKind.Array, }, }, docs: { summary: 'Custom log mappings for the service', }, }); ``` -------------------------------- ### Basic ProjenStruct Initialization Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Initializes ProjenStruct with the required 'name' option for generating a TypeScript interface. ```typescript new ProjenStruct(project, { name: 'MyFunctionProps', }); ``` -------------------------------- ### Define AWS Lambda Function Props Struct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/README.md Example of creating a jsii struct for AWS Lambda Function properties, mixing in base properties, removing deprecated ones, making all optional, and omitting the 'code' property. This is useful for defining common configurations for Lambda functions. ```typescript import { ProjenStruct, Struct } from '@mrgrain/jsii-struct-builder'; import { awscdk } from 'projen'; const project = new awscdk.AwsCdkConstructLibrary({ // your config - see https://projen.io/awscdk-construct.html }); new ProjenStruct(project, { name: 'MyFunctionProps' }) .mixin(Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps')) .withoutDeprecated() .allOptional() .omit('code'); // our construct always provides the code ``` -------------------------------- ### Load Struct from FQN Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Access assembly loading functionality by using the public Struct.fromFqn() method. ```typescript Struct.fromFqn(fqn: string): Struct; ``` -------------------------------- ### Nested Module ProjenStruct Configuration Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Configuring ProjenStruct for a nested module structure, specifying documentation details, FQN, and file path. ```typescript new ProjenStruct(project, { name: 'RestApiProps', docs: { summary: 'REST API Configuration', remarks: 'Custom properties for API Gateway REST API', stability: 'stable', }, fqn: 'my_org.apis.rest.RestApiProps', filePath: 'src/apis/rest/props.ts', importLocations: { 'aws-cdk-lib': 'aws-cdk-lib', 'my_org': '../../', }, }); ``` -------------------------------- ### Instance Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Access properties of the underlying Struct builder. ```APIDOC ## Instance Properties All properties from the underlying `Struct` builder are accessible: ### `spec` ```typescript readonly spec: InterfaceType ``` The current jsii interface specification. Changes are reflected here but the file is only written during projen synthesis. --- ### `properties` ```typescript readonly properties: Property[] ``` The list of properties in the struct. --- ### `fqn` ```typescript readonly fqn: string ``` The fully-qualified name of the struct. --- ``` -------------------------------- ### Create Empty Struct Builder Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Use `empty` to initialize an empty struct builder, optionally providing a custom FQN. This is useful for constructing a struct from scratch. You can then add properties using methods like `add`. ```typescript import { Struct } from '@mrgrain/jsii-struct-builder'; import { PrimitiveType } from '@jsii/spec'; const custom = Struct.empty('my_org.custom.CustomOptions'); custom.add({ name: 'enabled', type: { primitive: PrimitiveType.Boolean }, optional: true, }); ``` -------------------------------- ### Full AWS CDK ProjenStruct Configuration Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Comprehensive configuration for ProjenStruct, including FQN, file path, import locations, and output file options for AWS CDK projects. ```typescript new ProjenStruct(project, { name: 'MyFunctionProps', description: 'Customized Lambda function properties', fqn: 'my_org.constructs.MyFunctionProps', filePath: 'src/constructs/my-function-props.ts', importLocations: { 'aws-cdk-lib': 'aws-cdk-lib', 'my_org': './', }, outputFileOptions: { readonly: false, editGithubWorkflow: true, }, }); ``` -------------------------------- ### Optimization Tip: Minimize Work with `only()` Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Recommends using the `only()` method early in the chain to minimize subsequent processing. This technique is beneficial for reducing downstream computational load. ```typescript Use `only()` early ``` -------------------------------- ### Full Imports for jsii-struct-builder and @jsii/spec Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/exports.md Comprehensive imports for various classes, interfaces, and options from '@mrgrain/jsii-struct-builder', along with type definitions from '@jsii/spec'. ```typescript import { // Classes Struct, ProjenStruct, TypeScriptRenderer, TypeScriptInterfaceFile, // Interfaces IStructBuilder, HasProperties, HasFullyQualifiedName, HasStructSpec, // Options ProjenStructOptions, TypeScriptInterfaceFileOptions, TypeScriptRendererOptions, } from '@mrgrain/jsii-struct-builder'; import type { InterfaceType, Property, TypeReference, Docs, } from '@jsii/spec'; import { TypeKind, PrimitiveType, CollectionKind, } from '@jsii/spec'; ``` -------------------------------- ### Reuse Struct Instances Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Demonstrates reusing a loaded Struct instance to create multiple variants with different mixins and omissions. ```typescript const baseProps = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps'); const variant1 = baseProps.mixin(...).omit(...); const variant2 = baseProps.mixin(...).only(...); ``` -------------------------------- ### Instance Methods Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/projen-struct.md Instance methods for manipulating struct properties, all returning `this` for chaining. ```APIDOC ## Instance Methods All instance methods return `this` for chaining and mirror the `Struct` API: ### `add(...props: Property[])` ```typescript add(...props: Property[]): this ``` Add properties to the struct. --- ### `mixin(...sources: HasProperties[])` ```typescript mixin(...sources: HasProperties[]): this ``` Mix in properties from other sources. --- ### `replace(name: string, replacement: Property)` ```typescript replace(name: string, replacement: Property): this ``` Replace an existing property. --- ### `map(callbackfn: (prop: Property) => Property)` ```typescript map(callbackfn: (prop: Property) => Property): this ``` Transform all properties. --- ### `update(name: string, update: Partial)` ```typescript update(name: string, update: Partial): this ``` Update an existing property. --- ### `updateEvery(callbackfn: (prop: Property) => Partial)` ```typescript updateEvery(callbackfn: (prop: Property) => Partial): this ``` Update all properties using a callback. --- ### `updateAll(update: Partial)` ```typescript updateAll(update: Partial): this ``` Apply an update to all properties. --- ### `rename(from: string, to: string)` ```typescript rename(from: string, to: string): this ``` Rename a property. --- ### `allOptional()` ```typescript allOptional(): this ``` Make all properties optional. --- ### `filter(predicate: (prop: Property) => boolean)` ```typescript filter(predicate: (prop: Property) => boolean): this ``` Filter properties by predicate. --- ### `only(...keep: string[])` ```typescript only(...keep: string[]): this ``` Keep only specified properties. --- ### `omit(...remove: string[])` ```typescript omit(...remove: string[]): this ``` Remove specified properties. --- ### `withoutDeprecated()` ```typescript withoutDeprecated(): this ``` Remove deprecated properties. --- ``` -------------------------------- ### Build Struct from Scratch Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Create a new struct definition using `Struct.empty()`. This is useful for defining entirely new types. ```typescript const custom = Struct.empty('org.pkg.Options') .add( { name: 'enabled', type: { primitive: PrimitiveType.Boolean } }, { name: 'timeout', type: { primitive: PrimitiveType.Number }, optional: true } ); ``` -------------------------------- ### Instance Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md These properties provide access to the current state of the struct specification. ```APIDOC ## `spec` ### Description Returns the current jsii interface specification as an `InterfaceType` object. This property reflects all accumulated changes from method calls. It creates a fresh copy each time. ### Type `InterfaceType` ### Example ```typescript const builder = Struct.fromFqn('projen.typescript.TypeScriptProjectOptions'); const spec = builder.spec; console.log(spec.name); // 'TypeScriptProjectOptions' console.log(spec.properties?.length); // number of properties ``` ``` ```APIDOC ## `properties` ### Description Returns the list of properties in the current struct specification. Equivalent to accessing `spec.properties`, but provides convenient direct access. ### Type `Property[]` ### Example ```typescript const builder = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps'); builder.properties.forEach((prop) => { console.log(`${prop.name}: ${prop.type}`); }); ``` ``` ```APIDOC ## `fqn` ### Description Returns the fully-qualified name of the struct. ### Type `string` ### Example ```typescript const builder = Struct.empty('org.pkg.MyStruct'); console.log(builder.fqn); // 'org.pkg.MyStruct' ``` ``` -------------------------------- ### Instantiate TypeScriptRenderer Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/typescript-renderer.md Create a new instance of TypeScriptRenderer with custom options for indentation and type import syntax. ```typescript import { TypeScriptRenderer } from '@mrgrain/jsii-struct-builder'; const renderer = new TypeScriptRenderer({ indent: 2, useTypeImports: true, }); ``` -------------------------------- ### Projen Integration Imports Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/exports.md Imports for ProjenStruct and Struct from '@mrgrain/jsii-struct-builder', along with projen modules and types from '@jsii/spec'. ```typescript import { ProjenStruct, Struct } from '@mrgrain/jsii-struct-builder'; import { typescript, awscdk } from 'projen'; import { CollectionKind, PrimitiveType } from '@jsii/spec'; ``` -------------------------------- ### Reading and Building Structs Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md This flow describes how a user-defined interface is loaded from a jsii assembly, wrapped into a Struct object, and how its properties are managed through various builder methods before being rendered into a spec. ```plaintext 1. User calls Struct.fromFqn('assembly.InterfaceName') ↓ 2. findInterface() loads assembly from node_modules/.jsii ↓ 3. Struct wraps InterfaceType in internal _base and _properties Map ↓ 4. User calls .omit(), .add(), .update(), etc. ↓ 5. Struct updates _properties Map ↓ 6. User calls .spec to get InterfaceType with current properties ``` -------------------------------- ### Optimization Tip: Chain Operations Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Suggests chaining method calls in sequence to perform operations in a single pass. This approach optimizes property traversal and processing. ```typescript Call methods in sequence ``` -------------------------------- ### Use Structs as Property Types Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/README.md Shows how to use Struct and ProjenStruct instances as the type for a property within another struct. ```typescript const foo = new ProjenStruct(project, { name: 'Foo' }); const bar = new ProjenStruct(project, { name: 'Bar' }); foo.add({ name: 'barSettings', type: bar, }); ``` -------------------------------- ### Handling Non-Existent Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Illustrates how to avoid errors when trying to update or modify properties that do not exist on a struct. Use `add()` to create new properties. ```typescript builder.update('nonExistent', {...}) // ❌ Error // Solution: Check what properties exist console.log(builder.properties.map(p => p.name)); // Or use add() to create new properties builder.add({name: 'newProp', type: {...}}) // ✓ OK ``` -------------------------------- ### Access Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/INDEX.md Properties to access the current specification, properties list, and the fully-qualified name (FQN) of the struct. ```APIDOC ## Access ### `spec` **Type:** `InterfaceType` **Purpose:** Get the current interface specification. ### `properties` **Type:** `Property[]` **Purpose:** Get the list of current properties. ### `fqn` **Type:** `string` **Purpose:** Get the fully-qualified name of the struct. ``` -------------------------------- ### Directly Render Struct to File Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Use this when not using projen to render a TypeScript struct definition directly to a file. Ensure the necessary types are imported. ```typescript import { Struct, TypeScriptRenderer } from '@mrgrain/jsii-struct-builder'; import fs from 'fs'; const myStruct = Struct.fromFqn('aws-cdk-lib.aws_lambda.FunctionProps') .allOptional(); const renderer = new TypeScriptRenderer({ indent: 2, useTypeImports: true, }); const code = renderer.renderStruct(myStruct); fs.writeFileSync('function-props.ts', code); ``` -------------------------------- ### Mixed Import Locations Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Demonstrates how to use `importLocations` to manage imports from various sources, including external packages, local modules, and nested directories. This allows for fine-grained control over module resolution. ```typescript new ProjenStruct(project, { name: 'MyOptions', importLocations: { 'aws-cdk-lib': '@aws-cdk/core', 'my_org': '../types', 'shared': '../../shared', }, }); ``` -------------------------------- ### TypeScriptInterfaceFileOptions Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/exports.md Configuration options for TypeScriptInterfaceFile, extending TypeScriptRendererOptions and SourceCodeOptions. ```APIDOC ## Interface: TypeScriptInterfaceFileOptions ### Description Configuration for `TypeScriptInterfaceFile`. ### Extends - `TypeScriptRendererOptions` - `SourceCodeOptions` ### Fields from TypeScriptRendererOptions - `importLocations?: Record` - Optional - Custom import locations. - `indent?: number` - Optional - The number of spaces for indentation (default: 2). - `useTypeImports?: boolean` - Optional - Whether to use type imports (default: true). ### Fields from SourceCodeOptions (projen) - `readonly?: boolean` - Optional - Whether the file should be read-only. - `editGithubWorkflow?: boolean` - Optional - Whether to edit GitHub workflow files. - `committed?: boolean` - Optional - Whether the file should be committed. ``` -------------------------------- ### Configure Projen for jsii-struct-builder Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/quick-start.md Import the ProjenStruct class into your .projenrc.ts file when using jsii-struct-builder with projen. ```typescript import { typescript } from 'projen'; import { ProjenStruct } from '@mrgrain/jsii-struct-builder'; ``` -------------------------------- ### Apply the Same Update to All Properties Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/struct.md Apply the same partial property specification to all properties. Use this for bulk modifications like marking all properties as immutable. ```typescript builder.updateAll({ immutable: true }); ``` -------------------------------- ### Manage Struct Generation Workflow with Projen Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md Utilize ProjenStruct for a complete struct generation workflow in projen. This high-level component manages file paths, imports, and synthesis. ```typescript new ProjenStruct(project, { name: 'MyOptions', // ... options }) .mixin(Struct.fromFqn(...)) .omit(...); ``` -------------------------------- ### Create Custom Options Struct Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/INDEX.md Defines a completely custom options struct with specified properties and their types. Use this when no existing struct can be mixed in. ```typescript Struct.empty('my_org.CustomOptions') .add( { name: 'enabled', type: { primitive: PrimitiveType.Boolean } }, { name: 'timeout', type: { primitive: PrimitiveType.Number } } ); ``` -------------------------------- ### ProjenStruct with File Path Option Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/configuration.md Sets a custom output file path for the generated TypeScript interface, overriding the default auto-generation logic. ```typescript new ProjenStruct(project, { name: 'MyOptions', filePath: 'src/custom/my-options.ts', }); ``` -------------------------------- ### Extend Struct Options Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/feature-matrix.md Extend the configuration options for ProjenStruct by implementing the ProjenStructOptions interface. ```typescript interface ProjenStructOptions {} ``` -------------------------------- ### Integrate Struct Generation with Projen Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/module-overview.md Use TypeScriptInterfaceFile to generate a single TypeScript interface file within a projen project. This component wraps the TypeScriptRenderer. ```typescript new TypeScriptInterfaceFile(project, 'src/my.ts', spec, options); ``` -------------------------------- ### Importing jsii-struct-builder Types Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/types.md Import core classes and interfaces from the main entry point of the jsii-struct-builder package. Ensure these types are available in your project. ```typescript import { // Classes Struct, ProjenStruct, TypeScriptRenderer, TypeScriptInterfaceFile, // Interfaces IStructBuilder, HasProperties, HasFullyQualifiedName, HasStructSpec, ProjenStructOptions, TypeScriptInterfaceFileOptions, TypeScriptRendererOptions, } from '@mrgrain/jsii-struct-builder'; ``` -------------------------------- ### Configure TypeScriptRenderer Options Source: https://github.com/mrgrain/jsii-struct-builder/blob/main/_autodocs/api-reference/typescript-renderer.md Instantiate TypeScriptRenderer with specific import location mappings, indentation, and type import preferences. The `importLocations` option allows overriding default import paths for assemblies. ```typescript const renderer = new TypeScriptRenderer({ importLocations: { 'aws-cdk-lib': 'aws-cdk-lib', 'my_pkg': './types', }, indent: 4, useTypeImports: true, }); ```