@towerai/sdk
v1.2.0
Published
TowerAI frontend SDK
Readme
@towerai/sdk
TowerAI frontend SDK. It is aligned with the TowerAI backend contracts:
POST /api/v1/auth/loginPOST /api/v1/auth/refresh-tokenGET /api/v1/users/meGET /api/v1/menus/routesGET /api/v1/menusPOST /api/v1/files/upload-policyPOST /api/v1/files/access-urlPOST /api/v1/files/uploadPOST /api/v1/files/chunk/initGET /api/v1/files/chunk/{uploadId}POST /api/v1/files/chunkPOST /api/v1/files/chunk/completeDELETE /api/v1/files/chunk/{uploadId}
pnpm add @towerai/sdkThe SDK is framework agnostic. It does not depend on Vue, Pinia, Vue Router, Element Plus, or any app module.
Docs
Auth + HTTP
import {
createAuthClient,
createAuthSession,
createAuthStore,
createAuthTokenStorage,
createCurrentUserClient,
createHttpClient,
} from "@towerai/sdk";
const tokenStorage = createAuthTokenStorage({
accessToken: "access_token",
refreshToken: "refresh_token",
rememberMe: "remember_me",
username: "username",
password: "password",
});
// By default, tokenStorage only persists the username for remembered login.
// If a project must persist password, pass { persistPassword: true } and
// provide its own encryption/storage policy at the application layer.
const request = createHttpClient({
baseURL: "/api",
appId: "tower-admin",
deviceId: () => deviceId,
resultCodes: {
success: 200,
accessTokenInvalid: 40101,
refreshTokenInvalid: 40102,
},
tokenStorage,
refreshToken: async () => authSession.refreshToken(),
onAuthExpired: async () => {
tokenStorage.clearAllAuth();
},
logger: {
request(ctx) {
console.debug("[request]", ctx.method, ctx.url);
},
response(ctx) {
console.debug("[response]", ctx.method, ctx.url, ctx.status, ctx.duration);
},
error(ctx) {
console.warn("[request:error]", ctx.method, ctx.url, ctx.status, ctx.msg);
},
},
});
const passwordSecretParts = [
import.meta.env.VITE_APP_BIZ_SECRET_P1,
import.meta.env.VITE_APP_BIZ_SECRET_P2,
];
const authClient = createAuthClient({
request,
passwordSecretParts,
});
const authSession = createAuthSession({ authClient, tokenStorage });
const currentUserClient = createCurrentUserClient({
request,
passwordSecretParts,
});
const user = await currentUserClient.getInfo();
const authStore = createAuthStore({
authClient,
currentUserClient,
tokenStorage,
});
authStore.subscribe((state) => {
console.log(state.currentUser, state.rememberMe);
});
await authStore.login({
username: "admin",
password: "123456",
rememberMe: true,
});Permission
import { hasPermission, hasRole } from "@towerai/sdk";
hasPermission(user, "sys:user:add");
hasRole(user, ["ADMIN", "TENANT_ADMIN"]);Menu
import {
createMenuClient,
createModuleViewPathResolver,
filterMenuTree,
filterMenuTreeByPermission,
flattenMenuTree,
transformMenuRoutes,
} from "@towerai/sdk";
const menuClient = createMenuClient({ request });
const serverRoutes = await menuClient.getRoutes();
const visibleMenus = filterMenuTree(menus, (menu) => !menu.meta?.hidden);
const authorizedMenus = filterMenuTreeByPermission(visibleMenus, user);
const flatMenus = flattenMenuTree(visibleMenus);
const resolveComponentPath = createModuleViewPathResolver({
moduleRoot: "/src/modules",
viewDir: "views",
mobileDir: "mobile",
routeComponentPathMap: {
"system/tenant/index": "tenant/tenant-manage/index",
},
});
const routes = transformMenuRoutes(serverRoutes, {
isMobile,
layoutComponent,
notFoundComponent,
resolveComponentPath,
resolveComponent: (path) => modules[path],
});File
import {
createFileClient,
createFileUploader,
downloadFile,
resolvePreviewUrl,
type FileInfo,
type PageResult,
} from "@towerai/sdk";
const fileClient = createFileClient({
request,
baseUrl: "/api/v1/files",
});
const fileUploader = createFileUploader(fileClient, {
defaultUploadMode: "direct",
chunkedUploadThresholdMb: 50,
});
const uploaded = await fileUploader.uploadFile(file, {
uploadType: "image",
onProgress: (percent) => console.log(percent),
});
const url = await resolvePreviewUrl("tenant/logo.png", fileClient);
await downloadFile({ objectKey: "tenant/logo.png", name: "logo.png" }, fileClient);
const page: PageResult<FileInfo[]> = {
list: [uploaded],
total: 1,
};Watermark
import { createWatermark } from "@towerai/sdk";
const watermark = createWatermark({
text: ["TowerAI", "tenant / username"],
});
watermark.update({ text: "new text" });
watermark.remove();