Skip to content

Commit 185682d

Browse files
authored
Fix command service invocation return type (#3622)
1 parent 3009c3b commit 185682d

File tree

8 files changed

+48
-43
lines changed

8 files changed

+48
-43
lines changed

src/SIL.XForge.Scripture/ClientApp/src/app/core/sf-project.service.ts

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
8080
}
8181

8282
async onlineCreate(settings: SFProjectCreateSettings): Promise<string> {
83-
return (await this.onlineInvoke<string>('create', { settings }))!;
83+
return await this.onlineInvoke<string>('create', { settings });
8484
}
8585

8686
/**
8787
* Creates an SF project/resource with the given paratext id, and adds the user to it.
8888
* @param paratextId The paratext id of the project or resource.
8989
* @returns The SF project id.
9090
*/
91-
async onlineCreateResourceProject(paratextId: string): Promise<string | undefined> {
91+
async onlineCreateResourceProject(paratextId: string): Promise<string> {
9292
return this.onlineInvoke<string>('createResourceProject', { paratextId });
9393
}
9494

@@ -219,7 +219,7 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
219219
scriptureRange: string,
220220
targetProjectId: string,
221221
timestamp: Date
222-
): Promise<string | undefined> {
222+
): Promise<string> {
223223
return this.onlineInvoke<string>('applyPreTranslationToProject', {
224224
projectId,
225225
scriptureRange,
@@ -244,40 +244,40 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
244244
}
245245

246246
async onlineIsAlreadyInvited(id: string, email: string): Promise<boolean> {
247-
return (await this.onlineInvoke<boolean>('isAlreadyInvited', {
247+
return await this.onlineInvoke<boolean>('isAlreadyInvited', {
248248
projectId: id,
249249
email
250-
}))!;
250+
});
251251
}
252252

253253
/** Get list of email addresses that have outstanding invitations on project.
254254
* Caller must be an admin on the project. */
255255
async onlineInvitedUsers(projectId: string): Promise<InviteeStatus[]> {
256-
return (await this.onlineInvoke<InviteeStatus[]>('invitedUsers', {
256+
return await this.onlineInvoke<InviteeStatus[]>('invitedUsers', {
257257
projectId
258-
}))!;
258+
});
259259
}
260260

261261
/** Get added into project with specified shareKey code. */
262262
async onlineJoinWithShareKey(shareKey: string): Promise<string> {
263-
return (await this.onlineInvoke<string>('joinWithShareKey', { shareKey }))!;
263+
return await this.onlineInvoke<string>('joinWithShareKey', { shareKey });
264264
}
265265

266-
onlineInvite(id: string, email: string, locale: string, role: string): Promise<string | undefined> {
266+
onlineInvite(id: string, email: string, locale: string, role: string): Promise<string> {
267267
return this.onlineInvoke('invite', { projectId: id, email, locale, role });
268268
}
269269

270270
async onlineUninviteUser(projectId: string, emailToUninvite: string): Promise<string> {
271-
return (await this.onlineInvoke<string>('uninviteUser', {
271+
return await this.onlineInvoke<string>('uninviteUser', {
272272
projectId,
273273
emailToUninvite
274-
}))!;
274+
});
275275
}
276276

277277
async onlineIsSourceProject(projectId: string): Promise<boolean> {
278-
return (await this.onlineInvoke<boolean>('isSourceProject', {
278+
return await this.onlineInvoke<boolean>('isSourceProject', {
279279
projectId
280-
}))!;
280+
});
281281
}
282282

283283
async onlineGetLinkSharingKey(
@@ -286,14 +286,12 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
286286
shareLinkType: ShareLinkType,
287287
daysBeforeExpiration: number
288288
): Promise<string> {
289-
return (
290-
(await this.onlineInvoke<string>('linkSharingKey', {
291-
projectId,
292-
role,
293-
shareLinkType,
294-
daysBeforeExpiration
295-
})) ?? ''
296-
);
289+
return await this.onlineInvoke<string>('linkSharingKey', {
290+
projectId,
291+
role,
292+
shareLinkType,
293+
daysBeforeExpiration
294+
});
297295
}
298296

299297
async onlineReserveLinkSharingKey(shareKey: string, daysBeforeExpiration: number): Promise<void> {
@@ -305,19 +303,19 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
305303
}
306304

307305
async onlineSetRoleProjectPermissions(projectId: string, role: string, permissions: string[]): Promise<void> {
308-
return (await this.onlineInvoke<void>('setRoleProjectPermissions', {
306+
return await this.onlineInvoke<void>('setRoleProjectPermissions', {
309307
projectId,
310308
role,
311309
permissions
312-
}))!;
310+
});
313311
}
314312

315313
async onlineSetUserProjectPermissions(projectId: string, userId: string, permissions: string[]): Promise<void> {
316-
return (await this.onlineInvoke<void>('setUserProjectPermissions', {
314+
return await this.onlineInvoke<void>('setUserProjectPermissions', {
317315
projectId,
318316
userId,
319317
permissions
320-
}))!;
318+
});
321319
}
322320

323321
async onlineCreateAudioTimingData(
@@ -383,11 +381,7 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
383381
});
384382
}
385383

386-
async onlineEventMetrics(
387-
projectId: string,
388-
pageIndex: number,
389-
pageSize: number
390-
): Promise<QueryResults<EventMetric> | undefined> {
384+
async onlineEventMetrics(projectId: string, pageIndex: number, pageSize: number): Promise<QueryResults<EventMetric>> {
391385
return await this.onlineInvoke<QueryResults<EventMetric>>('eventMetrics', { projectId, pageIndex, pageSize });
392386
}
393387

@@ -396,7 +390,7 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
396390
projectId?: string,
397391
startDate?: Date,
398392
endDate?: Date
399-
): Promise<QueryResults<EventMetric> | undefined> {
393+
): Promise<QueryResults<EventMetric>> {
400394
const params: any = {
401395
projectId: projectId ?? null,
402396
scopes: [3], // Drafting scope

src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class TestEnvironment {
187187
when(mockedUserService.currentUserId).thenReturn('user01');
188188
when(mockedAuthService.currentUserRoles).thenReturn([]);
189189
when(mockDialogService.openMatDialog(EventMetricDialogComponent, anything())).thenReturn(instance(this.dialogRef));
190-
when(mockedProjectService.onlineEventMetrics(anything(), anything(), anything())).thenResolve(undefined);
190+
when(mockedProjectService.onlineEventMetrics(anything(), anything(), anything())).thenResolve({} as any);
191191

192192
this.fixture = TestBed.createComponent(EventMetricsLogComponent);
193193
this.component = this.fixture.componentInstance;

src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ export class EventMetricsLogComponent extends DataLoadingComponent implements On
130130
this.loadingStarted();
131131
if (isOnline) {
132132
const queryResults = await this.projectService.onlineEventMetrics(projectId, pageIndex, pageSize);
133-
this.length = queryResults?.unpagedCount ?? 0;
134-
if (Array.isArray(queryResults?.results)) {
133+
this.length = queryResults.unpagedCount ?? 0;
134+
if (Array.isArray(queryResults.results)) {
135135
this.eventMetrics = queryResults.results as EventMetric[];
136136
} else {
137137
this.eventMetrics = [];

src/SIL.XForge.Scripture/ClientApp/src/app/shared/share/share-control.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ class TestEnvironment {
334334

335335
when(
336336
mockedProjectService.onlineInvite(anything(), 'unknown-address@example.com', anything(), anything())
337-
).thenResolve(undefined);
337+
).thenResolve({} as any);
338338
when(
339339
mockedProjectService.onlineInvite(anything(), 'already-project-member@example.com', anything(), anything())
340340
).thenResolve(this.component.alreadyProjectMemberResponse);

src/SIL.XForge.Scripture/ClientApp/src/app/translate/editor/tabs/editor-tab-add-resource-dialog/editor-tab-add-resource-dialog.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ describe('EditorTabAddResourceDialogComponent', () => {
144144

145145
it('should set projectFetchFailed to true when fetchProject returns undefined', fakeAsync(() => {
146146
const env = new TestEnvironment();
147-
when(mockSFProjectService.onlineCreateResourceProject(env.paratextId)).thenReturn(Promise.resolve(undefined));
147+
when(mockSFProjectService.onlineCreateResourceProject(env.paratextId)).thenResolve({} as any);
148148
env.component.confirmSelection();
149149
tick();
150150
verify(mockSFProjectService.onlineCreateResourceProject(env.paratextId)).once();

src/SIL.XForge.Scripture/ClientApp/src/xforge-common/command.service.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,30 @@ interface JsonRpcRequest {
2525
id?: string;
2626
}
2727

28-
export interface JsonRpcResponse<T> {
28+
interface JsonRpcFailure {
2929
jsonrpc: '2.0';
30-
result?: T;
31-
error?: JsonRpcError;
3230
id: string;
31+
error: JsonRpcError;
3332
}
3433

34+
interface JsonRpcSuccess<T> {
35+
jsonrpc: '2.0';
36+
id: string;
37+
result: T;
38+
}
39+
40+
export type JsonRpcResponse<T> = JsonRpcSuccess<T> | JsonRpcFailure;
41+
3542
export interface JsonRpcError {
3643
code: number;
3744
message: string;
3845
data?: any;
3946
}
4047

48+
function isJsonRpcFailure<T>(response: JsonRpcResponse<T>): response is JsonRpcFailure {
49+
return 'error' in response && response.error != null;
50+
}
51+
4152
export function isNetworkError(error: any): boolean {
4253
return (
4354
error instanceof CommandError && hasStringProp(error, 'message') && error.message.includes('504 Gateway Timeout')
@@ -70,7 +81,7 @@ export class CommandService {
7081
private readonly bugsnagService: BugsnagService
7182
) {}
7283

73-
async onlineInvoke<T>(url: string, method: string, params: any = {}): Promise<T | undefined> {
84+
async onlineInvoke<T>(url: string, method: string, params: any = {}): Promise<T> {
7485
url = `${COMMAND_API_NAMESPACE}/${url}`;
7586
const request: JsonRpcRequest = {
7687
jsonrpc: '2.0',
@@ -92,7 +103,7 @@ export class CommandService {
92103
const response = await lastValueFrom(
93104
this.http.post<JsonRpcResponse<T>>(url, request, { headers: { 'Content-Type': 'application/json' } })
94105
);
95-
if (response.error != null) {
106+
if (isJsonRpcFailure(response)) {
96107
throw response.error;
97108
}
98109
return response.result;

src/SIL.XForge.Scripture/ClientApp/src/xforge-common/project.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export abstract class ProjectService<
9494
return this.onlineInvoke<void>('setSyncDisabled', { projectId, isDisabled });
9595
}
9696

97-
protected onlineInvoke<T>(method: string, params?: any): Promise<T | undefined> {
97+
protected onlineInvoke<T>(method: string, params?: any): Promise<T> {
9898
return this.commandService.onlineInvoke<T>(PROJECTS_URL, method, params);
9999
}
100100

src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export class UserService {
139139
}
140140
}
141141

142-
private onlineInvoke<T>(method: string, params?: any): Promise<T | undefined> {
142+
private onlineInvoke<T>(method: string, params?: any): Promise<T> {
143143
return this.commandService.onlineInvoke<T>(USERS_URL, method, params);
144144
}
145145
}

0 commit comments

Comments
 (0)