Skip to content

chore: scaffolding node-client-sdk migration#1352

Merged
joker23 merged 2 commits into
mainfrom
skz/sdk-2195/node-client-sdk-next-scaffold
May 26, 2026
Merged

chore: scaffolding node-client-sdk migration#1352
joker23 merged 2 commits into
mainfrom
skz/sdk-2195/node-client-sdk-next-scaffold

Conversation

@joker23
Copy link
Copy Markdown
Contributor

@joker23 joker23 commented May 4, 2026

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

Provide links to any issues in this repository or elsewhere relating to this pull request.

Describe the solution you've provided

Provide a clear and concise description of what you expect to happen.

Describe alternatives you've considered

Provide a clear and concise description of any alternative solutions or features you've considered.

Additional context

Add any other context about the pull request here.


Note

Low Risk
Adds a new workspace and release metadata with no runtime SDK behavior or changes to existing packages beyond repo configuration.

Overview
Introduces @launchdarkly/node-client-sdk at packages/sdk/node-client as the first step of a Node client-side SDK migration. The package is wired into the monorepo (root workspaces, root tsconfig project reference, .release-please-manifest at 0.0.1, and release-please-config with bump-minor-pre-major and version bumps in src/index.ts).

The new package ships build/lint/docs scaffolding (tsup ESM+CJS, TypeScript configs, Typedoc, ESLint override for future contract tests) plus LICENSE, CHANGELOG, and a README that marks the SDK as experimental / not production-ready. The public entry point is a placeholder: src/index.ts only exports a version constant; comments note that createClient, logging, and types land in a follow-up (SDK-2312).

Reviewed by Cursor Bugbot for commit 0a15d58. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 26389 bytes
Compressed size limit: 29000
Uncompressed size: 129320 bytes

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

@launchdarkly/browser size report
This is the brotli compressed size of the ESM build.
Compressed size: 179496 bytes
Compressed size limit: 200000
Uncompressed size: 830875 bytes

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 38516 bytes
Compressed size limit: 39000
Uncompressed size: 211129 bytes

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 31870 bytes
Compressed size limit: 34000
Uncompressed size: 113696 bytes

@joker23
Copy link
Copy Markdown
Contributor Author

joker23 commented May 4, 2026

@cursor review

cursor[bot]

This comment was marked as resolved.

@joker23 joker23 force-pushed the skz/sdk-2195/node-client-sdk-next-scaffold branch from fb8608c to 9193aa8 Compare May 4, 2026 21:19
@joker23
Copy link
Copy Markdown
Contributor Author

joker23 commented May 4, 2026

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 9193aa8. Configure here.

@joker23 joker23 marked this pull request as ready for review May 4, 2026 21:57
@joker23 joker23 requested a review from a team as a code owner May 4, 2026 21:57
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@joker23 joker23 force-pushed the skz/sdk-2195/node-client-sdk-next-scaffold branch from 9193aa8 to 390d00b Compare May 26, 2026 18:07
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 390d00b. Configure here.

@@ -0,0 +1,6 @@
// Placeholder entry point for @launchdarkly/node-client-sdk. The functional
// implementation (createClient, basicLogger, type re-exports) is added in
// the source-port slice (SDK-2312); this file exists so the package builds
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Internal identifier SDK-2312 referenced in code comment

Low Severity

The comment references SDK-2312, an opaque internal identifier (likely a Jira ticket). Internal identifiers are meaningless to external/OSS consumers and become stale over time. The comment could instead directly describe what the source-port slice will add without referencing the ticket number.

Fix in Cursor Fix in Web

Triggered by learned rule: Do not reference internal specification documents in code comments

Reviewed by Cursor Bugbot for commit 390d00b. Configure here.

@joker23 joker23 force-pushed the skz/sdk-2195/node-client-sdk-next-scaffold branch from 861ad18 to 0a15d58 Compare May 26, 2026 22:11
@joker23 joker23 merged commit f1729bb into main May 26, 2026
43 checks passed
@joker23 joker23 deleted the skz/sdk-2195/node-client-sdk-next-scaffold branch May 26, 2026 22:21
joker23 added a commit that referenced this pull request May 26, 2026
joker23 added a commit that referenced this pull request May 28, 2026
joker23 added a commit that referenced this pull request May 28, 2026
Holistic-branch commit containing the entire migration of the
standalone launchdarkly/node-client-sdk repo into the js-core monorepo
as @launchdarkly/node-client-sdk. Sliced for review into atomic PRs per
the stack manifest at .claude/stacked-pr/plan.json (SDK-2309..SDK-2315).
This commit shrinks as each atomic PR merges to main and the holistic
branch is rebased.

Contents:
- packages/sdk/node-client/ -- the new SDK workspace
  - Modern js-core layout: tsup dual ESM/CJS, ts-jest, eslint, typedoc
  - tsconfig uses module=ESNext + moduleResolution=bundler (tsup
    handles emit), types=[jest, node], skipLibCheck
  - src/ ports the legacy SDK onto @launchdarkly/js-client-sdk-common
  - Public API: createClient + start (no auto-start), basicLogger,
    version, plus export * from common
  - Node-specific options: localStoragePath, tlsParams (10-key
    whitelist), hash for Secure Mode
  - platform/ adapts NodeCrypto/Info/Requests/Response/HeaderWrapper
    from packages/sdk/server-node and adds an fs/promises-backed
    NodeStorage with the no-throw storage contract. Storage is a
    process-level singleton matching the electron pattern, with an
    @internal resetNodeStorage exported for tests.
  - __tests__/ smoke test
  - examples/hello-node-client/ following the EXAM/HELLO spec:
    streaming flag-change listener, continuous-run mode with CI
    opt-out, ASCII LAUNCHDARKLY banner on true, env-var-driven
    credentials and flag key, tsconfig=nodenext for the ESM example
  - contract-tests/ with sdk-test-harness service entity. Includes
    run-contract-tests.sh for one-command local runs, npm scripts
    (contract-tests, contract-test-service), bridging in
    sdkClientEntity.ts that maps options.polling -> polling mode,
    options.hooks[] -> ClientSideTestHook instances, and disables
    the per-process flag cache so tests don't bleed state into each
    other. testharness-suppressions.txt suppresses three hook
    ordering tests pending an upstream fix in js-contract-test-utils.
  - temp_docs/MIGRATION.md describing the v3 -> v4 breaking changes
- .github/workflows/node-client.yml -- CI build/lint/test plus
  contract-tests run, mirroring server-node.yml
- Root package.json workspaces, tsconfig.json references, and
  release-please-config extra-files wired up;
  .release-please-manifest seeded at 0.0.1 (this is treated as a
  fresh package; release-please will track from there)

BREAKING CHANGE: Package is renamed from launchdarkly-node-client-sdk to
@launchdarkly/node-client-sdk and rebuilt on the modern
@launchdarkly/js-client-sdk-common (FDv2-capable). Initialization now
uses the createClient + start pattern: createClient returns a client
that is not yet started, and the caller must await client.start()
before the first variation or identify call. identify() now resolves
to LDIdentifyResult instead of throwing. Minimum Node version is now
18. The persistent cache file format changed from node-localstorage's
per-key files to a single JSON file in the same directory; existing
v3 cache data will not be read.

chore: Mark scaffold slice merged (PR #1352)

chore: Mark port-platform slice in-flight (PR #1393)

chore: Replan stack -- add contract-tests-features and storage-override slices

- New `contract-tests-features` slice after `contract-tests` exercising
  hooks, identify result statuses, connection-mode switching, and FDv2
  init markers + fallback.
- New `storage-override` slice (SDK-2420) after `hello` providing
  caller-supplied storage override on NodeOptions.
- per-slice MIGRATION.md updates: port-client owns hooks / inspectors /
  plugins / connection-mode / applicationInfo / proxy / TLS sections;
  storage-override owns its own section; archive becomes the final
  doc-pass.
- Manifest now declares `tool: "sculptor"` so the SessionStart
  watch-arm hook activates for future cycles.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

chore: Reconcile holistic with PR #1393 reviewed content + manifest scope-update

- Took PR #1393's reviewed source content as authoritative for the
  port-platform-only files: NodeInfo, NodePlatform, NodeRequests,
  NodeResponse, NodeStorage. The atomic's post-review versions
  (e.g., sdkName = 'node-client-sdk', NodeStorage logger param,
  direct getNodeStorage wiring) replace holistic's pre-review state.
  Reconciliation follows the same pattern advance uses when rebasing
  onto main.
- release-please-config.json reverted to atomic's version (re-adds
  src/platform/NodeInfo.ts to extra-files for release-please version
  bumping).
- Added atomic's PR-review additions: 10 platform unit tests under
  __tests__/platform/, __tests__/testHelpers.ts, and a package-level
  .gitignore. All 58 tests pass.
- Manifest port-platform paths expanded to reflect actual ship scope
  (unit tests + .gitignore + testHelpers added during review);
  contract-tests-features.jira_subtask set to SDK-2422.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

feat: Add storage override on NodeOptions (SDK-2420)

Replaces `localStoragePath` with a discriminated `storage` option:

  storage?:
    | { type: 'file'; localStoragePath?: string }
    | { type: 'custom'; implementation: Storage }

- `undefined` or `{ type: 'file' }` -> file-backed default at
  `<cwd>/ldclient-user-cache`.
- `{ type: 'file', localStoragePath: '/path' }` -> file-backed at
  the given path.
- `{ type: 'custom', implementation }` -> caller-supplied store.

Re-exports the common `Storage` interface as `LDStorage` so consumers
can type their own implementations without depending on common.

Adds 10 new unit tests; all 68 tests pass. Lint and build are clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

test: Declare common-base capabilities and wire harness commands

Adds capability declarations for the new common-base features that
were missing from node-client's contract-test surface:

- anonymous-redaction
- strongly-typed
- event-gzip
- flag-change-listeners
- tls:skip-verify-peer
- tls:custom-ca

Wires the corresponding config + command handlers in sdkClientEntity:

- makeSdkConfig: TLS options (skipVerifyPeer / customCAFile),
  proxy options (httpProxy URL -> proxyOptions), event-gzip
  (enableGzip -> enableEventCompression).
- doCommand: RegisterFlagChangeListener (binds client.on('change'),
  fans out per-flag POSTs to the callback URI) and UnregisterListener.

Also registers `packages/sdk/node-client/contract-tests` as a yarn
workspace in root package.json so `yarn workspace
@launchdarkly/node-client-sdk-contract-tests build` actually resolves.
This belongs to the contract-tests slice; the manifest has been
updated to claim root package.json with a single-line extraction
note.

The `http-proxy` capability is intentionally left undeclared --
node-client's NodeRequests only routes HTTPS targets through the
proxy (https-proxy-agent), so the harness's HTTP-target proxy
tests fail. Tracked separately as SDK-2423; the line in index.ts
references the follow-up.

Manifest also updated: contract-tests-features slice's paths now
include contract-tests/src/index.ts (capability declarations live
there), and its provides / extraction_notes reflect the revised
scope.

Harness baseline: 841 tests passed, 18 skipped, 0 failed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

docs: Add MIGRATION sections for new common-base features

Adds seven sections documenting feature surfaces that are new in
node-client (relative to the legacy launchdarkly-node-client-sdk)
and that are introduced by the port-client slice:

- Evaluation, identify, and track hooks (Hook type + addHook method)
- Inspectors (with deprecation note pointing to hooks)
- Plugins and application metadata (LDPlugin + applicationInfo)
- Runtime connection-mode control (setConnectionMode / getConnectionMode)
- HTTP proxy options (proxyOptions, with note on HTTPS-target-only)
- TLS configuration (tlsParams; fields mirror Node's https.request)
- (Storage configuration already documented as part of SDK-2420)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
joker23 added a commit that referenced this pull request May 28, 2026
Holistic-branch commit containing the entire migration of the
standalone launchdarkly/node-client-sdk repo into the js-core monorepo
as @launchdarkly/node-client-sdk. Sliced for review into atomic PRs per
the stack manifest at .claude/stacked-pr/plan.json (SDK-2309..SDK-2315).
This commit shrinks as each atomic PR merges to main and the holistic
branch is rebased.

Contents:
- packages/sdk/node-client/ -- the new SDK workspace
  - Modern js-core layout: tsup dual ESM/CJS, ts-jest, eslint, typedoc
  - tsconfig uses module=ESNext + moduleResolution=bundler (tsup
    handles emit), types=[jest, node], skipLibCheck
  - src/ ports the legacy SDK onto @launchdarkly/js-client-sdk-common
  - Public API: createClient + start (no auto-start), basicLogger,
    version, plus export * from common
  - Node-specific options: localStoragePath, tlsParams (10-key
    whitelist), hash for Secure Mode
  - platform/ adapts NodeCrypto/Info/Requests/Response/HeaderWrapper
    from packages/sdk/server-node and adds an fs/promises-backed
    NodeStorage with the no-throw storage contract. Storage is a
    process-level singleton matching the electron pattern, with an
    @internal resetNodeStorage exported for tests.
  - __tests__/ smoke test
  - examples/hello-node-client/ following the EXAM/HELLO spec:
    streaming flag-change listener, continuous-run mode with CI
    opt-out, ASCII LAUNCHDARKLY banner on true, env-var-driven
    credentials and flag key, tsconfig=nodenext for the ESM example
  - contract-tests/ with sdk-test-harness service entity. Includes
    run-contract-tests.sh for one-command local runs, npm scripts
    (contract-tests, contract-test-service), bridging in
    sdkClientEntity.ts that maps options.polling -> polling mode,
    options.hooks[] -> ClientSideTestHook instances, and disables
    the per-process flag cache so tests don't bleed state into each
    other. testharness-suppressions.txt suppresses three hook
    ordering tests pending an upstream fix in js-contract-test-utils.
  - temp_docs/MIGRATION.md describing the v3 -> v4 breaking changes
- .github/workflows/node-client.yml -- CI build/lint/test plus
  contract-tests run, mirroring server-node.yml
- Root package.json workspaces, tsconfig.json references, and
  release-please-config extra-files wired up;
  .release-please-manifest seeded at 0.0.1 (this is treated as a
  fresh package; release-please will track from there)

BREAKING CHANGE: Package is renamed from launchdarkly-node-client-sdk to
@launchdarkly/node-client-sdk and rebuilt on the modern
@launchdarkly/js-client-sdk-common (FDv2-capable). Initialization now
uses the createClient + start pattern: createClient returns a client
that is not yet started, and the caller must await client.start()
before the first variation or identify call. identify() now resolves
to LDIdentifyResult instead of throwing. Minimum Node version is now
18. The persistent cache file format changed from node-localstorage's
per-key files to a single JSON file in the same directory; existing
v3 cache data will not be read.

chore: Mark scaffold slice merged (PR #1352)

chore: Mark port-platform slice in-flight (PR #1393)

chore: Replan stack -- add contract-tests-features and storage-override slices

- New `contract-tests-features` slice after `contract-tests` exercising
  hooks, identify result statuses, connection-mode switching, and FDv2
  init markers + fallback.
- New `storage-override` slice (SDK-2420) after `hello` providing
  caller-supplied storage override on NodeOptions.
- per-slice MIGRATION.md updates: port-client owns hooks / inspectors /
  plugins / connection-mode / applicationInfo / proxy / TLS sections;
  storage-override owns its own section; archive becomes the final
  doc-pass.
- Manifest now declares `tool: "sculptor"` so the SessionStart
  watch-arm hook activates for future cycles.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

chore: Reconcile holistic with PR #1393 reviewed content + manifest scope-update

- Took PR #1393's reviewed source content as authoritative for the
  port-platform-only files: NodeInfo, NodePlatform, NodeRequests,
  NodeResponse, NodeStorage. The atomic's post-review versions
  (e.g., sdkName = 'node-client-sdk', NodeStorage logger param,
  direct getNodeStorage wiring) replace holistic's pre-review state.
  Reconciliation follows the same pattern advance uses when rebasing
  onto main.
- release-please-config.json reverted to atomic's version (re-adds
  src/platform/NodeInfo.ts to extra-files for release-please version
  bumping).
- Added atomic's PR-review additions: 10 platform unit tests under
  __tests__/platform/, __tests__/testHelpers.ts, and a package-level
  .gitignore. All 58 tests pass.
- Manifest port-platform paths expanded to reflect actual ship scope
  (unit tests + .gitignore + testHelpers added during review);
  contract-tests-features.jira_subtask set to SDK-2422.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

feat: Add storage override on NodeOptions (SDK-2420)

Replaces `localStoragePath` with a discriminated `storage` option:

  storage?:
    | { type: 'file'; localStoragePath?: string }
    | { type: 'custom'; implementation: Storage }

- `undefined` or `{ type: 'file' }` -> file-backed default at
  `<cwd>/ldclient-user-cache`.
- `{ type: 'file', localStoragePath: '/path' }` -> file-backed at
  the given path.
- `{ type: 'custom', implementation }` -> caller-supplied store.

Re-exports the common `Storage` interface as `LDStorage` so consumers
can type their own implementations without depending on common.

Adds 10 new unit tests; all 68 tests pass. Lint and build are clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

test: Declare common-base capabilities and wire harness commands

Adds capability declarations for the new common-base features that
were missing from node-client's contract-test surface:

- anonymous-redaction
- strongly-typed
- event-gzip
- flag-change-listeners
- tls:skip-verify-peer
- tls:custom-ca

Wires the corresponding config + command handlers in sdkClientEntity:

- makeSdkConfig: TLS options (skipVerifyPeer / customCAFile),
  proxy options (httpProxy URL -> proxyOptions), event-gzip
  (enableGzip -> enableEventCompression).
- doCommand: RegisterFlagChangeListener (binds client.on('change'),
  fans out per-flag POSTs to the callback URI) and UnregisterListener.

Also registers `packages/sdk/node-client/contract-tests` as a yarn
workspace in root package.json so `yarn workspace
@launchdarkly/node-client-sdk-contract-tests build` actually resolves.
This belongs to the contract-tests slice; the manifest has been
updated to claim root package.json with a single-line extraction
note.

The `http-proxy` capability is intentionally left undeclared --
node-client's NodeRequests only routes HTTPS targets through the
proxy (https-proxy-agent), so the harness's HTTP-target proxy
tests fail. Tracked separately as SDK-2423; the line in index.ts
references the follow-up.

Manifest also updated: contract-tests-features slice's paths now
include contract-tests/src/index.ts (capability declarations live
there), and its provides / extraction_notes reflect the revised
scope.

Harness baseline: 841 tests passed, 18 skipped, 0 failed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

docs: Add MIGRATION sections for new common-base features

Adds seven sections documenting feature surfaces that are new in
node-client (relative to the legacy launchdarkly-node-client-sdk)
and that are introduced by the port-client slice:

- Evaluation, identify, and track hooks (Hook type + addHook method)
- Inspectors (with deprecation note pointing to hooks)
- Plugins and application metadata (LDPlugin + applicationInfo)
- Runtime connection-mode control (setConnectionMode / getConnectionMode)
- HTTP proxy options (proxyOptions, with note on HTTPS-target-only)
- TLS configuration (tlsParams; fields mirror Node's https.request)
- (Storage configuration already documented as part of SDK-2420)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
joker23 added a commit that referenced this pull request May 29, 2026
## Summary
- Adds the Node platform abstraction layer for
`@launchdarkly/node-client-sdk`: `HeaderWrapper`, `NodeCrypto`,
`NodeEncoding`, `NodeInfo`, `NodePlatform`, `NodeRequests`,
`NodeResponse`, `NodeStorage`. These implement the `Platform` contract
from `@launchdarkly/js-client-sdk-common`.
- Adds runtime dependencies the platform code imports:
`@launchdarkly/js-client-sdk-common`, `https-proxy-agent`,
`launchdarkly-eventsource`.
- Modernizes `packages/sdk/node-client/tsconfig.json` to `module:
ESNext` + `moduleResolution: bundler` (tsup handles emit), adds
`esModuleInterop`, `types: ["jest", "node"]`, `skipLibCheck`. Matches
the pattern used by `packages/sdk/server-ai`.
- Part of the SDK-2195 stacked migration of
`launchdarkly-node-client-sdk` into js-core. Follows PR #1352
(scaffold).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> New TLS, HTTP streaming, and on-disk cache behavior affect runtime
networking and local persistence, though it is isolated behind platform
interfaces and covered by unit tests; the public client API is not wired
yet.
> 
> **Overview**
> Adds the **Node platform layer** for `@launchdarkly/node-client-sdk`
so the package can plug into `@launchdarkly/js-client-sdk-common`:
`NodePlatform` wires **info**, **crypto**, **encoding**, **file-backed
storage**, and **HTTP/HTTPS + EventSource** requests. New `NodeOptions`
covers **TLS** (`tlsParams`), optional **POST gzip** for events, and
**`localStoragePath`** (default `ldclient-user-cache`).
> 
> `NodeRequests` / `NodeResponse` implement fetch-like behavior
(timeouts, gzip on GET, optional body compression, custom CA for HTTPS)
via `launchdarkly-eventsource`. `NodeStorage` persists a JSON cache with
atomic writes and a process singleton.
> 
> Also adds **Jest** coverage for the platform modules, a
**`sdk/node-client` GitHub Actions** job (Node 18 & 22), package
**test** script and dependencies, **tsconfig** shift to `ESNext` /
`bundler`, and **release-please** bumping `NodeInfo.ts` for version
stamps.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
eb89832. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants