events & initialize

This commit is contained in:
Julian Krauser 2025-02-06 09:38:30 +01:00
parent 3f7fc8a147
commit afbcae4add
5 changed files with 73 additions and 9 deletions

View file

@ -6,7 +6,7 @@ Zur Verfügung gestellt werden Requests mit den benötigten Models, Types und En
Der WebApiClient realisiert den automatischen refresh von Zugangs-Tokens.
Beispiele:\
Beispiele:
1. Verwendung des Clients:
``` ts
import { WebApiClient, AdminRequests } from "@ff-admin/webapi-client"
@ -15,7 +15,10 @@ let myClient = new WebApiClient({
serverAdress: "",
webapiToken: ""
});
myClient.initialize() // asynchrone Funktion - muss vollständig ausgeführt sein, bevor irgendwelche Anfragen gestellt werden
```
2. Nutzung der Requests
```ts
let data = AdminRequests.MemberRequests.getAllMembers(myClient)
.then((res) => {
console.log(res)
@ -49,12 +52,24 @@ AdminRequests.MemberRequests.updateMember(myClient, {
.then(() => {})
.catch(() => {});
```
2. Zugriff auf Typen, Models und Enums:
3. Zugriff auf Typen, Models und Enums:
``` ts
import { AdminModels, AdminTypes, AdminEnums } from "@ff-admin/webapi-client"
let model: AdminModels.MemberModels.CreateMemberViewModel;
let type: AdminTypes.DynamicQueries.DynamicQueryStructure
let enum = AdminEnums.NewsletterType.NewsletterConfigType.mail
```
4. http Events:
Es können Events wie Fehler oder Informationen direkt aus der Middleware des Clients angezapft werden.
``` ts
import { WebApiClient, AdminRequests } from "@ff-admin/webapi-client"
let myClient = new WebApiClient({
serverAdress: "",
webapiToken: ""
});
myClient.initialize()
client.httpEvents.on(<"error" | "info">, (data) => {})
```

View file

@ -12,6 +12,12 @@ export class BaseClient extends Config {
return this.httpInstance.http;
}
get httpEvents() {
return this.httpInstance.httpEvents;
}
public async initialize(): Promise<void> {}
public refreshToken(): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
reject("api token refresh not implemented");

View file

@ -5,8 +5,8 @@ export class WebApiClient extends BaseClient {
super({ serverAdress, webapiToken });
}
get http() {
return this.httpInstance.http;
public async initialize(): Promise<void> {
await this.refreshToken();
}
public refreshToken(): Promise<void> {

View file

@ -1,9 +1,16 @@
import axios, { AxiosInstance } from "axios";
import { BaseClient } from "./clients/clientBase";
import { EventEmitterReadonly, TypedEventEmitter } from "./utils/typedEmitter";
type HttpEvents = {
info: [arg1: string];
error: [arg1: { code: string; message: string }];
};
export default class HTTP {
public http: AxiosInstance;
private client: BaseClient;
public readonly http: AxiosInstance;
protected readonly httpEmitter: TypedEventEmitter<HttpEvents>;
protected client: BaseClient;
constructor(client: BaseClient) {
this.client = client;
@ -15,15 +22,20 @@ export default class HTTP {
Expires: "0",
},
});
this.httpEmitter = new TypedEventEmitter<HttpEvents>();
this.setRequestInterceptor();
this.setResponseInterceptor();
}
get httpEvents(): EventEmitterReadonly<HttpEvents> {
return this.httpEmitter;
}
private setRequestInterceptor() {
this.http.interceptors.request.use(
(config) => {
if (config.headers && config.headers.Authorization == "") {
if (config.headers && !config.headers.Authorization) {
config.headers.Authorization = `Bearer ${this.client.accessToken}`;
}
@ -53,11 +65,16 @@ export default class HTTP {
return await this.client
.refreshToken()
.then(() => {
this.httpEmitter.emit("info", "successfully refreshed token");
return this.http(originalRequest);
})
.catch(() => {});
}
this.httpEmitter.emit("error", {
code: error.code,
message: error.message,
});
return Promise.reject(error);
}
);

26
src/utils/typedEmitter.ts Normal file
View file

@ -0,0 +1,26 @@
import EventEmitter = require("node:events");
export interface EventEmitterReadonly<TEvents extends Record<string, any>> {
on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void;
off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void;
}
export interface EventEmitterFull<TEvents extends Record<string, any>> extends EventEmitterReadonly<TEvents> {
emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArg: TEvents[TEventName]): void;
}
export class TypedEventEmitter<TEvents extends Record<string, any>> implements EventEmitterFull<TEvents> {
private emitter = new EventEmitter();
emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArg: TEvents[TEventName]) {
this.emitter.emit(eventName, ...(eventArg as []));
}
on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void) {
this.emitter.on(eventName, handler as any);
}
off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void) {
this.emitter.off(eventName, handler as any);
}
}