77 *
88 **/
99
10+ import { journey } from '@forgerock/journey-client' ;
1011import type {
1112 BaseCallback ,
1213 JourneyStep ,
@@ -15,9 +16,11 @@ import type {
1516 NextOptions ,
1617 ResumeOptions ,
1718 JourneyClient ,
19+ JourneyClientConfig ,
1820 GenericError ,
1921} from '@forgerock/journey-client/types' ;
2022import { writable , type Writable } from 'svelte/store' ;
23+ import { z } from 'zod' ;
2124
2225import { htmlDecode } from '$journey/_utilities/decode.utilities' ;
2326import type { JourneyStore , JourneyStoreValue , StackStore , StepTypes } from './journey.interfaces' ;
@@ -30,7 +33,85 @@ import {
3033} from './stages/_utilities/step.utilities' ;
3134import { buildCallbackMetadata , buildStepMetadata } from '$journey/_utilities/metadata.utilities' ;
3235import type { Maybe } from '$core/interfaces' ;
33- import { getJourneyClient } from '$core/journey-client.config' ;
36+
37+ /**
38+ * Configure Journey Client
39+ */
40+
41+ const wellknownSchema = z
42+ . string ( {
43+ invalid_type_error :
44+ '`serverConfig.wellknown` must be a URL string (this is generated by the Zod library).' ,
45+ required_error :
46+ 'Setting the `serverConfig.wellknown` is required (this is generated by the Zod library).' ,
47+ } )
48+ . url ( {
49+ message : '`serverConfig.wellknown` must be a full URL (this is generated by the Zod library).' ,
50+ } ) ;
51+
52+ export const journeyClientConfigSchema : z . ZodType < JourneyClientConfig > = z
53+ . object ( {
54+ serverConfig : z
55+ . object ( {
56+ wellknown : wellknownSchema ,
57+ } )
58+ . strict ( ) ,
59+ } )
60+ . strict ( ) ;
61+
62+ let journeyClientConfig : JourneyClientConfig | undefined ;
63+
64+ /**
65+ * We cache the journey client promise instead of only caching the resolved client so concurrent callers
66+ * share the same initialization work and we don't create multiple Journey Client instances in parallel.
67+ */
68+ let journeyClientPromise : Promise < JourneyClient > | undefined ;
69+
70+ /**
71+ * @function setJourneyClientConfig - Sets (or ensures) the Journey Client configuration.
72+ * @param {JourneyClientConfig } [config] If omitted, reuses existing config.
73+ * @throws {Error } If called without config before configuration is set.
74+ * @throws {z.ZodError } If provided config fails validation.
75+ * @returns {JourneyClientConfig } The active Journey Client configuration.
76+ */
77+ export function setJourneyClientConfig ( config ?: JourneyClientConfig ) : JourneyClientConfig {
78+ const parsed =
79+ config === undefined ? journeyClientConfig : journeyClientConfigSchema . parse ( config ) ;
80+
81+ if ( ! parsed ) {
82+ throw new Error ( 'Journey Client is not configured. Call setJourneyClientConfig() first.' ) ;
83+ }
84+
85+ const hasChanged = parsed . serverConfig . wellknown !== journeyClientConfig ?. serverConfig . wellknown ;
86+ journeyClientConfig = parsed ;
87+ // Reset the cached client promise when config changes.
88+ if ( hasChanged ) {
89+ journeyClientPromise = undefined ;
90+ }
91+ return journeyClientConfig ;
92+ }
93+
94+ /**
95+ * @function getJourneyClient - Gets a cached Journey Client (promise).
96+ * @throws {Error } If no Journey Client configuration is available.
97+ * @returns {Promise<JourneyClient> } A promise that resolves to a Journey Client.
98+ */
99+ export async function getJourneyClient ( ) : Promise < JourneyClient > {
100+ if ( ! journeyClientConfig ) {
101+ throw new Error ( 'Journey Client is not configured. Call setJourneyClientConfig() first.' ) ;
102+ }
103+
104+ // Cache the journey client promise to reuse an existing journey client.
105+ if ( ! journeyClientPromise ) {
106+ journeyClientPromise = journey ( { config : journeyClientConfig } ) . catch ( ( err ) => {
107+ // If creation fails, clear the cache so a later call can try again.
108+ journeyClientPromise = undefined ;
109+ throw err ;
110+ } ) ;
111+ }
112+
113+ return await journeyClientPromise ;
114+ }
34115
35116/**
36117 * @function initializeJourney - Initializes the journey stack for tracking journey switches
@@ -104,9 +185,13 @@ export const journeyStore: Writable<JourneyStoreValue> = writable({
104185
105186/**
106187 * @function initialize - Initializes the journey store
107- * @returns {object } - The journey store
188+ * @param {JourneyClientConfig } Optional Journey Client configuration.
189+ * @throws {Error } If no Journey Client configuration is available.
190+ * @returns {JourneyStore } Journey store API.
108191 */
109- export function initialize ( ) : JourneyStore {
192+ export function initialize ( config ?: JourneyClientConfig | undefined ) : JourneyStore {
193+ setJourneyClientConfig ( config ) ;
194+
110195 const stack = initializeStack ( ) ;
111196 let stepNumber = 0 ;
112197 // TODO: JourneyResult is not currently exported by Journey Client, so we define it here
0 commit comments