https://pulumi.com logo
Title
i

important-australia-24045

12/22/2022, 3:06 PM
Hi, I’m having trouble getting started with reusable components. I’m trying to use TypeScript to author a simple reusable component resource that I can use to deploy an S3 bucket on AWS. I’ll start a thread here to share what I have tried and the issue I’m having! 🧶
To demonstrate the issue I’m having, I have created two public GitHub repos: -
briancaffey/pulumi-alpha
(link) is the repo that consumes my S3 component -
briancaffey/pulumi-beta
(link) is the repo where I define the reusable S3 component I created both of these with
pulumi new aws-typescript
.
For
pulumi-beta
, I am using the following code to define my component resource:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

export interface S3BucketArgs {
  name: string;
}

export class S3Bucket extends pulumi.ComponentResource {
  public readonly bucket: aws.s3.Bucket;

  constructor(name: string, args: S3BucketArgs, opts?: pulumi.ComponentResourceOptions) {
    super("my:modules:S3Bucket", name, {}, opts);

    this.bucket = new aws.s3.Bucket(name, {
      bucket: args.name,
    }, { parent: this });
  }
}
In
pulumi-alpha
, I installed the
pulumi-beta
this package with the following command:
npm i git+<https://github.com/briancaffey/pulumi-beta.git>
Then I use it like this in `index.ts`:
import * as pulumi from "@pulumi/pulumi";
import { S3Bucket } from "pulumi-beta";

const bucket = new S3Bucket("my-bucket", {
  name: "my-example-pulumi-bucket",
});

export const bucketName = bucket.bucket.id;
Then I ran
tsc
and I can see that it built the application in the
bin
directory:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bucketName = void 0;
const pulumi_beta_1 = require("pulumi-beta");
const bucket = new pulumi_beta_1.S3Bucket("my-bucket", {
    name: "my-example-pulumi-bucket",
});
exports.bucketName = bucket.bucket.id;
//# sourceMappingURL=index.js.map
Now I want to run
pulumi preview
to see how things will look, but I get this error:
~/git/github/pulumi-alpha$ pulumi preview
Previewing update (dev)

View Live: <https://app.pulumi.com/briancaffey/pulumi-alpha/dev/previews/f8469d80-a9d5-4e95-9d9f-8a5830220f5c>

     Type                 Name              Plan       Info
 +   pulumi:pulumi:Stack  pulumi-alpha-dev  create     1 error


Diagnostics:
  pulumi:pulumi:Stack (pulumi-alpha-dev):
    error: Running program '/Users/brian/git/github/pulumi-alpha' failed with an unhandled exception:
    /Users/brian/git/github/pulumi-alpha/node_modules/pulumi-beta/index.ts:1
    import * as pulumi from "@pulumi/pulumi";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module
Back in the
pulumi-beta
repo, I added
"type": "module",
to
package.json
, pushed to GitHub, then reinstalled everything in `pulumi-alpha`:
rm -rf bin
rm -rf node_modules
rm package-lock.json
npm i
tsc
Running
pulumi preview
again I get the same error as before:
Diagnostics:
  pulumi:pulumi:Stack (pulumi-alpha-dev):
    error: Running program '/Users/brian/git/github/pulumi-alpha' failed with an unhandled exception:
    /Users/brian/git/github/pulumi-alpha/node_modules/pulumi-beta/index.ts:1
    import * as pulumi from "@pulumi/pulumi";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module
Can anyone help guide me on how I can get this basic example to work?
m

many-telephone-49025

12/22/2022, 3:13 PM
Hi Brian, I will take a look into it
i

important-australia-24045

12/22/2022, 3:14 PM
Hi @many-telephone-49025, thanks a lot! Please let me know if there is anything else I can provide.
m

many-telephone-49025

12/22/2022, 3:31 PM
Hey Brian, can you check this please? https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#including-declarations-in-your-npm-package
If your package has a main .js file, you will need to indicate the main declaration file in your package.json file as well. Set the types property to point to your bundled declaration file. For example:

{
  "name": "awesome",
  "author": "Vandelay Industries",
  "version": "1.0.0",
  "main": "./lib/main.js",
  "types": "./lib/main.d.ts"
}
Could be `pulumi-beta`is using the wrong
index.ts
when imported
i

important-australia-24045

12/22/2022, 3:40 PM
OK, thanks for sharing @many-telephone-49025.
If your package has a main .js file,
Should my
pulumi-beta
reusable component resource have a main
.js
file?
m

many-telephone-49025

12/22/2022, 3:40 PM
no could be index too
it was just the example from the TS page
i

important-australia-24045

12/22/2022, 3:41 PM
"main": "index.ts",
This is what I have in my
pulumi-beta
package.json
This is also what I have in my
pulumi-alpha
repo (the pulumi project that consumes the
pulumi-beta
component resource)
"main": "index.ts",
m

many-telephone-49025

12/22/2022, 3:42 PM
probably change it to :
{
  "name": "pulumi-beta",
  "main": "./bin/index.js",
  "types": "./bin/index.d.ts",
   ...
}
i

important-australia-24045

12/22/2022, 3:42 PM
OK, thanks. I can try this.
v

victorious-church-57397

12/22/2022, 3:44 PM
we have a reusable component library. let me grab you the package.json
i

important-australia-24045

12/22/2022, 3:44 PM
v

victorious-church-57397

12/22/2022, 3:45 PM
{
  "name": "@jugo-io/jugo-pulumi-common",
  "version": "1.0.0",
  "description": "Jugo Common Pulumi Library",
  "main": "dist/index.js",
  "typings": "dist/index.d.ts",
  "scripts": {
    "build": "npx tsc",
    "lint": "node_modules/.bin/eslint .",
    "lint:fix": "node_modules/.bin/eslint . --fix"
  },
  "repository": {
    "type": "git",
    "url": ""
  },
  "release": {
    "branches": [
      "main"
    ]
  },
  "publishConfig": {
    "registry": "<https://npm.pkg.github.com>"
  },
  "files": [
    "dist"
  ],
  "peerDependencies": {
     ...
  },
  "author": "<mailto:jugo-admin+platform-team@gdsgroup.com|jugo-admin+platform-team@gdsgroup.com>",
  "license": "MIT",
  "devDependencies": {
    ...
  }
}
i

important-australia-24045

12/22/2022, 3:45 PM
I’m still getting:
import * as pulumi from "@pulumi/pulumi";
    ^^^^^^
    
    SyntaxError: Cannot use import statement outside a module
m

many-telephone-49025

12/22/2022, 3:46 PM
Ah thx @victorious-church-57397, so its "typings"
and the exact location of the d.ts
v

victorious-church-57397

12/22/2022, 3:47 PM
tsconfig is
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2015",
    "declaration": true,
    "outDir": "./dist"
  },
  "include": [
    "src/**/*"
  ]
}
hope this helps!
i

important-australia-24045

12/22/2022, 3:49 PM
OK, thanks @victorious-church-57397 and @many-telephone-49025. I will try some of the suggestions here and post back here if i’m able to make this work or if I keep getting failures. I will keep my two repos updated with my latest changes so this can be easily reproducible if I’m still having issues.
@victorious-church-57397 I noticed that your package.json file does not have a type: module, so I will remove that from my
pulumi-beta
repo
v

victorious-church-57397

12/22/2022, 3:50 PM
yeah we did originally have it in there but it was causing us problems
i

important-australia-24045

12/22/2022, 3:50 PM
OK.
v

victorious-church-57397

12/22/2022, 3:50 PM
if you adapt the package.json and the tsconfig.json i've sent over, it should work for you
i

important-australia-24045

12/22/2022, 3:51 PM
Awesome! I will report back here soon
:large_yellow_circle: Hmm, I’m still not having luck with this. I made the following changes and I’m getting the same error about
SyntaxError: Cannot use import statement outside a module
in
pulumi-beta
: • add
"declaration": true,
in
tsconfig.json
• add
"files": ["bin"]
(I’m using
bin
where you are using
dist
@victorious-church-57397. If I do this, then nothing is installed in
node_modules
in when i run
npm i
in
pulumi-alpha
, since I am not committing the
bin
directory to the repo on GitHub
Does anyone know of any good open-source examples of what I’m trying to do?
(publish a simple pulumi package with typescript, and consume it in another pulumi project)
v

victorious-church-57397

12/22/2022, 4:21 PM
I have closed source examples I can probably tweak
i

important-australia-24045

12/22/2022, 4:22 PM
That would be helpful @victorious-church-57397, thanks
m

many-telephone-49025

12/22/2022, 4:51 PM
I will try to reconstruct your case
So I can better play around but maybe @victorious-church-57397 is quicker with his source code
i

important-australia-24045

12/22/2022, 5:00 PM
Thanks @many-telephone-49025. I think one issue might be that in
pulumi-alpha
when I do
npm i
, it only has
.ts
files and doesn't have any
.js
files. I am not super experienced with typescript, but I think that is part of what is going on with the error message I am seeing. Thank you for helping me to reproduce this 🙏
Could this be because I'm installing directly from github? I didn't want to bother pushing to npm
maybe I just need to add a
build
script in package.json?
c

clever-painter-96148

12/22/2022, 5:55 PM
@important-australia-24045 If I understand your issue properly, you want to split your deployment code as multiple TypeScript packages, and your issue is that Pulumi doesn't understand TypeScript across packages? Here is how solve this as a monorepo: https://github.com/pmuller/website Basically, I use yarn to manage the monorepo, and yarn.build to manage dependencies. Not sure however that you can do that across repositories (did not try that).
i

important-australia-24045

12/22/2022, 5:56 PM
c

clever-painter-96148

12/22/2022, 5:57 PM
Yep, we're talking about the same thing here.
i

important-australia-24045

12/22/2022, 5:57 PM
It’s not really pulumi-specific. I think there are some good suggestions in the answer here: https://stackoverflow.com/a/58257602/6084948
c

clever-painter-96148

12/22/2022, 5:57 PM
I tried all methods described in your SO answer. Monorepos is the cleanest approach IMO.
i

important-australia-24045

12/22/2022, 5:58 PM
I do like this one tho:
"postinstall": "tsc --outDir ./build"
Maybe it will be easier if I just publish to npm then, I guess
c

clever-painter-96148

12/22/2022, 5:59 PM
I did that in the past. I don't remember why I discarded that approach (maybe because it didn't work with a complex set of dependencies?)
v

victorious-church-57397

12/22/2022, 5:59 PM
You don’t need to publish to npm, you can use gh packages
I can send over my examples probably tomorrow if this could wait?
c

clever-painter-96148

12/22/2022, 6:00 PM
Maybe it will be easier if I just publish to npm then, I guess
I did that too. Working with multi repos and packages does the job. But that's still a lot of overhead compared to monorepos.
i

important-australia-24045

12/22/2022, 6:00 PM
Thanks @victorious-church-57397, I think I’m OK at this point. I thought I had some weird issues in all of the config files, but I now realize that installing from github directly with typescript has some limitations that I need to work around in some way
v

victorious-church-57397

12/22/2022, 6:02 PM
What do you mean? We use GitHub in multiple repos and it’s fine
You need to setup a token which utilises packages and just run a build and then npm publish
c

clever-painter-96148

12/22/2022, 6:04 PM
"Overhead" = You still need to do release management of multiple packages and setup CI for them
v

victorious-church-57397

12/22/2022, 6:05 PM
I can send over a full template repo tomorrow, it’s worth doing right sometimes. Depends if you’re a one man band or will be expanding.
c

clever-painter-96148

12/22/2022, 6:05 PM
That's a good point. I went the monorepo way on a 3 people-sized project.
v

victorious-church-57397

12/22/2022, 6:06 PM
I love monorepo for smaller projects and even larger ones, I think for a package you might be using in multiple places should probably be independently managed and released
c

clever-painter-96148

12/22/2022, 6:06 PM
We lived with multi-repos + GH packages for a while, but we were quite happy to get rid of this as we had no need for such complexity.
v

victorious-church-57397

12/22/2022, 6:06 PM
That’s just my opinion though
Yeah it’s all about context
i

important-australia-24045

12/22/2022, 6:16 PM
~/git/github/pulumi-alpha$ pulumi preview
Previewing update (dev)

View Live: <https://app.pulumi.com/briancaffey/pulumi-alpha/dev/previews/f28c1725-f76e-4631-a26d-5fef4670eeca>

     Type                    Name              Plan       
 +   pulumi:pulumi:Stack     pulumi-alpha-dev  create     
 +   └─ my:modules:S3Bucket  my-bucket         create     
 +      └─ aws:s3:Bucket     my-bucket         create     


Outputs:
    bucketName: output<string>

Resources:
    + 3 to create

~/git/github/pulumi-alpha$
m

many-telephone-49025

12/22/2022, 6:17 PM
Nice, what did you do?
i

important-australia-24045

12/22/2022, 6:17 PM
Thanks everyone for helping me with this. Now I can get started actually building things 🙂
As I described above, I had to commit the
bin
directory to my
pulumi-alpha
repo @many-telephone-49025, this is because I’m installing directly from github. Then I removed
"type": "module"
from the
pulumi-beta
repo and it worked
m

many-telephone-49025

12/22/2022, 6:20 PM
Nice work!
i

important-australia-24045

12/22/2022, 6:43 PM
Helpful article: https://cameronnokes.com/blog/the-30-second-guide-to-publishing-a-typescript-package-to-npm/ I was able to use this to publish my dummy package and then install it in
pulumi-alpha
v

victorious-church-57397

12/22/2022, 7:04 PM
Let me know if you still want any examples tomorrow @important-australia-24045
Good stuff getting it working tho
m

many-telephone-49025

12/23/2022, 8:31 AM
Interesting @important-australia-24045 that in the article it is written
types
but you still have
typings
in yor
package.json
of
pulumi-beta
! And it’s still working!