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/routers/conversation-router.ts b/server/src/routers/conversation-router.ts
index b306bf1..bd3a900 100644
--- a/server/src/routers/conversation-router.ts
+++ b/server/src/routers/conversation-router.ts
@@ -18,24 +18,26 @@
 import { Request, Router } from 'express';
 import asyncHandler from 'express-async-handler';
 import { ParamsDictionary } from 'express-serve-static-core';
-import { HttpStatusCode } from 'jami-web-common';
+import {
+  ContactDetails,
+  HttpStatusCode,
+  IConversation,
+  IConversationMember,
+  NewConversationRequestBody,
+  NewMessageRequestBody,
+} from 'jami-web-common';
 import { Container } from 'typedi';
 
 import { Jamid } from '../jamid/jamid.js';
 import { authenticateToken } from '../middleware/auth.js';
 
-interface ConversationMembers {
-  members: string[];
-}
-
-interface ConversationMessage {
-  message: string;
-}
-
 const jamid = Container.get(Jamid);
 
-// TODO: Create interface for return type in common/ when Records and interfaces are refactored
-async function createConversationResponseObject(accountId: string, accountUri: string, conversationId: string) {
+async function createConversationResponseObject(
+  accountId: string,
+  accountUri: string,
+  conversationId: string
+): Promise<IConversation | undefined> {
   const infos = jamid.getConversationInfos(accountId, conversationId);
   if (Object.keys(infos).length === 0) {
     return undefined;
@@ -43,7 +45,7 @@
 
   const members = jamid.getConversationMembers(accountId, conversationId);
 
-  const namedMembers = [];
+  const namedMembers: IConversationMember[] = [];
   for (const member of members) {
     // Exclude current user from returned conversation members
     if (member.uri === accountUri) {
@@ -51,7 +53,6 @@
     }
 
     // Add usernames for conversation members
-    // TODO: Add caching in jamid to avoid too many address -> username lookups?
     const { username } = await jamid.lookupAddress(member.uri, accountId);
     namedMembers.push({
       role: member.role,
@@ -68,8 +69,8 @@
 
   return {
     id: conversationId,
-    messages: messages,
     members: namedMembers,
+    messages: messages,
     infos: infos,
   };
 }
@@ -100,7 +101,7 @@
 
 conversationRouter.post(
   '/',
-  (req: Request<ParamsDictionary, Record<string, string> | string, ConversationMembers>, res) => {
+  (req: Request<ParamsDictionary, ContactDetails | string, Partial<NewConversationRequestBody>>, res) => {
     const { members } = req.body;
     if (members === undefined || members.length !== 1) {
       res.status(HttpStatusCode.BadRequest).send('Missing members or more than one member in body');
@@ -125,7 +126,6 @@
 );
 
 // TODO: Check if we actually need this endpoint to return messages.
-// Verify by checking what is truly needed in the client when migrating, to clean up the API.
 // At the moment, /conversations does a lot of work returning all the conversations with the same
 // level of detail as this, and /conversations/messages returns just the messages. Check whether or not
 // this is what we want, and if so, if we can be more economical with client requests.
@@ -167,7 +167,7 @@
 
 conversationRouter.post(
   '/:conversationId/messages',
-  (req: Request<ParamsDictionary, any, ConversationMessage>, res) => {
+  (req: Request<ParamsDictionary, string, Partial<NewMessageRequestBody>>, res) => {
     const { message } = req.body;
     if (message === undefined) {
       res.status(HttpStatusCode.BadRequest).send('Missing message in body');