44 * An API client for SuluHeadlessBundle.
55 */
66export default class Client {
7+ basePath ;
78 baseUrl ;
89 fetchClient ;
910 fetchOptions ;
@@ -15,8 +16,9 @@ export default class Client {
1516 /**
1617 * Creates a client.
1718 *
18- * @param {Object } options - The options for the client.
19- * @param {string } [options.baseUrl=window.location.origin] - The base URL for the API.
19+ * @param {Object } [options={}] - The options for the client.
20+ * @param {string } [options.baseUrl='/api'] - The base path of the API.
21+ * @param {string } [options.baseUrl=window.location.origin] - The base URL of the API.
2022 * @param {function } [options.fetchClient=fetch.bind(window)] - The fetch client to use.
2123 * @param {Object } [options.fetchOptions={}] - The fetch client options.
2224 * @param {string } [options.locale=''] - The locale for every request.
@@ -25,14 +27,16 @@ export default class Client {
2527 * @param {boolean } [options.removeEmbedded=false] - Whether to remove the _embedded layer from the response if present.
2628 */
2729 constructor ( {
30+ basePath = '/api' ,
2831 baseUrl = window . location . origin ,
2932 fetchClient = fetch . bind ( window ) ,
3033 fetchOptions = { } ,
3134 locale = '' ,
3235 onError = ( ) => { } ,
3336 onResponse = ( r ) => r ,
3437 removeEmbedded = false ,
35- } ) {
38+ } = { } ) {
39+ this . basePath = basePath ;
3640 this . baseUrl = baseUrl ;
3741 this . fetchClient = fetchClient ;
3842 this . fetchOptions = fetchOptions ;
@@ -46,12 +50,25 @@ export default class Client {
4650 * Builds a URL with the given path and optional query parameters.
4751 *
4852 * @param {string } path - The path for the URL.
49- * @param {Object } [params={}] - The query parameters for the URL.
50- * @param {boolean } [withLocale=true] - Whether to prepend locale to path.
53+ * @param {Object } [options={}] - The options for building the URL.
54+ * @param {Object } [options.params={}] - The query parameters for the URL.
55+ * @param {boolean } [options.withBasePath=true] - Whether to apply the base path.
56+ * @param {boolean } [options.withLocale=true] - Whether to prepend locale to path.
5157 * @returns {URL } The built URL.
5258 */
53- buildUrl ( path , params = { } , withLocale = true ) {
54- const url = new URL ( ( this . locale && withLocale ? `/${ this . locale } ` : '' ) + path , this . baseUrl ) ;
59+ buildUrl (
60+ path ,
61+ {
62+ params = { } ,
63+ withBasePath = true ,
64+ withLocale = true ,
65+ } = { }
66+ ) {
67+ const url = new URL ( [
68+ ...( this . locale && withLocale ? [ this . locale ] : [ ] ) ,
69+ ...( this . basePath && withBasePath ? [ this . basePath ] : [ ] ) ,
70+ path ,
71+ ] . join ( '/' ) . replaceAll ( '//' , '/' ) , this . baseUrl ) ;
5572
5673 if ( params ) {
5774 url . search = new URLSearchParams ( params ) ;
@@ -61,21 +78,16 @@ export default class Client {
6178 }
6279
6380 /**
64- * Sends a request to the API with the given path and query parameters .
81+ * Sends a request to the API with the given path and URL options .
6582 *
66- * @param {string } path - The path for the request.
67- * @param {Object } [params] - The query parameters for the request.
68- * @param {boolean } [withLocale] - Whether to build a localized URL.
83+ * @param {URL } url - The URL for the request.
6984 * @returns {Promise<Object> } A Promise that resolves to the request's JSON.
7085 */
71- async request ( path , params , withLocale ) {
86+ async request ( url ) {
7287 let response = null ;
7388
7489 try {
75- response = await this . fetchClient (
76- this . buildUrl ( path , params , withLocale ) . toString ( ) ,
77- this . fetchOptions
78- ) ;
90+ response = await this . fetchClient ( url . toString ( ) , this . fetchOptions ) ;
7991 } catch ( error ) {
8092 this . onError ( error ) ;
8193 throw error ;
@@ -107,7 +119,12 @@ export default class Client {
107119 * @returns {Promise<Object> } A Promise that resolves to the page data.
108120 */
109121 getPageByPath ( path ) {
110- return this . request ( `${ path } .json` , null , false ) ;
122+ return this . request (
123+ this . buildUrl ( `${ path } .json` , {
124+ withBasePath : false ,
125+ withLocale : false ,
126+ }
127+ ) ) ;
111128 }
112129
113130 /**
@@ -118,7 +135,11 @@ export default class Client {
118135 * @returns {Promise<Object> } A Promise that resolves to the navigation data.
119136 */
120137 getNavigationByKey ( key , params ) {
121- return this . request ( `/api/navigations/${ key } ` , params ) ;
138+ return this . request (
139+ this . buildUrl ( `/navigations/${ key } ` , {
140+ params,
141+ }
142+ ) ) ;
122143 }
123144
124145 /**
@@ -129,7 +150,11 @@ export default class Client {
129150 * @returns {Promise<Object> } A Promise that resolves to the snippet area data.
130151 */
131152 getSnippetByArea ( area , params ) {
132- return this . request ( `/api/snippet-areas/${ area } ` , params ) ;
153+ return this . request (
154+ this . buildUrl ( `/snippet-areas/${ area } ` , {
155+ params,
156+ } )
157+ ) ;
133158 }
134159
135160 /**
@@ -139,8 +164,12 @@ export default class Client {
139164 * @returns {Promise<Object> } A Promise that resolves to the search results.
140165 */
141166 search ( query ) {
142- return this . request ( '/api/search' , {
143- q : query ,
144- } ) ;
167+ return this . request (
168+ this . buildUrl ( '/search' , {
169+ params : {
170+ q : query ,
171+ } ,
172+ }
173+ ) ) ;
145174 }
146175}
0 commit comments