projen / projen

Rapidly build modern applications with advanced configuration management
https://projen.io
Apache License 2.0
2.63k stars 368 forks source link

New project type projen dep issue #3169

Closed automartin5000 closed 9 months ago

automartin5000 commented 9 months ago

I'm trying to extend AwsCdkTypeScriptApp to create a new project type, but I'm running into issues during build.

Everything looks correct in VSCode (inspections, etc), but when I run projen build, I get a number of errors with the first being: error JSII9000: Encountered use of module that is not declared in "dependencies" or "peerDependencies": "projen"

My new project class is still pretty minimal:


import ( awscdk } from 'projen';

export interface MyAwsCdkTypescriptAppProps extends awscdk.AwsCdkTypeScriptAppOptions {
    readonly serverless?: boolean;
}
/**
* My CDK Typescript App
* Supported compute environments: aws-lambda
* @pjid my-awscdk-app-ts
export class MyAwsCdkTypescriptApp extends awscdk.AwsCdkTypeScriptApp {
    constructor (props: MyAwsCdkTypescriptAppProps) {
        super ({
            ...props, 
            cdkVersion: '2.114.1', 
            defaultReleaseBranch: 'main',
            renovatebot: true, 
            projenrcTs: true,
        });
    }
}

I'm sure I could manually declare projen as a dependency, but I figured it was supposed to "just work" as is. So I thought I'd try to debug it as is first.

Using projen 0.77.6

automartin5000 commented 9 months ago

Ok so digging through others’ examples in GitHub, I discovered that the following params are required:

projenDevDependency: false,
deps: [‘projen’],
peerDeps: [‘projen’] // And ‘constructs’ for the CDK app

This configuration feels a bit weird and seems like something that should be abstracted into a ProjectType class. Is that now available somewhere? Is that what this class is for?

And then in MyAwsCdkTypescriptApp I have to manually set:

projenDevDependency: true

Why wouldn’t the default be true?

automartin5000 commented 9 months ago

As a follow up to this, I just realized that even though it’s building successfully, JSII is still throwing a warning:

warning JSII6: A “peerDependency” on “projen” at “^0.77.6” means you should take a “devDependency” on “projen” at “0.77.6” (found “undefined”)

But as soon as I set projenDevDependency to true in the JsiiProject class (or just remove it), I get a Duplicate dependency error.

mrgrain commented 9 months ago

Hi @automartin5000 Thanks for your questions!

I'm trying to extend AwsCdkTypeScriptApp to create a new project type, but I'm running into issues during build.

To be clear, are you trying to

It sounds like you are trying to do the latter and I am going to assume this for the rest of my reply. But if not, please confirm because the steps are very different.

This configuration feels a bit weird and seems like something that should be abstracted into a ProjectType class. Is that now available somewhere?

You need a JsiiProject to publish a new projen project type. There is currently no official project type for it. We probably should have one though. If you are looking for an easy fix, you could use one that I maintained (projen new --from mrpj projen) or check the code for inspiration.

As a follow up to this, I just realized that even though it’s building successfully, JSII is still throwing a warning:

This is just a warning. It's up to you if you want to fix it or not. Do you understand the intention behind the warning? Asking so you can make an informed decision for yourself if you are okay with it or not.


To get this working the way I think you want, you need to do the following. See comments for explanations of lines.

const project = new cdk.JsiiProject({
  // This is a projen project type and this setting adds projen with a loose-ish version constraint.
  // We don't want that.
  projenDevDependency: false,
  // Don't use this, it has no effect because of the line above
  // projenVersion: '0.77.0',

  // Define projen as a peer dependency. This will also add projen as a fixed dev dependency.
  peerDeps: [
    'projen',
    // To depend on a specific version of projen, you can use this instead
    // 'projen@^0.77.0',

    // Uncomment this only if you DIRECTLY use constructs in your code
    // Will give you a peer AND dev dependency
    // 'constructs',
  ],
});
automartin5000 commented 9 months ago
  • do you want to publish a projen package so others can use your new projen project type?

It sounds like you are trying to do the latter and I am going to assume this for the rest of my reply. But if not, please confirm because the steps are very different.

This is correct

This is just a warning. It's up to you if you want to fix it or not. Do you understand the intention behind the warning? Asking so you can make an informed decision for yourself if you are okay with it or not.

Is the intention of the warning here because without the devDep, the consumer would have to install projen themselves?

To get this working the way I think you want, you need to do the following. See comments for explanations of lines.

const project = new cdk.JsiiProject({
  // This is a projen project type and this setting adds projen with a loose-ish version constraint.
  // We don't want that.
  projenDevDependency: false,
  // Don't use this, it has no effect because of the line above
  // projenVersion: '0.77.0',

  // Define projen as a peer dependency. This will also add projen as a fixed dev dependency.
  peerDeps: [
    'projen',
    // To depend on a specific version of projen, you can use this instead
    // 'projen@^0.77.0',

    // Uncomment this only if you DIRECTLY use constructs in your code
    // Will give you a peer AND dev dependency
    // 'constructs',
  ],
});

This did the trick, thanks!

mrgrain commented 9 months ago

Is the intention of the warning here because without the devDep, the consumer would have to install projen themselves

It's about making sure you actually develop against the lowest possible version of the peer dependency and not accidentally rely on a feature that is not present in older versions.

When you define only a peer dependency as say ^1.0.0, npm might install version 1.2.0 into your project, which might have a new feature and you might accidentally start depending your code on that.

By adding a dev dependency of 1.0.0 (no caret), you still allow your users to install any newer version, but make sure you are always assuming the lowest commitment denominator in your code.