1.2.0 - Has been implemented the "user-info" method exposed by the Tuitio API.

master
Tudor Stanciu 2023-03-28 19:20:32 +03:00
parent 5804ca084d
commit 13083aecf7
15 changed files with 112 additions and 51 deletions

View File

@ -38,4 +38,5 @@ All tests in the package can be executed by running: `npm test`.
1.0.2 - Validate that Tuitio's URL parameter is a valid URL
1.0.3 - Added LICENSE file
1.0.4 - TuitioState's token property can be null
1.1.0 - In this version, the account logout method and the latest changes published by Tuitio were implemented.
1.1.0 - In this version, the account logout method and the latest changes published by Tuitio were implemented.
1.2.0 - Has been implemented the "user-info" method exposed by the Tuitio API.

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "@flare/tuitio-client",
"version": "1.1.0",
"version": "1.2.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@flare/tuitio-client",
"version": "1.1.0",
"version": "1.2.0",
"license": "MIT",
"dependencies": {
"@flare/js-utils": "^1.0.3",

View File

@ -1,6 +1,6 @@
{
"name": "@flare/tuitio-client",
"version": "1.1.0",
"version": "1.2.0",
"description": "Tuitio client is an npm package written in typescript that facilitates the integration of a javascript application with Tuitio.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",

View File

@ -2,7 +2,7 @@
import { getUrlTemplates } from "../config";
import { TuitioClient } from "../client";
import type { TuitioLoginResponse } from "../client";
import type { TuitioLoginResponse } from "../types";
test("Get url templates", () => {
const result = getUrlTemplates("https://test.com/api");

View File

@ -5,7 +5,8 @@
// Copyright (c) 2023 Tudor Stanciu
import axios from "axios";
import { TuitioClient, fetch } from "../client";
import { TuitioClient } from "../client";
import { fetch } from "../state";
jest.mock("axios");

View File

@ -5,7 +5,8 @@
// Copyright (c) 2023 Tudor Stanciu
import axios from "axios";
import { TuitioClient, fetch } from "../client";
import { TuitioClient } from "../client";
import { fetch } from "../state";
import { localStorage } from "@flare/js-utils";
import { storageKeys } from "../constants";

View File

@ -4,7 +4,7 @@
// Copyright (c) 2023 Tudor Stanciu
import { fetch } from "../client";
import { fetch } from "../state";
test("Tuitio empty storage", () => {
const result = fetch();

View File

@ -1,6 +1,6 @@
// Copyright (c) 2023 Tudor Stanciu
import { combineUrls, isValidURL } from "../utils";
import { combineUrls, isValidURL } from "../../utils/validations";
test("Combine urls with trailing slash", () => {
const result = combineUrls("https://test.com/api/", "/test");

View File

@ -1,33 +1,15 @@
// Copyright (c) 2023 Tudor Stanciu
import axios from "axios";
import { request } from "./utils/axios";
import { localStorage } from "@flare/js-utils";
import { storageKeys } from "./constants";
import { getUrlTemplates } from "./config";
import { isValidURL } from "./utils";
import { isValidURL } from "./utils/validations";
import type { UrlTemplates } from "./config";
import type { TuitioLoginResponse, TuitioLogoutResponse, TuitioUserInfoResponse } from "./types";
const { setItem, getItem, removeItem } = localStorage;
async function request(url: string, method: string) {
try {
const res = await axios.request({ url, method });
return res.data;
} catch (error: any) {
if (error.response && error.response.data) {
const { detail, title } = error.response.data;
throw {
...error.response.data,
message: detail || title
};
}
throw error;
}
}
export type TuitioLoginResponse = { result: { token: string; expiresIn: number; validUntil: Date } | null; error: string | null };
export type TuitioLogoutResponse = { result: { userId: number; userName: string; logoutDate: Date } | null; error: string };
class TuitioClient {
tuitioUrl: string;
urlTemplates: UrlTemplates;
@ -67,22 +49,13 @@ class TuitioClient {
}
return response;
}
async getUserInfo(): Promise<TuitioUserInfoResponse> {
const url = this.urlTemplates.userInfo;
const response = await request(url, "get");
return response;
}
}
export type TuitioState = { token: string | null; validUntil: Date | null; userName: string | null };
const defaultTuitioState: TuitioState = { token: null, validUntil: null, userName: null };
const fetch = (): TuitioState => {
const authData = getItem(storageKeys.AUTH_DATA);
if (!authData) return defaultTuitioState;
const { token, validUntil, userName } = authData;
const data: TuitioState = {
token,
validUntil,
userName
};
return data;
};
export { TuitioClient, fetch };
export { TuitioClient };
export default TuitioClient;

View File

@ -1,15 +1,17 @@
// Copyright (c) 2023 Tudor Stanciu
import { combineUrls } from "./utils";
import { combineUrls } from "./utils/validations";
export type UrlTemplates = {
login: string;
logout: string;
userInfo: string;
};
const getUrlTemplates = (tuitioUrl: string): UrlTemplates => ({
login: combineUrls(tuitioUrl, "/account/login?UserName={username}&Password={password}"),
logout: combineUrls(tuitioUrl, "/account/logout?Token={token}")
logout: combineUrls(tuitioUrl, "/account/logout?Token={token}"),
userInfo: combineUrls(tuitioUrl, "/connect/user-info")
});
export { getUrlTemplates };

View File

@ -1,8 +1,9 @@
// Copyright (c) 2023 Tudor Stanciu
import { TuitioClient, fetch } from "./client";
import type { TuitioLoginResponse, TuitioLogoutResponse, TuitioState } from "./client";
import { TuitioClient } from "./client";
import { fetch } from "./state";
export * from "./types";
export { TuitioClient, fetch };
export type { TuitioLoginResponse, TuitioLogoutResponse, TuitioState };
export default TuitioClient;

23
src/state.ts Normal file
View File

@ -0,0 +1,23 @@
// Copyright (c) 2023 Tudor Stanciu
import { localStorage } from "@flare/js-utils";
import { storageKeys } from "./constants";
import type { TuitioState } from "./types";
const { getItem } = localStorage;
const defaultTuitioState: TuitioState = { token: null, validUntil: null, userName: null };
const fetch = (): TuitioState => {
const authData = getItem(storageKeys.AUTH_DATA);
if (!authData) return defaultTuitioState;
const { token, validUntil, userName } = authData;
const data: TuitioState = {
token,
validUntil,
userName
};
return data;
};
export { fetch };

25
src/types.ts Normal file
View File

@ -0,0 +1,25 @@
export type TuitioLoginResponse = { result: { token: string; expiresIn: number; validUntil: Date } | null; error: string | null };
export type TuitioLogoutResponse = { result: { userId: number; userName: string; logoutDate: Date } | null; error: string };
export type TuitioState = { token: string | null; validUntil: Date | null; userName: string | null };
export type TuitioUserContactOption = {
id: number;
contactTypeCode: string;
contactTypeName: string;
contactValue: string;
};
export type TuitioUserInfoResponse = {
userId: number;
userName: string;
firstName: string;
lastName: string;
email: string;
profilePictureUrl: string;
securityStamp: string;
creationDate: Date;
failedLoginAttempts: number;
lastLoginDate: Date;
claim?: object;
contactOptions?: [TuitioUserContactOption];
};

34
src/utils/axios.ts Normal file
View File

@ -0,0 +1,34 @@
// Copyright (c) 2023 Tudor Stanciu
import axios, { AxiosHeaders } from "axios";
import { fetch } from "../state";
function getHeaders(): AxiosHeaders {
const { token } = fetch();
const headers = new AxiosHeaders({
"Content-Type": "application/json"
});
if (token) {
headers["Authorization"] = `Tuitio ${token}`;
}
return headers;
}
async function request(url: string, method: string) {
const headers = getHeaders();
try {
const res = await axios.request({ url, method, headers });
return res.data;
} catch (error: any) {
if (error.response && error.response.data) {
const { detail, title } = error.response.data;
throw {
...error.response.data,
message: detail || title
};
}
throw error;
}
}
export { request };