Create new interfaces for objects transmitted using the REST API
Changes:
- Create new IContact, IAccount, and IConversation interfaces in common/
- These interfaces represent the serialized versions of the models which are transferred
- The client models are classes which implement these interfaces
- Create new LookupResult interface for nameserver lookup results
- Create new IConversationMember interface for conversation members
- The client interface ConversationMember extends this interface to have a Contact field rather than IContact
- Create new ConversationInfos interface for conversation infos
- Create new ContactDetails interface for contact details (used by contacts routes)
- Move request and response body interfaces into common/
- Merge AccountConfig into AccountDetails interface
- Create interfaces for server-only objects:
- ConversationMemberInfos
- ConversationRequestMetadata
- Ensure interfaces in jami-signal-interfaces.ts do not contain fields with JamiSwig types
- Rename models/ filenames to camelCase as they are not components
- Rewrite client models to have proper TypeScript accessors and remove unused getters
- Rewrite how client models are initialized from the serialized interface using .fromInterface static methods
- Make client models implement the interfaces in common/ for consistency
- Remove unneeded _next parameter for Express.js route handlers
- Use Partial<T> for all Express.js request body types on server
- Type all Axios response body types with interfaces
GitLab: #92
Change-Id: I4b2c75ac632ec5d9bf12a874a5ba04467c76fa6d
diff --git a/server/src/jamid/jamid.ts b/server/src/jamid/jamid.ts
index 30439ef..bb47b4e 100644
--- a/server/src/jamid/jamid.ts
+++ b/server/src/jamid/jamid.ts
@@ -19,7 +19,11 @@
import {
AccountDetails,
+ ContactDetails,
+ ConversationInfos,
ConversationMessage,
+ Devices,
+ LookupResult,
Message,
VolatileDetails,
WebSocketMessage,
@@ -30,6 +34,8 @@
import { Service } from 'typedi';
import { WebSocketServer } from '../websocket/websocket-server.js';
+import { ConversationMemberInfos } from './conversation-member-infos.js';
+import { ConversationRequestMetadata } from './conversation-request-metadata.js';
import { JamiSignal } from './jami-signal.js';
import {
AccountDetailsChanged,
@@ -53,8 +59,6 @@
const require = createRequire(import.meta.url);
-// TODO: Convert Records to interfaces and replace them in common/ (e.g. Contact)
-
@Service()
export class Jamid {
private jamiSwig: JamiSwig;
@@ -100,7 +104,7 @@
onRegisteredNameFound.next({ accountId, state, address, username });
const onKnownDevicesChanged = new Subject<KnownDevicesChanged>();
- handlers.KnownDevicesChanged = (accountId: string, devices: Record<string, string>) =>
+ handlers.KnownDevicesChanged = (accountId: string, devices: Devices) =>
onKnownDevicesChanged.next({ accountId, devices });
const onIncomingAccountMessage = new Subject<IncomingAccountMessage>();
@@ -120,8 +124,11 @@
onContactRemoved.next({ accountId, contactId, banned });
const onConversationRequestReceived = new Subject<ConversationRequestReceived>();
- handlers.ConversationRequestReceived = (accountId: string, conversationId: string, metadata: StringMap) =>
- onConversationRequestReceived.next({ accountId, conversationId, metadata });
+ handlers.ConversationRequestReceived = (
+ accountId: string,
+ conversationId: string,
+ metadata: ConversationRequestMetadata
+ ) => onConversationRequestReceived.next({ accountId, conversationId, metadata });
const onConversationReady = new Subject<ConversationReady>();
handlers.ConversationReady = (accountId: string, conversationId: string) =>
@@ -232,8 +239,7 @@
this.jamiSwig.sendAccountTextMessage(accountId, contactId, messageStringMap);
}
- // TODO: Add interface for returned type
- async lookupUsername(username: string, accountId?: string) {
+ async lookupUsername(username: string, accountId?: string): Promise<LookupResult> {
const hasRingNs = this.jamiSwig.lookupName(accountId || '', '', username);
if (!hasRingNs) {
throw new Error('Jami does not have NS');
@@ -246,8 +252,7 @@
);
}
- // TODO: Add interface for returned type
- async lookupAddress(address: string, accountId?: string) {
+ async lookupAddress(address: string, accountId?: string): Promise<LookupResult> {
const hasRingNs = this.jamiSwig.lookupAddress(accountId || '', '', address);
if (!hasRingNs) {
throw new Error('Jami does not have NS');
@@ -274,7 +279,7 @@
);
}
- getDevices(accountId: string): Record<string, string> {
+ getDevices(accountId: string): Devices {
return stringMapToRecord(this.jamiSwig.getKnownRingDevices(accountId));
}
@@ -294,14 +299,12 @@
this.jamiSwig.removeContact(accountId, contactId, true);
}
- // TODO: Replace Record with interface
- getContacts(accountId: string): Record<string, string>[] {
- return vectMapToRecordArray(this.jamiSwig.getContacts(accountId));
+ getContacts(accountId: string): ContactDetails[] {
+ return vectMapToRecordArray(this.jamiSwig.getContacts(accountId)) as unknown as ContactDetails[];
}
- // TODO: Replace Record with interface
- getContactDetails(accountId: string, contactId: string): Record<string, string> {
- return stringMapToRecord(this.jamiSwig.getContactDetails(accountId, contactId));
+ getContactDetails(accountId: string, contactId: string): ContactDetails {
+ return stringMapToRecord(this.jamiSwig.getContactDetails(accountId, contactId)) as unknown as ContactDetails;
}
getDefaultModeratorUris(accountId: string): string[] {
@@ -320,14 +323,16 @@
return stringVectToArray(this.jamiSwig.getConversations(accountId));
}
- // TODO: Replace Record with interface
- getConversationInfos(accountId: string, conversationId: string): Record<string, string> {
- return stringMapToRecord(this.jamiSwig.conversationInfos(accountId, conversationId));
+ getConversationInfos(accountId: string, conversationId: string): ConversationInfos {
+ return stringMapToRecord(
+ this.jamiSwig.conversationInfos(accountId, conversationId)
+ ) as unknown as ConversationInfos;
}
- // TODO: Replace Record with interface
- getConversationMembers(accountId: string, conversationId: string): Record<string, string>[] {
- return vectMapToRecordArray(this.jamiSwig.getConversationMembers(accountId, conversationId));
+ getConversationMembers(accountId: string, conversationId: string): ConversationMemberInfos[] {
+ return vectMapToRecordArray(
+ this.jamiSwig.getConversationMembers(accountId, conversationId)
+ ) as unknown as ConversationMemberInfos[];
}
async getConversationMessages(accountId: string, conversationId: string, fromMessage?: string): Promise<Message[]> {