Skip to content

chore: adding the implementation for main process client#1103

Open
joker23 wants to merge 3 commits intomainfrom
skz/electron-add-main-process-client
Open

chore: adding the implementation for main process client#1103
joker23 wants to merge 3 commits intomainfrom
skz/electron-add-main-process-client

Conversation

@joker23
Copy link
Contributor

@joker23 joker23 commented Feb 13, 2026

This PR will:

  • add the LD client implementation that runs in the main process
  • add in the docs on how we are going to implement the renderer clients
  • add testing for the client when running without renderers

NOTE: most of the additions are unit tests and documentation


Note

Medium Risk
Touches core SDK initialization/identify and connection-management paths, which can impact flag delivery and event sending; mitigated by substantial new unit tests covering bootstrap, modes, and credential behaviors.

Overview
Adds a new Electron main-process LaunchDarkly client (ElectronClient + createClient) that requires start() before use, supports bootstrap flag seeding, and exposes connection mode controls (offline/polling/streaming) with appropriate event/processor behavior.

Introduces Electron-specific option validation (enableIPC, initialConnectionMode, useClientSideId, plugins) and a new ElectronDataManager that handles bootstrap+cache identify flow and switches between polling/streaming processors.

Adds extensive unit coverage for main-process usage without IPC, credential-type URL/header behavior (mobile key vs useClientSideId), plugin hook registration/execution, bootstrap parsing, and option validation, plus temporary migration/IPC architecture documentation.

Written by Cursor Bugbot for commit 50b7675. This will update automatically on new commits. Configure here.

@joker23 joker23 requested a review from a team as a code owner February 13, 2026 21:02
@github-actions
Copy link
Contributor

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 25394 bytes
Compressed size limit: 26000
Uncompressed size: 124693 bytes

@github-actions
Copy link
Contributor

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

@github-actions
Copy link
Contributor

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

@github-actions
Copy link
Contributor

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 23334 bytes
Compressed size limit: 25000
Uncompressed size: 81070 bytes

}
});
return ret;
}
Copy link

Choose a reason for hiding this comment

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

Duplicated bootstrap.ts from browser SDK package

Low Severity

The readFlagsFromBootstrap function is an exact character-for-character copy of packages/sdk/browser/src/bootstrap.ts. This duplication means any future bug fix or improvement to bootstrap parsing needs to be applied in both places. This function could be extracted into @launchdarkly/js-client-sdk-common to avoid the duplication.

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tracking as sdk-1874

() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return useClientSideId
? `/sdk/evalx/${credential}/contexts/${base64UrlEncode(_plainContextString, encoding)}`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is where we are letting developers define whether they are using client side sdk or the default mobile sdk. I have a task open to clarify that secure mode is only available if you are using client side id (SDK-1875)

Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we could hoist the paths up to a higher packages and then import the correct ones. It should be tree shake-able.

I like having a file with like "this is all the mobile stuff" then using that for RN and electron. Using the client-side id stuff for browser and electron.

Similar to the flutter pattern.
https://github.com/launchdarkly/flutter-client-sdk/blob/fa48b8e2b833b51c4201b4803701a7cc8ec3efec/packages/common_client/lib/src/config/defaults/io_config.dart#L6

https://github.com/launchdarkly/flutter-client-sdk/blob/fa48b8e2b833b51c4201b4803701a7cc8ec3efec/packages/common_client/lib/src/config/defaults/js_config.dart

Copy link
Member

Choose a reason for hiding this comment

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

Could be a task + followup.

* Builds the LaunchDarkly client facade (PIMPL). Exposes a single identify method that returns
* identify results. Plugins are registered with the facade.
*/
export function makeClient(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this file should be very similar to the browser client sdk

this.setEventSendingEnabled(!this.isOffline(), false);

if (validatedElectronOptions.enableIPC) {
// Not implemented yet
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Separated this out to the next PR since we will probably have the most concerns there

Copy link

@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 and found 2 potential issues.

} catch (error) {
this.logger.error('Failed to bootstrap data', error);
}
}
Copy link

Choose a reason for hiding this comment

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

Redundant bootstrap processing in start() method

Low Severity

The bootstrap processing block in start() (parsing via readFlagsFromBootstrap and calling presetFlags) is entirely redundant. start() immediately calls this.identifyResult() on line 195, which contains an identical bootstrap processing block that re-parses (if needed) and calls presetFlags again with the same data. Since both are synchronous and execute sequentially, the block in start() provides no timing benefit and just duplicates logic that identifyResult() already handles.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Member

Choose a reason for hiding this comment

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

I assume this is a result of the synchronous availability changes. We may just want some comments to help human and robot alike.

getConnectionMode(): ConnectionMode {
return this.connectionMode;
}
}
Copy link

Choose a reason for hiding this comment

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

ElectronDataManager duplicates MobileDataManager almost entirely

Low Severity

ElectronDataManager is a near-verbatim copy of MobileDataManager from the React Native SDK. The _setupConnection, setConnectionMode, getConnectionMode, setNetworkAvailability, _debugLog methods and the core identify flow (cache loading, offline handling, connection setup) are identical. Only bootstrap handling is Electron-specific. This risks inconsistent bug fixes across the two data managers.

Fix in Cursor Fix in Web

const logTag = '[ElectronDataManager]';

export default class ElectronDataManager extends BaseDataManager {
// Not implemented yet.
Copy link
Member

Choose a reason for hiding this comment

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

Should we attach a ticket to this? (Though we may also choose not to implement this, which maybe would be a little different comment).

Copy link
Member

Choose a reason for hiding this comment

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

I agree with the bot analysis that this likely could be a shared configuration of the MobileDataManager.

That said, with the client-side FDv2 work, I am going to see if we can change this pattern to reduce the complexity of customizing the data manager.

Maybe some more composable approach that allows configuring conditions in different ways. So I wouldn't worry about it too much right now.

// NOTE: we can choose to validate events with a whitelist? However, this might be
// more for the implementers to do.

// TODO: we will need to refactor the verbiage of client side id to mobile key in the future.
Copy link
Member

Choose a reason for hiding this comment

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

Did you already do this?

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