mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 20:54:14 +00:00
refactor(frontend): drop file-level eslint-disable from utils/index
- ObjectUtil.clone/deepClone become generic <T>
- cloneProps/delProps accept `object` (cast internally to AnyRecord)
- equals accepts `unknown` with proper narrowing
- ColorUtils.usageColor narrows data/threshold to `number`; total widened
to `number | { valueOf(): number } | null | undefined` so Dayjs works
- Utils.debounce replaces `const self = this` with lexical arrow
closure (no-this-alias clean)
- InboundList._expiryTime narrowed from `unknown` to `{ valueOf(): number } | null`
- Single-line eslint-disable remains on `Msg<T = any>` and HttpUtil
generic defaults (idiomatic API envelope; changing default to unknown
cascades through 34 consumer files)
This commit is contained in:
parent
3ca776f9c9
commit
9ee9b8b39f
2 changed files with 42 additions and 28 deletions
|
|
@ -57,7 +57,7 @@ interface DBInboundRecord extends ProtocolFlags {
|
||||||
down: number;
|
down: number;
|
||||||
total: number;
|
total: number;
|
||||||
expiryTime: number;
|
expiryTime: number;
|
||||||
_expiryTime: unknown;
|
_expiryTime: { valueOf(): number } | null;
|
||||||
nodeId?: number | null;
|
nodeId?: number | null;
|
||||||
toInbound: () => {
|
toInbound: () => {
|
||||||
stream?: { network?: string; isTls?: boolean; isReality?: boolean };
|
stream?: { network?: string; isTls?: boolean; isReality?: boolean };
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-this-alias */
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
|
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||||
import { getMessage } from './messageBus';
|
import { getMessage } from './messageBus';
|
||||||
|
|
||||||
type RespEnvelope = { success?: unknown; msg?: unknown; obj?: unknown };
|
type RespEnvelope = { success?: unknown; msg?: unknown; obj?: unknown };
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class Msg<T = any> {
|
export class Msg<T = any> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
msg: string;
|
msg: string;
|
||||||
|
|
@ -50,6 +50,7 @@ export class HttpUtil {
|
||||||
return typeof data === 'object' ? (data as Msg) : new Msg(false, 'unknown data:', data);
|
return typeof data === 'object' ? (data as Msg) : new Msg(false, 'unknown data:', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
static async get<T = any>(url: string, params?: unknown, options: HttpOptions = {}): Promise<Msg<T>> {
|
static async get<T = any>(url: string, params?: unknown, options: HttpOptions = {}): Promise<Msg<T>> {
|
||||||
const { silent, ...axiosOpts } = options;
|
const { silent, ...axiosOpts } = options;
|
||||||
try {
|
try {
|
||||||
|
|
@ -66,6 +67,7 @@ export class HttpUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
static async post<T = any>(url: string, data?: unknown, options: HttpOptions = {}): Promise<Msg<T>> {
|
static async post<T = any>(url: string, data?: unknown, options: HttpOptions = {}): Promise<Msg<T>> {
|
||||||
const { silent, ...axiosOpts } = options;
|
const { silent, ...axiosOpts } = options;
|
||||||
try {
|
try {
|
||||||
|
|
@ -82,6 +84,7 @@ export class HttpUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
static async postWithModal<T = any>(url: string, data?: unknown, modal?: HttpModal | null): Promise<Msg<T>> {
|
static async postWithModal<T = any>(url: string, data?: unknown, modal?: HttpModal | null): Promise<Msg<T>> {
|
||||||
if (modal) {
|
if (modal) {
|
||||||
modal.loading(true);
|
modal.loading(true);
|
||||||
|
|
@ -262,51 +265,53 @@ export class ObjectUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static clone(obj: any): any {
|
static clone<T>(obj: T): T {
|
||||||
if (obj instanceof Array) {
|
if (obj instanceof Array) {
|
||||||
const newArr: unknown[] = [];
|
const newArr: unknown[] = [];
|
||||||
this.copyArr(newArr, obj);
|
this.copyArr(newArr, obj);
|
||||||
return newArr;
|
return newArr as unknown as T;
|
||||||
}
|
}
|
||||||
if (obj instanceof Object) {
|
if (obj instanceof Object) {
|
||||||
const newObj: AnyRecord = {};
|
const newObj: AnyRecord = {};
|
||||||
const rec = obj as AnyRecord;
|
const rec = obj as unknown as AnyRecord;
|
||||||
for (const key of Object.keys(rec)) {
|
for (const key of Object.keys(rec)) {
|
||||||
newObj[key] = rec[key];
|
newObj[key] = rec[key];
|
||||||
}
|
}
|
||||||
return newObj;
|
return newObj as unknown as T;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static deepClone(obj: any): any {
|
static deepClone<T>(obj: T): T {
|
||||||
if (obj instanceof Array) {
|
if (obj instanceof Array) {
|
||||||
const newArr: unknown[] = [];
|
const newArr: unknown[] = [];
|
||||||
for (const item of obj) {
|
for (const item of obj) {
|
||||||
newArr.push(this.deepClone(item));
|
newArr.push(this.deepClone(item));
|
||||||
}
|
}
|
||||||
return newArr;
|
return newArr as unknown as T;
|
||||||
}
|
}
|
||||||
if (obj instanceof Object) {
|
if (obj instanceof Object) {
|
||||||
const newObj: AnyRecord = {};
|
const newObj: AnyRecord = {};
|
||||||
const rec = obj as AnyRecord;
|
const rec = obj as unknown as AnyRecord;
|
||||||
for (const key of Object.keys(rec)) {
|
for (const key of Object.keys(rec)) {
|
||||||
newObj[key] = this.deepClone(rec[key]);
|
newObj[key] = this.deepClone(rec[key]);
|
||||||
}
|
}
|
||||||
return newObj;
|
return newObj as unknown as T;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cloneProps(dest: any, src: any, ...ignoreProps: string[]): void {
|
static cloneProps(dest: object, src: object, ...ignoreProps: string[]): void {
|
||||||
if (dest == null || src == null) return;
|
if (dest == null || src == null) return;
|
||||||
const ignoreEmpty = this.isArrEmpty(ignoreProps);
|
const ignoreEmpty = this.isArrEmpty(ignoreProps);
|
||||||
for (const key of Object.keys(src)) {
|
const d = dest as AnyRecord;
|
||||||
if (!Object.prototype.hasOwnProperty.call(src, key)) continue;
|
const s = src as AnyRecord;
|
||||||
if (!Object.prototype.hasOwnProperty.call(dest, key)) continue;
|
for (const key of Object.keys(s)) {
|
||||||
if (src[key] === undefined) continue;
|
if (!Object.prototype.hasOwnProperty.call(s, key)) continue;
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(d, key)) continue;
|
||||||
|
if (s[key] === undefined) continue;
|
||||||
if (ignoreEmpty) {
|
if (ignoreEmpty) {
|
||||||
dest[key] = src[key];
|
d[key] = s[key];
|
||||||
} else {
|
} else {
|
||||||
let ignore = false;
|
let ignore = false;
|
||||||
for (let i = 0; i < ignoreProps.length; ++i) {
|
for (let i = 0; i < ignoreProps.length; ++i) {
|
||||||
|
|
@ -316,16 +321,17 @@ export class ObjectUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ignore) {
|
if (!ignore) {
|
||||||
dest[key] = src[key];
|
d[key] = s[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static delProps(obj: any, ...props: string[]): void {
|
static delProps(obj: object, ...props: string[]): void {
|
||||||
|
const o = obj as AnyRecord;
|
||||||
for (const prop of props) {
|
for (const prop of props) {
|
||||||
if (prop in obj) {
|
if (prop in o) {
|
||||||
delete obj[prop];
|
delete o[prop];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,13 +347,18 @@ export class ObjectUtil {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static equals(a: any, b: any): boolean {
|
static equals(a: unknown, b: unknown): boolean {
|
||||||
const aKeys = Object.keys(a);
|
if (a == null || b == null || typeof a !== 'object' || typeof b !== 'object') {
|
||||||
const bKeys = Object.keys(b);
|
return a === b;
|
||||||
|
}
|
||||||
|
const ra = a as AnyRecord;
|
||||||
|
const rb = b as AnyRecord;
|
||||||
|
const aKeys = Object.keys(ra);
|
||||||
|
const bKeys = Object.keys(rb);
|
||||||
if (aKeys.length !== bKeys.length) return false;
|
if (aKeys.length !== bKeys.length) return false;
|
||||||
for (const key of aKeys) {
|
for (const key of aKeys) {
|
||||||
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
|
if (!Object.prototype.hasOwnProperty.call(rb, key)) return false;
|
||||||
if (a[key] !== b[key]) return false;
|
if (ra[key] !== rb[key]) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -669,8 +680,7 @@ export class Utils {
|
||||||
let timeoutID: ReturnType<typeof setTimeout> | null = null;
|
let timeoutID: ReturnType<typeof setTimeout> | null = null;
|
||||||
return function (this: unknown, ...args: A) {
|
return function (this: unknown, ...args: A) {
|
||||||
if (timeoutID !== null) clearTimeout(timeoutID);
|
if (timeoutID !== null) clearTimeout(timeoutID);
|
||||||
const self = this;
|
timeoutID = setTimeout(() => fn.apply(this, args), delay);
|
||||||
timeoutID = setTimeout(() => fn.apply(self, args), delay);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -720,7 +730,11 @@ export interface ExpiryClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ColorUtils {
|
export class ColorUtils {
|
||||||
static usageColor(data: any, threshold: number, total: any): UsageColor {
|
static usageColor(
|
||||||
|
data: number | null | undefined,
|
||||||
|
threshold: number,
|
||||||
|
total: number | { valueOf(): number } | null | undefined,
|
||||||
|
): UsageColor {
|
||||||
const t = Number(total ?? 0);
|
const t = Number(total ?? 0);
|
||||||
const d = Number(data);
|
const d = Number(data);
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue