Compare commits

..

88 Commits

Author SHA1 Message Date
Derrick Hammer 456db25ad7
dep: update s5-js 2024-03-28 20:32:25 -04:00
Derrick Hammer 2744b40cfa
dep: update s5-js 2024-03-27 23:42:34 -04:00
Derrick Hammer 080fea1b1e
dep: update s5-js 2024-03-26 23:50:13 -04:00
Derrick Hammer afa853aa12
chore: update swagger.yaml 2024-03-26 16:44:50 -04:00
Derrick Hammer 1f69c9c1cc
style: prettier 2024-03-26 15:18:48 -04:00
Derrick Hammer db2212ab70
feat: add requestEmailVerification 2024-03-26 15:18:29 -04:00
Derrick Hammer dcd1fdc705
chore: update swagger.yaml 2024-03-26 15:17:59 -04:00
Derrick Hammer 574ef1ddb1
dep: update s5-js 2024-03-26 11:47:23 -04:00
Derrick Hammer 76751db499
dep: update s5-js 2024-03-22 18:37:24 -04:00
Derrick Hammer 8296e7410d
dep: update s5-js 2024-03-22 18:14:36 -04:00
Derrick Hammer 1bf1360937
dep: update s5-js 2024-03-21 16:36:01 -04:00
Derrick Hammer 2ee92db9ce
dep: update s5-js 2024-03-21 16:31:01 -04:00
Derrick Hammer 7239cc7ba1
dep: update s5-js 2024-03-21 16:11:58 -04:00
Derrick Hammer 08d24eebf4
dep: update s5-js 2024-03-21 15:16:48 -04:00
Derrick Hammer b74ea88900
dep: update s5-js 2024-03-21 13:20:04 -04:00
Derrick Hammer 61b8b3b554
dep: update s5-js 2024-03-21 13:15:18 -04:00
Derrick Hammer 93a7360537
dep: update s5-js 2024-03-21 13:09:23 -04:00
Derrick Hammer d5b27e946c
dep: update s5-js 2024-03-21 12:55:40 -04:00
Derrick Hammer 3b63255b75
dep: update s5-js 2024-03-21 12:39:13 -04:00
Derrick Hammer 1b136d2089
dep: update s5-js 2024-03-21 12:20:42 -04:00
Derrick Hammer f95fb116a8
dep: update s5-js 2024-03-21 12:15:01 -04:00
Derrick Hammer 01c66456a8
dep: update s5-js 2024-03-21 12:11:58 -04:00
Derrick Hammer 9131fc8b96
dep: update s5-js 2024-03-21 11:37:54 -04:00
Derrick Hammer 8ed63175bc
dep: update s5-js 2024-03-21 11:02:44 -04:00
Derrick Hammer 99a92b1625
dep: update s5-js 2024-03-21 10:57:09 -04:00
Derrick Hammer ccc30a2077
dep: update s5-js 2024-03-21 10:48:58 -04:00
Derrick Hammer c5396b5535
dep: update s5-js 2024-03-21 10:26:39 -04:00
Derrick Hammer 8431f5c9f8
fix: typo 2024-03-21 08:44:31 -04:00
Derrick Hammer a508347fb1
refactor: export AccountError 2024-03-20 16:16:26 -04:00
Derrick Hammer 55fc51ad0a
refactor: update more methods to return an error optionally, and switch to a custom Error child class so we can get the status code and message 2024-03-20 15:41:22 -04:00
Derrick Hammer b7a9484785
refactor: update some of the methods to return an error in the try catch/vs a false 2024-03-20 12:58:31 -04:00
Derrick Hammer 7a3248b21b
feat: add updatePassword api 2024-03-19 10:06:39 -04:00
Derrick Hammer ef3d0d3fbc
fix: add ?. 2024-03-19 08:00:22 -04:00
Derrick Hammer 788e424841
refactor: update api calls since we changed routes 2024-03-19 07:59:39 -04:00
Derrick Hammer c0345dec11
feat: add updateEmail 2024-03-19 07:58:32 -04:00
Derrick Hammer 5b04f7ecaf
refactor: update api calls since we changed routes 2024-03-19 07:55:38 -04:00
Derrick Hammer bc5f143ae6
chore: update swagger.yaml 2024-03-19 07:53:49 -04:00
Derrick Hammer 845c47fef9
dep: update s5-js 2024-03-18 18:41:35 -04:00
Derrick Hammer 6163b40d7b
dep: update s5-js 2024-03-18 18:30:56 -04:00
Derrick Hammer 0e09f2ecb3
dep: update s5-js 2024-03-18 18:04:48 -04:00
Derrick Hammer 3b2d839f04
refactor: if ping is successful, store the jwt token 2024-03-18 17:21:53 -04:00
Derrick Hammer 271917540d
chore: update swagger.yaml 2024-03-18 17:21:20 -04:00
Derrick Hammer 8cf56b4751
dep: update s5-js 2024-03-18 14:31:41 -04:00
Derrick Hammer f99c51e4df
fix: only call registerDefaults when registry isn't init'ed 2024-03-18 13:01:07 -04:00
Derrick Hammer 1f68b13180
dep: update s5-js 2024-03-18 11:35:35 -04:00
Derrick Hammer 51cb8d7a90
dep: update s5-js 2024-03-18 11:17:44 -04:00
Derrick Hammer 8911251288
dep: update s5-js 2024-03-18 11:11:32 -04:00
Derrick Hammer a135201dfb
dep: update s5-js 2024-03-18 11:04:13 -04:00
Derrick Hammer 14c854c455
fix: update imports 2024-03-18 10:46:45 -04:00
Derrick Hammer e3480d61f0
fix: update imports 2024-03-18 09:44:08 -04:00
Derrick Hammer 8d5f0ba539
feat: implement protocol support, starting with s5 2024-03-18 09:37:02 -04:00
Derrick Hammer cfcedc3670
dep: update @lumeweb/s5-js 2024-03-18 09:31:53 -04:00
Derrick Hammer ffe01db460
feat: add uploadLimit endpoint 2024-03-17 11:18:03 -04:00
Derrick Hammer b2b4d7b8ea
chore: update swagger 2024-03-17 11:17:09 -04:00
Derrick Hammer 5381184a07
feat: implement logout method 2024-03-17 09:35:37 -04:00
Derrick Hammer de5aa03ba3
style: prettier 2024-03-17 09:32:54 -04:00
Derrick Hammer 3c0510c272
chore: update account swagger.yaml 2024-03-17 09:29:02 -04:00
Derrick Hammer 713430f00f
dep: add @lumeweb/s5-js 2024-03-17 09:28:49 -04:00
Derrick Hammer cadd9e1d5c
refactor: put schema export in root 2024-03-14 07:07:29 -04:00
Derrick Hammer de4cb673cc
refactor: export all openapi types 2024-03-14 07:05:05 -04:00
Derrick Hammer 31505980c9
feat: add account info endpoint 2024-03-14 06:57:49 -04:00
Derrick Hammer 5e68896eea
style: prettier 2024-03-13 18:34:27 -04:00
Derrick Hammer 77e7f290d8
refactor: add jwtToken getter 2024-03-13 18:33:59 -04:00
Derrick Hammer f8f8780f97
fix: use _jwtToken 2024-03-13 18:27:59 -04:00
Derrick Hammer 3bc2dfadce
Revert "fix: use URL.URL"
This reverts commit d18e3a9da5.
2024-03-13 18:26:52 -04:00
Derrick Hammer 63e214cc49
feat: add setAuthToken 2024-03-13 18:15:01 -04:00
Derrick Hammer 070b117089
refactor: add setter for jwtToken 2024-03-13 18:13:24 -04:00
Derrick Hammer 0f3de13f52
refactor: don't use default exports 2024-03-13 18:12:44 -04:00
Derrick Hammer d18e3a9da5
fix: use URL.URL 2024-03-13 18:12:18 -04:00
Derrick Hammer 620e983011
fix: login needs to return bool 2024-03-13 17:54:26 -04:00
Derrick Hammer 42751d5214
refactor: update ping api to use new PingResponse 2024-03-13 17:30:03 -04:00
Derrick Hammer 6f1d761c99
chore: update swagger 2024-03-13 17:28:21 -04:00
Derrick Hammer 2d0c55848b
refactor: use try/catch on all apis to prevent axios errors 2024-03-13 17:13:19 -04:00
Derrick Hammer 9a9283cc8a
fix: return the full response 2024-03-13 14:58:30 -04:00
Derrick Hammer bc3550ab4b
feat: add logout 2024-03-13 13:04:57 -04:00
Derrick Hammer 9e7e0c7f65
style: prettier 2024-03-13 12:57:38 -04:00
Derrick Hammer 3e8aaa1dba
fix: prefix api endpoint with account subdomain 2024-03-13 12:57:21 -04:00
Derrick Hammer cde0ea645f
chore: add dom to tsconfig 2024-03-13 12:56:30 -04:00
Derrick Hammer daf38957a4
fix: if jwt is not set, don't send it 2024-03-13 12:56:01 -04:00
Derrick Hammer d490ac55ce
feat: add ping account api 2024-03-13 12:32:08 -04:00
Derrick Hammer 13712d2501
chore: add patch-package as a main dependency 2024-03-13 10:41:20 -04:00
Derrick Hammer d8dbc882a5
fix: add patch for tsc-alias 2024-03-13 10:36:43 -04:00
Derrick Hammer f51c4381b4
chore: add patch-package 2024-03-13 10:36:17 -04:00
Derrick Hammer 3250edf166
chore: prettier 2024-03-13 10:22:23 -04:00
Derrick Hammer 4797ea7be2
fix: bad import 2024-03-13 10:12:01 -04:00
Derrick Hammer f287e0793f
fix: change package to a module 2024-03-13 10:08:44 -04:00
Derrick Hammer aa9ed84aea
refactor: don't make Sdk as default export 2024-03-13 10:00:38 -04:00
Derrick Hammer 5de87a9b3f
feat: initial version 2024-03-06 18:17:47 -05:00
17 changed files with 18257 additions and 1 deletions

11
.changeset/config.json Normal file
View File

@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": []
}

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
# preset generated files
/.eslintrc.json
/.husky
/.jestrc.json
/.gitignore
/.lintstagedrc.json
/.npmignore
/.prettierrc.json
/tsconfig.json
/tsconfig.build.json
# dependency
node_modules
# output
/lib
/generated
# coverage
/coverage
*.lcov
# diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# log
/log
/logs
*.log
*-debug.log*
.*-debug.log*
# cache
.DS_Store
.cache
.npm
.pnpm*
*.tsbuildinfo
# configuration
.env*
!.env*.example
src/account/generated

25
.presetterrc.json Normal file
View File

@ -0,0 +1,25 @@
{
"preset": [
"presetter-preset-esm"
],
"config": {
"prettier": {
"singleQuote": false
},
"tsconfig.build": {
"include": {
"0": "src"
},
"compilerOptions": {
"rootDir": "src"
}
},
"tsconfig": {
"compilerOptions": {
"lib": [
"dom"
]
}
}
}
}

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 LumeWeb
Copyright (c) 2024 Hammer Technologies LLC
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

17236
npm-shrinkwrap.json generated Normal file

File diff suppressed because it is too large Load Diff

18
orval.config.ts Normal file
View File

@ -0,0 +1,18 @@
import { defineConfig } from 'orval';
export default defineConfig({
account: {
input: './src/account/swagger.yaml',
output: {
mode: 'split',
workspace: "./src/account/generated",
target: 'openapi.ts',
override: {
mutator: {
path: '../axios.ts',
name: 'customInstance',
},
},
},
},
});

39
package.json Normal file
View File

@ -0,0 +1,39 @@
{
"name": "@lumeweb/portal-sdk",
"version": "0.0.0",
"type": "module",
"description": "",
"main": "lib/index.js",
"files": [
"lib"
],
"scripts": {
"prepare": "presetter bootstrap",
"build": "run build",
"postinstall": "patch-package",
"patch-package": "patch-package",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "gitea@git.lumeweb.com:LumeWeb/portal-sdk.git"
},
"private": false,
"devDependencies": {
"@changesets/cli": "^2.27.1",
"presetter": "^4.7.0",
"presetter-preset-esm": "^4.7.0"
},
"readme": "ERROR: No README data found!",
"_id": "@lumeweb/portal-sdk@0.0.0",
"dependencies": {
"@lumeweb/s5-js": "0.0.0-20240329003038",
"axios": "^1.6.7",
"memize": "^2.1.0",
"orval": "^6.25.0",
"patch-package": "^8.0.0"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,15 @@
diff --git a/node_modules/tsc-alias/dist/utils/import-path-resolver.js b/node_modules/tsc-alias/dist/utils/import-path-resolver.js
index ebaf620..227d4c7 100644
--- a/node_modules/tsc-alias/dist/utils/import-path-resolver.js
+++ b/node_modules/tsc-alias/dist/utils/import-path-resolver.js
@@ -5,8 +5,9 @@ const normalizePath = require("normalize-path");
const fs_1 = require("fs");
const path_1 = require("path");
const anyQuote = `["']`;
+const excludeLocalImportSyntax = `[(?!\.)]`;
const pathStringContent = `[^"'\r\n]+`;
-const importString = `(?:${anyQuote}${pathStringContent}${anyQuote})`;
+const importString = `(?:${anyQuote}${excludeLocalImportSyntax}${pathStringContent}${anyQuote})`;
const funcStyle = `(?:\\b(?:import|require)\\s*\\(\\s*(\\/\\*.*\\*\\/\\s*)?${importString}\\s*\\))`;
const globalStyle = `(?:\\bimport\\s+${importString})`;
const fromStyle = `(?:\\bfrom\\s+${importString})`;

357
src/account.ts Normal file
View File

@ -0,0 +1,357 @@
import {
AccountInfoResponse,
getApiAccount,
LoginRequest,
LoginResponse,
OTPDisableRequest,
OTPGenerateResponse,
OTPValidateRequest,
OTPVerifyRequest,
PasswordResetVerifyRequest,
PingResponse,
postApiAccountPasswordResetRequest,
postApiAccountVerifyEmailResend,
postApiAuthPing,
RegisterRequest,
UploadLimitResponse,
VerifyEmailRequest,
} from "./account/generated/index.js";
import {
postApiAuthLogin,
postApiAuthRegister,
postApiAccountVerifyEmail,
getApiAuthOtpGenerate,
postApiAccountOtpVerify,
postApiAccountOtpValidate,
postApiAuthOtpDisable,
PasswordResetRequest,
postApiAccountPasswordResetConfirm,
postApiAuthLogout,
getApiUploadLimit,
postApiAccountUpdateEmail,
postApiAccountUpdatePassword,
} from "./account/generated/index.js";
import { AxiosError, AxiosResponse } from "axios";
export class AccountError extends Error {
public statusCode: number;
constructor(message: string, statusCode: number) {
super(message);
this.name = "AccountError";
this.statusCode = statusCode;
}
}
export class AccountApi {
private apiUrl: string;
private _jwtToken?: string;
constructor(apiUrl: string) {
let apiUrlParsed = new URL(apiUrl);
apiUrlParsed.hostname = `account.${apiUrlParsed.hostname}`;
this.apiUrl = apiUrlParsed.toString();
}
set jwtToken(value: string) {
this._jwtToken = value;
}
get jwtToken(): string {
return <string>this._jwtToken;
}
public static create(apiUrl: string): AccountApi {
return new AccountApi(apiUrl);
}
public async login(
loginRequest: LoginRequest,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<LoginResponse> | LoginResponse | boolean = false;
try {
ret = await postApiAuthLogin(loginRequest, { baseURL: this.apiUrl });
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
ret = this.checkSuccessVal<LoginResponse>(ret);
if (ret) {
this._jwtToken = (ret as LoginResponse).token;
return true;
}
return false;
}
public async register(
registerRequest: RegisterRequest,
): Promise<boolean | Error> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAuthRegister(registerRequest, {
baseURL: this.apiUrl,
});
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async verifyEmail(
verifyEmailRequest: VerifyEmailRequest,
): Promise<boolean | Error> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountVerifyEmail(
verifyEmailRequest,
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async requestEmailVerification(): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountVerifyEmailResend(this.buildOptions());
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async generateOtp(): Promise<
boolean | OTPGenerateResponse | AccountError
> {
let ret: AxiosResponse<OTPGenerateResponse>;
try {
ret = await getApiAuthOtpGenerate(this.buildOptions());
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessVal<OTPGenerateResponse>(ret);
}
public async verifyOtp(
otpVerifyRequest: OTPVerifyRequest,
): Promise<boolean | Error> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountOtpVerify(
otpVerifyRequest,
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async validateOtp(
otpValidateRequest: OTPValidateRequest,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountOtpValidate(
otpValidateRequest,
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async disableOtp(
otpDisableRequest: OTPDisableRequest,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAuthOtpDisable(otpDisableRequest, this.buildOptions());
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async requestPasswordReset(
passwordResetRequest: PasswordResetRequest,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountPasswordResetRequest(
passwordResetRequest,
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async confirmPasswordReset(
passwordResetVerifyRequest: PasswordResetVerifyRequest,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountPasswordResetConfirm(
passwordResetVerifyRequest,
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async ping(): Promise<boolean> {
let ret: AxiosResponse<PingResponse>;
try {
ret = await postApiAuthPing(this.buildOptions());
} catch (e) {
return false;
}
const success = this.checkSuccessVal(ret) && ret.data.ping == "pong";
if (success) {
this._jwtToken = ret.data.token;
}
return success;
}
public async info(): Promise<boolean | AccountInfoResponse> {
let ret: AxiosResponse<AccountInfoResponse>;
try {
ret = await getApiAccount(this.buildOptions());
} catch (e) {
return false;
}
return this.checkSuccessVal(ret);
}
public async logout(): Promise<boolean> {
try {
await postApiAuthLogout(this.buildOptions());
} catch (e) {
return false;
}
this._jwtToken = undefined;
return true;
}
public async uploadLimit(): Promise<number> {
let ret: AxiosResponse<UploadLimitResponse>;
try {
ret = await getApiUploadLimit(this.buildOptions());
} catch (e) {
return 0;
}
return this.checkSuccessVal<UploadLimitResponse>(ret) ? ret.data.limit : 0;
}
public async updateEmail(
email: string,
password: string,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountUpdateEmail(
{ email, password },
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
public async updatePassword(
currentPassword: string,
newPassword: string,
): Promise<boolean | AccountError> {
let ret: AxiosResponse<void>;
try {
ret = await postApiAccountUpdatePassword(
{ current_password: currentPassword, new_password: newPassword },
this.buildOptions(),
);
} catch (e) {
return new AccountError(
(e as AxiosError).response?.data as string,
(e as AxiosError).response?.status as number,
);
}
return this.checkSuccessBool(ret);
}
private checkSuccessBool(ret: AxiosResponse<void>): boolean {
return ret.status === 200;
}
private checkSuccessVal<T>(ret: AxiosResponse<T>): T | boolean {
if (ret.status === 200) {
return ret.data as T;
}
return false;
}
private buildOptions(): any {
const headers: any = {};
if (this.jwtToken) {
headers.Authorization = `Bearer ${this.jwtToken}`;
}
return {
baseURL: this.apiUrl,
headers: headers,
};
}
}

25
src/account/axios.ts Normal file
View File

@ -0,0 +1,25 @@
import Axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import memize from "memize";
const axiosCreate = memize(Axios.create);
export const customInstance = <T>(
config: AxiosRequestConfig,
options?: AxiosRequestConfig,
): Promise<AxiosResponse<T>> => {
const source = Axios.CancelToken.source();
const instance = axiosCreate({ baseURL: options?.baseURL });
const promise = instance({
...config,
...options,
cancelToken: source.token,
});
// @ts-ignore
promise.cancel = () => {
source.cancel("Query was cancelled");
};
return promise;
};

350
src/account/swagger.yaml Normal file
View File

@ -0,0 +1,350 @@
openapi: 3.0.0
info:
title: Account Management API
version: "1.0"
description: API for managing user accounts, including login, registration, OTP operations, and password resets.
paths:
/api/auth/login:
post:
summary: Login to the system
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LoginRequest"
responses:
"200":
description: Successfully logged in
content:
application/json:
schema:
$ref: "#/components/schemas/LoginResponse"
"401":
description: Unauthorized
/api/auth/logout:
post:
summary: Logout of account service
responses:
"200":
description: Successfully logged out
/api/auth/register:
post:
summary: Register a new account
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RegisterRequest"
responses:
"200":
description: Successfully registered
"400":
description: Bad Request
/api/account/verify-email:
post:
summary: Verify email address
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/VerifyEmailRequest"
responses:
"200":
description: Email verified successfully
/api/account/verify-email/resend:
post:
summary: Resend email verification
responses:
"200":
description: Email verification resent successfully
/api/auth/otp/generate:
get:
summary: Generate OTP for two-factor authentication
responses:
"200":
description: OTP generated successfully
content:
application/json:
schema:
$ref: "#/components/schemas/OTPGenerateResponse"
/api/account/otp/verify:
post:
summary: Verify OTP for enabling two-factor authentication
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/OTPVerifyRequest"
responses:
"200":
description: OTP verified successfully
/api/account/otp/validate:
post:
summary: Validate OTP for two-factor authentication login
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/OTPValidateRequest"
responses:
"200":
description: OTP validated successfully
/api/auth/otp/disable:
post:
summary: Disable OTP for two-factor authentication
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/OTPDisableRequest"
responses:
"200":
description: OTP disabled successfully
/api/account/password-reset/request:
post:
summary: Request a password reset
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/PasswordResetRequest"
responses:
"200":
description: Password reset requested successfully
/api/account/password-reset/confirm:
post:
summary: Confirm a password reset
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/PasswordResetVerifyRequest"
responses:
"200":
description: Password reset successfully
/api/auth/ping:
post:
summary: Auth check endpoint
responses:
"200":
description: Pong
content:
application/json:
schema:
$ref: "#/components/schemas/PingResponse"
"401":
description: Unauthorized
/api/account:
get:
summary: Get account information
responses:
"200":
description: Account information retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/AccountInfoResponse"
"401":
description: Unauthorized
/api/account/update-email:
post:
summary: Update email address
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateEmailRequest"
responses:
"200":
description: Email updated successfully
/api/account/update-password:
post:
summary: Update password
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdatePasswordRequest"
responses:
"200":
description: Password updated successfully
/api/upload-limit:
get:
summary: Get the basic file upload (POST) upload limit set by the portal
responses:
"200":
description: Upload limit retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/UploadLimitResponse"
/api/meta:
get:
summary: Get metadata about the portal
responses:
"200":
description: Metadata retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/MetaResponse"
components:
schemas:
LoginRequest:
type: object
required:
- email
- password
properties:
email:
type: string
password:
type: string
LoginResponse:
type: object
properties:
token:
type: string
RegisterRequest:
type: object
required:
- first_name
- last_name
- email
- password
properties:
first_name:
type: string
last_name:
type: string
email:
type: string
password:
type: string
VerifyEmailRequest:
type: object
required:
- email
- token
properties:
email:
type: string
token:
type: string
OTPGenerateResponse:
type: object
properties:
OTP:
type: string
OTPVerifyRequest:
type: object
required:
- OTP
properties:
OTP:
type: string
OTPValidateRequest:
type: object
required:
- OTP
properties:
OTP:
type: string
OTPDisableRequest:
type: object
required:
- password
properties:
password:
type: string
PasswordResetRequest:
type: object
required:
- email
properties:
email:
type: string
PasswordResetVerifyRequest:
type: object
required:
- email
- token
- password
properties:
email:
type: string
token:
type: string
password:
type: string
UpdateEmailRequest:
type: object
required:
- email
- password
properties:
email:
type: string
password:
type: string
UpdatePasswordRequest:
type: object
required:
- current_password
- new_password
properties:
current_password:
type: string
new_password:
type: string
PingResponse:
type: object
properties:
ping:
type: string
token:
type: string
AccountInfoResponse:
type: object
required:
- id
- first_name
- last_name
- email
- verified
properties:
id:
type: number
first_name:
type: string
last_name:
type: string
email:
type: string
verified:
type: boolean
UploadLimitResponse:
type: object
properties:
limit:
type: number
required:
- limit
MetaResponse:
type: object
required:
- domain
properties:
domain:
type: string

4
src/index.ts Normal file
View File

@ -0,0 +1,4 @@
export * from "./sdk.js";
export * from "./account/generated/openapi.schemas.js";
export * from "./protocol/index.js";
export { AccountError } from "./account.js";

View File

@ -0,0 +1,24 @@
export abstract class Protocol<T> {
private sdk: T;
constructor(sdk: T) {
this.sdk = sdk;
}
public getSdk(): T {
return this.sdk;
}
public abstract setAuthToken(token: string): Promise<void>;
}
export interface ProtocolConstructor<T> {
new (apiDomain: string): Protocol<T>;
}
export function createProtocol<T>(
implementation: ProtocolConstructor<T>,
apiDomain: string,
): Protocol<T> {
return new implementation(apiDomain);
}

18
src/protocol/impl/s5.ts Normal file
View File

@ -0,0 +1,18 @@
import { Protocol } from "./protocol";
import { S5Client } from "@lumeweb/s5-js";
export const PROTOCOL_S5 = "s5";
export class S5 extends Protocol<S5Client> {
constructor(apiDomain: string) {
const sdk = new S5Client(`s5.${apiDomain}`);
super(sdk);
}
async setAuthToken(token: string): Promise<void> {
const options = this.getSdk().clientOptions;
options.apiKey = token;
this.getSdk().clientOptions = options;
}
}

14
src/protocol/index.ts Normal file
View File

@ -0,0 +1,14 @@
import { Registry } from "./registry";
import { createProtocol, Protocol } from "./impl/protocol.js";
import { S5Client } from "@lumeweb/s5-js";
import { PROTOCOL_S5, S5 } from "./impl/s5.js";
export function registerDefaults(registry: Registry) {
registry.register<S5Client>(
PROTOCOL_S5,
createProtocol<S5Client>(S5, registry.getApiDomain()),
);
}
export { Protocol, Registry };
export { PROTOCOL_S5 };

34
src/protocol/registry.ts Normal file
View File

@ -0,0 +1,34 @@
import { Sdk } from "../sdk";
import { Protocol } from "./impl/protocol";
export class Registry {
private store: Map<string, Protocol<any>>;
private sdk: Sdk;
private _apiDomain?: string;
constructor(sdk: Sdk) {
this.store = new Map();
this.sdk = sdk;
}
public register<T>(name: string, value: Protocol<T>) {
this.store.set(name, value);
}
public get<T>(name: string): Protocol<T> {
return this.store.get(name) as Protocol<T>;
}
[Symbol.iterator]() {
return this.store[Symbol.iterator]();
}
public getApiDomain(): string {
if (!this._apiDomain) {
const urlObject = new URL(this.sdk.apiUrl);
this._apiDomain = urlObject.hostname;
}
return this._apiDomain;
}
}

49
src/sdk.ts Normal file
View File

@ -0,0 +1,49 @@
import { AccountApi } from "./account.js";
import { registerDefaults, Registry } from "./protocol/index.js";
export class Sdk {
private accountApi?: AccountApi;
private registry?: Registry;
constructor(apiUrl: string) {
this._apiUrl = apiUrl;
}
private _apiUrl: string;
get apiUrl(): string {
return this._apiUrl;
}
set apiUrl(value: string) {
this._apiUrl = value;
}
public static create(apiUrl: string): Sdk {
return new Sdk(apiUrl);
}
public account(): AccountApi {
if (!this.accountApi) {
this.accountApi = AccountApi.create(this._apiUrl);
}
return this.accountApi!;
}
public protocols(): Registry {
if (!this.registry) {
this.registry = new Registry(this);
registerDefaults(this.registry!);
}
return this.registry!;
}
public setAuthToken(token: string) {
this.account().jwtToken = token;
for (const [, protocol] of this.protocols()) {
protocol.setAuthToken(token);
}
}
}