@@ -15,7 +15,25 @@ import {
15
15
import { SERVER_LOCATION_ID } from "./constant" ;
16
16
17
17
import normalizeString from "./util/normalize_string" ;
18
- import { Data } from "./types" ;
18
+ import type {
19
+ ActionResponse ,
20
+ CallOptions ,
21
+ CreateComponentOptions ,
22
+ CreateResponse ,
23
+ Data ,
24
+ DeleteResponse ,
25
+ GetUploadMetadataResponse ,
26
+ IsTuple ,
27
+ MutationOptions ,
28
+ QueryOptions ,
29
+ QueryResponse ,
30
+ QueryServerInformationResponse ,
31
+ ResponseError ,
32
+ SearchOptions ,
33
+ SearchResponse ,
34
+ SessionOptions ,
35
+ UpdateResponse ,
36
+ } from "./types" ;
19
37
import { convertToIsoString } from "./util/convert_to_iso_string" ;
20
38
21
39
const logger = loglevel . getLogger ( "ftrack_api" ) ;
@@ -42,75 +60,6 @@ function splitFileExtension(fileName: string) {
42
60
return [ basename , extension ] ;
43
61
}
44
62
45
- export interface EventHubOptions {
46
- applicationId ?: string ;
47
- }
48
-
49
- export interface SessionOptions {
50
- autoConnectEventHub ?: boolean ;
51
- serverInformationValues ?: string [ ] ;
52
- eventHubOptions ?: EventHubOptions ;
53
- clientToken ?: string ;
54
- apiEndpoint ?: string ;
55
- additionalHeaders ?: Data ;
56
- strictApi ?: boolean ;
57
- }
58
-
59
- export interface CreateComponentOptions {
60
- name ?: string ;
61
- data ?: Data ;
62
- onProgress ?: ( progress : number ) => unknown ;
63
- xhr ?: XMLHttpRequest ;
64
- onAborted ?: ( ) => unknown ;
65
- }
66
-
67
- export interface Entity {
68
- id : string ;
69
- __entity_type__ : string ;
70
- }
71
-
72
- export interface SearchOptions {
73
- expression : string ;
74
- entityType : string ;
75
- terms ?: string [ ] ;
76
- contextId ?: string ;
77
- objectTypeIds ?: string [ ] ;
78
- }
79
-
80
- export interface Response < T > {
81
- url ?: any ;
82
- headers ?: any ;
83
- action : string ;
84
- metadata : {
85
- next : {
86
- offset : number | null ;
87
- } ;
88
- } ;
89
- data : T [ ] ;
90
- }
91
-
92
- export interface ResponseError {
93
- exception : string ;
94
- content : string ;
95
- error_code ?: string ;
96
- error ?: Data ;
97
- }
98
-
99
- export interface MutationOptions {
100
- pushToken ?: string ;
101
- additionalHeaders ?: Data ;
102
- decodeDatesAsIso ?: boolean ;
103
- }
104
-
105
- export interface QueryOptions {
106
- abortController ?: AbortController ;
107
- signal ?: AbortSignal ;
108
- additionalHeaders ?: Data ;
109
- decodeDatesAsIso ?: boolean ;
110
- }
111
-
112
- export interface CallOptions extends MutationOptions , QueryOptions { }
113
-
114
63
/**
115
64
* ftrack API session
116
65
* @class Session
@@ -264,7 +213,9 @@ export class Session {
264
213
* @instance
265
214
* @type {Promise }
266
215
*/
267
- this . initializing = this . call ( operations ) . then ( ( responses ) => {
216
+ this . initializing = this . call <
217
+ [ QueryServerInformationResponse , QueryResponse ]
218
+ > ( operations ) . then ( ( responses ) => {
268
219
this . serverInformation = responses [ 0 ] ;
269
220
this . schemas = responses [ 1 ] ;
270
221
this . serverVersion = this . serverInformation . version ;
@@ -558,6 +509,7 @@ export class Session {
558
509
* ServerError
559
510
* Generic server errors or network issues
560
511
*
512
+ * @typeParam T - Either an array of response types to get return type `Tuple<T[0], ..., T[n]>`, or a single response type to get return type T[]. Default is ActionResponse.
561
513
* @param {Array } operations - API operations.
562
514
* @param {Object } options
563
515
* @param {AbortController } options.abortController - Abort controller, deprecated in favor of options.signal
@@ -567,7 +519,7 @@ export class Session {
567
519
* @param {string } options.decodeDatesAsIso - Return dates as ISO strings instead of moment objects
568
520
*
569
521
*/
570
- call (
522
+ call < T = ActionResponse > (
571
523
operations : operation . Operation [ ] ,
572
524
{
573
525
abortController,
@@ -576,7 +528,7 @@ export class Session {
576
528
additionalHeaders = { } ,
577
529
decodeDatesAsIso = false ,
578
530
} : CallOptions = { }
579
- ) : Promise < Response < Data > [ ] > {
531
+ ) : Promise < IsTuple < T > extends true ? T : T [ ] > {
580
532
const url = `${ this . serverUrl } ${ this . apiEndpoint } ` ;
581
533
582
534
// Delay call until session is initialized if initialization is in
@@ -677,12 +629,13 @@ export class Session {
677
629
*
678
630
* Return update or create promise.
679
631
*/
680
- ensure (
632
+
633
+ ensure < T extends Data = Data > (
681
634
entityType : string ,
682
- data : Data ,
683
- identifyingKeys : string [ ] = [ ]
684
- ) : Promise < Data > {
685
- let keys = identifyingKeys ;
635
+ data : T ,
636
+ identifyingKeys : Array < keyof T > = [ ]
637
+ ) : Promise < T > {
638
+ let keys = identifyingKeys as string [ ] ;
686
639
687
640
logger . info (
688
641
"Ensuring entity with data using identifying keys: " ,
@@ -721,9 +674,9 @@ export class Session {
721
674
722
675
expression = `${ expression } ${ criteria . join ( " and " ) } ` ;
723
676
724
- return this . query ( expression ) . then ( ( response ) => {
677
+ return this . query < T > ( expression ) . then ( ( response ) => {
725
678
if ( response . data . length === 0 ) {
726
- return this . create ( entityType , data ) . then ( ( { data : responseData } ) =>
679
+ return this . create < T > ( entityType , data ) . then ( ( { data : responseData } ) =>
727
680
Promise . resolve ( responseData )
728
681
) ;
729
682
}
@@ -740,23 +693,23 @@ export class Session {
740
693
741
694
// Update entity if required.
742
695
let updated = false ;
743
- Object . keys ( data ) . forEach ( ( key ) => {
696
+ Object . keys ( data ) . forEach ( ( key : keyof T ) => {
744
697
if ( data [ key ] !== updateEntity [ key ] ) {
745
698
updateEntity [ key ] = data [ key ] ;
746
699
updated = true ;
747
700
}
748
701
} ) ;
749
702
750
703
if ( updated ) {
751
- return this . update (
704
+ return this . update < T > (
752
705
entityType ,
753
706
primaryKeys . map ( ( key : string ) => updateEntity [ key ] ) ,
754
- Object . keys ( data ) . reduce < Data > ( ( accumulator , key ) => {
707
+ Object . keys ( data ) . reduce < T > ( ( accumulator , key : keyof T ) => {
755
708
if ( primaryKeys . indexOf ( key ) === - 1 ) {
756
709
accumulator [ key ] = data [ key ] ;
757
710
}
758
711
return accumulator ;
759
- } , { } )
712
+ } , { } as T )
760
713
) . then ( ( { data : responseData } ) => Promise . resolve ( responseData ) ) ;
761
714
}
762
715
@@ -791,13 +744,15 @@ export class Session {
791
744
* @return {Promise } Promise which will be resolved with an object
792
745
* containing action, data and metadata
793
746
*/
794
- query ( expression : string , options : QueryOptions = { } ) {
747
+ query < T extends Data = Data > ( expression : string , options : QueryOptions = { } ) {
795
748
logger . debug ( "Query" , expression ) ;
796
749
const queryOperation = operation . query ( expression ) ;
797
- let request = this . call ( [ queryOperation ] , options ) . then ( ( responses ) => {
798
- const response = responses [ 0 ] ;
799
- return response ;
800
- } ) ;
750
+ let request = this . call < [ QueryResponse < T > ] > ( [ queryOperation ] , options ) . then (
751
+ ( responses ) => {
752
+ const response = responses [ 0 ] ;
753
+ return response ;
754
+ }
755
+ ) ;
801
756
802
757
return request ;
803
758
}
@@ -819,7 +774,7 @@ export class Session {
819
774
* @return {Promise } Promise which will be resolved with an object
820
775
* containing data and metadata
821
776
*/
822
- search (
777
+ search < T extends Data = Data > (
823
778
{
824
779
expression,
825
780
entityType,
@@ -844,7 +799,10 @@ export class Session {
844
799
contextId,
845
800
objectTypeIds,
846
801
} ) ;
847
- let request = this . call ( [ searchOperation ] , options ) . then ( ( responses ) => {
802
+ let request = this . call < [ SearchResponse < T > ] > (
803
+ [ searchOperation ] ,
804
+ options
805
+ ) . then ( ( responses ) => {
848
806
const response = responses [ 0 ] ;
849
807
return response ;
850
808
} ) ;
@@ -863,15 +821,20 @@ export class Session {
863
821
* @param {object } options.decodeDatesAsIso - Decode dates as ISO strings instead of moment objects
864
822
* @return {Promise } Promise which will be resolved with the response.
865
823
*/
866
- create ( entityType : string , data : Data , options : MutationOptions = { } ) {
824
+ create < T extends Data = Data > (
825
+ entityType : string ,
826
+ data : T ,
827
+ options : MutationOptions = { }
828
+ ) {
867
829
logger . debug ( "Create" , entityType , data , options ) ;
868
830
869
- let request = this . call ( [ operation . create ( entityType , data ) ] , options ) . then (
870
- ( responses ) => {
871
- const response = responses [ 0 ] ;
872
- return response ;
873
- }
874
- ) ;
831
+ let request = this . call < [ CreateResponse < T > ] > (
832
+ [ operation . create ( entityType , data ) ] ,
833
+ options
834
+ ) . then ( ( responses ) => {
835
+ const response = responses [ 0 ] ;
836
+ return response ;
837
+ } ) ;
875
838
876
839
return request ;
877
840
}
@@ -888,15 +851,15 @@ export class Session {
888
851
* @param {object } options.decodeDatesAsIso - Decode dates as ISO strings instead of moment objects
889
852
* @return {Promise } Promise resolved with the response.
890
853
*/
891
- update (
854
+ update < T extends Data = Data > (
892
855
type : string ,
893
856
keys : string [ ] ,
894
- data : Data ,
857
+ data : T ,
895
858
options : MutationOptions = { }
896
859
) {
897
860
logger . debug ( "Update" , type , keys , data , options ) ;
898
861
899
- const request = this . call (
862
+ const request = this . call < [ UpdateResponse < T > ] > (
900
863
[ operation . update ( type , keys , data ) ] ,
901
864
options
902
865
) . then ( ( responses ) => {
@@ -921,12 +884,13 @@ export class Session {
921
884
delete ( type : string , keys : string [ ] , options : MutationOptions = { } ) {
922
885
logger . debug ( "Delete" , type , keys , options ) ;
923
886
924
- let request = this . call ( [ operation . delete ( type , keys ) ] , options ) . then (
925
- ( responses ) => {
926
- const response = responses [ 0 ] ;
927
- return response ;
928
- }
929
- ) ;
887
+ let request = this . call < [ DeleteResponse ] > (
888
+ [ operation . delete ( type , keys ) ] ,
889
+ options
890
+ ) . then ( ( responses ) => {
891
+ const response = responses [ 0 ] ;
892
+ return response ;
893
+ } ) ;
930
894
931
895
return request ;
932
896
}
@@ -994,10 +958,12 @@ export class Session {
994
958
* @return {Promise } Promise resolved with the response when creating
995
959
* Component and ComponentLocation.
996
960
*/
997
- createComponent (
961
+ createComponent < T extends Data = Data > (
998
962
file : Blob ,
999
963
options : CreateComponentOptions = { }
1000
- ) : Promise < Response < Data > [ ] > {
964
+ ) : Promise <
965
+ [ CreateResponse < T > , CreateResponse < T > , GetUploadMetadataResponse ]
966
+ > {
1001
967
const componentName = options . name ?? ( file as File ) . name ;
1002
968
1003
969
let normalizedFileName ;
@@ -1052,7 +1018,9 @@ export class Session {
1052
1018
location_id : SERVER_LOCATION_ID ,
1053
1019
} ;
1054
1020
1055
- const componentAndLocationPromise = this . call ( [
1021
+ const componentAndLocationPromise = this . call <
1022
+ [ CreateResponse < T > , CreateResponse < T > , GetUploadMetadataResponse ]
1023
+ > ( [
1056
1024
operation . create ( "FileComponent" , component ) ,
1057
1025
operation . create ( "ComponentLocation" , componentLocation ) ,
1058
1026
{
0 commit comments