Open-Source Wikis

/

Pulumi

/

Packages

/

Node.js / TypeScript SDK

pulumi/pulumi

Node.js / TypeScript SDK

Active contributors: Justin Van Patten, Ian Wahbe, Thomas Gummerer

Purpose

sdk/nodejs/ is the Node.js SDK published as @pulumi/pulumi on npm. It is the most-used Pulumi SDK and the one with the longest production history. It is written in TypeScript; the build emits .js plus .d.ts declarations.

Directory layout

sdk/nodejs/
├── index.ts                    # Public re-exports
├── resource.ts                 # Resource, ComponentResource, CustomResource (≈68 KB)
├── output.ts                   # Output<T>, Input<T>, lifting helpers (≈53 KB)
├── config.ts                   # pulumi.Config (≈19 KB)
├── stackReference.ts           # StackReference
├── invoke.ts                   # invoke(), invokeAsync()
├── errors.ts                   # RunError, ResourceError, etc.
├── metadata.ts                 # getStack(), getProject(), getOrganization()
├── stash.ts                    # Per-context state stash
├── tsutils.ts                  # TS-specific helpers
├── version.ts                  # SDK version pin
├── runtime/                    # gRPC + monitor clients (the engine bridge)
├── proto/                      # Generated proto bindings
├── automation/                 # Automation API (subdir mirrors Go's auto/)
├── cmd/pulumi-language-nodejs/ # The Node language host
├── log/                        # pulumi.log helpers
├── asset/                      # Asset / Archive types
├── dynamic/                    # Dynamic provider (in-program providers)
├── iterable/                   # Iterable utility
├── queryable/                  # Queryable utility
├── provider/                   # Provider authoring
├── tests/                      # Mocha-driven tests
├── tests_with_mocks/           # Tests using SDK mocks
├── npm/                        # npm packaging metadata
├── tools/automation/           # Automation-API codegen
├── types/                      # Type declarations
├── biome.json                  # Lint + format config
├── .eslintrc.js                # ESLint rules
└── package.json

Key abstractions

Symbol File Role
Resource, CustomResource, ComponentResource resource.ts Inheritance hierarchy; user resources extend these
Output<T>, Input<T> output.ts The future-like type and its parameter type
output(value) output.ts Lift a plain value to an Output
all([a, b, c]) output.ts Combine outputs
Config config.ts Per-stack config reader
StackReference stackReference.ts Read outputs from another stack
ProviderResource resource.ts Explicit provider configuration
RuntimeOptions runtime/settings.ts Engine connection settings
runtime.registerResource runtime/resource.ts The internal RegisterResource call

Build

The build pipeline (sdk/nodejs/Makefile) does:

  1. tsc — compile TypeScript to JavaScript + .d.ts.
  2. Bundle into bin/ (mirroring the source tree).
  3. Generate proto bindings via grpc_tools (lives at sdk/nodejs/proto/).
  4. Install — copy into $HOME/.dev-pulumi/node_modules/@pulumi/pulumi/ and prepare yarn link.

Integration tests require make install so yarn link can find the freshly built SDK.

Linting and formatting

Two layers:

  • Biome (sdk/nodejs/biome.json) — fast formatter and linter for JS/TS/JSON.
  • ESLint (sdk/nodejs/.eslintrc.js) — additional rules biome doesn't cover.

Both run as part of make lint.

Output semantics

const url: pulumi.Output<string> = bucket.bucket.apply(
  (b) => `https://${b}.s3.amazonaws.com/`
);

apply is called when the inner value is resolved. Outputs preserve secrets (the result is secret if any input was). Outputs preserve dependencies (the registered resource gets the union of input dependencies).

pulumi.all([a, b, c]).apply(([va, vb, vc]) => ...) is the standard "wait for many" pattern.

Dynamic providers — dynamic/

A unique-to-Node feature: write a provider entirely in user code by implementing dynamic.ResourceProvider. The Node language host serializes the provider class and runs it inline:

class MyProvider implements dynamic.ResourceProvider {
    async create(inputs: any) { ... }
    async diff(id: string, olds: any, news: any) { ... }
    // ...
}
class MyResource extends dynamic.Resource {
    constructor(name: string, args: ..., opts?: pulumi.CustomResourceOptions) {
        super(new MyProvider(), name, args, opts);
    }
}

This is implemented by a built-in dynamic provider on the host side — no separate plugin process. Implementation lives in sdk/nodejs/dynamic/.

Tests

  • tests/ — Mocha-based tests covering type behavior, configs, etc.
  • tests_with_mocks/ — tests that use the SDK's mock harness (sdk/nodejs/runtime/mocks.ts).
  • Integration tests in tests/integration/ (the engine repo's tests, not these) exercise Node SDK end-to-end against a real engine.

Entry points for modification

  • Adding a public API — touch index.ts (re-export) plus the implementing module.
  • Changing serializationruntime/rpc.ts. Property dependency tracking lives here.
  • A new dynamic provider primitivedynamic/. Be careful: dynamic providers run in the user's environment, not a separate plugin process.

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Node.js / TypeScript SDK – Pulumi wiki | Factory