UNPKG

@etsoo/appscript

Version:

Applications shared TypeScript framework

884 lines (765 loc) 17.9 kB
import { INotifier, NotificationAlign, NotificationCallProps, NotificationContent, NotificationReturn } from "@etsoo/notificationbase"; import { ApiDataError, IApi, IPData } from "@etsoo/restclient"; import { DataTypes, DateUtils, ErrorData, ErrorType, IActionResult, IStorage, ListType, ListType1 } from "@etsoo/shared"; import { AddressRegion } from "../address/AddressRegion"; import { IUser } from "../state/User"; import { IAppSettings } from "./AppSettings"; import { UserRole } from "./UserRole"; import { EntityStatus } from "../business/EntityStatus"; import { Currency } from "../business/Currency"; import { ExternalEndpoint } from "./ExternalSettings"; import { ApiRefreshTokenDto } from "../api/dto/ApiRefreshTokenDto"; import { ApiRefreshTokenRQ } from "../api/rq/ApiRefreshTokenRQ"; /** * Detect IP callback interface */ export interface IDetectIPCallback { (): void; } /** * Navigate options */ export interface NavigateOptions { replace?: boolean; state?: any; } /** * Refresh token result type * array means success, false means failed but no any message * other cases means failed with differnet message */ export type RefreshTokenResult<R> = IActionResult | [string | null, R]; /** * Format result custom type */ export type FormatResultCustom = { title?: string; type?: string; field?: string; }; /** * Format result custom callback type */ export type FormatResultCustomCallback = | ((data: FormatResultCustom) => string | null | undefined) | boolean; /** * Login parameters */ export type AppLoginParams = { /** * Login parameters to pass */ params?: DataTypes.SimpleObject & { /** * Try login with cached refresh token */ tryLogin?: boolean; }; /** * Don't cache current URL instead of the default page */ removeUrl?: boolean; /** * Show loading bar or not */ showLoading?: boolean; }; /** * App try login parameters */ export type AppTryLoginParams = AppLoginParams & { /** * Callback on failure * @param type Failure type */ onFailure?: (type: string) => void; /** * Callback on success */ onSuccess?: () => void; }; /** * Refresh token props */ export interface RefreshTokenProps { /** * Refresh token */ token?: string; /** * API URL */ api?: string; /** * Show loading bar or not */ showLoading?: boolean; /** * Header token field name */ tokenField?: string; } /** * App fields */ export const appFields = [ "headerToken", "serversideDeviceId", "deviceId", "devices", "devicePassphrase", "cachedUrl", "embedded", "keepLogin" ] as const; /** * Basic type template */ export type IAppFields = { [key in (typeof appFields)[number]]: string }; /** * Application interface, for generic version, see ICoreApp */ export interface IApp { /** * Settings */ readonly settings: IAppSettings; /** * Default region */ readonly defaultRegion: AddressRegion; /** * Fields */ readonly fields: IAppFields; /** * API, not recommend to use it directly in code, wrap to separate methods */ readonly api: IApi; /** * Notifier */ readonly notifier: INotifier<unknown, NotificationCallProps>; /** * Label delegate */ readonly labelDelegate: <T = string>(key: string) => T | undefined; /** * Culture, like zh-CN */ readonly culture: string; /** * Currency, like USD for US dollar */ readonly currency: Currency; /** * Device id */ readonly deviceId: string; /** * Country or region, like CN */ readonly region: string; /** * Storage */ readonly storage: IStorage; /** * Is current authorized */ readonly authorized: boolean; /** * Is the app ready */ readonly isReady: boolean; /** * Is trying to login */ readonly isTryingLogin: boolean; /** * Application name */ readonly name: string; /** * Pending actions */ readonly pendings: (() => any)[]; /** * Is debug mode */ readonly debug: boolean; /** * Is embedded mode */ readonly embedded: boolean; /** * Cached URL */ cachedUrl: string | undefined | null; /** * Keep login or not */ keepLogin: boolean; /** * IP data */ ipData?: IPData; /** * User data */ userData?: IUser; /** * Search input element */ searchInput?: HTMLInputElement; /** * Is screen size down 'sm' */ smDown?: boolean; /** * Is screen size up 'md' */ mdUp?: boolean; /** * Add root (homepage) to the URL * @param url URL to add * @returns Result */ addRootUrl(url: string): string; /** * Add scheduled task * @param task Task, return false to stop * @param interval Interval in milliseconds */ addTask(task: () => PromiseLike<void | false>, interval: number): void; /** * Alert result * @param result Result message * @param callback Callback */ alertResult(result: string, callback?: NotificationReturn<void>): void; /** * Alert action result * @param result Action result * @param callback Callback * @param forceToLocal Force to local labels */ alertResult( result: IActionResult, callback?: NotificationReturn<void>, forceToLocal?: FormatResultCustomCallback ): void; /** * Authorize * @param token New access token * @param schema Access token schema * @param refreshToken Refresh token */ authorize(token?: string, schema?: string, refreshToken?: string): void; /** * Change country or region * @param region New country or region */ changeRegion(region: string | AddressRegion): void; /** * Change culture * @param culture New culture definition */ changeCulture( culture: DataTypes.CultureDefinition ): Promise<DataTypes.StringRecord>; /** * Check the action result is about device invalid * @param result Action result * @returns true means device is invalid */ checkDeviceResult(result: IActionResult): boolean; /** * Check language is supported or not * @param language Language * @returns Result */ checkLanguage(language?: string): string; /** * Check current app is in same session * @param callback Callback */ checkSession( callback: (isSame: boolean) => Promise<void | false> ): Promise<void>; /** * Clear cache data */ clearCacheData(): void; /** * Clear cached token */ clearCacheToken(): void; /** * Clear device id */ clearDeviceId(): void; /** * Clear user session */ clearSession(): void; /** * Create API client, override to implement custom client creation by name * @param name Client name * @param item External endpoint item * @returns Result */ createApi( name: string, item: ExternalEndpoint, refresh?: ( api: IApi, rq: ApiRefreshTokenRQ ) => Promise<[string, number] | undefined> ): IApi; /** * Decrypt message * @param messageEncrypted Encrypted message * @param passphrase Secret passphrase * @returns Pure text */ decrypt(messageEncrypted: string, passphrase?: string): string | undefined; /** * Enhanced decrypt message * @param messageEncrypted Encrypted message * @param passphrase Secret passphrase * @param durationSeconds Duration seconds, <= 12 will be considered as month * @returns Pure text */ decryptEnhanced( messageEncrypted: string, passphrase?: string, durationSeconds?: number ): string | undefined; /** * Detect IP data, call only one time * @param callback Callback will be called when the IP is ready */ detectIP(callback?: IDetectIPCallback): void; /** * Dispose the application */ dispose(): void; /** * Download file * @param stream File stream * @param filename File name * @param callback callback */ download( stream: ReadableStream, filename?: string, callback?: (success: boolean | undefined) => void ): Promise<void>; /** * Encrypt message * @param message Message * @param passphrase Secret passphrase * @param iterations Iterations, 1000 times, 1 - 99 * @returns Result */ encrypt(message: string, passphrase?: string, iterations?: number): string; /** * Enhanced encrypt message * @param message Message * @param passphrase Secret passphrase * @param iterations Iterations, 1000 times, 1 - 99 * @returns Result */ encryptEnhanced( message: string, passphrase?: string, iterations?: number ): string; /** * Exchange token data * @param api API * @param token Core system's refresh token to exchange * @returns Result */ exchangeToken(api: IApi, token: string): Promise<void>; /** * Exchange intergration tokens for all APIs * @param coreData Core system's token data to exchange */ exchangeTokenAll(coreData: ApiRefreshTokenDto): void; /** * Format date to string * @param input Input date * @param options Options * @param timeZone Time zone * @returns string */ formatDate( input?: Date | string, options?: DateUtils.FormatOptions, timeZone?: string ): string | undefined; /** * Format action * @param action Action * @param target Target name or title * @param items More items * @returns Result */ formatAction(action: string, target: string, ...items: string[]): string; /** * Format error * @param error Error * @returns Error message */ formatError(error: ApiDataError): string; /** * Format money number * @param input Input money number * @param isInteger Is integer * @param options Options * @returns Result */ formatMoney( input: number | bigint, isInteger?: boolean, options?: Intl.NumberFormatOptions ): string; /** * Format number * @param input Input number * @param options Options * @returns Result */ formatNumber( input: number | bigint, options?: Intl.NumberFormatOptions ): string; /** * Format as full name * @param familyName Family name * @param givenName Given name */ formatFullName( familyName: string | undefined | null, givenName: string | undefined | null ): string; /** * Format result text * @param result Action result * @param forceToLocal Force to local labels * @returns Message */ formatResult( result: IActionResult, forceToLocal?: FormatResultCustomCallback ): string; /** * Fresh countdown UI * @param callback Callback */ freshCountdownUI(callback?: () => PromiseLike<unknown>): void; /** * Get culture resource * @param key key * @returns Resource */ get<T = string>(key: string): T | undefined; /** * Get multiple culture labels * @param keys Keys */ getLabels<T extends string>(...keys: T[]): { [K in T]: string }; /** * Get bool items * @returns Bool items */ getBools(): ListType1[]; /** * Get cached token * @returns Cached token */ getCacheToken(): string | undefined; /** * Get data privacies * @returns Result */ getDataPrivacies(): ListType[]; /** * Get enum item number id list * @param em Enum * @param prefix Label prefix or callback * @param filter Filter * @returns List */ getEnumList<E extends DataTypes.EnumBase = DataTypes.EnumBase>( em: E, prefix: string | ((key: string) => string), filter?: (id: E[keyof E], key: keyof E & string) => E[keyof E] | undefined ): ListType[]; /** * Get enum item string id list * @param em Enum * @param prefix Label prefix or callback * @param filter Filter * @returns List */ getEnumStrList<E extends DataTypes.EnumBase = DataTypes.EnumBase>( em: E, prefix: string | ((key: string) => string), filter?: | ((id: E[keyof E], key: keyof E & string) => E[keyof E] | undefined) | E[keyof E][] ): ListType1[]; /** * Get region label * @param id Region id * @returns Label */ getRegionLabel(id: string): string; /** * Get all regions * @returns Regions */ getRegions(): AddressRegion[]; /** * Get role label * @param role Role value * @param joinChar Join char * @returns Label(s) */ getRoleLabel(role: number | null | undefined, joinChar?: string): string; /** * Get roles * @param role Combination role value, null for all roles */ getRoles(role?: number): ListType[]; /** * Get status label * @param status Status value */ getStatusLabel(status: number | null | undefined): string; /** * Get status list * @param ids Limited ids * @returns list */ getStatusList(ids?: EntityStatus[]): ListType[]; /** * Get refresh token from response headers * @param rawResponse Raw response from API call * @param tokenKey Refresh token key * @returns response refresh token */ getResponseToken(rawResponse: any, tokenKey: string): string | null; /** * Get time zone * @returns Time zone */ getTimeZone(): string; /** * Hash message, SHA3 or HmacSHA512, 512 as Base64 * https://cryptojs.gitbook.io/docs/ * @param message Message * @param passphrase Secret passphrase */ hash(message: string, passphrase?: string): string; /** * Hash message Hex, SHA3 or HmacSHA512, 512 as Base64 * https://cryptojs.gitbook.io/docs/ * @param message Message * @param passphrase Secret passphrase */ hashHex(message: string, passphrase?: string): string; /** * Check user has the minimum role permission or not * @param role Minumum role * @returns Result */ hasMinPermission(role: UserRole): boolean; /** * Check user has the specific role permission or not * @param roles Roles to check * @returns Result */ hasPermission(roles: number | UserRole | number[] | UserRole[]): boolean; /** * Init call * @param callback Callback * @param resetKeys Reset all keys first * @returns Result */ initCall( callback?: (result: boolean) => void, resetKeys?: boolean ): Promise<void>; /** * Is admin roles * @returns Result */ isAdminUser(): boolean; /** * Is Finance roles * @returns Result */ isFinanceUser(): boolean; /** * Is HR manager roles * @returns Result */ isHRUser(): boolean; /** * Is Manager roles * @returns Result */ isManagerUser(): boolean; /** * Is user roles * @returns Result */ isUser(): boolean; /** * Is valid password, override to implement custom check * @param password Input password */ isValidPassword(password: string): boolean; /** * Load URL * @param url URL * @param targetOrigin Target origin */ loadUrl(url: string, targetOrigin?: string): void; /** * Navigate to Url or delta * @param url Url or delta * @param options Options */ navigate<T extends number | string | URL>( to: T, options?: T extends number ? never : NavigateOptions ): void; /** * Notify user with success message * @param message Success message * @param callback Popup close callback */ ok( callback?: NotificationReturn<void>, message?: NotificationContent<unknown> ): void; /** * Callback where exit a page */ pageExit(): void; /** * Refresh token * @param props Props * @param callback Callback */ refreshToken( props?: RefreshTokenProps, callback?: (result?: boolean | IActionResult) => boolean | void ): Promise<void>; /** * Save refresh token to cache * @param token Refresh token */ saveCacheToken(token: string | undefined): void; /** * Setup Api error handler * @param api Api * @param handlerFor401 Handler for 401 error */ setApiErrorHandler( api: IApi, handlerFor401?: boolean | (() => Promise<void>) ): void; /** * Setup Api loading * @param api Api */ setApiLoading(api: IApi): void; /** * Setup frontend logging * @param action Custom action * @param preventDefault Is prevent default action */ setupLogging( action?: (data: ErrorData) => void | Promise<void>, preventDefault?: ((type: ErrorType) => boolean) | boolean ): void; /** * Signout, with userLogout and toLoginPage * @param action Callback */ signout(action?: () => void | boolean): Promise<void>; /** * Persist settings to source when application exit */ persist(): void; /** * Go to the login page * @param data Login parameters */ toLoginPage(data?: AppLoginParams): void; /** * Try login, returning false means is loading * UI get involved while refreshToken not intended * @param data Login parameters */ tryLogin(data?: AppLoginParams): Promise<boolean>; /** * Update API token and expires * @param name Api name * @param token Refresh token * @param seconds Access token expires in seconds */ updateApi(name: string, token: string | undefined, seconds: number): void; /** * Update embedded status * @param embedded New embedded status */ updateEmbedded(embedded?: boolean): void; /** * User login * @param user User data * @param refreshToken Refresh token */ userLogin(user: IUser, refreshToken: string): void; /** * User logout * @param clearToken Clear refresh token or not * @param noTrigger No trigger for state change */ userLogout(clearToken: boolean, noTrigger?: boolean): void; /** * User unauthorized */ userUnauthorized(): void; /** * Show warning message * @param message Message * @param align Align, default as TopRight */ warning( message: NotificationContent<unknown>, align?: NotificationAlign ): void; }