Repository: pulumi/pulumi-cdk
Pull request #229 (2024-11-18 23:49:16)

chore: fix all lint warnings
A combination of fixes and relaxed linter rules, `yarn run lint` now passes without warnings.


Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index 2146735..946ae8a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -12,6 +12,9 @@ module.exports = {
   rules: {
     // disabling this since it is used everywhere in this repo
     "@typescript-eslint/no-explicit-any": "off",
-    "@typescript-eslint/no-unused-vars": "warn"
+    "@typescript-eslint/no-unused-vars": ["warn", {
+        "varsIgnorePattern": "^[_]",
+        "argsIgnorePattern": "^[_]"
+    }]
   }
 };
diff --git a/src/converters/app-converter.ts b/src/converters/app-converter.ts
index 25c60c6..22cc65f 100644
--- a/src/converters/app-converter.ts
+++ b/src/converters/app-converter.ts
@@ -18,7 +18,7 @@ import {
 } from '@pulumi/aws-native';
 import { mapToAwsResource } from '../aws-resource-mappings';
 import { attributePropertyName, mapToCfnResource } from '../cfn-resource-mappings';
-import { CloudFormationMapping, CloudFormationResource, getDependsOn } from '../cfn';
+import { CloudFormationResource, getDependsOn } from '../cfn';
 import { OutputMap, OutputRepr } from '../output-map';
 import { parseSub } from '../sub';
 import { getPartition } from '@pulumi/aws-native/getPartition';
@@ -475,7 +475,7 @@ export class StackConverter extends ArtifactConverter {
 
             case 'Fn::Sub':
                 return lift((params) => {
-                    const [template, vars] =
+                    const [template, _vars] =
                         typeof params === 'string' ? [params, undefined] : [params[0] as string, params[1]];
 
                     const parts: string[] = [];
diff --git a/src/interop.ts b/src/interop.ts
index 919fbe9..6e99fb5 100644
--- a/src/interop.ts
+++ b/src/interop.ts
@@ -1,4 +1,4 @@
-// Copyright 2016-2022, Pulumi Corporation.
+// Copyright 2016-2024, Pulumi Corporation.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -38,18 +38,27 @@ export function firstToLower(str: string) {
 export function normalize(value: any, cfnType?: string, pulumiProvider?: PulumiProvider): any {
     if (!value) return value;
 
+    if (value instanceof Promise) {
+        return pulumi.output(value).apply(v => normalize(v, cfnType, pulumiProvider));
+    }
+
+    if (pulumi.Output.isInstance(value)) {
+        return value.apply(v => normalize(v, cfnType, pulumiProvider));
+    }
+
     if (Array.isArray(value)) {
         const result: any[] = [];
         for (let i = 0; i < value.length; i++) {
-            result[i] = normalize(value[i], cfnType);
+            result[i] = normalize(value[i], cfnType, pulumiProvider);
         }
         return result;
     }
 
-    if (typeof value !== 'object' || pulumi.Output.isInstance(value) || value instanceof Promise) {
+    if (typeof value !== 'object') {
         return value;
     }
 
+    // The remaining case is the object type, representing either Maps or Object types with known field types in Pulumi.
     const result: any = {};
     Object.entries(value).forEach(([k, v]) => {
         result[toSdkName(k)] = normalizeObject([k], v, cfnType, pulumiProvider);
diff --git a/src/pulumi-metadata.ts b/src/pulumi-metadata.ts
index 284f32c..c4ee574 100644
--- a/src/pulumi-metadata.ts
+++ b/src/pulumi-metadata.ts
@@ -1,10 +1,25 @@
+// Copyright 2016-2024, Pulumi Corporation.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 import * as path from 'path';
-import * as pulumi from '@pulumi/pulumi';
 import { toSdkName, typeToken } from './naming';
 // eslint-disable-next-line @typescript-eslint/no-var-requires
 const pulumiMetadata = require(path.join(__dirname, '../schemas/aws-native-metadata.json'));
 import { PulumiProvider } from './types';
 import { debug } from '@pulumi/pulumi/log';
+import * as pulumi from '@pulumi/pulumi';
+
 
 export class UnknownCfnType extends Error {
     constructor(cfnType: string) {
@@ -269,6 +284,15 @@ export function getNativeType(
  */
 export function normalizeObject(key: string[], value: any, cfnType?: string, pulumiProvider?: PulumiProvider): any {
     if (!value) return value;
+
+    if (value instanceof Promise) {
+        return pulumi.output(value).apply(v => normalizeObject(key, v, cfnType, pulumiProvider));
+    }
+
+    if (pulumi.Output.isInstance(value)) {
+        return value.apply(v => normalizeObject(key, v, cfnType, pulumiProvider));
+    }
+
     if (Array.isArray(value)) {
         const result: any[] = [];
         for (let i = 0; i < value.length; i++) {
@@ -277,10 +301,11 @@ export function normalizeObject(key: string[], value: any, cfnType?: string, pul
         return result;
     }
 
-    if (typeof value !== 'object' || pulumi.Output.isInstance(value) || value instanceof Promise) {
+    if (typeof value !== 'object') {
         return value;
     }
 
+    // The remaining case is the actual object type.
     const result: any = {};
     if (cfnType) {
         try {


Test patch:
diff --git a/tests/interop.test.ts b/tests/interop.test.ts
index 9609de3..b022c82 100644
--- a/tests/interop.test.ts
+++ b/tests/interop.test.ts
@@ -1,4 +1,5 @@
 import { normalize } from '../src/interop';
+import * as pulumi from '@pulumi/pulumi';
 
 beforeEach(() => {
     jest.resetAllMocks();
@@ -339,4 +340,31 @@ describe('normalize', () => {
             },
         });
     });
+
+    test('normalize changes the case of nested properties through an Output eventual type', async () => {
+        const normalized = normalize({
+            'StreamEncryption': pulumi.output({
+                EncryptionType: 'KMS',
+                KeyId: 'alias/aws/kinesis'
+            })
+        });
+
+        const finalValue = await awaitOutput(pulumi.output(normalized));
+
+        expect(finalValue).toEqual({
+            streamEncryption: {
+                encryptionType: 'KMS',
+                keyId: 'alias/aws/kinesis',
+            }
+        });
+    });
 });
+
+function awaitOutput<T>(out: pulumi.Output<T>): Promise<T> {
+    return new Promise((resolve, _reject) => {
+        out.apply(v => {
+            resolve(v);
+            return v;
+        })
+    });
+}