Compare commits
49 Commits
55e4aad0a9
...
1.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
| d3a295d598 | |||
| d97abc00e2 | |||
| cada5487bf | |||
| 2f9c65512b | |||
| edd87375c3 | |||
| b2d5b84435 | |||
| c460dc5385 | |||
| f54e76ab72 | |||
| fb1555338d | |||
| c98c917594 | |||
| cfb72d1772 | |||
| 01d07d65d1 | |||
| c6ad01b710 | |||
| 113cff5512 | |||
| 2c91b73a60 | |||
| 866c8a1838 | |||
| 926a28b7f9 | |||
| 9d6a18dda4 | |||
| 76f573023f | |||
| b217123b99 | |||
| 59f7e10dd7 | |||
| 56a0167120 | |||
| dc782003b0 | |||
| 2af9142d6c | |||
| 40905b225c | |||
| 77e032fdb2 | |||
| 96a5e5896b | |||
| 14fe7ef41d | |||
| d04bd6a437 | |||
| 0e553767b6 | |||
| b7af5497a4 | |||
| 1cd629e3c1 | |||
| 7d50692ece | |||
| d7422efcf0 | |||
| 1ccf534e04 | |||
| 7ba341203d | |||
| 54d466fb27 | |||
| 07d30f7e83 | |||
| cd806b7d17 | |||
| 7daf542961 | |||
| f911224847 | |||
| c8d2de9f9d | |||
| f8de78f3ab | |||
| e07114b1c0 | |||
| e8c6b9c920 | |||
| 0a97a2cc48 | |||
| 0b38b002df | |||
| a9322e3454 | |||
| e6798b4be8 |
30
.gitea/workflows/publish.yml
Normal file
30
.gitea/workflows/publish.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Publish to NPM
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build TypeScript
|
||||
run: npm run build
|
||||
|
||||
- name: Add NPM token
|
||||
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
|
||||
|
||||
- name: Publish to NPM
|
||||
run: npm publish --access public
|
||||
@@ -45,13 +45,11 @@ jobs:
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
- name: Create .env file
|
||||
run: |
|
||||
echo "API_URL=http://api:3000" >> .env
|
||||
echo "CDN_URL=http://cdn:4000" >> .env
|
||||
echo "WS_URL=ws://api:3000" >> .env
|
||||
|
||||
- name: Run Vitest
|
||||
env:
|
||||
API_URL: http://api:3000
|
||||
CDN_URL: http://cdn:4000
|
||||
WS_URL: ws://api:3000
|
||||
run: |
|
||||
npm install
|
||||
npm test --experimental-websocket
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -13,4 +13,5 @@ yarn-error.log*
|
||||
.DS_Store
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.example
|
||||
/dist
|
||||
6
README.md
Normal file
6
README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Chatenium SDK For TypeScript
|
||||
A library for interacting with the Chatenium API.
|
||||
## Quick Start
|
||||
```aiignore
|
||||
npm install @chatenium/chatenium-sdk
|
||||
```
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "chatenium-sdk",
|
||||
"version": "1.0.0",
|
||||
"name": "@chatenium/chatenium-sdk",
|
||||
"version": "1.0.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "chatenium-sdk",
|
||||
"version": "1.0.0",
|
||||
"name": "@chatenium/chatenium-sdk",
|
||||
"version": "1.0.8",
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "^10.4.0",
|
||||
"axios": "^1.14.0",
|
||||
|
||||
29
package.json
29
package.json
@@ -1,8 +1,28 @@
|
||||
{
|
||||
"name": "chatenium-sdk",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"name": "@chatenium/chatenium-sdk",
|
||||
"version": "1.2.1",
|
||||
"description": "A library for interacting with the Chatenium API",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./core/*": "./dist/core/*.js",
|
||||
"./services/*": "./dist/services/*.js",
|
||||
"./domain/*": "./dist/domain/*.js",
|
||||
"./mocks/*": "./dist/mocks/*.js",
|
||||
"./storage/*": "./dist/storage/*.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "vitest run",
|
||||
@@ -15,11 +35,10 @@
|
||||
"typescript": "^5.5.3",
|
||||
"vitest": "^4.1.2"
|
||||
},
|
||||
"private": true,
|
||||
"private": false,
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "^10.4.0",
|
||||
"axios": "^1.14.0",
|
||||
"dotenv": "^17.4.0",
|
||||
"msw": "^2.12.14",
|
||||
"uuid": "^13.0.0"
|
||||
}
|
||||
|
||||
@@ -4,17 +4,13 @@ export interface SDKConfig {
|
||||
wsUrl: string;
|
||||
}
|
||||
|
||||
declare const process: any;
|
||||
|
||||
const isNode =
|
||||
typeof process !== 'undefined' &&
|
||||
typeof process.versions !== 'undefined' &&
|
||||
typeof process.versions.node !== 'undefined';
|
||||
|
||||
if (isNode) {
|
||||
try {
|
||||
require('dotenv').config();
|
||||
} catch { }
|
||||
}
|
||||
|
||||
const getEnv = (key: string): string | undefined => {
|
||||
if (!isNode) return undefined;
|
||||
return process.env?.[key];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios, {AxiosInstance} from 'axios';
|
||||
import {environment} from "./environment";
|
||||
import {environment} from './environment.js';
|
||||
|
||||
export const getClient = (cdn: boolean) => {
|
||||
const env = environment.get();
|
||||
|
||||
32
src/core/permissions.ts
Normal file
32
src/core/permissions.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export const permissions = {
|
||||
createAndEditCategories: 2,
|
||||
deleteCategories: 4,
|
||||
createAndEditChannels: 8,
|
||||
deleteChannels: 16,
|
||||
deleteAnyMessage: 32,
|
||||
pinMessages: 64,
|
||||
createAndEditRanks: 128,
|
||||
deleteRanks: 256,
|
||||
changeNetworkNamePictureAndVisibility: 512,
|
||||
createEmojis: 1024,
|
||||
deleteEmojis: 2048,
|
||||
manageEmbed: 4096,
|
||||
createWebhooks: 8192,
|
||||
deleteWebhooks: 16384,
|
||||
createInvites: 32768,
|
||||
deleteInvites: 65536,
|
||||
sendMessages: 131072,
|
||||
seeChannels: 262144,
|
||||
banMembers: 524288,
|
||||
kickMembers: 1048576,
|
||||
unAndAssignRanksToMember: 2097152,
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the set of permissions includes the permission. Note that network owners have regular permissions just like the other members, so if the userid matches with the network's creator ID, then the permission is automatically granted. This logic is not included in this function.
|
||||
* @param permissions
|
||||
* @param permission
|
||||
*/
|
||||
export function permissionGranted(permissions: number, permission: number): Boolean {
|
||||
return (permissions & permission) === permission;
|
||||
}
|
||||
@@ -4,12 +4,12 @@ import {
|
||||
WSMakeTokenReq,
|
||||
WSMakeTokenResp,
|
||||
WSMessagePayload
|
||||
} from "../domain/websocket.schema";
|
||||
import {getClient} from "./http";
|
||||
import {CreateNetworkReq, Network} from "../domain/networkService.schema";
|
||||
} from '../domain/websocket.schema.js';
|
||||
import {getClient} from './http.js';
|
||||
import {CreateNetworkReq, Network} from '../domain/networkService.schema.js';
|
||||
import {isAxiosError} from "axios";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {environment} from "./environment";
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {environment} from './environment.js';
|
||||
|
||||
export class WebSocketHandler {
|
||||
private static instance: WebSocketHandler;
|
||||
@@ -43,6 +43,13 @@ export class WebSocketHandler {
|
||||
this.connection = new WebSocket(`${environment.get().wsUrl}/v2/ws?userid=${userid}&access_token=${resp.data.token}`)
|
||||
console.log("Connected to websocket successfully")
|
||||
this.startListening()
|
||||
|
||||
this.connection.onclose = () => {
|
||||
console.error("The WebSocket connection was closed unexpectedly. Reconnecting...")
|
||||
setTimeout(() => {
|
||||
this.connect(userid, token)
|
||||
}, 3000)
|
||||
}
|
||||
return
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
@@ -64,9 +71,10 @@ export class WebSocketHandler {
|
||||
if (payl.action == "connectionId") {
|
||||
console.log("ConnectionID received")
|
||||
const data: WSConnIdPayload = JSON.parse(payl.data);
|
||||
this.connectionId = data.connId;
|
||||
this.listeners.forEach(listener => {
|
||||
console.log(data.connId, listener)
|
||||
listener.onNewConnId(data.connId)
|
||||
this.connectionId = data.connId;
|
||||
})
|
||||
} else {
|
||||
this.listeners.forEach(listener => {
|
||||
@@ -78,6 +86,10 @@ export class WebSocketHandler {
|
||||
}
|
||||
|
||||
public registerService(service: WSListenerPipe) {
|
||||
console.log("Registering service", service)
|
||||
if (this.connId) {
|
||||
service.onNewConnId(this.connId)
|
||||
}
|
||||
this.listeners.add(service);
|
||||
}
|
||||
|
||||
|
||||
29
src/domain/broadcastChannelService.schema.ts
Normal file
29
src/domain/broadcastChannelService.schema.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
export interface CreateServerReq {
|
||||
type: "rtmp",
|
||||
channelId: string
|
||||
categoryId: string
|
||||
networkId: string
|
||||
}
|
||||
|
||||
export interface GetRTMPDataReq {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface JoinWebsocketRoomReq {
|
||||
userid: string
|
||||
connId: string
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
disableAutoRemove: boolean
|
||||
}
|
||||
|
||||
export interface StreamRegistry {
|
||||
streamKey: string
|
||||
status: "idling" | "broadcasting" | "broadcasting_starting"
|
||||
type: "rtmp"
|
||||
streamURL: string
|
||||
channelId: string
|
||||
}
|
||||
@@ -24,4 +24,5 @@ export interface Attachment {
|
||||
path: string
|
||||
height: number
|
||||
width: number
|
||||
extraMetaData: Record<string, any> // Used by clients
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Attachment, TimeStamp} from "./common.schema";
|
||||
import {Attachment, TimeStamp} from './common.schema.js';
|
||||
|
||||
export interface GetMessageReq {
|
||||
from: number
|
||||
@@ -58,6 +58,7 @@ export interface JoinWsRoomReq {
|
||||
connId: string
|
||||
chatid: string
|
||||
userid: string
|
||||
disableAutoRemove: boolean
|
||||
}
|
||||
|
||||
// Response schemas
|
||||
|
||||
95
src/domain/fileTransferService.schema.ts
Normal file
95
src/domain/fileTransferService.schema.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
export interface StartNewFileTransferReq {
|
||||
userid: string
|
||||
targetUserId: string
|
||||
metadata: TransferableFileMetadata[]
|
||||
}
|
||||
|
||||
export interface AcceptFileTransferReq {
|
||||
userid: string
|
||||
senderId: string
|
||||
transferId: string
|
||||
}
|
||||
|
||||
export interface DeclineFileTransferReq {
|
||||
userid: string
|
||||
senderId: string
|
||||
transferId: string
|
||||
}
|
||||
|
||||
export interface FileTransferSendOfferRTCReq {
|
||||
userid: string
|
||||
peerId: string
|
||||
transferId: string
|
||||
offer: string
|
||||
}
|
||||
|
||||
export interface FileTransferSendAnswerRTCReq {
|
||||
userid: string
|
||||
peerId: string
|
||||
transferId: string
|
||||
answer: string
|
||||
}
|
||||
|
||||
export interface FileTransferSendICERTCReq {
|
||||
userid: string
|
||||
peerId: string
|
||||
transferId: string
|
||||
candidate: string
|
||||
}
|
||||
|
||||
// Response schemas
|
||||
export interface StartNewFileTransferResp {
|
||||
transferId: string
|
||||
}
|
||||
|
||||
// WebSocket payloads
|
||||
export interface WSNewFileTransferPayload {
|
||||
from: string
|
||||
transferId: string
|
||||
metadata: TransferableFileMetadata[]
|
||||
}
|
||||
|
||||
export interface WSFileTransferAcceptedPayload {
|
||||
transferId: string
|
||||
rtcConfig: RTCConfiguration
|
||||
}
|
||||
|
||||
export interface WSFileTransferDeclinedPayload {
|
||||
transferId: string
|
||||
}
|
||||
|
||||
export interface WSFileTransferRTCOfferPayload {
|
||||
transferId: string
|
||||
offer: string
|
||||
}
|
||||
|
||||
export interface WSFileTransferRTCAnswerPayload {
|
||||
transferId: string
|
||||
answer: string
|
||||
}
|
||||
|
||||
export interface WSFileTransferRTCIcePayload {
|
||||
transferId: string
|
||||
candidate: string
|
||||
}
|
||||
|
||||
// DataChannel payloads
|
||||
export interface DCStartNewFilePayload {
|
||||
fileId: string
|
||||
fileIndex: number
|
||||
fileName: string
|
||||
totalChunks: number
|
||||
}
|
||||
|
||||
export interface DCTransferFilePayload {
|
||||
fileId: string
|
||||
fileIndex: string
|
||||
chunk: string
|
||||
}
|
||||
|
||||
// Types
|
||||
export interface TransferableFileMetadata {
|
||||
fileId: string
|
||||
name: string
|
||||
size: number
|
||||
}
|
||||
@@ -33,8 +33,13 @@ export interface FileUploadRegistration {
|
||||
}
|
||||
|
||||
export interface FileData {
|
||||
fileId: string
|
||||
name: string
|
||||
extension: string
|
||||
type: string
|
||||
data: File
|
||||
}
|
||||
|
||||
export interface FileUploadProgressListener {
|
||||
fileProgressUpdate: (tempMsgId: string, fileId: string, allChunks: number, chunksDone: number) => void
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Request schemas
|
||||
import {PublicUserData, RGB, TimeStamp} from "./common.schema";
|
||||
import {PublicUserData, RGB, TimeStamp} from './common.schema.js';
|
||||
|
||||
export interface GetInvitesReq {
|
||||
networkId: string
|
||||
@@ -208,9 +208,11 @@ export interface GetMembersReq {
|
||||
}
|
||||
|
||||
export interface UploadNewPictureReq {
|
||||
picId: string
|
||||
userid: string
|
||||
networkId: string
|
||||
data: string
|
||||
isImage: boolean
|
||||
monogramColors: RGB | null
|
||||
}
|
||||
|
||||
export interface ChangeVisibilityReq {
|
||||
@@ -255,6 +257,7 @@ export interface JoinWebSocketRoomReq {
|
||||
userid: string
|
||||
connId: string
|
||||
networkId: string
|
||||
disableAutoRemove: boolean
|
||||
}
|
||||
|
||||
export interface GetFromInviteReq {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {PublicUserData, TimeStamp} from "./common.schema";
|
||||
import {PublicUserData, TimeStamp} from './common.schema.js';
|
||||
|
||||
// Request schemas
|
||||
export interface GetReq {
|
||||
|
||||
19
src/domain/sessionManager.schema.ts
Normal file
19
src/domain/sessionManager.schema.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import {PublicUserData} from './common.schema.js';
|
||||
import {GIF, PersonalUserData} from './userService.schema.js';
|
||||
|
||||
export interface Session {
|
||||
userData: PersonalUserData
|
||||
token: string
|
||||
}
|
||||
|
||||
export interface ValidateSessionReq {
|
||||
token: string
|
||||
}
|
||||
|
||||
export interface ValidateSessionResp {
|
||||
validationOk: boolean
|
||||
}
|
||||
|
||||
export interface UpdateUserDataReq {
|
||||
userid: string
|
||||
}
|
||||
139
src/domain/textChannelService.schema.ts
Normal file
139
src/domain/textChannelService.schema.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import {Attachment, PublicUserData, TimeStamp} from './common.schema.js';
|
||||
|
||||
export interface GetMessageReq {
|
||||
from: number
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface GetMessagePosReq {
|
||||
messageId: string
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface GetPinnedMessagesReq {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface EditMessageReq {
|
||||
message: string
|
||||
messageId: string
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
userid: string
|
||||
}
|
||||
|
||||
export interface FinishMessageReq {
|
||||
uploadId: string | null
|
||||
message: string
|
||||
replyTo: string
|
||||
replyToMessage: string
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
userid: string
|
||||
}
|
||||
|
||||
export interface ReadMessagesReq {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
userid: string
|
||||
}
|
||||
|
||||
export interface PinMessageReq {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
messageId: string
|
||||
userid: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface UnpinMessageReq {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string,
|
||||
messageId: string,
|
||||
userid: string
|
||||
}
|
||||
|
||||
export interface DeleteMessagesReq {
|
||||
messageIds: string[]
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
userid: string
|
||||
}
|
||||
|
||||
export interface JoinWsRoomReq {
|
||||
connId: string
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
userid: string
|
||||
disableAutoRemove: boolean
|
||||
}
|
||||
|
||||
// Response schemas
|
||||
export interface GetMessagePosResp {
|
||||
messagePos: number
|
||||
}
|
||||
|
||||
// Types
|
||||
export interface Message {
|
||||
msgid: string
|
||||
author: PublicUserData
|
||||
message: string
|
||||
sent_at: TimeStamp
|
||||
isEdited: boolean
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
files: Attachment[]
|
||||
seen: boolean
|
||||
replyTo: string
|
||||
replyToId: string
|
||||
forwardedFrom: string
|
||||
forwardedFromName: string
|
||||
}
|
||||
|
||||
export interface PinnedMessage {
|
||||
message: string
|
||||
messageId: string
|
||||
}
|
||||
|
||||
// WebSocket payloads
|
||||
export interface WSMessageDeletedPayload {
|
||||
messageId: string
|
||||
}
|
||||
|
||||
export interface WSMessageEditedPayload {
|
||||
messageId: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface WSMessagePinnedPayload {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
messageId: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface WSMessagesReadPayload {
|
||||
userid: string
|
||||
}
|
||||
|
||||
export interface WSMessageUnpinnedPayload {
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
messageId: string
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {TimeStamp} from "./common.schema";
|
||||
import {TimeStamp} from './common.schema.js';
|
||||
|
||||
export interface ChangeUsernameReq {
|
||||
newUsername: string;
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
OtpSendCodeReq,
|
||||
OtpVerifyCodeReq, PleVerifyCodeReq, PleVerifyCodeResp, RegisterReq, SignInSuccessResp,
|
||||
UserDataValidationResp, VerifyPasswordResetReq
|
||||
} from "../../domain/authService.schema";
|
||||
import {GenericSuccessBody} from "../../domain/http.schema";
|
||||
} from '../../domain/authService.schema.js';
|
||||
import {GenericSuccessBody} from '../../domain/http.schema.js';
|
||||
|
||||
export const networkHandlers = [
|
||||
http.get('*/user/authOptions', () => {
|
||||
|
||||
11
src/mocks/handlers/brcChan.http.ts
Normal file
11
src/mocks/handlers/brcChan.http.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {GetRTCAccessResp} from '../../domain/callService.schema.js';
|
||||
import {StreamRegistry} from '../../domain/broadcastChannelService.schema.js';
|
||||
|
||||
export const brcChanHandlers = [
|
||||
http.get('*/network/channel/rtmpData', () => {
|
||||
return HttpResponse.json(<StreamRegistry>{
|
||||
status: "broadcasting_starting"
|
||||
})
|
||||
}),
|
||||
]
|
||||
@@ -1,5 +1,5 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {GetRTCAccessResp} from "../../domain/callService.schema";
|
||||
import {GetRTCAccessResp} from '../../domain/callService.schema.js';
|
||||
|
||||
export const callHandlers = [
|
||||
http.post('*/v2/chat/getRTCAccess', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {Chat, GetAvailabilityResp, StartNewReq} from "../../domain/chatService.schema";
|
||||
import {Chat, GetAvailabilityResp, StartNewReq} from '../../domain/chatService.schema.js';
|
||||
|
||||
export const chatHandlers = [
|
||||
http.get('*/chat/get', () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {Chat} from "../../domain/chatService.schema";
|
||||
import {FinishMessageReq, GetMessagePosResp, Message, PinnedMessage} from "../../domain/dmService.schema";
|
||||
import {CreateNetworkReq, Network} from "../../domain/networkService.schema";
|
||||
import {Chat} from '../../domain/chatService.schema.js';
|
||||
import {FinishMessageReq, GetMessagePosResp, Message, PinnedMessage} from '../../domain/dmService.schema.js';
|
||||
import {CreateNetworkReq, Network} from '../../domain/networkService.schema.js';
|
||||
|
||||
export const dmHandlers = [
|
||||
http.get('*/chat/dm/messages', () => {
|
||||
@@ -28,4 +28,8 @@ export const dmHandlers = [
|
||||
message: body.message,
|
||||
})
|
||||
}),
|
||||
|
||||
http.post('*/v2/chat/dm/joinWebSocketRoom', async () => {
|
||||
return HttpResponse.json()
|
||||
}),
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {GetRTCAccessResp} from "../../domain/callService.schema";
|
||||
import {RegisterUploadResp} from "../../domain/fileUploadService.schema";
|
||||
import {GetRTCAccessResp} from '../../domain/callService.schema.js';
|
||||
import {RegisterUploadResp} from '../../domain/fileUploadService.schema.js';
|
||||
|
||||
export const fileUploadHandlers = [
|
||||
http.post('*/chat/cdnRegisterUpload', () => {
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
Network,
|
||||
NetworkCategory,
|
||||
NetworkInvite, POW
|
||||
} from "../../domain/networkService.schema";
|
||||
import {PublicUserData} from "../../domain/common.schema";
|
||||
} from '../../domain/networkService.schema.js';
|
||||
import {PublicUserData} from '../../domain/common.schema.js';
|
||||
|
||||
export const authHandlers = [
|
||||
http.get('*/network/invites', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {CreateNetworkReq, Network, NetworkInvite} from "../../domain/networkService.schema";
|
||||
import {Album, Comment, CreateAlbumReq, GetResp} from "../../domain/pictureService.schema";
|
||||
import {CreateNetworkReq, Network, NetworkInvite} from '../../domain/networkService.schema.js';
|
||||
import {Album, Comment, CreateAlbumReq, GetResp} from '../../domain/pictureService.schema.js';
|
||||
|
||||
export const pictureHandlers = [
|
||||
http.get('*/picture/pictures', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {http, HttpResponse} from "msw";
|
||||
import {GetResp} from "../../domain/pictureService.schema";
|
||||
import {Session} from "../../domain/userService.schema";
|
||||
import {GetResp} from '../../domain/pictureService.schema.js';
|
||||
import {Session} from '../../domain/userService.schema.js';
|
||||
|
||||
export const userHandler = [
|
||||
http.post('*/user/getSessions', () => {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {networkHandlers} from "./handlers/auth.http";
|
||||
import {authHandlers} from "./handlers/network.http";
|
||||
import {pictureHandlers} from "./handlers/picture.http";
|
||||
import {callHandlers} from "./handlers/call.http";
|
||||
import {fileUploadHandlers} from "./handlers/fUpl.http";
|
||||
import {chatHandlers} from "./handlers/chat.http";
|
||||
import {dmHandlers} from "./handlers/dm.http";
|
||||
import {userHandler} from "./handlers/user.http";
|
||||
import {networkHandlers} from './handlers/auth.http.js';
|
||||
import {authHandlers} from './handlers/network.http.js';
|
||||
import {pictureHandlers} from './handlers/picture.http.js';
|
||||
import {callHandlers} from './handlers/call.http.js';
|
||||
import {fileUploadHandlers} from './handlers/fUpl.http.js';
|
||||
import {chatHandlers} from './handlers/chat.http.js';
|
||||
import {dmHandlers} from './handlers/dm.http.js';
|
||||
import {userHandler} from './handlers/user.http.js';
|
||||
import {brcChanHandlers} from './handlers/brcChan.http.js';
|
||||
|
||||
export const allHandlers = [
|
||||
...authHandlers,
|
||||
@@ -15,5 +16,6 @@ export const allHandlers = [
|
||||
...fileUploadHandlers,
|
||||
...chatHandlers,
|
||||
...dmHandlers,
|
||||
...userHandler
|
||||
...userHandler,
|
||||
...brcChanHandlers
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
import {setupServer} from "msw/node";
|
||||
import {allHandlers} from "./index";
|
||||
import {allHandlers} from './index.js';
|
||||
|
||||
export const mockServer = setupServer(...allHandlers)
|
||||
@@ -1,9 +1,12 @@
|
||||
import {DatabaseAPI} from "../../storage/database";
|
||||
import {DatabaseAPI} from '../../storage/database.js';
|
||||
|
||||
export class DatabaseMock implements DatabaseAPI {
|
||||
database: { [collection: string]: { [key: string]: string } } = {};
|
||||
|
||||
set(collection: string, key: string, value: any) {
|
||||
if (!this.database[collection]) {
|
||||
this.database[collection] = {};
|
||||
}
|
||||
this.database[collection][key] = JSON.stringify(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {KeyringAPI} from "../../storage/keyring";
|
||||
import {KeyringAPI} from '../../storage/keyring.js';
|
||||
|
||||
export class KeyringMock implements KeyringAPI {
|
||||
ring: { [key: string]: string } = {};
|
||||
@@ -7,15 +7,15 @@ export class KeyringMock implements KeyringAPI {
|
||||
this.ring[key] = value;
|
||||
}
|
||||
|
||||
get(key: string): string {
|
||||
return this.ring[key];
|
||||
get(key: string): Promise<string> {
|
||||
return Promise.resolve(this.ring[key]);
|
||||
}
|
||||
|
||||
getAll(): Promise<string[]> {
|
||||
return Promise.resolve(Object.keys(this.ring));
|
||||
}
|
||||
|
||||
delete(key: string) {
|
||||
delete this.ring[key];
|
||||
}
|
||||
|
||||
flush() {
|
||||
this.ring = {};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {AuthService} from "./authService";
|
||||
import {VerificationTypeEmail} from "../domain/authService.schema";
|
||||
import {AuthService} from './authService.js';
|
||||
import {VerificationTypeEmail} from '../domain/authService.schema.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
|
||||
describe("AuthService", () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {getClient} from "../core/http";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {
|
||||
AuthMethods, FinishPleAccountReq,
|
||||
LoginPasswordAuthReq, LoginWithApple, LoginWithGoogleReq, OtpPleCodeSendTestingResp,
|
||||
@@ -6,9 +6,9 @@ import {
|
||||
OtpVerifyCodeReq, PleSendCodeReq,
|
||||
PleVerifyCodeReq, PleVerifyCodeResp, RegisterReq, ResetPasswordReq, ResetPasswordResp,
|
||||
SignInSuccessResp, UserDataValidationResp, VerifyPasswordResetReq
|
||||
} from "../domain/authService.schema";
|
||||
} from '../domain/authService.schema.js';
|
||||
import {isAxiosError} from "axios";
|
||||
import {GenericErrorBody, GenericSuccessBody} from "../domain/http.schema";
|
||||
import {GenericErrorBody, GenericSuccessBody} from '../domain/http.schema.js';
|
||||
|
||||
export class AuthService {
|
||||
/**
|
||||
|
||||
11
src/services/broadcastChannelService.test.ts
Normal file
11
src/services/broadcastChannelService.test.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {BroadcastChannelService} from './broadcastChannelService.js';
|
||||
|
||||
describe("BroadcastChannelService", () => {
|
||||
const service = new BroadcastChannelService("", "", "", "", "", () => {})
|
||||
|
||||
it("should get stream registry data", async () => {
|
||||
const data = await service.getData()
|
||||
expect(data.status).toBe("broadcasting_starting")
|
||||
})
|
||||
})
|
||||
94
src/services/broadcastChannelService.ts
Normal file
94
src/services/broadcastChannelService.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {AcceptInviteReq} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {
|
||||
CreateServerReq,
|
||||
GetRTMPDataReq,
|
||||
JoinWebsocketRoomReq,
|
||||
StreamRegistry
|
||||
} from '../domain/broadcastChannelService.schema.js';
|
||||
|
||||
export class BroadcastChannelService {
|
||||
userid: string
|
||||
channelId: string
|
||||
networkId: string
|
||||
categoryId: string
|
||||
client: AxiosInstance;
|
||||
|
||||
constructor(token: string, userid: string, networkId: string, categoryId: string, channelId: string, wsMessageListener: MessageListener) {
|
||||
this.userid = userid;
|
||||
this.channelId = channelId;
|
||||
this.categoryId = categoryId;
|
||||
this.networkId = networkId;
|
||||
this.client = getClient(false).create({
|
||||
headers: {
|
||||
"Authorization": token,
|
||||
"X-WS-ID": WebSocketHandler.getInstance().connId
|
||||
}
|
||||
})
|
||||
WebSocketHandler.getInstance().registerService({
|
||||
identifier: channelId,
|
||||
onNewConnId: newConnId => this.onNewConnId(newConnId),
|
||||
onNewMessage: wsMessageListener,
|
||||
})
|
||||
}
|
||||
|
||||
private onNewConnId(newConnId: string) {
|
||||
console.log("NetworkService: New connection id")
|
||||
this.client.defaults.headers["X-WS-ID"] = newConnId;
|
||||
}
|
||||
|
||||
async getData(): Promise<StreamRegistry> {
|
||||
try {
|
||||
const resp = await this.client.get<StreamRegistry>(`network/channel/rtmpData?userid=${this.userid}&channelId=${this.channelId}&networkId=${this.networkId}&categoryId=${this.categoryId}`);
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
async createServer(): Promise<StreamRegistry> {
|
||||
try {
|
||||
const resp = await this.client.post<StreamRegistry>("network/channel/createServer", <CreateServerReq>{
|
||||
userid: this.userid,
|
||||
channelId: this.channelId,
|
||||
networkId: this.networkId,
|
||||
type: "rtmp",
|
||||
categoryId: this.categoryId,
|
||||
});
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
async joinWebSocketRoom(): Promise<void> {
|
||||
try {
|
||||
await this.client.post("v2/network/channel/joinWebSocketRoom", <JoinWebsocketRoomReq>{
|
||||
userid: this.userid,
|
||||
channelId: this.channelId,
|
||||
networkId: this.networkId,
|
||||
connId: WebSocketHandler.getInstance().connId,
|
||||
categoryId: this.categoryId,
|
||||
disableAutoRemove: true
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {CallService} from "./callService";
|
||||
import {CallService} from './callService.js';
|
||||
|
||||
describe("CallService", () => {
|
||||
const handler = new CallService("", "")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {getClient} from "../core/http";
|
||||
import {OtpPleCodeSendTestingResp, OtpSendCodeReq} from "../domain/authService.schema";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {OtpPleCodeSendTestingResp, OtpSendCodeReq} from '../domain/authService.schema.js';
|
||||
import {isAxiosError} from "axios";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {GetRTCAccessReq, GetRTCAccessResp, InviteToCallReq} from "../domain/callService.schema";
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {GetRTCAccessReq, GetRTCAccessResp, InviteToCallReq} from '../domain/callService.schema.js';
|
||||
|
||||
export class CallService {
|
||||
userid: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {ChatService} from "./chatService";
|
||||
import {DatabaseMock} from "../mocks/storage/database";
|
||||
import {ChatService} from './chatService.js';
|
||||
import {DatabaseMock} from '../mocks/storage/database.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
|
||||
describe("ChatService", () => {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import {DatabaseAPI} from "../storage/database";
|
||||
import {MessageListener} from "../domain/websocket.schema";
|
||||
import {getClient} from "../core/http";
|
||||
import {WebSocketHandler} from "../core/webSocketHandler";
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {getClient} from '../core/http.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {NetworkInvite} from "../domain/networkService.schema";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {NetworkInvite} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {
|
||||
Chat,
|
||||
GetAvailabilityReq,
|
||||
GetAvailabilityResp,
|
||||
StartNewReq,
|
||||
ToggleChatMuteReq
|
||||
} from "../domain/chatService.schema";
|
||||
import {Message} from "../domain/dmService.schema";
|
||||
} from '../domain/chatService.schema.js';
|
||||
import {Message} from '../domain/dmService.schema.js';
|
||||
|
||||
/**
|
||||
* ChatService is an exception because it's one instance for all chats because it's unnecessary to create a new instance for each chat
|
||||
@@ -32,7 +32,7 @@ export class ChatService {
|
||||
})
|
||||
WebSocketHandler.getInstance().registerService({
|
||||
identifier: userid,
|
||||
onNewConnId: this.onNewConnId,
|
||||
onNewConnId: newConnId => this.onNewConnId(newConnId),
|
||||
onNewMessage: wsMessageListener,
|
||||
})
|
||||
}
|
||||
@@ -58,8 +58,8 @@ export class ChatService {
|
||||
}
|
||||
}
|
||||
|
||||
getQuick(): Message[] {
|
||||
const chats = this.database.get("chats", this.userid)
|
||||
async getQuick(): Promise<Chat[]> {
|
||||
const chats = await this.database.get("chats", this.userid)
|
||||
if (chats) {
|
||||
return JSON.parse(chats)
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {DMService} from "./dmService";
|
||||
import {DatabaseMock} from "../mocks/storage/database";
|
||||
import {DMService} from './dmService.js';
|
||||
import {DatabaseMock} from '../mocks/storage/database.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
|
||||
describe("DmService", () => {
|
||||
@@ -23,7 +23,7 @@ describe("DmService", () => {
|
||||
|
||||
it('should send a new message', async () => {
|
||||
const message = faker.internet.displayName()
|
||||
const newMessage = await service.sendMessage(message)
|
||||
const newMessage = await service.sendMessage("", message)
|
||||
expect(newMessage.message).toBe(message)
|
||||
});
|
||||
})
|
||||
@@ -1,8 +1,8 @@
|
||||
import {DatabaseAPI} from "../storage/database";
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {MessageListener} from "../domain/websocket.schema";
|
||||
import {getClient} from "../core/http";
|
||||
import {WebSocketHandler} from "../core/webSocketHandler";
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {getClient} from '../core/http.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {
|
||||
DeleteMessagesReq,
|
||||
EditMessageReq,
|
||||
@@ -10,11 +10,11 @@ import {
|
||||
GetMessagePosResp, JoinWsRoomReq,
|
||||
Message, PinMessageReq,
|
||||
PinnedMessage, ReadMessagesReq, UnpinMessageReq
|
||||
} from "../domain/dmService.schema";
|
||||
import {NetworkInvite} from "../domain/networkService.schema";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {FileData} from "../domain/fileUploadService.schema";
|
||||
import {FileUploadService} from "./fileUploadService";
|
||||
} from '../domain/dmService.schema.js';
|
||||
import {NetworkInvite} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {FileData, FileUploadProgressListener} from '../domain/fileUploadService.schema.js';
|
||||
import {FileUploadService} from './fileUploadService.js';
|
||||
|
||||
export class DMService {
|
||||
userid: string;
|
||||
@@ -36,14 +36,15 @@ export class DMService {
|
||||
})
|
||||
WebSocketHandler.getInstance().registerService({
|
||||
identifier: chatid,
|
||||
onNewConnId: this.onNewConnId,
|
||||
onNewConnId: newConnId => this.onNewConnId(newConnId),
|
||||
onNewMessage: wsMessageListener,
|
||||
})
|
||||
}
|
||||
|
||||
private onNewConnId(newConnId: string) {
|
||||
console.log("NetworkService: New connection id")
|
||||
console.log("DmService: New connection id")
|
||||
this.client.defaults.headers["X-WS-ID"] = newConnId;
|
||||
this.joinWebSocketRoom().then()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,8 +66,8 @@ export class DMService {
|
||||
}
|
||||
}
|
||||
|
||||
getQuick(): Message[] {
|
||||
const messages = this.database.get("messages", this.chatid)
|
||||
async getQuick(): Promise<Message[]> {
|
||||
const messages = await this.database.get("messages", this.chatid)
|
||||
if (messages) {
|
||||
return JSON.parse(messages)
|
||||
} else {
|
||||
@@ -129,16 +130,18 @@ export class DMService {
|
||||
|
||||
/**
|
||||
* Sends a new message to the chat
|
||||
* @param tempMsgId
|
||||
* @param message
|
||||
* @param replyTo
|
||||
* @param replyToMessage
|
||||
* @param attachments
|
||||
* @param progressListener
|
||||
*/
|
||||
async sendMessage(message: string, replyTo: string | null = null, replyToMessage: string | null = null, attachments: FileData[] | null = null): Promise<Message> {
|
||||
async sendMessage(tempMsgId: string, message: string, replyTo: string | null = null, replyToMessage: string | null = null, attachments: FileData[] | null = null, progressListener: FileUploadProgressListener | null = null): Promise<Message> {
|
||||
let uploadId = ""
|
||||
if (attachments) {
|
||||
const uploader = new FileUploadService(this.token)
|
||||
uploadId = await uploader.uploadFiles(this.chatid, this.userid, attachments)
|
||||
uploadId = await uploader.uploadFiles(tempMsgId, this.chatid, this.userid, attachments, progressListener!)
|
||||
}
|
||||
try {
|
||||
const resp = await this.client.post<Message>("chat/dm/finishMessage", <FinishMessageReq>{
|
||||
@@ -243,10 +246,11 @@ export class DMService {
|
||||
*/
|
||||
async joinWebSocketRoom(): Promise<void> {
|
||||
try {
|
||||
const resp = await this.client.patch("chat/dm/joinWebSocketRoom", <JoinWsRoomReq>{
|
||||
await this.client.post("v2/chat/dm/joinWebSocketRoom", <JoinWsRoomReq>{
|
||||
chatid: this.chatid,
|
||||
userid: this.userid,
|
||||
connId: WebSocketHandler.getInstance().connId,
|
||||
disableAutoRemove: true
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
|
||||
156
src/services/fileTransferService.ts
Normal file
156
src/services/fileTransferService.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {getClient} from '../core/http.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {CreateNetworkReq, Network} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {
|
||||
AcceptFileTransferReq, DeclineFileTransferReq, FileTransferSendAnswerRTCReq,
|
||||
FileTransferSendICERTCReq, FileTransferSendOfferRTCReq,
|
||||
StartNewFileTransferReq,
|
||||
StartNewFileTransferResp,
|
||||
TransferableFileMetadata
|
||||
} from '../domain/fileTransferService.schema.js';
|
||||
|
||||
export class FileTransferService {
|
||||
userid: string;
|
||||
peerId: string;
|
||||
transferId: string = "";
|
||||
client: AxiosInstance
|
||||
|
||||
constructor(userid: string, token: string, peerId: string) {
|
||||
this.userid = userid;
|
||||
this.peerId = peerId;
|
||||
this.client = getClient(false).create({
|
||||
headers: {
|
||||
"Authorization": token,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new file transfer with the specified user. The new transferId will be saved automatically and not required to be provided later.
|
||||
* @param transferableFiles
|
||||
*/
|
||||
async startNew(transferableFiles: TransferableFileMetadata[]): Promise<string> {
|
||||
try {
|
||||
const resp = await this.client.post<StartNewFileTransferResp>("v2/chat/dm/startNewFileTransfer", <StartNewFileTransferReq>{
|
||||
userid: this.userid,
|
||||
targetUserId: this.peerId,
|
||||
metadata: transferableFiles
|
||||
});
|
||||
this.transferId = resp.data.transferId
|
||||
return resp.data.transferId
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts the file transfer with the specified transferId. The transferId will be saved automatically and not required to be provided later.
|
||||
* @param transferId
|
||||
*/
|
||||
async accept(transferId: string): Promise<RTCConfiguration> {
|
||||
try {
|
||||
const resp = await this.client.post<RTCConfiguration>("v2/chat/dm/acceptFileTransfer", <AcceptFileTransferReq>{
|
||||
userid: this.userid,
|
||||
senderId: this.peerId,
|
||||
transferId: transferId
|
||||
});
|
||||
this.transferId = transferId
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Declines the file transfer with the specified transferId.
|
||||
* @param transferId
|
||||
*/
|
||||
async decline(transferId: string): Promise<void> {
|
||||
try {
|
||||
await this.client.post("v2/chat/dm/declineFileTransfer", <DeclineFileTransferReq>{
|
||||
userid: this.userid,
|
||||
senderId: this.peerId,
|
||||
transferId: transferId
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards your RTC offer to the specified user.
|
||||
* @param offer
|
||||
*/
|
||||
async sendRtcOffer(offer: string): Promise<void> {
|
||||
try {
|
||||
await this.client.post("v2/chat/dm/sendRtcOfferFileTransfer", <FileTransferSendOfferRTCReq>{
|
||||
userid: this.userid,
|
||||
peerId: this.peerId,
|
||||
transferId: this.transferId,
|
||||
offer: offer,
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards your RTC answer to the specified user.
|
||||
* @param answer
|
||||
*/
|
||||
async sendRtcAnswer(answer: string): Promise<void> {
|
||||
try {
|
||||
await this.client.post("v2/chat/dm/sendRtcAnswerFileTransfer", <FileTransferSendAnswerRTCReq>{
|
||||
userid: this.userid,
|
||||
peerId: this.peerId,
|
||||
transferId: this.transferId,
|
||||
answer: answer,
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards your RTC ICE candidate to the specified user.
|
||||
* @param candidate
|
||||
*/
|
||||
async sendRtcICE(candidate: string): Promise<void> {
|
||||
try {
|
||||
await this.client.post("v2/chat/dm/sendRtcICEFileTransfer", <FileTransferSendICERTCReq>{
|
||||
userid: this.userid,
|
||||
peerId: this.peerId,
|
||||
transferId: this.transferId,
|
||||
candidate: candidate,
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {FileUploadService} from "./fileUploadService";
|
||||
import {FileUploadService} from './fileUploadService.js';
|
||||
|
||||
describe("fileUploadService", () => {
|
||||
it('should upload files', async () => {
|
||||
const service = new FileUploadService("");
|
||||
const uploadId = await service.uploadFiles("", "", [])
|
||||
const uploadId = await service.uploadFiles("","", "", [], {
|
||||
fileProgressUpdate: () => {}
|
||||
})
|
||||
expect(uploadId).toBe("MockUploadId")
|
||||
});
|
||||
})
|
||||
@@ -1,14 +1,14 @@
|
||||
import {
|
||||
ChunkUploadReq,
|
||||
FileData,
|
||||
FileData, FileUploadProgressListener,
|
||||
FileUploadRegistration, FinishUploadReq,
|
||||
RegisterUploadReq,
|
||||
RegisterUploadResp
|
||||
} from "../domain/fileUploadService.schema";
|
||||
} from '../domain/fileUploadService.schema.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {getClient} from "../core/http";
|
||||
import {InviteToCallReq} from "../domain/callService.schema";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {InviteToCallReq} from '../domain/callService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
export class FileUploadService {
|
||||
@@ -39,16 +39,18 @@ export class FileUploadService {
|
||||
|
||||
/**
|
||||
* Automatically registers the upload, calculates chunksize and uploads each chunk and returns with an uploadId that must be provided when sending the message
|
||||
* @param tempMsgId
|
||||
* @param roomId chatid or channelId
|
||||
* @param userid
|
||||
* @param files
|
||||
* @param listener
|
||||
*/
|
||||
async uploadFiles(roomId: string, userid: string, files: FileData[]): Promise<string> {
|
||||
async uploadFiles(tempMsgId: string, roomId: string, userid: string, files: FileData[], listener: FileUploadProgressListener): Promise<string> {
|
||||
let registrations: FileUploadRegistration[] = [];
|
||||
|
||||
files.forEach(file => {
|
||||
registrations.push({
|
||||
fileId: uuidv4(),
|
||||
fileId: file.fileId,
|
||||
name: file.name,
|
||||
type: file.type,
|
||||
size: file.data.size,
|
||||
@@ -62,7 +64,7 @@ export class FileUploadService {
|
||||
files: registrations,
|
||||
});
|
||||
for (let filesUploaded = 0; filesUploaded < files.length; filesUploaded++) {
|
||||
await this.uploadFile(resp.data.uploadId, roomId, userid, files[filesUploaded], registrations[filesUploaded])
|
||||
await this.uploadFile(tempMsgId, resp.data.uploadId, roomId, userid, files[filesUploaded], registrations[filesUploaded], listener)
|
||||
}
|
||||
await this.finishUpload(roomId, userid, resp.data.uploadId)
|
||||
return resp.data.uploadId
|
||||
@@ -92,7 +94,7 @@ export class FileUploadService {
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadFile(uploadId: string, roomId: string, userid: string, file: FileData, registration: FileUploadRegistration): Promise<void> {
|
||||
private async uploadFile(tempMsgId: string, uploadId: string, roomId: string, userid: string, file: FileData, registration: FileUploadRegistration, listener: FileUploadProgressListener): Promise<void> {
|
||||
const chunkSize = this.calculateChunkSize(file.data.size);
|
||||
const totalChunks = Math.ceil(file.data.size / chunkSize);
|
||||
|
||||
@@ -104,6 +106,7 @@ export class FileUploadService {
|
||||
const chunk = new Uint8Array(arrayBuffer.slice(start, end));
|
||||
const base64 = this.uint8ToBase64(chunk);
|
||||
await this.uploadChunk(uploadId, roomId, userid, registration.fileId, base64);
|
||||
listener.fileProgressUpdate(tempMsgId, file.fileId, totalChunks, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {NetworkService} from "./networkService";
|
||||
import {DatabaseMock} from "../mocks/storage/database";
|
||||
import {NetworkService} from './networkService.js';
|
||||
import {DatabaseMock} from '../mocks/storage/database.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
import {getClient} from "../core/http";
|
||||
import {environment, SDKConfig} from "../core/environment";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {environment, SDKConfig} from '../core/environment.js';
|
||||
|
||||
describe("NetworkService", () => {
|
||||
const service = new NetworkService("", "", "", new DatabaseMock(), (action, data) => {})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {DatabaseAPI} from "../storage/database";
|
||||
import {getClient} from "../core/http";
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {getClient} from '../core/http.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {
|
||||
AcceptInviteReq, AssignRankToMemberReq, BanMemberReq, ChangeVisibilityReq, CreateCategoryReq, CreateChannelReq,
|
||||
CreateInviteReq,
|
||||
@@ -15,11 +15,11 @@ import {
|
||||
NetworkInvite, NetworkRank, OverwriteChannelPermissionReq, OverwritePermissionReq, PermissionUpdate, POW,
|
||||
RemoveRankFromMemberReq, ToggleCategoryMuteReq, ToggleChannelNetworkMuteReq, ToggleNetworkMuteReq,
|
||||
UnbanMemberReq, UploadNewPictureReq
|
||||
} from "../domain/networkService.schema";
|
||||
import {PublicUserData, RGB} from "../domain/common.schema";
|
||||
import {WebSocketHandler} from "../core/webSocketHandler";
|
||||
import {MessageListener} from "../domain/websocket.schema";
|
||||
import {Message} from "../domain/dmService.schema";
|
||||
} from '../domain/networkService.schema.js';
|
||||
import {PublicUserData, RGB} from '../domain/common.schema.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {Message} from '../domain/dmService.schema.js';
|
||||
|
||||
export class NetworkService {
|
||||
userid: string;
|
||||
@@ -39,7 +39,7 @@ export class NetworkService {
|
||||
})
|
||||
WebSocketHandler.getInstance().registerService({
|
||||
identifier: networkId,
|
||||
onNewConnId: this.onNewConnId,
|
||||
onNewConnId: newConnId => this.onNewConnId(newConnId),
|
||||
onNewMessage: wsMessageListener,
|
||||
})
|
||||
}
|
||||
@@ -108,8 +108,8 @@ export class NetworkService {
|
||||
}
|
||||
}
|
||||
|
||||
getQuick(): Message[] {
|
||||
const networks = this.database.get("networks", this.userid)
|
||||
async getQuick(): Promise<Network[]> {
|
||||
const networks = await this.database.get("networks", this.userid)
|
||||
if (networks) {
|
||||
return JSON.parse(networks)
|
||||
} else {
|
||||
@@ -711,14 +711,18 @@ export class NetworkService {
|
||||
|
||||
/**
|
||||
* Uploads a new network picture
|
||||
* @param picId
|
||||
* @param isImage
|
||||
* @param image
|
||||
* @param colors
|
||||
*/
|
||||
async uploadNewPic(picId: string): Promise<void> {
|
||||
async uploadNewPic(isImage: boolean, image: string | null, colors: RGB | null): Promise<void> {
|
||||
try {
|
||||
await this.client.patch<PublicUserData[]>("network/uploadNewPic", <UploadNewPictureReq>{
|
||||
await this.client.patch<PublicUserData[]>("v2/network/uploadNewPic", <UploadNewPictureReq>{
|
||||
userid: this.userid,
|
||||
networkId: this.networkId,
|
||||
picId: picId,
|
||||
data: image,
|
||||
isImage: isImage,
|
||||
monogramColors: colors
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
@@ -863,6 +867,7 @@ export class NetworkService {
|
||||
userid: this.userid,
|
||||
networkId: this.networkId,
|
||||
connId: connId,
|
||||
disableAutoRemove: true
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {PictureService} from "./pictureService";
|
||||
import {DatabaseMock} from "../mocks/storage/database";
|
||||
import {PictureService} from './pictureService.js';
|
||||
import {DatabaseMock} from '../mocks/storage/database.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
|
||||
describe("PictureService", () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {DatabaseAPI} from "../storage/database";
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {getClient} from "../core/http";
|
||||
import {NetworkInvite} from "../domain/networkService.schema";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {NetworkInvite} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {
|
||||
Album, ChangePictureVisibilityReq, Comment,
|
||||
CreateAlbumReq,
|
||||
@@ -10,9 +10,9 @@ import {
|
||||
DiscoveryResp, EditPictureTitleReq,
|
||||
FinalizeUploadReq,
|
||||
GetResp, PostCommentReq, ToggleFollowReq, TogglePictureLikeReq, UploadImageReq
|
||||
} from "../domain/pictureService.schema";
|
||||
import {environment} from "../core/environment";
|
||||
import {Message} from "../domain/dmService.schema";
|
||||
} from '../domain/pictureService.schema.js';
|
||||
import {environment} from '../core/environment.js';
|
||||
import {Message} from '../domain/dmService.schema.js';
|
||||
|
||||
export class PictureService {
|
||||
userid: string;
|
||||
@@ -54,8 +54,8 @@ export class PictureService {
|
||||
}
|
||||
}
|
||||
|
||||
getQuick(): Message[] {
|
||||
const pictures = this.database.get("pictures", this.uploaderId)
|
||||
async getQuick(): Promise<Message[]> {
|
||||
const pictures = await this.database.get("pictures", this.uploaderId)
|
||||
if (pictures) {
|
||||
return JSON.parse(pictures)
|
||||
} else {
|
||||
|
||||
148
src/services/sessionManager.ts
Normal file
148
src/services/sessionManager.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import {PublicUserData} from '../domain/common.schema.js';
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {KeyringAPI} from '../storage/keyring.js';
|
||||
import {KeyValueAPI} from '../storage/keyvalue.js';
|
||||
import {Session, ValidateSessionReq, ValidateSessionResp} from '../domain/sessionManager.schema.js';
|
||||
import {AxiosInstance} from "axios";
|
||||
import {getClient} from '../core/http.js';
|
||||
import {PersonalUserData} from '../domain/userService.schema.js';
|
||||
|
||||
export class SessionManager {
|
||||
client: AxiosInstance;
|
||||
database: DatabaseAPI;
|
||||
keyring: KeyringAPI;
|
||||
KeyValue: KeyValueAPI;
|
||||
|
||||
constructor(database: DatabaseAPI, keyring: KeyringAPI, KeyValue: KeyValueAPI) {
|
||||
this.database = database;
|
||||
this.keyring = keyring;
|
||||
this.KeyValue = KeyValue;
|
||||
this.client = getClient(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the new session to the database and the keyring
|
||||
* @param userData
|
||||
* @param token
|
||||
*/
|
||||
addSession(userData: PublicUserData, token: string): void {
|
||||
this.database.set("sessions", userData.userid, JSON.stringify(userData))
|
||||
this.keyring.set(userData.userid, token)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all saved sessions
|
||||
*/
|
||||
async loadSessions(): Promise<Session[]> {
|
||||
const tokens = await this.keyring.getAll()
|
||||
const sessions: Session[] = []
|
||||
|
||||
for (const tokenKey of tokens) {
|
||||
try {
|
||||
const token = await this.keyring.get(tokenKey)
|
||||
const userData = await this.database.get("sessions", tokenKey)
|
||||
|
||||
if (userData && userData.trim().length > 0) {
|
||||
sessions.push({
|
||||
token: token,
|
||||
userData: JSON.parse(userData)
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Failed to parse session for ${tokenKey}:`, e)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return sessions
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the preferred user set by the client
|
||||
*/
|
||||
async getPreferredUser(): Promise<string> {
|
||||
return await this.KeyValue.get("preferredUser") ?? ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new preferred user
|
||||
* @param userid
|
||||
*/
|
||||
setPreferredUser(userid: string): void {
|
||||
this.KeyValue.set("preferredUser", userid)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the preferred session by the client
|
||||
*/
|
||||
async loadPreferredSession() {
|
||||
const sessions = await this.loadSessions()
|
||||
|
||||
if (sessions.length == 0) {
|
||||
throw new Error("No sessions found")
|
||||
}
|
||||
|
||||
let preferredUser = await this.getPreferredUser()
|
||||
if (preferredUser == "") {
|
||||
preferredUser = sessions[0].userData.userid
|
||||
this.setPreferredUser(sessions[0].userData.userid)
|
||||
}
|
||||
|
||||
const preferredSession = sessions.find(s => s.userData.userid == preferredUser)
|
||||
if (preferredSession) {
|
||||
return preferredSession
|
||||
} else {
|
||||
return sessions[0]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and updates all sessions and returns with a new session list
|
||||
* @param sessions
|
||||
*/
|
||||
async updateSessions(sessions: Session[]): Promise<Session[]> {
|
||||
const activeSessions: Session[] = [];
|
||||
|
||||
for (const session of sessions) {
|
||||
if (!await this.validateSession(session.token)) {
|
||||
this.database.delete("sessions", session.userData.userid);
|
||||
this.keyring.delete(session.userData.userid);
|
||||
console.warn(`Validating session for user ${session.userData.userid} failed. Deleting session...`)
|
||||
continue;
|
||||
}
|
||||
|
||||
const updatedUserData = await this.updateUserData(session);
|
||||
this.database.set("sessions", session.userData.userid, updatedUserData);
|
||||
activeSessions.push(updatedUserData);
|
||||
}
|
||||
|
||||
return activeSessions;
|
||||
}
|
||||
|
||||
private async validateSession(token: string): Promise<boolean> {
|
||||
try {
|
||||
const resp = await this.client.post<ValidateSessionResp>("v2/user/validateSession", <ValidateSessionReq>{
|
||||
token: token,
|
||||
})
|
||||
return resp.data.validationOk
|
||||
} catch (e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private async updateUserData(session: Session): Promise<Session> {
|
||||
const authenticatedClient = this.client.create({
|
||||
headers: {
|
||||
"Authorization": session.token,
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
const resp = await authenticatedClient.get<PersonalUserData>(`user/byUseridPersonal?userid=${session.userData.userid}`)
|
||||
session.userData = resp.data
|
||||
return session
|
||||
} catch (e) {
|
||||
throw new Error("Session update error")
|
||||
}
|
||||
}
|
||||
}
|
||||
283
src/services/textChannelService.ts
Normal file
283
src/services/textChannelService.ts
Normal file
@@ -0,0 +1,283 @@
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {getClient} from '../core/http.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {
|
||||
DeleteMessagesReq,
|
||||
EditMessageReq,
|
||||
FinishMessageReq,
|
||||
GetMessagePosResp, JoinWsRoomReq,
|
||||
Message, PinMessageReq,
|
||||
PinnedMessage, ReadMessagesReq, UnpinMessageReq
|
||||
} from '../domain/textChannelService.schema.js';
|
||||
import {NetworkInvite} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {FileData, FileUploadProgressListener} from '../domain/fileUploadService.schema.js';
|
||||
import {FileUploadService} from './fileUploadService.js';
|
||||
|
||||
export class TextChannelServiceService {
|
||||
userid: string;
|
||||
networkId: string;
|
||||
categoryId: string;
|
||||
channelId: string;
|
||||
token: string;
|
||||
database: DatabaseAPI;
|
||||
client: AxiosInstance
|
||||
|
||||
constructor(userid: string, token: string, networkId: string, categoryId: string, channelId: string, database: DatabaseAPI, wsMessageListener: MessageListener) {
|
||||
this.userid = userid;
|
||||
this.networkId = networkId;
|
||||
this.categoryId = categoryId;
|
||||
this.channelId = channelId;
|
||||
this.database = database;
|
||||
this.token = token;
|
||||
this.client = getClient(false).create({
|
||||
headers: {
|
||||
"Authorization": token,
|
||||
"X-WS-ID": WebSocketHandler.getInstance().connId
|
||||
}
|
||||
})
|
||||
WebSocketHandler.getInstance().registerService({
|
||||
identifier: channelId,
|
||||
onNewConnId: newConnId => this.onNewConnId(newConnId),
|
||||
onNewMessage: wsMessageListener,
|
||||
})
|
||||
}
|
||||
|
||||
private onNewConnId(newConnId: string) {
|
||||
console.log("NetworkService: New connection id")
|
||||
this.client.defaults.headers["X-WS-ID"] = newConnId;
|
||||
this.joinWebSocketRoom().then()
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all messages in the chat
|
||||
* @param from
|
||||
*/
|
||||
async get(from: number = 0): Promise<Message[]> {
|
||||
try {
|
||||
const resp = await this.client.get<Message[]>(`network/channel/messages?networkId=${this.networkId}&channelId=${this.channelId}&categoryId=${this.categoryId}&userid=${this.userid}&from=${from}`);
|
||||
if (from == 0) {
|
||||
this.database.set("networkmessages", this.channelId, JSON.stringify(resp.data))
|
||||
}
|
||||
console.log(resp.data, "ASD")
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
async getQuick(): Promise<Message[]> {
|
||||
const messages = await this.database.get("networkmessages", this.channelId)
|
||||
if (messages) {
|
||||
return JSON.parse(messages)
|
||||
} else {
|
||||
throw new Error("No messages in database")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the position of the specified message which can be used in get() to fetch an old message with it's surrounding messages
|
||||
* @param messageId
|
||||
*/
|
||||
async getMessagePos(messageId: string): Promise<number> {
|
||||
try {
|
||||
const resp = await this.client.get<GetMessagePosResp>(`network/channel/getMessagePosition?networkId=${this.networkId}&channelId=${this.channelId}&categoryId=${this.categoryId}&userid=${this.userid}&messageId=${messageId}`);
|
||||
return resp.data.messagePos
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all messages pinned in the chat
|
||||
*/
|
||||
async getPinnedMessages(): Promise<PinnedMessage[]> {
|
||||
try {
|
||||
const resp = await this.client.get<PinnedMessage[]>(`network/channel/pinnedMessages?networkId=${this.networkId}&channelId=${this.channelId}&categoryId=${this.categoryId}&userid=${this.userid}`);
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the specified message
|
||||
* @param messageId
|
||||
* @param newMessage
|
||||
*/
|
||||
async editMessage(messageId: string, newMessage: string): Promise<void> {
|
||||
try {
|
||||
const resp = await this.client.patch("network/channel/editMessage", <EditMessageReq>{
|
||||
messageId: messageId,
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
userid: this.userid,
|
||||
message: newMessage
|
||||
});
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a new message to the chat
|
||||
* @param tempMsgId
|
||||
* @param message
|
||||
* @param replyTo
|
||||
* @param replyToMessage
|
||||
* @param attachments
|
||||
* @param progressListener
|
||||
*/
|
||||
async sendMessage(tempMsgId: string, message: string, replyTo: string | null = null, replyToMessage: string | null = null, attachments: FileData[] | null = null, progressListener: FileUploadProgressListener | null = null): Promise<Message> {
|
||||
let uploadId = ""
|
||||
if (attachments) {
|
||||
const uploader = new FileUploadService(this.token)
|
||||
uploadId = await uploader.uploadFiles(tempMsgId, this.channelId, this.userid, attachments, progressListener!)
|
||||
}
|
||||
try {
|
||||
const resp = await this.client.post<Message>("network/channel/finishMessage", <FinishMessageReq>{
|
||||
message: message,
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
replyTo: replyTo,
|
||||
replyToMessage: replyToMessage,
|
||||
userid: this.userid,
|
||||
uploadId: uploadId,
|
||||
});
|
||||
return resp.data
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all messages sent to you in the chat
|
||||
*/
|
||||
async readMessages(): Promise<void> {
|
||||
try {
|
||||
await this.client.patch("network/channel/readMessages", <ReadMessagesReq>{
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
userid: this.userid,
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins the specified message
|
||||
* @param messageId
|
||||
* @param message
|
||||
*/
|
||||
async pinMessage(messageId: string, message: string): Promise<void> {
|
||||
try {
|
||||
const resp = await this.client.patch("network/channel/pinMessage", <PinMessageReq>{
|
||||
messageId: messageId,
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
userid: this.userid,
|
||||
message: message
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpins the specified message
|
||||
* @param messageId
|
||||
*/
|
||||
async unpinMessage(messageId: string): Promise<void> {
|
||||
try {
|
||||
const resp = await this.client.patch("network/channel/unpinMessage", <UnpinMessageReq>{
|
||||
messageId: messageId,
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
userid: this.userid,
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the message(s)
|
||||
* @param messageIds
|
||||
*/
|
||||
async deleteMessages(messageIds: string[]): Promise<void> {
|
||||
try {
|
||||
const resp = await this.client.patch("network/channel/deleteMessages", <DeleteMessagesReq>{
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
userid: this.userid,
|
||||
messageIds: messageIds
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins the WebSocket room to start receiving realtime messages
|
||||
*/
|
||||
async joinWebSocketRoom(): Promise<void> {
|
||||
try {
|
||||
const resp = await this.client.post("v2/network/channel/joinWebSocketRoom", <JoinWsRoomReq>{
|
||||
networkId: this.networkId,
|
||||
channelId: this.channelId,
|
||||
categoryId: this.categoryId,
|
||||
userid: this.userid,
|
||||
connId: WebSocketHandler.getInstance().connId,
|
||||
disableAutoRemove: true
|
||||
});
|
||||
return
|
||||
} catch (e) {
|
||||
if (isAxiosError<GenericErrorBody>(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("Unexpected error")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {UserService} from "./userService";
|
||||
import {DatabaseMock} from "../mocks/storage/database";
|
||||
import {UserService} from './userService.js';
|
||||
import {DatabaseMock} from '../mocks/storage/database.js';
|
||||
|
||||
describe("UserService", () => {
|
||||
const service = new UserService("", "", new DatabaseMock())
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {DatabaseAPI} from "../storage/database";
|
||||
import {DatabaseAPI} from '../storage/database.js';
|
||||
import {AxiosInstance, isAxiosError} from "axios";
|
||||
import {MessageListener} from "../domain/websocket.schema";
|
||||
import {getClient} from "../core/http";
|
||||
import {WebSocketHandler} from "../core/webSocketHandler";
|
||||
import {DeleteCategoryReq} from "../domain/networkService.schema";
|
||||
import {GenericErrorBody} from "../domain/http.schema";
|
||||
import {MessageListener} from '../domain/websocket.schema.js';
|
||||
import {getClient} from '../core/http.js';
|
||||
import {WebSocketHandler} from '../core/webSocketHandler.js';
|
||||
import {DeleteCategoryReq} from '../domain/networkService.schema.js';
|
||||
import {GenericErrorBody} from '../domain/http.schema.js';
|
||||
import {
|
||||
ChangeDisplayNameReq,
|
||||
ChangeEmailReq,
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
ChangeUsernameReq, CurrNewCodeTestingResp, DeleteReq, GetSessionsReq, GIF, RegisterFCMTokenReq, Session,
|
||||
ToggleGifSaveReq, UploadNewPfpCdnReq, UploadNewPfpCdnResp,
|
||||
UploadNewPfpReq, VerifyMailChangeReq, VerifyPhoneChange
|
||||
} from "../domain/userService.schema";
|
||||
import {RGB} from "../domain/common.schema";
|
||||
import {OtpPleCodeSendTestingResp} from "../domain/authService.schema";
|
||||
} from '../domain/userService.schema.js';
|
||||
import {RGB} from '../domain/common.schema.js';
|
||||
import {OtpPleCodeSendTestingResp} from '../domain/authService.schema.js';
|
||||
|
||||
export class UserService {
|
||||
userid: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface DatabaseAPI {
|
||||
set(collection: string, key: string, value: any): void;
|
||||
get(collection: string, key: string): string;
|
||||
get(collection: string, key: string): Promise<string>;
|
||||
delete(collection: string, key: string): void;
|
||||
flush(): void;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface KeyringAPI {
|
||||
set(key: string, value: any): void;
|
||||
get(key: string): string;
|
||||
get(key: string): Promise<string>;
|
||||
getAll(): Promise<string[]>;
|
||||
delete(key: string): void;
|
||||
flush(): void;
|
||||
}
|
||||
6
src/storage/keyvalue.ts
Normal file
6
src/storage/keyvalue.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface KeyValueAPI {
|
||||
set(key: string, value: any): void;
|
||||
get(key: string): Promise<string>;
|
||||
delete(key: string): void;
|
||||
flush(): void;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {beforeAll, afterEach, afterAll, vi} from 'vitest';
|
||||
import {mockServer} from "./mocks/node";
|
||||
import {mockServer} from './mocks/node.js';
|
||||
|
||||
beforeAll(() => mockServer.listen({onUnhandledRequest: 'error'}));
|
||||
afterEach(() => mockServer.resetHandlers());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {AuthService} from "../src/services/authService";
|
||||
import {VerificationTypeEmail} from "../src/domain/authService.schema";
|
||||
import {AuthService} from '../src/services/authService.js';
|
||||
import {VerificationTypeEmail} from '../src/domain/authService.schema.js';
|
||||
|
||||
describe("AuthService", () => {
|
||||
it("should return authMethods", async () => {
|
||||
|
||||
29
tests/broadcastChannelService.test.ts
Normal file
29
tests/broadcastChannelService.test.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {BroadcastChannelService} from '../src/services/broadcastChannelService.js';
|
||||
|
||||
const BRC_CHAN_SERVICE_TESTING_NETWORK_ID = "000000000000000000000000"
|
||||
const BRC_CHAN_SERVICE_TESTING_USER_ID = "000000000000000000000000"
|
||||
const BRC_CHAN_SERVICE_TESTING_CHANNEL_ID = "333333333333333333333333"
|
||||
const BRC_CHAN_SERVICE_TESTING_TOKEN = "testingToken"
|
||||
const BRC_CHAN_SERVICE_TESTING_CATEGORY_ID = "111111111111111111111111"
|
||||
|
||||
describe("BroadcastChannelService Integration Testing", () => {
|
||||
const service = new BroadcastChannelService(
|
||||
BRC_CHAN_SERVICE_TESTING_TOKEN,
|
||||
BRC_CHAN_SERVICE_TESTING_USER_ID,
|
||||
BRC_CHAN_SERVICE_TESTING_NETWORK_ID,
|
||||
BRC_CHAN_SERVICE_TESTING_CATEGORY_ID,
|
||||
BRC_CHAN_SERVICE_TESTING_CHANNEL_ID,
|
||||
(action, data) => {}
|
||||
)
|
||||
|
||||
it('should create a new server and fetch it', async () => {
|
||||
await service.createServer()
|
||||
const registry = await service.getData()
|
||||
expect(registry.status).toBe("idling")
|
||||
});
|
||||
|
||||
it('should join ws room', async () => {
|
||||
await service.joinWebSocketRoom()
|
||||
});
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {DatabaseMock} from "../src/mocks/storage/database";
|
||||
import {ChatService} from "../src/services/chatService";
|
||||
import {DatabaseMock} from '../src/mocks/storage/database.js';
|
||||
import {ChatService} from '../src/services/chatService.js';
|
||||
|
||||
describe("ChatService Integration Testing", () => {
|
||||
const CHAT_SERVICE_TESTING_USER_ID = "000000000000000000000000"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {DMService} from "../src/services/dmService";
|
||||
import {ChatService} from "../src/services/chatService";
|
||||
import {DatabaseMock} from "../src/mocks/storage/database";
|
||||
import {DMService} from '../src/services/dmService.js';
|
||||
import {ChatService} from '../src/services/chatService.js';
|
||||
import {DatabaseMock} from '../src/mocks/storage/database.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
|
||||
describe("DmService Integration Testing", () => {
|
||||
@@ -38,7 +38,7 @@ describe("DmService Integration Testing", () => {
|
||||
|
||||
it('should send a message', async () => {
|
||||
const message = faker.lorem.paragraph()
|
||||
const newMessage = await service.sendMessage(message)
|
||||
const newMessage = await service.sendMessage("", message)
|
||||
expect(newMessage.message).toBe(message)
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import {describe, it} from "vitest";
|
||||
import {FileUploadService} from "../src/services/fileUploadService";
|
||||
import {environment, SDKConfig} from "../src/core/environment";
|
||||
import {getClient} from "../src/core/http";
|
||||
import {FileData} from "../src/domain/fileUploadService.schema";
|
||||
import {FileUploadService} from '../src/services/fileUploadService.js';
|
||||
import {environment, SDKConfig} from '../src/core/environment.js';
|
||||
import {getClient} from '../src/core/http.js';
|
||||
import {FileData} from '../src/domain/fileUploadService.schema.js';
|
||||
import axios from "axios";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
describe("FileUploadService Integration Testing", () => {
|
||||
const FILE_UPL_SERVICE_TESTING_USER_ID = "000000000000000000000000"
|
||||
@@ -17,16 +18,21 @@ describe("FileUploadService Integration Testing", () => {
|
||||
|
||||
const service = new FileUploadService(FILE_UPL_SERVICE_TESTING_TOKEN);
|
||||
await service.uploadFiles(
|
||||
"",
|
||||
FILE_UPL_SERVICE_TESTING_CHAT_ID,
|
||||
FILE_UPL_SERVICE_TESTING_USER_ID,
|
||||
[
|
||||
{
|
||||
fileId: uuidv4(),
|
||||
name: "filename",
|
||||
type: "image",
|
||||
extension: "jpeg",
|
||||
data: new File([response.data], "filename", { type: "image/jpeg" })
|
||||
}
|
||||
]
|
||||
],
|
||||
{
|
||||
fileProgressUpdate: () => {},
|
||||
}
|
||||
)
|
||||
});
|
||||
})
|
||||
@@ -1,12 +1,12 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {NetworkService} from "../src/services/networkService";
|
||||
import {DatabaseMock} from "../src/mocks/storage/database";
|
||||
import {environment, SDKConfig} from "../src/core/environment";
|
||||
import {getClient} from "../src/core/http";
|
||||
import {NetworkService} from '../src/services/networkService.js';
|
||||
import {DatabaseMock} from '../src/mocks/storage/database.js';
|
||||
import {environment, SDKConfig} from '../src/core/environment.js';
|
||||
import {getClient} from '../src/core/http.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
import {AuthService} from "../src/services/authService";
|
||||
import {RGB} from "../src/domain/common.schema";
|
||||
import {NetworkPermissions, PermissionUpdate} from "../src/domain/networkService.schema";
|
||||
import {AuthService} from '../src/services/authService.js';
|
||||
import {RGB} from '../src/domain/common.schema.js';
|
||||
import {NetworkPermissions, PermissionUpdate} from '../src/domain/networkService.schema.js';
|
||||
|
||||
const NETWORK_SERVICE_TESTING_NETWORK_ID = "000000000000000000000000"
|
||||
const NETWORK_SERVICE_TESTING_USER_ID = "000000000000000000000000"
|
||||
@@ -56,12 +56,6 @@ describe("NetworkService Integration Testing", () => {
|
||||
expect(category.name).toBe(catName)
|
||||
});
|
||||
|
||||
it('should delete category', async () => {
|
||||
await service.deleteCategory(NETWORK_SERVICE_TESTING_CATEGORY_ID)
|
||||
const networks = await service.get()
|
||||
expect(networks[0].categories.length).toBe(0)
|
||||
});
|
||||
|
||||
it('should move category', async () => {
|
||||
await service.createCategory("Test name", "Test desc")
|
||||
await service.moveCategory(0, 1)
|
||||
@@ -74,7 +68,7 @@ describe("NetworkService Integration Testing", () => {
|
||||
});
|
||||
|
||||
it('should create rank', async () => {
|
||||
const rankName = faker.internet.displayName()
|
||||
const rankName = faker.internet.displayName().substring(0, 10)
|
||||
const rank = await service.createRank(rankName, <RGB>{r: 0, g: 0, b: 0}, null)
|
||||
expect(rank.name).toBe(rankName)
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {environment, SDKConfig} from "../src/core/environment";
|
||||
import {NetworkService} from "../src/services/networkService";
|
||||
import {DatabaseMock} from "../src/mocks/storage/database";
|
||||
import {getClient} from "../src/core/http";
|
||||
import {PictureService} from "../src/services/pictureService";
|
||||
import {environment, SDKConfig} from '../src/core/environment.js';
|
||||
import {NetworkService} from '../src/services/networkService.js';
|
||||
import {DatabaseMock} from '../src/mocks/storage/database.js';
|
||||
import {getClient} from '../src/core/http.js';
|
||||
import {PictureService} from '../src/services/pictureService.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
|
||||
const PICTURE_SERVICE_TESTING_TOKEN = "testingToken"
|
||||
@@ -24,7 +24,7 @@ describe("PictureService Integration Test", () => {
|
||||
});
|
||||
|
||||
it('should create an album', async () => {
|
||||
const albumName = faker.internet.displayName()
|
||||
const albumName = faker.internet.displayName().substring(0, 10)
|
||||
await service.createAlbum(albumName)
|
||||
const uploads = await service.get()
|
||||
expect(uploads.pictures[1].name).toBe(albumName)
|
||||
|
||||
66
tests/textChannelService.test.ts
Normal file
66
tests/textChannelService.test.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {DMService} from '../src/services/dmService.js';
|
||||
import {ChatService} from '../src/services/chatService.js';
|
||||
import {DatabaseMock} from '../src/mocks/storage/database.js';
|
||||
import {faker} from "@faker-js/faker/locale/en";
|
||||
import {TextChannelServiceService} from '../src/services/textChannelService.js';
|
||||
|
||||
describe("DmService Integration Testing", () => {
|
||||
const TXT_CHAN_SERVICE_TESTING_CHANNEL_ID = "222222222222222222222222"
|
||||
const TXT_CHAN_SERVICE_TESTING_USER_ID = "000000000000000000000000"
|
||||
const TXT_CHAN_SERVICE_TESTING_MESSAGE_ID = "111111111111111111111111"
|
||||
const TXT_CHAN_SERVICE_TESTING_TOKEN = "testingToken"
|
||||
const NETWORK_SERVICE_TESTING_NETWORK_ID = "000000000000000000000000"
|
||||
const NETWORK_SERVICE_TESTING_CATEGORY_ID = "111111111111111111111111"
|
||||
|
||||
const service = new TextChannelServiceService(
|
||||
TXT_CHAN_SERVICE_TESTING_USER_ID,
|
||||
TXT_CHAN_SERVICE_TESTING_TOKEN,
|
||||
NETWORK_SERVICE_TESTING_NETWORK_ID,
|
||||
NETWORK_SERVICE_TESTING_CATEGORY_ID,
|
||||
TXT_CHAN_SERVICE_TESTING_CHANNEL_ID,
|
||||
new DatabaseMock(),
|
||||
() => {}
|
||||
)
|
||||
|
||||
it('should get messages', async () => {
|
||||
const messages = await service.get()
|
||||
expect(messages[0].message).toBe("This is a message")
|
||||
expect(messages[0].isEdited).toBeTruthy()
|
||||
});
|
||||
|
||||
it('should get message position', async () => {
|
||||
const pos = await service.getMessagePos(TXT_CHAN_SERVICE_TESTING_MESSAGE_ID)
|
||||
expect(pos).toBe(0)
|
||||
});
|
||||
|
||||
it('should edit message', async () => {
|
||||
const newMessage = faker.lorem.paragraph()
|
||||
await service.editMessage(TXT_CHAN_SERVICE_TESTING_MESSAGE_ID, newMessage)
|
||||
const messages = await service.get()
|
||||
expect(messages[0].message).toBe(newMessage)
|
||||
});
|
||||
|
||||
it('should send a message', async () => {
|
||||
const message = faker.lorem.paragraph()
|
||||
const newMessage = await service.sendMessage("", message)
|
||||
expect(newMessage.message).toBe(message)
|
||||
});
|
||||
|
||||
it('should read messages', async () => {
|
||||
await service.readMessages()
|
||||
});
|
||||
|
||||
it('should pin and unpin messages', async () => {
|
||||
let pinnedMessages = await service.getPinnedMessages()
|
||||
expect(pinnedMessages.length).toBe(0)
|
||||
|
||||
await service.pinMessage(TXT_CHAN_SERVICE_TESTING_MESSAGE_ID, "message")
|
||||
pinnedMessages = await service.getPinnedMessages()
|
||||
expect(pinnedMessages.length).toBe(1)
|
||||
|
||||
await service.unpinMessage(TXT_CHAN_SERVICE_TESTING_MESSAGE_ID)
|
||||
pinnedMessages = await service.getPinnedMessages()
|
||||
expect(pinnedMessages.length).toBe(0)
|
||||
});
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
import {describe, expect, it} from "vitest";
|
||||
import {UserService} from "../src/services/userService";
|
||||
import {DatabaseMock} from "../src/mocks/storage/database";
|
||||
import {RGB} from "../src/domain/common.schema"
|
||||
import {UserService} from '../src/services/userService.js';
|
||||
import {DatabaseMock} from '../src/mocks/storage/database.js';
|
||||
import {RGB} from '../src/domain/common.schema.js'
|
||||
|
||||
const USER_SERVICE_TESTING_USER_ID = "000000000000000000000000"
|
||||
const USER_SERVICE_TESTING_TOKEN = "testingToken"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {beforeAll, beforeEach} from 'vitest';
|
||||
import {environment, SDKConfig} from "../src/core/environment";
|
||||
import {getClient} from "../src/core/http";
|
||||
import {environment, SDKConfig} from '../src/core/environment.js';
|
||||
import {getClient} from '../src/core/http.js';
|
||||
|
||||
beforeEach(async () => {
|
||||
await getClient(false).post("v2/reset")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {describe, it} from "vitest";
|
||||
import {WebSocketHandler} from "../src/core/webSocketHandler";
|
||||
import {WebSocketHandler} from '../src/core/webSocketHandler.js';
|
||||
|
||||
const WEBSOCKET_HANDLER_TESTING_USER_ID = "000000000000000000000000"
|
||||
const WEBSOCKET_HANDLER_TESTING_USER_TOKEN = "testingToken"
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "commonjs",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "nodenext",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist"
|
||||
"outDir": "dist",
|
||||
"verbatimModuleSyntax": false,
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user