@@ -7,6 +7,7 @@ export type ClientConfiguration = {
77 accessTokenSecret ?: string ;
88 staticAuthToken ?: string ;
99 sessionId ?: string ;
10+ shopApiToken ?: string ;
1011 origin ?: string ;
1112} ;
1213
@@ -27,6 +28,11 @@ type ProfilingOptions = {
2728
2829export type CreateClientOptions = {
2930 profiling ?: ProfilingOptions ;
31+ shopApiToken ?: {
32+ doNotFetch ?: boolean ;
33+ scopes ?: string [ ] ;
34+ expiresIn ?: number ;
35+ } ;
3036} ;
3137
3238export type VariablesType = Record < string , any > ;
@@ -38,10 +44,12 @@ export type ClientInterface = {
3844 orderApi : ApiCaller < any > ;
3945 subscriptionApi : ApiCaller < any > ;
4046 pimApi : ApiCaller < any > ;
47+ nextPimApi : ApiCaller < any > ;
48+ shopCartApi : ApiCaller < any > ;
4149 config : Pick < ClientConfiguration , 'tenantIdentifier' | 'tenantId' | 'origin' > ;
4250} ;
4351
44- function authenticationHeaders ( config : ClientConfiguration ) {
52+ function authenticationHeaders ( config : ClientConfiguration ) : Record < string , string > {
4553 if ( config . sessionId ) {
4654 return {
4755 Cookie : 'connect.sid=' + config . sessionId ,
@@ -67,14 +75,15 @@ async function post<T>(
6775 profiling ?: ProfilingOptions ,
6876) : Promise < T > {
6977 try {
70- const commonHeaders = {
78+ const { headers : initHeaders , ...initRest } = init || { } ;
79+
80+ const headers = {
7181 'Content-type' : 'application/json; charset=UTF-8' ,
7282 Accept : 'application/json' ,
73- } ;
74- const headers = {
75- ...commonHeaders ,
7683 ...authenticationHeaders ( config ) ,
84+ ...initHeaders ,
7785 } ;
86+
7887 const body = JSON . stringify ( { query, variables } ) ;
7988 let start : number = 0 ;
8089 if ( profiling ) {
@@ -85,7 +94,7 @@ async function post<T>(
8594 }
8695
8796 const response = await fetch ( path , {
88- ...init ,
97+ ...initRest ,
8998 method : 'POST' ,
9099 headers,
91100 body,
@@ -133,6 +142,12 @@ async function post<T>(
133142 }
134143}
135144
145+ function apiHost ( configuration : ClientConfiguration ) {
146+ const origin = configuration . origin || '.crystallize.com' ;
147+ return ( path : string [ ] , prefix : 'api' | 'pim' | 'shop-api' = 'api' ) =>
148+ `https://${ prefix } ${ origin } /${ path . join ( '/' ) } ` ;
149+ }
150+
136151function createApiCaller (
137152 uri : string ,
138153 configuration : ClientConfiguration ,
@@ -143,16 +158,58 @@ function createApiCaller(
143158 } ;
144159}
145160
161+ function shopApiCaller ( configuration : ClientConfiguration , options ?: CreateClientOptions ) {
162+ const identifier = configuration . tenantIdentifier ;
163+ let shopApiToken = configuration . shopApiToken ;
164+ return async function callApi < T > ( query : string , variables ?: VariablesType ) : Promise < T > {
165+ if ( ! shopApiToken && options ?. shopApiToken ?. doNotFetch !== true ) {
166+ const headers = {
167+ 'Content-type' : 'application/json; charset=UTF-8' ,
168+ Accept : 'application/json' ,
169+ ...authenticationHeaders ( configuration ) ,
170+ } ;
171+ const response = await fetch ( apiHost ( configuration ) ( [ `@${ identifier } ` , 'auth' , 'token' ] , 'shop-api' ) , {
172+ method : 'POST' ,
173+ headers,
174+ body : JSON . stringify ( {
175+ scopes : options ?. shopApiToken ?. scopes || [ 'cart' ] ,
176+ expiresIn : options ?. shopApiToken ?. expiresIn || 3600 * 12 ,
177+ } ) ,
178+ } ) ;
179+ const results = await response . json ( ) ;
180+ if ( results . success !== true ) {
181+ throw new Error ( 'Could not fetch shop api token: ' + results . error ) ;
182+ }
183+ shopApiToken = results . token ;
184+ }
185+ return post < T > (
186+ apiHost ( configuration ) ( [ `@${ identifier } ` , 'cart' ] , 'shop-api' ) ,
187+ {
188+ ...configuration ,
189+ shopApiToken : shopApiToken ,
190+ } ,
191+ query ,
192+ variables ,
193+ {
194+ headers : {
195+ Authorization : `Bearer ${ shopApiToken } ` ,
196+ } ,
197+ } ,
198+ options ?. profiling ,
199+ ) ;
200+ } ;
201+ }
202+
146203export function createClient ( configuration : ClientConfiguration , options ?: CreateClientOptions ) : ClientInterface {
147204 const identifier = configuration . tenantIdentifier ;
148- const origin = configuration . origin || '.crystallize.com' ;
149- const apiHost = ( path : string [ ] , prefix : 'api' | 'pim' = 'api' ) => `https://${ prefix } ${ origin } /${ path . join ( '/' ) } ` ;
150205 return {
151- catalogueApi : createApiCaller ( apiHost ( [ identifier , 'catalogue' ] ) , configuration , options ) ,
152- searchApi : createApiCaller ( apiHost ( [ identifier , 'search' ] ) , configuration , options ) ,
153- orderApi : createApiCaller ( apiHost ( [ identifier , 'orders' ] ) , configuration , options ) ,
154- subscriptionApi : createApiCaller ( apiHost ( [ identifier , 'subscriptions' ] ) , configuration , options ) ,
155- pimApi : createApiCaller ( apiHost ( [ 'graphql' ] , 'pim' ) , configuration , options ) ,
206+ catalogueApi : createApiCaller ( apiHost ( configuration ) ( [ identifier , 'catalogue' ] ) , configuration , options ) ,
207+ searchApi : createApiCaller ( apiHost ( configuration ) ( [ identifier , 'search' ] ) , configuration , options ) ,
208+ orderApi : createApiCaller ( apiHost ( configuration ) ( [ identifier , 'orders' ] ) , configuration , options ) ,
209+ subscriptionApi : createApiCaller ( apiHost ( configuration ) ( [ identifier , 'subscriptions' ] ) , configuration , options ) ,
210+ pimApi : createApiCaller ( apiHost ( configuration ) ( [ 'graphql' ] , 'pim' ) , configuration , options ) ,
211+ nextPimApi : createApiCaller ( apiHost ( configuration ) ( [ `@${ identifier } ` ] ) , configuration , options ) ,
212+ shopCartApi : shopApiCaller ( configuration , options ) ,
156213 config : {
157214 tenantId : configuration . tenantId ,
158215 tenantIdentifier : configuration . tenantIdentifier ,
0 commit comments