Skip to content

refactor: update forwarder module to TS#1260

Open
jaissica12 wants to merge 9 commits into
developmentfrom
refactor/SDKE-1109-update-forwarders-to-TS
Open

refactor: update forwarder module to TS#1260
jaissica12 wants to merge 9 commits into
developmentfrom
refactor/SDKE-1109-update-forwarders-to-TS

Conversation

@jaissica12
Copy link
Copy Markdown
Contributor

@jaissica12 jaissica12 commented May 12, 2026

Background

  • Continuing the effort to migrate remaining JavaScript modules to TypeScript for improved type safety and developer experience across the SDK codebase.

What Has Changed

  • Converted src/forwarders.js to src/forwarders.ts with full type annotations on all methods, parameters, and return types
  • Updated src/forwarders.interfaces.ts with corrected and expanded interface definitions to support the conversion
  • Updated src/sdkRuntimeModels.ts with type adjustments needed for forwarder-related models
  • Updated src/store.ts with type refinements required by the forwarder module

Screenshots/Video

Screenshot 2026-05-20 at 11 30 43 PM Screenshot 2026-05-20 at 11 33 06 PM Screenshot 2026-05-20 at 11 33 59 PM Screenshot 2026-05-20 at 11 34 39 PM

Checklist

  • I have performed a self-review of my own code.
  • I have made corresponding changes to the documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have tested this locally.

Additional Notes

Reference Issue (For employees only. Ignore if you are an outside contributor)

@jaissica12 jaissica12 marked this pull request as ready for review May 21, 2026 02:45
@jaissica12 jaissica12 requested a review from a team as a code owner May 21, 2026 02:45
@cursor
Copy link
Copy Markdown

cursor Bot commented May 21, 2026

PR Summary

Medium Risk
Touches core kit forwarding, filtering, and batch paths; risk is mainly compile-time/cast regressions rather than intentional logic changes.

Overview
Migrates the kit forwarder implementation from JavaScript to TypeScript: forwarders.js becomes forwarders.ts with typed constructor (this: IForwarders), instance dependencies (IMParticleWebSDKInstance, KitBlocker), and annotations on event/batch forwarding, kit configuration (UI-enabled, sideloaded, pixels), and forwarding-stats upload.

forwarders.interfaces.ts gains a full IForwarders contract plus supporting types (SideloadedKit, expanded imports). ConfiguredKit now documents optional processBatch, initialized, and logger. sdkRuntimeModels adds optional filterUserIdentities on SDKHelpersApi to align helpers typing with forwarder usage.

Implementation detail: several internal calls use (method as Function)(...) and as unknown as ConfiguredKit[] so the legacy constructor pattern type-checks; sendBatchToForwarders switches from for...of to an indexed loop (same behavior).

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

Comment thread src/forwarders.ts Outdated
import { Batch } from '@mparticle/event-models';
import { IMParticleUser, ISDKUserIdentity } from './identity-user-interfaces';
import KitBlocker from './kitBlocking';
import { Dictionary } from './utils';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clean up these imports

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread src/forwarders.ts
}
if (
!self.isEnabledForUserAttributes(
!(this.isEnabledForUserAttributes as Function)(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do we need as Function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The method is defined later in the constructor body but called here, TS can't verify it exists at this point. Cast has no runtime effect, it's a TS workaround for the constructor-function pattern.

Comment thread src/forwarders.ts

// Check user attribute filtering rules
clonedEvent.UserAttributes = KitFilterHelper.filterUserAttributes(
clonedEvent.UserAttributes = (KitFilterHelper.filterUserAttributes as Function)(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here. This feels like we're trying to bypass type safety.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Type mismatch: UserAttributes is string | string[] | null values, but filterUserAttributes expects string only. Cast avoids the TS error, I thought fixing the signature in KitFilterHelper is out of scope for this migration.

Comment thread src/forwarders.ts
}

for (const forwarder of mpInstance._Store.activeForwarders) {
for (
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a reason we needed to change this to a standard for loop?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reverted to the original for...of loop.

Comment thread src/forwarders.ts Outdated

if (result) {
mpInstance.Logger.verbose(result);
mpInstance.Logger.verbose(result as string);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Isn't this already a string?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, forwarder.process() and forwarder.processBatch() already return string per the interface, so as string is unnecessary there. Removed it from processBatch.

Comment thread src/forwarders.ts Outdated
// sideloaded kits, this will need to be refactored.
this.processSideloadedKits = function(mpConfig) {
this.processSideloadedKits = function(
mpConfig: IConfigResponse & { sideloadedKits?: { kitInstance: { register: Function; name: string }; filterDictionary: IKitFilterSettings }[] }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If we don't have a type for this, let's make one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Created a SideloadedKit interface in forwarders.interfaces.ts that reuses the existing UnregisteredKit type. Replaced the inline type.

Comment thread src/sdkRuntimeModels.ts Outdated
endSession(): void;
init(apiKey: string, config: SDKInitConfig, instanceName?: string): void;
_getActiveForwarders(): ConfiguredKit[];
_getActiveForwarders(): MPForwarder[];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's be careful with this because MPForwarder and ConfiguredKit might have specific "contracts".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, reverted to ConfiguredKit[]. Active forwarders have gone through configuration, so ConfiguredKit is the correct contract. The MPForwarder (Dictionary) type was too loose.

Comment thread src/sdkRuntimeModels.ts Outdated
name: string
): Dictionary<string> | null;
filterUserIdentities?(
userIdentitiesObject: Record<string, string>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we may have this type defined for this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated to use Dictionary, which is already used in kitFilterHelper.ts for the same purpose and is already imported in this file.

@jaissica12 jaissica12 force-pushed the refactor/SDKE-1109-update-forwarders-to-TS branch from 94f8634 to d614b96 Compare May 25, 2026 23:10
Comment thread src/sdkRuntimeModels.ts
filterUserIdentities?(
userIdentitiesObject: Dictionary<string>,
filterList: number[]
): ISDKUserIdentity[];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wrong parameter type for filterUserIdentities declaration

Medium Severity

The newly added filterUserIdentities type declaration specifies userIdentitiesObject: Dictionary<string> as its first parameter, but all callers in forwarders.ts pass ISDKUserIdentity[] (an array of user identity objects, not a string dictionary). This incorrect type definition misrepresents the actual API contract and will mislead any future TypeScript consumer relying on this interface for type checking.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d614b96. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The Dictionary type matches the actual implementation in helpers.js - it iterates with for...in and Object.keys(), expecting an object like { email: "foo@bar.com" }. The callers in forwarders.ts pass ISDKUserIdentity[] which is a pre-existing type mismatch in the JS codebase - the as Function casts already bypass the type check. Fixing this properly would require refactoring helpers.filterUserIdentities to accept both shapes, which is out of scope for this migration.

Comment thread src/store.ts Outdated
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 and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 1ba077d. Configure here.

Comment thread src/forwarders.ts
@sonarqubecloud
Copy link
Copy Markdown

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.

3 participants