Skip to content

feat(sdk-node): add Node.js SDK - #170

Merged
macalbert merged 72 commits into
mainfrom
feat/sdk-nodejs
Apr 30, 2026
Merged

feat(sdk-node): add Node.js SDK#170
macalbert merged 72 commits into
mainfrom
feat/sdk-nodejs

Conversation

@macalbert

@macalbert macalbert commented Apr 27, 2026

Copy link
Copy Markdown
Owner

Summary

Add the Node.js SDK (@envilder/sdk) — an independent, async-first runtime library that loads secrets from AWS SSM Parameter Store or Azure Key Vault directly into process.env. No .env files, no intermediaries. Works with both JavaScript and TypeScript projects.

Changes

SDK Source (src/sdks/nodejs/)

  • Domain: ISecretProvider interface (batch getSecrets), MapFileConfig, EnvilderOptions, ParsedMapFile, SecretProviderType enum
  • Application: Envilder async facade (load, resolveFile, fromMapFile + env-routing overloads), EnvilderClient core resolver, MapFileParser, validateSecrets opt-in validation
  • Infrastructure: AwsSsmSecretProvider (batch GetParametersCommand), AzureKeyVaultSecretProvider, createSecretProvider factory (internal)

Tests (tests/sdks/nodejs/)

  • 55 unit tests across 7 files (facade, client, parser, validation, providers, factory)
  • 4 acceptance tests using TestContainers (LocalStack for AWS, Lowkey Vault for Azure)
  • Should_<Expected>_When_<Condition> naming, AAA pattern

CI & Workflows

  • tests-nodejs-sdk.yml — runs all tests (unit + acceptance) on every PR and push to main
  • publish-npm-sdk.yml — publishes to npm with OIDC provenance on sdk-nodejs/v* tags
  • coverage-report.yml — Node.js SDK coverage section added

Website & Docs

  • SDK card, docs section, and changelog page for all 3 locales (en, es, ca)
  • i18n keys for Node.js SDK across all locales
  • ROADMAP, ADR, and changelogs updated

Supporting

  • pnpm-workspace.yaml and dependabot.yml updated
  • Copilot instructions and skills updated for Node.js SDK conventions
  • SDK release checklist skill added

Testing

  • pnpm build passes (SDK)
  • 55/55 unit tests pass
  • Biome formatting clean
  • Zero stale typescript-sdk references in codebase

Open in Devin Review

Summary by CodeRabbit

  • New Features
    • Introduced a Node.js SDK that loads secrets into runtime env, with AWS SSM and Azure Key Vault support, fluent builder API, env-based routing, and optional secret validation.
  • Documentation
    • Added Node.js SDK docs, examples, and initial changelog; added ADR standardizing SDK acceptance-test infrastructure.
  • Tests
    • Added extensive unit and acceptance tests and test container utilities for LocalStack and Lowkey Vault.
  • Chores
    • Website and tooling updates for SDK/version/changelog integration and test config scripts.

Domain types (ISecretProvider, MapFileConfig, EnvilderOptions,
ParsedMapFile, SecretProviderType), application layer (Envilder
facade, EnvilderClient, MapFileParser, validateSecrets), and
infrastructure (AwsSsmSecretProvider, AzureKeyVaultSecretProvider,
createSecretProvider factory).

Async-first API with fluent builder pattern. Supports AWS SSM
Parameter Store and Azure Key Vault. Published as @envilder/sdk.
46 tests covering MapFileParser (6), EnvilderClient (5),
SecretValidation (5), AwsSsmSecretProvider (5),
AzureKeyVaultSecretProvider (5), SecretProviderFactory (7),
and Envilder facade (13) with environment routing and fluent
builder. Vitest with vi.fn() mocks at port boundaries.
- Add TypeScript SDK to landing page (available status with code
  example and npm package link)
- Add #sdk-typescript docs section with install, quick start,
  resolve, fluent builder, env routing, and validation examples
- Add i18n translations for TypeScript SDK (en, ca, es)
- Add changelog infrastructure (sdk-typescript.md, astro config,
  env.d.ts type declaration)
- Move TypeScript SDK from Up Next to Shipped in ROADMAP.md
- Add TypeScript SDK section to copilot-instructions.md
Set root to repo root and use relative include patterns so v8 coverage
provider can instrument SDK source files. Also fix the resolve alias
path (was 2 levels up, needed 3).
Replace !x || !x.trim() with !x?.trim() in 7 locations across
facade, validation, providers, and factory modules.
Split all // Act & Assert combined comments into separate // Act and
// Assert phases. Rewrite try/catch test to use expect().toThrow().
Add missing Should_ResolveFromMappedFile_When_EnvMappingProvided test
for resolveFile with environment routing.
Add test-typescript-sdk job that runs vitest with v8 coverage and
generates lcov report. Wire into publish-report needs array, failure
check, and coverage-config.json gate (80% line threshold).
Add tests-typescript-sdk.yml: biome check, build, vitest run with
junit reporter, and dorny/test-reporter for PR annotations.
Add publish-npm-sdk.yml: version bump detection against npm registry,
lint + build + test gate, pnpm publish, git tag, GitHub Release.
Replace NPM_TOKEN secret with npm publish --provenance to match
the CLI publish workflow. OIDC is already configured via id-token
permission and registry-url in setup-node.
Change pre-push biome-format from read-only 'pnpm format' to
'pnpm format:write' so formatting issues are fixed automatically
instead of blocking the push.
The format:write in pre-push creates an infinite loop: it modifies
files without committing, so the next push triggers the same fix.
Pre-push must be read-only. Auto-fix belongs in pre-commit only.
vitest root is set to repo root in vitest.config.ts, so relative
outputFile paths resolve from there. Use github.workspace to write
test-results.xml at the repo root where dorny/test-reporter can
find it.
coverage-v8 resolves reportsDirectory relative to cwd, not vitest
root. Use github.workspace to write to a known absolute path.
Replace single-secret getSecret(name) with batch getSecrets(names[])
returning Map<string, string>. Missing secrets are silently omitted.

- AWS SSM: uses GetParametersCommand with batches of 10
- Azure KV: fetches in parallel via Promise.all
- EnvilderClient: single getSecrets() call instead of sequential loop
- Tests updated with 4 new cases (batch, empty, omit, parallel)
Chain biome format --write after biome check --write in the
pre-commit hook so formatting is always applied before commit.
Prevents pre-push format check from rejecting already committed code.

This comment was marked as resolved.

Use plain npm install + npm run for examples. No pnpm-workspace.yaml
needed — npm resolves @envilder/sdk from the registry independently.
…tion

Trim and convert empty/whitespace-only strings to undefined before
cross-provider validation checks and provider construction.
The options object is intentionally mutated by withProvider/withVaultUrl/
withProfile. Removing readonly to reflect actual usage.
Copilot AI review requested due to automatic review settings April 30, 2026 14:10
devin-ai-integration[bot]

This comment was marked as resolved.

This comment was marked as resolved.

Copilot AI review requested due to automatic review settings April 30, 2026 15:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
examples/sdk/nodejs/2_env_routing.ts (1)

13-15: ⚡ Quick win

Prefer masked output in examples instead of raw secret values.

Printing raw values (${value}) can leak secrets into terminal history and CI logs when users copy this sample.

♻️ Suggested patch
 for (const [key, value] of secrets) {
-  console.log(`${key} = ${value}`);
+  const masked = value.length > 3 ? `***${value.slice(-3)}` : '***';
+  console.log(`${key} = ${masked}`);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/sdk/nodejs/2_env_routing.ts` around lines 13 - 15, The example
currently logs raw secret values in the for loop iterating over secrets (for
(const [key, value] of secrets) { ... }) which can leak sensitive data; change
the console output to mask or redact the value (e.g., log `${key} = ****` or
show only last4 chars) instead of printing `${value}` so examples never emit
full secret values to terminal or CI logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@examples/sdk/nodejs/2_env_routing.ts`:
- Around line 13-15: The example currently logs raw secret values in the for
loop iterating over secrets (for (const [key, value] of secrets) { ... }) which
can leak sensitive data; change the console output to mask or redact the value
(e.g., log `${key} = ****` or show only last4 chars) instead of printing
`${value}` so examples never emit full secret values to terminal or CI logs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5f4a482b-b3e4-4a3d-b640-d2aa70c4bf4e

📥 Commits

Reviewing files that changed from the base of the PR and between ca91538 and fd2bc8b.

⛔ Files ignored due to path filters (2)
  • .github/workflows/coverage-report/extract-test-stats.mjs is excluded by none and included by none
  • examples/sdk/nodejs/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json and included by examples/**
📒 Files selected for processing (10)
  • examples/sdk/nodejs/1_fluent.ts
  • examples/sdk/nodejs/2_env_routing.ts
  • examples/sdk/nodejs/3_validation.ts
  • examples/sdk/nodejs/4_load.ts
  • examples/sdk/nodejs/5_resolve.ts
  • examples/sdk/nodejs/README.md
  • examples/sdk/nodejs/package.json
  • src/sdks/nodejs/package.json
  • src/sdks/nodejs/src/application/envilder.ts
  • src/sdks/nodejs/src/infrastructure/secret-provider-factory.ts
✅ Files skipped from review due to trivial changes (5)
  • examples/sdk/nodejs/4_load.ts
  • examples/sdk/nodejs/5_resolve.ts
  • examples/sdk/nodejs/README.md
  • src/sdks/nodejs/package.json
  • examples/sdk/nodejs/package.json

This comment was marked as resolved.

Ensures the workspace-locked Biome version is used, avoiding potential
version mismatches from npx resolution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants