Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/sdks-4726-signals-init-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@forgerock/journey-client': patch
'@forgerock/protect': patch
---

Support `signalsInitializationOptions` pass-through config from AM in `PingOneProtectInitializeCallback`.

- `getConfig()` detects `signalsInitializationOptions` in the callback output; if it is a valid plain object, returns it directly as `SignalsInitializationOptions`
- Falls back to the existing `ProtectConfig` construction when the property is absent or invalid (null, string, array)
- `protect()` now accepts `ProtectConfig | SignalsInitializationOptions` so the pass-through config flows in without type assertions
- Updates vendored Signals SDK from v5.6.0w to v5.6.9w
2 changes: 1 addition & 1 deletion packages/journey-client/api-report/journey-client.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export class PingOneProtectEvaluationCallback extends BaseCallback {
// @public
export class PingOneProtectInitializeCallback extends BaseCallback {
constructor(payload: Callback);
getConfig(): {
getConfig(): Record<string, unknown> | {
envId: string;
consoleLogEnabled: boolean;
deviceAttributesToIgnore: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ export class PingOneProtectEvaluationCallback extends BaseCallback {
// @public
export class PingOneProtectInitializeCallback extends BaseCallback {
constructor(payload: Callback);
getConfig(): {
getConfig(): Record<string, unknown> | {
envId: string;
consoleLogEnabled: boolean;
deviceAttributesToIgnore: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* ping-protect-intitialize-callback.test.ts
*
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All rights reserved.
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
Expand Down Expand Up @@ -89,6 +89,128 @@ describe('PingOneProtectInitializeCallback', () => {
disableHub: false,
});
});
it('should return signalsInitializationOptions directly when it is a valid plain object', () => {
const signalsInitializationOptions = {
agentIdentification: 'false',
htmlGeoLocation: 'true',
behavioralDataCollection: 'true',
universalDeviceIdentification: 'false',
option1: 'value1',
disableTags: 'false',
};

const callback = new PingOneProtectInitializeCallback({
type: callbackType.PingOneProtectInitializeCallback,
input: [],
output: [
{
name: 'signalsInitializationOptions',
value: signalsInitializationOptions,
},
{
name: 'envId',
value: 'legacy-env-id-that-should-be-ignored',
},
],
});

const config = callback.getConfig();
expect(config).toEqual(signalsInitializationOptions);
expect(config).not.toHaveProperty('envId');
});

it('should fallback to legacy config when signalsInitializationOptions is an array (invalid)', () => {
const callback = new PingOneProtectInitializeCallback({
type: callbackType.PingOneProtectInitializeCallback,
input: [],
output: [
{
name: 'signalsInitializationOptions',
value: [],
},
{
name: 'envId',
value: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
},
],
});

const config = callback.getConfig();
expect(config).toMatchObject({
envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
behavioralDataCollection: true,
disableTags: false,
});
});

it('should fallback to legacy config when signalsInitializationOptions is null (invalid)', () => {
const callback = new PingOneProtectInitializeCallback({
type: callbackType.PingOneProtectInitializeCallback,
input: [],
output: [
{
name: 'signalsInitializationOptions',
value: null,
},
{
name: 'envId',
value: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
},
],
});

const config = callback.getConfig();
expect(config).toMatchObject({
envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
behavioralDataCollection: true,
disableTags: false,
});
});

it('should fallback to legacy config when signalsInitializationOptions is a string (invalid)', () => {
const callback = new PingOneProtectInitializeCallback({
type: callbackType.PingOneProtectInitializeCallback,
input: [],
output: [
{
name: 'signalsInitializationOptions',
value: 'somestring',
},
{
name: 'envId',
value: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
},
],
});

const config = callback.getConfig();
expect(config).toMatchObject({
envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
behavioralDataCollection: true,
disableTags: false,
});
});

it('should fallback to legacy config when signalsInitializationOptions is missing', () => {
const callback = new PingOneProtectInitializeCallback({
type: callbackType.PingOneProtectInitializeCallback,
input: [],
output: [
{
name: 'envId',
value: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
},
],
});

const config = callback.getConfig();
expect(config).toMatchObject({
envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
behavioralDataCollection: true,
disableTags: false,
});
});

it('should test the setClientError method', () => {
const callback = new PingOneProtectInitializeCallback({
type: callbackType.PingOneProtectInitializeCallback,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All rights reserved.
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
Expand All @@ -23,6 +23,18 @@ export class PingOneProtectInitializeCallback extends BaseCallback {
* Get callback's initialization config settings
*/
public getConfig() {
const signalsInitializationOptions = this.getOutputByName<Record<string, unknown> | undefined>(
'signalsInitializationOptions',
undefined,
);
if (
signalsInitializationOptions !== null &&
typeof signalsInitializationOptions === 'object' &&
!Array.isArray(signalsInitializationOptions)
) {
return signalsInitializationOptions;
}

const config = {
envId: this.getOutputByName<string>('envId', ''),
consoleLogEnabled: this.getOutputByName<boolean>('consoleLogEnabled', false),
Expand Down
25 changes: 24 additions & 1 deletion packages/protect/src/lib/protect.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright © 2025 Ping Identity Corporation. All right reserved.
* Copyright © 2025 - 2026 Ping Identity Corporation. All right reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
Expand Down Expand Up @@ -68,6 +68,29 @@ describe('protect (with successfully loaded signals sdk)', () => {
});

describe('native node methods', () => {
it('should call start with a signalsInitializationOptions pass-through config', async () => {
const passthroughConfig = {
envId: '12345',
behavioralDataCollection: 'true',
customOption: 'value1',
};
const protectApi = protect(passthroughConfig);
await protectApi.start();
expect(window._pingOneSignals.init).toHaveBeenCalledWith(passthroughConfig);
});

it('should resume behavioralData when behavioralDataCollection is string "true"', async () => {
const protectApi = protect({ envId: '12345', behavioralDataCollection: 'true' });
await protectApi.start();
expect(window._pingOneSignals.resumeBehavioralData).toHaveBeenCalled();
});

it('should not resume behavioralData when behavioralDataCollection is string "false"', async () => {
const protectApi = protect({ envId: '12345', behavioralDataCollection: 'false' });
await protectApi.start();
expect(window._pingOneSignals.resumeBehavioralData).not.toHaveBeenCalled();
});

it('should call start', async () => {
const protectApi = protect(config);
const protectMock = vi.spyOn(protectApi, 'start');
Expand Down
15 changes: 9 additions & 6 deletions packages/protect/src/lib/protect.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/*
*
* Copyright © 2025 Ping Identity Corporation. All right reserved.
* Copyright © 2025 - 2026 Ping Identity Corporation. All right reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
*/

import { Protect, ProtectConfig } from './protect.types.js';
import { Protect, ProtectConfig, SignalsInitializationOptions } from './protect.types.js';

// Add Signals SDK namespace to the window object
declare global {
interface Window {
_pingOneSignals: {
init: (initParams?: ProtectConfig) => Promise<void>;
init: (initParams?: ProtectConfig | SignalsInitializationOptions) => Promise<void>;
getData: () => Promise<string>;
pauseBehavioralData: () => void;
resumeBehavioralData: () => void;
Expand All @@ -24,10 +24,10 @@ declare global {
/**
* @async
* @function protect - returns a set of methods to interact with the PingOne Signals SDK
* @param {ProtectConfig} options - the configuration options for the PingOne Signals SDK
* @param {ProtectConfig | SignalsInitializationOptions} options - the configuration options for the PingOne Signals SDK
* @returns {Promise<Protect>} - a set of methods to interact with the PingOne Signals SDK
*/
export function protect(options: ProtectConfig): Protect {
export function protect(options: ProtectConfig | SignalsInitializationOptions): Protect {
let protectApiInitialized = false;

return {
Expand All @@ -48,7 +48,10 @@ export function protect(options: ProtectConfig): Protect {
try {
await window._pingOneSignals.init(options);

if (options.behavioralDataCollection === true) {
if (
options.behavioralDataCollection === true ||
options.behavioralDataCollection === 'true'
) {
window._pingOneSignals.resumeBehavioralData();
}
} catch (err) {
Expand Down
8 changes: 7 additions & 1 deletion packages/protect/src/lib/protect.types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
/*
*
* Copyright © 2025 Ping Identity Corporation. All right reserved.
* Copyright © 2025 - 2026 Ping Identity Corporation. All right reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
*/

/**
* @type SignalsInitializationOptions - Arbitrary key-value map passed directly to the Signals SDK initialization.
* Used when AM returns a `signalsInitializationOptions` output on the `PingOneProtectInitializeCallback`.
*/
export type SignalsInitializationOptions = Record<string, unknown>;
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 can narrow this down to just Record<string, string>. I'd like to ask @witrisna if the value is limited to just a string. Can you confirm this?


/**
* @interface ProtectConfig - Interface for the Protect module configuration parameters
* @description - envId is required. All other parameters are optional.
Expand Down
Loading
Loading