Skip to content

Conversation

@lposen
Copy link
Contributor

@lposen lposen commented Oct 20, 2025

🔹 JIRA Ticket(s) if any

✏️ Description

Adds a token generator

Testing

  • Run the example app on ios and android
  • Logging in should work

@lposen lposen requested a review from Copilot October 20, 2025 22:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements JWT token generation functionality for the Iterable SDK, enabling support for JWT-enabled API keys. The implementation includes TypeScript type definitions, native iOS and Android implementations, and comprehensive test coverage.

  • Adds JWT token generator method accessible via IterableAuthManager.generateJwtToken()
  • Implements native token generation for both iOS (Swift) and Android (Java) platforms
  • Updates example app to demonstrate JWT authentication flow

Reviewed Changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/index.tsx Exports new IterableGenerateJwtTokenArgs type
src/core/types/index.ts Re-exports JWT token arguments type
src/core/types/IterableGenerateJwtTokenArgs.ts Defines TypeScript type for JWT token generation parameters with email/userId union
src/core/classes/IterableAuthManager.ts Adds generateJwtToken method with comprehensive documentation
src/core/classes/IterableApi.ts Implements static generateJwtToken method and corrects typo in comment
src/core/classes/Iterable.ts Removes unused timeout variable and cleanup code
src/api/NativeRNIterableAPI.ts Defines native module interface for JWT token generation
src/__tests__/IterableAuthManager.test.ts Adds comprehensive test suite for auth manager functionality
src/__mocks__/MockRNIterableAPI.ts Implements mock for JWT token generation testing
ios/RNIterableAPI/ReactIterableAPI.swift Implements native iOS JWT generation with validation
ios/RNIterableAPI/RNIterableAPI.mm Bridges Swift implementation to React Native
example/src/hooks/useIterableApp.tsx Demonstrates JWT auth handler usage in example app
example/README.md Updates documentation with JWT setup instructions
example/.env.example Adds JWT secret configuration template
android/src/oldarch/java/com/RNIterableAPIModule.java Adds JWT generation method to old architecture module
android/src/newarch/java/com/RNIterableAPIModule.java Adds JWT generation method to new architecture module
android/src/main/java/com/iterable/reactnative/RNIterableAPIModuleImpl.java Implements Android JWT token generation logic

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

userId: userId
)
} else if let email = email {
token = IterableTokenGenerator.generateJwtForEial(
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'generateJwtForEial' to 'generateJwtForEmail'.

Suggested change
token = IterableTokenGenerator.generateJwtForEial(
token = IterableTokenGenerator.generateJwtForEmail(

Copilot uses AI. Check for mistakes.
1. Sign into your Iterable account
2. Go to [Integrations > API Keys](https://app.iterable.com/settings/apiKeys)
3. Click "New API Key" in the top right corner
4. Fill in the followsing fields:
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'followsing' to 'following'.

Suggested change
4. Fill in the followsing fields:
4. Fill in the following fields:

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

Lines Statements Branches Functions
Coverage: 57%
57.5% (318/553) 30.45% (67/220) 56.37% (115/204)

@Ayyanchira
Copy link
Member

We might have to re-consider JWT generator in native SDKs. Idea of JWT is that tokens will be generated on Client's server side. The generator on client side was just for testing purpose and should have lived in the Tester apps for purpose of test. Will need to investigate how native layer jwt generation code made it to public SDK

@lposen lposen added the jwt label Oct 20, 2025
@qltysh
Copy link

qltysh bot commented Oct 21, 2025

3 new issues

Tool Category Rule Count
qlty Structure High total complexity (count = 56) 1
qlty Structure Function with high complexity (count = 7): generateJwtToken 1
qlty Structure Function with many returns (count = 9): IterableAppProvider 1

This is from Qlty Cloud, the successor to Code Climate Quality. Learn more.

@qltysh
Copy link

qltysh bot commented Oct 21, 2025

❌ 3 blocking issues (6 total)

Tool Category Rule Count
eslint Lint Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
3
qlty Structure High total complexity (count = 56) 1
qlty Structure Function with high complexity (count = 7): generateJwtToken 1
qlty Structure Function with many returns (count = 9): IterableAppProvider 1

This is from Qlty Cloud, the successor to Code Climate Quality. Learn more.

Comment on lines +600 to +619
public void generateJwtToken(ReadableMap opts, Promise promise) {
try {
String secret = opts.getString("secret");
long durationMs = (long) opts.getDouble("duration");
String userId = opts.hasKey("userId") && !opts.isNull("userId") ? opts.getString("userId") : null;
String email = opts.hasKey("email") && !opts.isNull("email") ? opts.getString("email") : null;

// Validate that exactly one of userId or email is provided
if ((userId != null && email != null) || (userId == null && email == null)) {
promise.reject("E_INVALID_ARGS", "The token must include a userId or email, but not both.", (Throwable) null);
return;
}

// Use the Android SDK's Duration-based JWT generator
Duration duration = Duration.ofMillis(durationMs);
String token = IterableJwtGenerator.generateToken(secret, duration, email, userId);
promise.resolve(token);
} catch (Exception e) {
promise.reject("E_JWT_GENERATION_FAILED", "Failed to generate JWT: " + e.getMessage(), e);
}
Copy link

Choose a reason for hiding this comment

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

Function with high complexity (count = 7): generateJwtToken [qlty:function-complexity]

@@ -0,0 +1,186 @@
import { MockRNIterableAPI } from '../__mocks__/MockRNIterableAPI';
Copy link

Choose a reason for hiding this comment

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

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

@@ -1,5 +1,6 @@
import { IterableAuthResponse } from './IterableAuthResponse';
import type { IterableGenerateJwtTokenArgs } from '../types/IterableGenerateJwtTokenArgs';
Copy link

Choose a reason for hiding this comment

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

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

@@ -0,0 +1,28 @@
interface IterableGenerateJwtTokenArgsBase {
Copy link

Choose a reason for hiding this comment

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

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Comment on lines +600 to +619
public void generateJwtToken(ReadableMap opts, Promise promise) {
try {
String secret = opts.getString("secret");
long durationMs = (long) opts.getDouble("duration");
String userId = opts.hasKey("userId") && !opts.isNull("userId") ? opts.getString("userId") : null;
String email = opts.hasKey("email") && !opts.isNull("email") ? opts.getString("email") : null;

// Validate that exactly one of userId or email is provided
if ((userId != null && email != null) || (userId == null && email == null)) {
promise.reject("E_INVALID_ARGS", "The token must include a userId or email, but not both.", (Throwable) null);
return;
}

// Use the Android SDK's Duration-based JWT generator
Duration duration = Duration.ofMillis(durationMs);
String token = IterableJwtGenerator.generateToken(secret, duration, email, userId);
promise.resolve(token);
} catch (Exception e) {
promise.reject("E_JWT_GENERATION_FAILED", "Failed to generate JWT: " + e.getMessage(), e);
}
Copy link

Choose a reason for hiding this comment

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

Function with high complexity (count = 7): generateJwtToken [qlty:function-complexity]

Comment on lines +600 to +619
public void generateJwtToken(ReadableMap opts, Promise promise) {
try {
String secret = opts.getString("secret");
long durationMs = (long) opts.getDouble("duration");
String userId = opts.hasKey("userId") && !opts.isNull("userId") ? opts.getString("userId") : null;
String email = opts.hasKey("email") && !opts.isNull("email") ? opts.getString("email") : null;

// Validate that exactly one of userId or email is provided
if ((userId != null && email != null) || (userId == null && email == null)) {
promise.reject("E_INVALID_ARGS", "The token must include a userId or email, but not both.", (Throwable) null);
return;
}

// Use the Android SDK's Duration-based JWT generator
Duration duration = Duration.ofMillis(durationMs);
String token = IterableJwtGenerator.generateToken(secret, duration, email, userId);
promise.resolve(token);
} catch (Exception e) {
promise.reject("E_JWT_GENERATION_FAILED", "Failed to generate JWT: " + e.getMessage(), e);
}
Copy link

Choose a reason for hiding this comment

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

Function with high complexity (count = 7): generateJwtToken [qlty:function-complexity]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants