@@ -30,11 +30,13 @@ import type {
30
30
Schema ,
31
31
SearchOptions ,
32
32
SearchResponse ,
33
+ ServerInformation ,
33
34
SessionOptions ,
34
35
UpdateResponse ,
35
36
} from "./types.js" ;
36
37
import { convertToIsoString } from "./util/convert_to_iso_string.js" ;
37
38
import { Uploader } from "./uploader.js" ;
39
+ import getSchemaMappingFromSchemas from "./util/get_schema_mapping.js" ;
38
40
39
41
const logger = loglevel . getLogger ( "ftrack_api" ) ;
40
42
@@ -54,10 +56,14 @@ export class Session {
54
56
clientToken : string | null ;
55
57
initialized : boolean ;
56
58
initializing : Promise < Session > ;
57
- serverInformation ? : Data ;
59
+ additionalHeaders : Data ;
58
60
schemas ?: Schema [ ] ;
61
+ serverInformation ?: QueryServerInformationResponse ;
59
62
serverVersion ?: string ;
60
- additionalHeaders : Data ;
63
+ private schemasPromise ?: Promise < Schema [ ] > ;
64
+ private serverInformationPromise ?: Promise < ServerInformation > ;
65
+ private serverInformationValues ?: string [ ] ;
66
+ private schemaMapping ?: Record < string , Schema > ;
61
67
62
68
/**
63
69
* Construct Session instance with API credentials.
@@ -122,6 +128,8 @@ export class Session {
122
128
*/
123
129
this . serverUrl = serverUrl ;
124
130
131
+ this . serverInformationValues = serverInformationValues ;
132
+
125
133
/**
126
134
* API Endpoint. Specified relative to server URL with leading slash.
127
135
* @memberof Session
@@ -164,13 +172,15 @@ export class Session {
164
172
}
165
173
166
174
// Always include is_timezone_support_enabled as required by API.
175
+ // TODO: Remove this in next major.
167
176
if (
168
177
serverInformationValues &&
169
178
! serverInformationValues . includes ( "is_timezone_support_enabled" )
170
179
) {
171
180
serverInformationValues . push ( "is_timezone_support_enabled" ) ;
172
181
}
173
182
183
+ // TODO: remove these operations from session initialization in next major
174
184
const operations : operation . Operation [ ] = [
175
185
{
176
186
action : "query_server_information" ,
@@ -187,22 +197,36 @@ export class Session {
187
197
*/
188
198
this . initialized = false ;
189
199
200
+ const initializingPromise =
201
+ this . call < [ QueryServerInformationResponse , QuerySchemasResponse ] > (
202
+ operations
203
+ ) ;
204
+
190
205
/**
191
206
* Resolved once session is initialized.
192
207
* @memberof Session
193
208
* @instance
194
209
* @type {Promise }
195
210
*/
196
- this . initializing = this . call <
197
- [ QueryServerInformationResponse , QuerySchemasResponse ]
198
- > ( operations ) . then ( ( responses ) => {
211
+ this . initializing = initializingPromise . then ( ( responses ) => {
212
+ // TODO: Make this.serverInformation, this.schemas, and this.serverVersion private in next major
213
+ // and require calling getServerInformation, getSchemas, and this.getServerVersion instead.
199
214
this . serverInformation = responses [ 0 ] ;
200
215
this . schemas = responses [ 1 ] ;
216
+ this . schemaMapping = getSchemaMappingFromSchemas ( this . schemas ) ;
201
217
this . serverVersion = this . serverInformation . version ;
202
218
this . initialized = true ;
203
219
204
220
return Promise . resolve ( this ) ;
205
221
} ) ;
222
+
223
+ this . serverInformationPromise = initializingPromise
224
+ . then ( ( responses ) => responses [ 0 ] )
225
+ . catch ( ( ) => ( { } as ServerInformation ) ) ;
226
+
227
+ this . schemasPromise = initializingPromise
228
+ . then ( ( responses ) => responses [ 1 ] )
229
+ . catch ( ( ) => [ ] as Schema [ ] ) ;
206
230
}
207
231
208
232
/**
@@ -211,11 +235,12 @@ export class Session {
211
235
* @return {Array|null } List of primary key attributes.
212
236
*/
213
237
getPrimaryKeyAttributes ( entityType : string ) : string [ ] | null {
238
+ // Todo: make this async in next major
214
239
if ( ! this . schemas ) {
215
240
logger . warn ( "Schemas not available." ) ;
216
241
return null ;
217
242
}
218
- const schema = this . schemas . find ( ( item ) => item . id === entityType ) ;
243
+ const schema = this . schemaMapping ?. [ entityType ] ;
219
244
if ( ! schema || ! schema . primary_key || ! schema . primary_key . length ) {
220
245
logger . warn ( "Primary key could not be found for: " , entityType ) ;
221
246
return null ;
@@ -474,6 +499,52 @@ export class Session {
474
499
return JSON . stringify ( this . encode ( operations ) ) ;
475
500
}
476
501
502
+ /**
503
+ * Returns server information for the session, using serverInformationValues as set on session initialization.
504
+ * This is cached after the first call, and assumes that the server information will not change during the session.
505
+ * @returns Promise with the server information for the session.
506
+ */
507
+ async getServerInformation ( ) : Promise < ServerInformation > {
508
+ if ( ! this . serverInformationPromise ) {
509
+ this . serverInformationPromise = this . call < QueryServerInformationResponse > (
510
+ [
511
+ {
512
+ action : "query_server_information" ,
513
+ values : this . serverInformationValues ,
514
+ } ,
515
+ ]
516
+ ) . then ( ( responses ) => responses [ 0 ] ) ;
517
+ }
518
+
519
+ return this . serverInformationPromise ;
520
+ }
521
+
522
+ /**
523
+ * Returns server version for the session, using serverInformationValues as set on session initialization.
524
+ * This is cached after the first call, and assumes that the server information will not change during the session.
525
+ * @returns Promise with the server version for the session.
526
+ */
527
+ async getServerVersion ( ) : Promise < string > {
528
+ return ( await this . getServerInformation ( ) ) . version ;
529
+ }
530
+
531
+ /**
532
+ * Returns the API schemas for the session.
533
+ * This is cached after the first call, and assumes that the schemas will not change during the session.
534
+ * @returns Promise with the API schemas for the session.
535
+ */
536
+ async getSchemas ( ) : Promise < Schema [ ] > {
537
+ if ( ! this . schemasPromise ) {
538
+ this . schemasPromise = this . call < QuerySchemasResponse > ( [
539
+ { action : "query_schemas" } ,
540
+ ] ) . then ( ( responses ) => {
541
+ this . schemaMapping = getSchemaMappingFromSchemas ( responses [ 0 ] ) ;
542
+ return responses [ 0 ] ;
543
+ } ) ;
544
+ }
545
+ return this . schemasPromise ;
546
+ }
547
+
477
548
/**
478
549
* Call API with array of operation objects in *operations*.
479
550
*
@@ -509,7 +580,9 @@ export class Session {
509
580
decodeDatesAsIso = false ,
510
581
} : CallOptions = { }
511
582
) : Promise < IsTuple < T > extends true ? T : T [ ] > {
512
- await this . initializing ;
583
+ if ( this . initializing ) {
584
+ await this . initializing ;
585
+ }
513
586
const url = `${ this . serverUrl } ${ this . apiEndpoint } ` ;
514
587
515
588
try {
@@ -688,7 +761,8 @@ export class Session {
688
761
* @return {Object|null } Schema definition
689
762
*/
690
763
getSchema ( schemaId : string ) : Schema | null {
691
- const schema = this . schemas ?. find ( ( s ) => s . id === schemaId ) ;
764
+ // TODO: make this async in next major
765
+ const schema = this . schemaMapping ?. [ schemaId ] ;
692
766
return schema ?? null ;
693
767
}
694
768
0 commit comments