Skip to content

Commit 569eeb9

Browse files
committed
Support generic object data provider
Implement fetchObject for /obj endpoint Add ObjectModel for response Add selectionRange to OutputCapabilities Add optional replacer and space arguments to JSONBigUtils.stringify Add unit tests Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
1 parent 8250103 commit 569eeb9

9 files changed

Lines changed: 135 additions & 4 deletions

File tree

tsp-typescript-client/fixtures/tsp-client/experiment-outputs-0.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"type": "TABLE"
1313
},
1414
{
15-
"id": "data.output.id",
15+
"id": "datatree.output.id",
1616
"name": "Output name",
1717
"description": "Output description",
1818
"type": "DATA_TREE"
@@ -52,5 +52,14 @@
5252
"canCreate": false,
5353
"canDelete": true
5454
}
55+
},
56+
{
57+
"id": "data.output.id",
58+
"name": "Output name",
59+
"description": "Output description",
60+
"type": "DATA",
61+
"capabilities": {
62+
"selectionRange": true
63+
}
5564
}
5665
]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"model": {
3+
"object": {
4+
"fooNumber": 1234567890123456789,
5+
"fooString": "foo",
6+
"fooObj": { "fooA": { "A1key": "A1val", "A2key": 1 },
7+
"fooB": { "B1key": "B1val", "B2key": 2 } },
8+
"fooNumArray": [1, 2, 3],
9+
"fooObjArray": [{"k": "v1"}, {"k": "v2"}, {"k": "v3"}]
10+
},
11+
"next": 9876543210987654321,
12+
"previous": { "rank": 0 }
13+
},
14+
"statusMessage": "Completed",
15+
"status": "COMPLETED"
16+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { createNormalizer } from '../protocol/serialization';
2+
3+
export const ObjectModel = createNormalizer<ObjectModel>({
4+
object: undefined,
5+
next: undefined,
6+
previous: undefined
7+
});
8+
9+
/**
10+
* Object model that will be returned by the server
11+
*/
12+
export interface ObjectModel {
13+
/**
14+
* Generic object
15+
*/
16+
object: any;
17+
18+
/**
19+
* Next navigation parameter object
20+
*/
21+
next?: any;
22+
23+
/**
24+
* Previous navigation parameter object
25+
*/
26+
previous?: any;
27+
}

tsp-typescript-client/src/models/output-capabilities.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* "canCreate" indicates that a given data provider can create a derived data
66
* provider. "canDelete" indicates that a given data provider can be deleted.
77
*
8+
* "selectionRange" indicates that a given data provider can use the selection
9+
* range to compute its data. Clients should include the selection range in
10+
* query parameters and refresh the data when the selection range changes.
811
*/
912
export class OutputCapabilities {
1013
/**
@@ -16,4 +19,9 @@ export class OutputCapabilities {
1619
* Whether the data provider can be deleted. 'false' if absent.
1720
*/
1821
canDelete?: boolean;
22+
23+
/**
24+
* Whether the data provider uses the selection range. 'false' if absent.
25+
*/
26+
selectionRange?: boolean;
1927
}

tsp-typescript-client/src/models/output-descriptor.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export enum ProviderType {
4343
* A provider for a gantt chart (abitrary x-axis). E.g. flame graph.
4444
*/
4545
GANTT_CHART = "GANTT_CHART",
46+
/**
47+
* A provider of generic data objects.
48+
*/
49+
DATA = "DATA",
4650
}
4751

4852
/**

tsp-typescript-client/src/protocol/http-tsp-client.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { MarkerSet } from "../models/markerset";
1313
import { OutputDescriptor } from "../models/output-descriptor";
1414
import { ConfigurationQuery, OutputConfigurationQuery, Query } from "../models/query/query";
1515
import { GenericResponse } from "../models/response/responses";
16+
import { ObjectModel } from "../models/object";
1617
import { OutputStyleModel } from "../models/styles";
1718
import { ColumnHeaderEntry, TableModel } from "../models/table";
1819
import {
@@ -167,6 +168,32 @@ export class HttpTspClient implements ITspClient {
167168
return RestClient.get(url, undefined, array(OutputDescriptor));
168169
}
169170

171+
/**
172+
* Fetch object
173+
* @param expUUID Experiment UUID
174+
* @param outputID Output ID
175+
* @param parameters Query object
176+
* @returns Generic object response
177+
*/
178+
public async fetchObject(
179+
expUUID: string,
180+
outputID: string,
181+
parameters: Query
182+
): Promise<TspClientResponse<GenericResponse<ObjectModel>>> {
183+
const url =
184+
this.baseUrl +
185+
"/experiments/" +
186+
expUUID +
187+
"/outputs/data/" +
188+
outputID +
189+
"/obj";
190+
return RestClient.post(
191+
url,
192+
parameters,
193+
GenericResponse(ObjectModel)
194+
);
195+
}
196+
170197
/**
171198
* Fetch Data tree
172199
* @param expUUID Experiment UUID

tsp-typescript-client/src/protocol/tsp-client.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ describe('HttpTspClient Deserialization', () => {
126126
httpRequestMock.mockReturnValueOnce(fixtures.asResponse('experiment-outputs-0.json'));
127127
const response = await client.experimentOutputs('not-relevant');
128128
const outputs = response.getModel()!;
129-
expect(outputs).toHaveLength(6);
129+
expect(outputs).toHaveLength(7);
130130

131131
let output = outputs.find((item) => item.id === 'timegraph.output.id1');
132132
expect(output).toBeDefined();
@@ -141,6 +141,11 @@ describe('HttpTspClient Deserialization', () => {
141141
expect(output?.capabilities?.canCreate).toBeFalsy();
142142
expect(output?.capabilities?.canDelete).toBeTruthy();
143143
expect(output?.configuration).toBeDefined();
144+
145+
output = outputs.find((item) => item.id === 'data.output.id');
146+
expect(output).toBeDefined();
147+
expect(output?.capabilities).toBeDefined();
148+
expect(output?.capabilities?.selectionRange).toBeTruthy();
144149
});
145150

146151
it('fetchAnnotationsCategories', async () => {
@@ -210,6 +215,27 @@ describe('HttpTspClient Deserialization', () => {
210215
expect(identifier.productId).toBeDefined();
211216
});
212217

218+
it('fetchObject', async () => {
219+
httpRequestMock.mockReturnValueOnce(fixtures.asResponse('fetch-object-0.json'));
220+
const response = await client.fetchObject('not-relevant', 'not-relevant', new Query({}));
221+
const genericResponse = response.getModel()!;
222+
const object = genericResponse.model.object;
223+
const next = genericResponse.model.next;
224+
const previous = genericResponse.model.previous;
225+
226+
expect(object).toBeDefined();
227+
expect(object['fooNumber']).toEqual(BigInt('1234567890123456789'));
228+
expect(object['fooString']).toEqual('foo');
229+
expect(object['fooObj']['fooA']).toEqual({ "A1key": "A1val", "A2key": 1 });
230+
expect(object['fooObj']['fooB']).toEqual({ "B1key": "B1val", "B2key": 2 });
231+
expect(object['fooNumArray']).toEqual([1, 2, 3]);
232+
expect(object['fooObjArray']).toEqual([{"k": "v1"}, {"k": "v2"}, {"k": "v3"}]);
233+
expect(next).toBeDefined();
234+
expect(next).toEqual(BigInt('9876543210987654321'));
235+
expect(previous).toBeDefined();
236+
expect(previous).toEqual({ "rank": 0 });
237+
});
238+
213239
it('fetchMarkerSets', async () => {
214240
httpRequestMock.mockReturnValueOnce(fixtures.asResponse('fetch-marker-sets-0.json'));
215241
const response = await client.fetchMarkerSets('not-relevant');

tsp-typescript-client/src/protocol/tsp-client.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Experiment } from "../models/experiment";
1616
import { OutputDescriptor } from "../models/output-descriptor";
1717
import { EntryModel } from "../models/entry";
1818
import { TspClientResponse } from "./tsp-client-response";
19+
import { ObjectModel } from "../models/object";
1920
import { OutputStyleModel } from "../models/styles";
2021
import { HealthStatus } from "../models/health";
2122
import { MarkerSet } from "../models/markerset";
@@ -111,6 +112,19 @@ export interface ITspClient {
111112
expUUID: string
112113
): Promise<TspClientResponse<OutputDescriptor[]>>;
113114

115+
/**
116+
* Fetch object
117+
* @param expUUID Experiment UUID
118+
* @param outputID Output ID
119+
* @param parameters Query object
120+
* @returns Generic object response
121+
*/
122+
fetchObject(
123+
expUUID: string,
124+
outputID: string,
125+
parameters: Query
126+
): Promise<TspClientResponse<GenericResponse<ObjectModel>>>;
127+
114128
/**
115129
* Fetch Data tree
116130
* @param expUUID Experiment UUID

tsp-typescript-client/src/utils/jsonbig-utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class JSONBigUtils {
4242
/**
4343
* Stringify JS objects. Can stringify `BigInt` values.
4444
*/
45-
public static stringify(data: any): string {
46-
return JSONBig.stringify(data);
45+
public static stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string {
46+
return JSONBig.stringify(value, replacer, space);
4747
}
4848
}

0 commit comments

Comments
 (0)