Pulumi & TypeScript & JavaScript (Node.js)
Pulumi supports writing your infrastructure as code in any JavaScript language running on Node.js using any of the Current, Active and Maintenance LTS versions.
Because programs are just JavaScript, you may elect to write them in any manner you’d normally write Node.js programs. That includes TypeScript, CoffeeScript, or Babel, in addition to your favorite tools such as build systems, linters, or test frameworks.
Pulumi Programming Model
The Pulumi programming model defines the core concepts you will use when creating infrastructure as code programs using Pulumi. Concepts describes these concepts with examples available in JavaScript and TypeScript. These concepts are made available to you in the Pulumi SDK.
The Pulumi SDK is available to Node.js developers as a NPM package. To learn more, refer to the Pulumi SDK Reference Guide.
The Pulumi programming model includes a core concept of Input
and Output
values, which are used to track how outputs of one resource flow in as inputs to another resource. This concept is important to understand when getting started with JavaScript and Pulumi, and the Inputs and Outputs documentation is recommended to get a feel for how to work with this core part of Pulumi in common cases.
Entrypoint
Pulumi executes your program by loading the entrypoint file as a Node module: require("index.ts")
. By default, Pulumi will load index.ts
or index.js
. Alternatively, if you specify main
within your package.json
, Pulumi will load that module instead:
{
"name": "my-package",
"version": "1.0.0",
...
"main": "src/entry.ts"
}
// create resources
...
exports.out = myResource.output;
// create resources
...
export const out = myResource.output;
module.exports = async () => {
// create resources
return { out: myResource.output };
}
export = async () => {
// create resources
return { out: myResource.output };
}
Most Pulumi programs use the first option, but programs that need to do async work at the top level (such as calling getOutputValue
) may find they want to use the second.
TypeScript
You can elect to write Pulumi programs in TypeScript to get additional verification and tooling benefits. Pulumi supports TypeScript natively so you don’t need to explicitly run tsc
on your program before running pulumi
.
If you would like full control of the TypeScript build process, you can compile ahead of time, and point your package.json main entry point at the compiled JavaScript instead. If you do this, you can disable the automatic compilation of TypeScript files.
The fastest way to get started with Pulumi in TypeScript, is to use a template:
$ mkdir myproject && cd myproject
$ pulumi new typescript
This will auto-generate all the basic artifacts required to use TypeScript. If you prefer, you can instead run the following manual steps.
1. Update package.json
Update your package.json
to look like the following (with your own values for name
, version
, etc.). This
is what tells Node.js and NPM what packages you depend on, where to find your code’s entry points, and so on:
{
"name": "my-package",
"version": "1.0.0",
"devDependencies": {
"@types/node": "^12.0.0"
},
"dependencies": {
... as before ...
}
}
You can customize this however you’d like, such as adding test scripts, npm package dependencies, etc. For more information on package.json
, refer to the NPM documentation.
2. Install dependencies
Run npm install
or yarn install
to install the new development-time dependencies to your node_modules
directory.
3. Create tsconfig.json
When using Pulumi’s built in TypeScript support, a tsconfig.json
file is optional. However, defining one allows your to set additional TypeScript compiler options, for example not allowing implicit returns from a function. In addition, other tools like VS Code will use these settings to give you additional warnings at development time. Any options set in your tsconfig.json
file will be picked up by Pulumi. We recommend creating a tsconfig.json
file with the following settings:
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
You may customize this however you’d like, including the TypeScript settings that work for you. For
information on additional settings, see the TypeScript documentation for tsconfig.json
.
Tools like VS Code will give you completion lists, live error reporting and inline documentation help.
TypeScript Versions
Pulumi ships with a bundled version of TypeScript 3.8.3 and uses this compiler by default. You can use a different version by adding the desired version of TypeScript to your package.json file. When Pulumi runs a TypeScript program, it will first attempt to load the compiler from the local node_modules directory, and then fallback to the bundled version. Pulumi supports all TypeScript versions from 3.8 and up, including the latest TypeScript 5 release.
{
"name": "my-package",
"version": "1.0.0",
"dependencies": {
...
"typescript": "^5.4.2",
...
}
}
Disabling built in TypeScript support
You can disable the built in TypeScript support by changing the runtime
setting in Pulumi.yaml
to look like the following:
runtime:
name: nodejs
options:
typescript: false
Package Management
Pulumi has official support for NPM and Yarn Classic. Pulumi does not support Yarn Plug’n’Play.
Pulumi defaults to using NPM. However, if Pulumi detects a yarn.lock
file
in the project root, or the environment variable PULUMI_PREFER_YARN=true
,
then Pulumi will use Yarn instead of NPM if the executable is available in the
path.
Dependencies on Provider Packages within Component Packages
Some package management systems allow for different versions of a package to be installed concurrently. You can include a package as a direct dependency in your project and another dependency could depend on the same package too, but with a different version.
Suppose we are building a component package where you use @pulumi/random
, major version 3.
In our package.json
file for the component package, you have this:
{
"name": "components",
"version": "1.0.0",
...
"dependencies": {
...
"@pulumi/random": "^3",
...
},
...
}
In a project where you consume this component library, you can add more random
resources, but now using
major v4:
{
"name": "components-consume",
...
"dependencies": {
...
"@pulumi/random": "^4",
"components": "^1",
...
},
...
}
In the situation where you mix major versions, the specification ^3
excludes major version 4
.
If we check on our dependency graph, we see two versions included
$ npm why @pulumi/random
@pulumi/random@v4.14.0
node_modules/@pulumi/random
@pulumi/random@"^4.14.0" from the root project
@pulumi/random@v3.2.0 extraneous
@pulumi/random@"^3" from components@1.0.0
components@1.0.0
When you use a Pulumi NodeJS SDK for a provider, Pulumi will always use the plugin binary of the same version.
By having multiple versions of an SDK in our dependency graph, you will see multiple versions of the
default provider in your Pulumi state file as a result. The child random
resources of components from your library
will be provisioned with plugin binary v3, while the top level random
resources will use v4.
A similar situation would happen if you would pin the component library and the consuming project to explicit
but different versions. For instance, using "4.11.0"
in the component library and "4.14.0"
in the consuming
project would result in 2 default providers with exactly these versions.
If you only want to have a single version of the package and default provider, we suggest to use the caret
style notation in your component package. Use ^
, followed by the minimum version of the dependency, and
use a compatible version in your consuming project for your components to work correctly.
For instance, if @pulumi/random
v4.8.2 contained a fix you rely on, use this in your library package.json
:
{
"name": "components",
"version": "1.0.0",
...
"dependencies": {
...
"@pulumi/random": "^4.8.2",
...
},
...
}
When you use a version of @pulumi/random
in your consuming project which is too old, NPM will warn you that you
need to upgrade.
Dev Versions
Pulumi SDKs also publish pre-release versions, that include all the latest changes from the main development branch. If you would like to install them, you can use the dev
tag to do so. For example using npm
you can use npm add @pulumi/pulumi@dev
, and similarly for yarn
yarn add @pulumi/pulumi@dev
.
Package Documentation
In addition to the standard and cloud-agnostic packages the Pulumi Registry houses 100+ Node.js packages.
Standard Packages
- Pulumi SDK
- @pulumi/pulumi
- Pulumi Policy
- @pulumi/policy
- Pulumi Terraform
- @pulumi/terraform
Cloud-Agnostic Packages
- Pulumi Cloud Framework
- @pulumi/cloud
PREVIEW
A highly productive, cloud-agnostic package for container and serverless programming.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.