Repository: cdklabs/cdk-monitoring-constructs (language: python)

Issue:
Can only be used with specific aws-cdk-lib versions due to alpha module peer dependencies
### Version

v1.18.4

### Steps and/or minimal code example to reproduce

The peer-dependencies are specified in a way that is not working when using any cdk version higher than 2.18.0.

```
    "@aws-cdk/aws-apigatewayv2-alpha": "^2.18.0-alpha.0",
    "@aws-cdk/aws-appsync-alpha": "^2.18.0-alpha.0",
    "@aws-cdk/aws-redshift-alpha": "^2.18.0-alpha.0",
    "@aws-cdk/aws-synthetics-alpha": "^2.18.0-alpha.0",
```

These only match `2.18.0-alpha.0`, `2.18.0-alpha.1`, `2.18.0-alpha.2` and so on but not `2.19.0-alpha.0` or in my case `2.22.0-alpha.0`

### Expected behavior

Any minor version higher than 2.18.0-alpha.0 can be used.

### Actual behavior

Error: Error: Declared dependency on version ^2.18.0-alpha.0 of @aws-cdk/aws-apigatewayv2-alpha, but version 2.22.0-alpha.0 was found

### Other details

I couldn't find a way to make it work with overrides or resolutions and to make it even worse there is no notation that matches `2.18.0-alpha.0` and `2.19.0-alpha.0` other than `2.18.0-alpha.0 || 2.19.0-alpha.0`.


Discussion / hints:
Assuming you're using npm >= 7, you should be able to configure `legacy-peer-deps` ([docs](https://docs.npmjs.com/cli/v7/using-npm/config#legacy-peer-deps)) to allow for newer versions to be installed, at the risk that the alpha modules' APIs may not match up.

One solution would be to occasionally bump our peer dependencies' versions, but that may be annoying for users.
There is no problem when installing the new versions. The problem is that the jsii compiler is not able to compile my construct with the newer versions. Sorry if that was not clear.

```
$ jsii
Error: Error: Declared dependency on version ^2.18.0-alpha.0 of @aws-cdk/aws-apigatewayv2-alpha, but version 2.22.0-alpha.0 was found
    at DependencyResolver.discoverDependencyTree (/*REMOVED*/node_modules/jsii/lib/project-info.js:131:23)
    at DependencyResolver.loadAssemblyAndRecurse (/*REMOVED*/node_modules/jsii/lib/project-info.js:180:20)
    at DependencyResolver.resolveDependency (/*REMOVED*/node_modules/jsii/lib/project-info.js:168:34)
    at DependencyResolver.discoverDependencyTree (/*REMOVED*/node_modules/jsii/lib/project-info.js:128:35)
    at Object.loadProjectInfo (/*REMOVED*/node_modules/jsii/lib/project-info.js:51:31)
    at /*REMOVED*/node_modules/jsii/bin/jsii.js:78:81
    at Object.<anonymous> (/*REMOVED*/node_modules/jsii/bin/jsii.js:104:3)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
```

Is this in the context of building a construct that uses `cdk-monitoring-constructs`, or a CDK project that isn't using TypeScript?
I am trying to build a construct in TypeScript that is using ˋcdk-monitoring-constructsˋ 
A few options that I can see:

1. Occasionally bump our peer dependencies, which would be considered a breaking change and therefore a major version bump. We'll notably need to do this anyway if the alpha modules have breaking changes that affect our usages or when they go stable.
2. Modify the alpha module peer dependencies to include all possible versions (e.g. `2.18.0-alpha.0 || 2.19.0-alpha.0`), occasionally updating it to keep up. Our projen setup doesn't really lend itself to doing matrix-based tests against all possible versions that easily.
3. Try to drop the dependencies. This could entail splitting out any alpha functionality into a separate package (but that would have the same issues as we do today), or duplicating the needed features in our codebase (interfaces and metric declarations; we could probably keep the alpha modules for unit testing purposes).

@voho @ayush987goyal Any thoughts?
I am mostly inclined towards approach 2 which does not change any exiting behavior by a lot and also addresses this use-case. On a side note, have we checked if `>` operators etc. work instead of `^` ?
> On a side note, have we checked if `>` operators etc. work instead of `^` ?

Yeah, it doesn't work. You can try it out on https://semver.npmjs.com/
A quick revive of this thread
Do we have a work around for this ? 
Or is the only solution a `npm i --force` in the meantime for consumer of the library who are using aws-cdk > 2.18 ?
Workarounds would be to use `npm i --force`, use `legacy-peer-deps`, or use [overrides](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides).

---

I'm personally inclined to go with option 1 (occasionally bump our peer dependencies as a major version bump), since it'd also allow us to use newer AWS CDK CloudWatch features like new widget types. The eventual updates to handle alpha modules graduating to stable would necessitate a similar change anyhow.

@ayush987goyal Any concerns with the above?
Checked the issues so far but it seems I'm forced to include all of the alpha dependencies which are currently sitting inside of the cdk-monitoring package as well even though I'm not using them
```
node_modules/cdk-monitoring-constructs/lib/monitoring/aws-synthetics/SyntheticsCanaryMetricFactory.d.ts(1,24): error TS2307: Cannot find module '@aws-cdk/aws-synthetics-alpha' or its corresponding type declarations.
52
```

After adding this particular dependency I'm having run-time failures because I don't have the exact matching versions
```
● Test suite failed to run
--
61 |  
62 | Cannot find module '@aws-cdk/aws-redshift-alpha' from 'node_modules/cdk-monitoring-constructs/lib/facade/MonitoringAspect.js'
63 |  
64 | Require stack:
65 | node_modules/cdk-monitoring-constructs/lib/facade/MonitoringAspect.js
66 | node_modules/cdk-monitoring-constructs/lib/facade/MonitoringFacade.js
67 | node_modules/cdk-monitoring-constructs/lib/facade/index.js
68 | node_modules/cdk-monitoring-constructs/lib/index.js
````

is it an expected behavior ?
I'm having the same issue as @svrielynck described, adding all of the alpha as deps fixed that, but is not the most elegant solution and is also not described as requirement in the README
The current strategy is just to wait for the existing alpha dependencies to go stable (2 of 4 have gone stable thus far), and no longer adding any dependencies on alpha modules as part of this library.

The easiest way of dealing with the conflicts right now is using overrides to explicitly use whatever versions your project directly declares a dependency on, for example:

```
{
  "dependencies": {
    "cdk-monitoring-constructs": "^6.0.0",

    // These are notably a higher version that what the used version
    // of cdk-monitoring-constructs depends on
    "@aws-cdk/aws-apigatewayv2-alpha": "^2.106.0-alpha.0",
    "@aws-cdk/aws-redshift-alpha": "^2.106.0-alpha.0",
    "aws-cdk-lib": "^2.106.0",

    // etc.
  },
  "overrides": {
    "cdk-monitoring-constructs": {
      "@aws-cdk/aws-apigatewayv2-alpha": "$@aws-cdk/aws-apigatewayv2-alpha",
      "@aws-cdk/aws-redshift-alpha": "$@aws-cdk/aws-redshift-alpha"
    }
  }
}
```
We're currently left with only `@aws-cdk/aws-redshift-alpha` after #464.

Fix patch:
diff --git a/.projen/deps.json b/.projen/deps.json
index 0dd3a5f4..ea47b889 100644
--- a/.projen/deps.json
+++ b/.projen/deps.json
@@ -119,11 +119,6 @@
       "version": "2.6.0",
       "type": "override"
     },
-    {
-      "name": "@aws-cdk/aws-redshift-alpha",
-      "version": "^2.112.0-alpha.0",
-      "type": "peer"
-    },
     {
       "name": "aws-cdk-lib",
       "version": "^2.112.0",
diff --git a/.projenrc.ts b/.projenrc.ts
index 4dca79ff..4da782af 100644
--- a/.projenrc.ts
+++ b/.projenrc.ts
@@ -79,10 +79,6 @@ _By submitting this pull request, I confirm that my contribution is made under t
 
 // Experimental modules
 ["@aws-cdk/aws-redshift-alpha"].forEach((dep) => {
-  project.deps.addDependency(
-    `${dep}@^${CDK_VERSION}-alpha.0`,
-    DependencyType.PEER
-  );
   project.deps.addDependency(
     `${dep}@${CDK_VERSION}-alpha.0`,
     DependencyType.DEVENV
diff --git a/README.md b/README.md
index c2040ff9..88077b67 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,6 @@ In your `package.json`:
     "cdk-monitoring-constructs": "^7.0.0",
 
     // peer dependencies of cdk-monitoring-constructs
-    "@aws-cdk/aws-redshift-alpha": "^2.112.0-alpha.0",
     "aws-cdk-lib": "^2.112.0",
     "constructs": "^10.0.5"
 
diff --git a/lib/facade/MonitoringAspect.ts b/lib/facade/MonitoringAspect.ts
index da7e08e4..e678ad9c 100644
--- a/lib/facade/MonitoringAspect.ts
+++ b/lib/facade/MonitoringAspect.ts
@@ -1,4 +1,3 @@
-import * as redshift from "@aws-cdk/aws-redshift-alpha";
 import { IAspect } from "aws-cdk-lib";
 import * as apigw from "aws-cdk-lib/aws-apigateway";
 import * as apigwv2 from "aws-cdk-lib/aws-apigatewayv2";
@@ -17,6 +16,7 @@ import * as kinesisfirehose from "aws-cdk-lib/aws-kinesisfirehose";
 import * as lambda from "aws-cdk-lib/aws-lambda";
 import * as opensearch from "aws-cdk-lib/aws-opensearchservice";
 import * as rds from "aws-cdk-lib/aws-rds";
+import { CfnCluster } from "aws-cdk-lib/aws-redshift";
 import * as s3 from "aws-cdk-lib/aws-s3";
 import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
 import * as sns from "aws-cdk-lib/aws-sns";
@@ -341,15 +341,24 @@ export class MonitoringAspect implements IAspect {
 
   private monitorRedshift(node: IConstruct) {
     const [isEnabled, props] = this.getMonitoringDetails(this.props.redshift);
-    if (isEnabled && node instanceof redshift.Cluster) {
+    if (isEnabled && this.isProbablyL2RedshiftCluster(node)) {
+      const cfnCluster = (node as any).cluster as CfnCluster;
       this.monitoringFacade.monitorRedshiftCluster({
-        clusterIdentifier: node.clusterName,
-        alarmFriendlyName: node.node.path,
+        clusterIdentifier: cfnCluster.ref,
+        alarmFriendlyName: cfnCluster.node.path,
         ...props,
       });
     }
   }
 
+  private isProbablyL2RedshiftCluster(node: IConstruct): boolean {
+    return (
+      (node as any).cluster instanceof CfnCluster &&
+      !!(node as any).clusterName &&
+      !!(node as any).node?.path
+    );
+  }
+
   private monitorS3(node: IConstruct) {
     const [isEnabled, props] = this.getMonitoringDetails(this.props.s3);
     if (isEnabled && node instanceof s3.Bucket) {
diff --git a/package.json b/package.json
index 05ff7394..9b5a6a2a 100644
--- a/package.json
+++ b/package.json
@@ -65,7 +65,6 @@
     "typescript": "^4.9.5"
   },
   "peerDependencies": {
-    "@aws-cdk/aws-redshift-alpha": "^2.112.0-alpha.0",
     "aws-cdk-lib": "^2.112.0",
     "constructs": "^10.0.5"
   },


Test patch:
diff --git a/test/facade/__snapshots__/MonitoringAspect.test.ts.snap b/test/facade/__snapshots__/MonitoringAspect.test.ts.snap
index 4099d57d..413db18b 100644
--- a/test/facade/__snapshots__/MonitoringAspect.test.ts.snap
+++ b/test/facade/__snapshots__/MonitoringAspect.test.ts.snap
@@ -7457,7 +7457,7 @@ Object {
           "Fn::Join": Array [
             "",
             Array [
-              "{\\"start\\":\\"-PT8H\\",\\"periodOverride\\":\\"inherit\\",\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### Redshift Cluster **[Default/DummyCluster](https://",
+              "{\\"start\\":\\"-PT8H\\",\\"periodOverride\\":\\"inherit\\",\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### Redshift Cluster **[Default/DummyCluster/Resource](https://",
               Object {
                 "Ref": "AWS::Region",
               },
@@ -7539,7 +7539,7 @@ Object {
           "Fn::Join": Array [
             "",
             Array [
-              "{\\"start\\":\\"-P14D\\",\\"periodOverride\\":\\"inherit\\",\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### Redshift Cluster **[Default/DummyCluster](https://",
+              "{\\"start\\":\\"-P14D\\",\\"periodOverride\\":\\"inherit\\",\\"widgets\\":[{\\"type\\":\\"text\\",\\"width\\":24,\\"height\\":1,\\"x\\":0,\\"y\\":0,\\"properties\\":{\\"markdown\\":\\"### Redshift Cluster **[Default/DummyCluster/Resource](https://",
               Object {
                 "Ref": "AWS::Region",
               },