11import { QueryAST , SortNode , AggregationNode , WindowFunctionNode } from '@objectstack/spec/data' ;
2+ import { Logger , createLogger } from '@objectstack/core' ;
23
34export interface ClientConfig {
45 baseUrl : string ;
@@ -7,6 +8,14 @@ export interface ClientConfig {
78 * Custom fetch implementation (e.g. node-fetch or for Next.js caching)
89 */
910 fetch ?: ( input : RequestInfo | URL , init ?: RequestInit ) => Promise < Response > ;
11+ /**
12+ * Logger instance for debugging
13+ */
14+ logger ?: Logger ;
15+ /**
16+ * Enable debug logging
17+ */
18+ debug ?: boolean ;
1019}
1120
1221export interface DiscoveryResult {
@@ -41,27 +50,44 @@ export class ObjectStackClient {
4150 private token ?: string ;
4251 private fetchImpl : ( input : RequestInfo | URL , init ?: RequestInit ) => Promise < Response > ;
4352 private routes ?: DiscoveryResult [ 'routes' ] ;
53+ private logger : Logger ;
4454
4555 constructor ( config : ClientConfig ) {
4656 this . baseUrl = config . baseUrl . replace ( / \/ $ / , '' ) ; // Remove trailing slash
4757 this . token = config . token ;
4858 this . fetchImpl = config . fetch || globalThis . fetch . bind ( globalThis ) ;
59+
60+ // Initialize logger
61+ this . logger = config . logger || createLogger ( {
62+ level : config . debug ? 'debug' : 'info' ,
63+ format : 'pretty'
64+ } ) ;
65+
66+ this . logger . debug ( 'ObjectStack client created' , { baseUrl : this . baseUrl } ) ;
4967 }
5068
5169 /**
5270 * Initialize the client by discovering server capabilities and routes.
5371 */
5472 async connect ( ) {
73+ this . logger . debug ( 'Connecting to ObjectStack server' , { baseUrl : this . baseUrl } ) ;
74+
5575 try {
5676 // Connect to the discovery endpoint
5777 // During boot, we might not know routes, so we check convention /api/v1 first
5878 const res = await this . fetch ( `${ this . baseUrl } /api/v1` ) ;
5979
6080 const data = await res . json ( ) ;
6181 this . routes = data . routes ;
82+
83+ this . logger . info ( 'Connected to ObjectStack server' , {
84+ routes : Object . keys ( data . routes || { } ) ,
85+ capabilities : data . capabilities
86+ } ) ;
87+
6288 return data as DiscoveryResult ;
6389 } catch ( e ) {
64- console . error ( 'Failed to connect to ObjectStack Server ' , e ) ;
90+ this . logger . error ( 'Failed to connect to ObjectStack server ' , e as Error , { baseUrl : this . baseUrl } ) ;
6591 throw e ;
6692 }
6793 }
@@ -225,6 +251,12 @@ export class ObjectStackClient {
225251 }
226252
227253 private async fetch ( url : string , options : RequestInit = { } ) : Promise < Response > {
254+ this . logger . debug ( 'HTTP request' , {
255+ method : options . method || 'GET' ,
256+ url,
257+ hasBody : ! ! options . body
258+ } ) ;
259+
228260 const headers : Record < string , string > = {
229261 'Content-Type' : 'application/json' ,
230262 ...( options . headers as Record < string , string > || { } ) ,
@@ -236,13 +268,28 @@ export class ObjectStackClient {
236268
237269 const res = await this . fetchImpl ( url , { ...options , headers } ) ;
238270
271+ this . logger . debug ( 'HTTP response' , {
272+ method : options . method || 'GET' ,
273+ url,
274+ status : res . status ,
275+ ok : res . ok
276+ } ) ;
277+
239278 if ( ! res . ok ) {
240279 let errorBody ;
241280 try {
242281 errorBody = await res . json ( ) ;
243282 } catch {
244283 errorBody = { message : res . statusText } ;
245284 }
285+
286+ this . logger . error ( 'HTTP request failed' , undefined , {
287+ method : options . method || 'GET' ,
288+ url,
289+ status : res . status ,
290+ error : errorBody
291+ } ) ;
292+
246293 throw new Error ( `[ObjectStack] Request failed: ${ res . status } ${ JSON . stringify ( errorBody ) } ` ) ;
247294 }
248295
@@ -252,7 +299,10 @@ export class ObjectStackClient {
252299 private getRoute ( key : keyof DiscoveryResult [ 'routes' ] ) : string {
253300 if ( ! this . routes ) {
254301 // Fallback for strictness, but we allow bootstrapping
255- console . warn ( `[ObjectStackClient] Accessing ${ key } route before connect(). Using default /api/v1/${ key } ` ) ;
302+ this . logger . warn ( 'Accessing route before connect()' , {
303+ route : key ,
304+ fallback : `/api/v1/${ key } `
305+ } ) ;
256306 return `/api/v1/${ key } ` ;
257307 }
258308 return this . routes [ key ] || `/api/v1/${ key } ` ;
0 commit comments