@dune2/tools 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -8
- package/readme.md +105 -2
- package/src/numbro/index.ts +1 -65
- package/src/numbro/shared.ts +0 -25
- package/src/rq/RequestBuilder.react-server.ts +1 -1
- package/src/rq/RequestBuilder.ts +1 -1
- package/src/rq/createApi.ts +1 -1
- package/src/rq/options.ts +28 -4
- package/src/logger/Logger.ts +0 -104
- package/src/logger/index.ts +0 -71
- package/src/logger/shared.ts +0 -25
- package/src/numbro/currencies.ts +0 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dune2/tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n"
|
|
@@ -25,8 +25,6 @@
|
|
|
25
25
|
"./shared/*": "./src/shared/*.ts",
|
|
26
26
|
"./storage": "./src/storage/index.ts",
|
|
27
27
|
"./storage/*": "./src/storage/*.ts",
|
|
28
|
-
"./logger": "./src/logger/index.ts",
|
|
29
|
-
"./logger/*": "./src/logger/*.ts",
|
|
30
28
|
"./store": "./src/store/index.ts",
|
|
31
29
|
"./package.json": "./package.json",
|
|
32
30
|
".": "./src/index.ts"
|
|
@@ -35,17 +33,16 @@
|
|
|
35
33
|
"src"
|
|
36
34
|
],
|
|
37
35
|
"dependencies": {
|
|
36
|
+
"@tanstack/react-query": "^5",
|
|
38
37
|
"bignumber.js": "^9.1.2",
|
|
39
38
|
"es-toolkit": "^1",
|
|
40
39
|
"js-cookie": "^3.0.5",
|
|
41
|
-
"store2": "^2.14.3"
|
|
40
|
+
"store2": "^2.14.3",
|
|
41
|
+
"valtio": "^2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@tanstack/react-query": "5.51.11",
|
|
45
44
|
"@types/js-cookie": "3.0.3",
|
|
46
|
-
"
|
|
47
|
-
"react": "^19",
|
|
48
|
-
"valtio": "^2"
|
|
45
|
+
"react": "^19"
|
|
49
46
|
},
|
|
50
47
|
"publishConfig": {
|
|
51
48
|
"access": "public"
|
package/readme.md
CHANGED
|
@@ -1,3 +1,106 @@
|
|
|
1
|
-
|
|
1
|
+
# @dune2/tools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React utility library with common tools and components.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @dune2/tools
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Modules
|
|
12
|
+
|
|
13
|
+
### Factory
|
|
14
|
+
|
|
15
|
+
React state management utilities for creating context providers.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { createStateContext } from "@dune2/tools/factory/createStateContext";
|
|
19
|
+
|
|
20
|
+
const { Provider, useContextValue } = createStateContext({
|
|
21
|
+
name: "Counter",
|
|
22
|
+
useValueHooks: ({ initialCount = 0 }) => {
|
|
23
|
+
const [count, setCount] = useState(initialCount);
|
|
24
|
+
return { count, setCount };
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Storage
|
|
30
|
+
|
|
31
|
+
Browser storage wrapper with React hooks integration.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createStorage } from "@dune2/tools/storage";
|
|
35
|
+
|
|
36
|
+
class DataMap {
|
|
37
|
+
token = "";
|
|
38
|
+
user = null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const storage = createStorage({
|
|
42
|
+
DataMap,
|
|
43
|
+
namespace: "app",
|
|
44
|
+
storageType: "local", // or 'session'
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Use in React
|
|
48
|
+
const token = storage.token.useValue();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### RQ (React Query)
|
|
52
|
+
|
|
53
|
+
Enhanced React Query utilities with built-in request building.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { RequestBuilder } from "@dune2/tools/rq";
|
|
57
|
+
|
|
58
|
+
const userApi = new RequestBuilder({
|
|
59
|
+
url: "/api/users/{id}",
|
|
60
|
+
method: "get",
|
|
61
|
+
urlPathParams: ["id"],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Use in components
|
|
65
|
+
const { data, isLoading } = userApi.useQuery({ id: "123" });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Store
|
|
69
|
+
|
|
70
|
+
Valtio-based state management with TypeScript support.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { createStore } from "@dune2/tools/store";
|
|
74
|
+
|
|
75
|
+
const counterStore = createStore({
|
|
76
|
+
name: "counter",
|
|
77
|
+
state: { count: 0 },
|
|
78
|
+
actionsCreator: (state) => ({
|
|
79
|
+
increment: () => state.count++,
|
|
80
|
+
decrement: () => state.count--,
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Use in components
|
|
85
|
+
const { count } = counterStore.useSnapshot();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Numbro
|
|
89
|
+
|
|
90
|
+
BigNumber.js wrapper for precise number formatting and calculations.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { numbro } from "@dune2/tools/numbro";
|
|
94
|
+
|
|
95
|
+
const price = numbro(123.456);
|
|
96
|
+
price.format({ mantissa: 2 }); // "123.46"
|
|
97
|
+
price.formatCurrency({ symbol: "$" }); // "$123.46"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Shared
|
|
101
|
+
|
|
102
|
+
TypeScript utility types for better type safety.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import type { OptionalKeys, Overwrite, Print } from "@dune2/tools/shared";
|
|
106
|
+
```
|
package/src/numbro/index.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import {
|
|
3
|
-
import { defaultCurrencies } from "./currencies";
|
|
4
|
-
import type { CurrencyFormat, Format } from "./shared";
|
|
2
|
+
import type { Format } from "./shared";
|
|
5
3
|
import { RoundingMode } from "./shared";
|
|
6
4
|
|
|
7
5
|
export * from "./shared";
|
|
@@ -161,68 +159,6 @@ export class Numbro {
|
|
|
161
159
|
}
|
|
162
160
|
//#endregion
|
|
163
161
|
|
|
164
|
-
//#region currency format
|
|
165
|
-
/**
|
|
166
|
-
* currency format default
|
|
167
|
-
*/
|
|
168
|
-
static locale: string = LocalesEnum.id;
|
|
169
|
-
static setLocale(locale: string) {
|
|
170
|
-
// check locale is valid
|
|
171
|
-
if (!(locale in Numbro.defaultCurrencies)) {
|
|
172
|
-
throw new Error(`在 defaultCurrencies 中,找不到 ${locale},请先检查`);
|
|
173
|
-
}
|
|
174
|
-
Numbro.locale = locale;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* 默认的货币格式化配置
|
|
179
|
-
* key: locale
|
|
180
|
-
* value: currency format
|
|
181
|
-
*/
|
|
182
|
-
static defaultCurrencies = defaultCurrencies;
|
|
183
|
-
static setDefaultCurrencies(currencies: typeof defaultCurrencies) {
|
|
184
|
-
Numbro.defaultCurrencies = currencies;
|
|
185
|
-
}
|
|
186
|
-
formatCurrency(format: CurrencyFormat = {}) {
|
|
187
|
-
// 根据语言解析出来的默认格式
|
|
188
|
-
const defaultCurrencyFormat =
|
|
189
|
-
Numbro.defaultCurrencies[format.locale ?? Numbro.locale];
|
|
190
|
-
|
|
191
|
-
format = {
|
|
192
|
-
...defaultCurrencyFormat,
|
|
193
|
-
...format,
|
|
194
|
-
};
|
|
195
|
-
let {
|
|
196
|
-
position = "prefix",
|
|
197
|
-
symbol,
|
|
198
|
-
spaceSeparated,
|
|
199
|
-
|
|
200
|
-
...rest
|
|
201
|
-
} = format;
|
|
202
|
-
// 是否强制显示正负号
|
|
203
|
-
const sign = this.getPrefixSign(rest.forceSign);
|
|
204
|
-
|
|
205
|
-
let space = spaceSeparated ? " " : "";
|
|
206
|
-
// 在 currency format 中,需要使用绝对值来格式化
|
|
207
|
-
// 方便后续添加 正负号
|
|
208
|
-
rest.absoluteValue = true;
|
|
209
|
-
rest.forceSign = false;
|
|
210
|
-
let formattedString = this.format(rest);
|
|
211
|
-
|
|
212
|
-
//#region NaN 的 fallback
|
|
213
|
-
const { NaNFormat } = this.combineFormatOptions(rest);
|
|
214
|
-
if (formattedString === NaNFormat) {
|
|
215
|
-
return formattedString;
|
|
216
|
-
}
|
|
217
|
-
//#endregion
|
|
218
|
-
|
|
219
|
-
if (position === "prefix") {
|
|
220
|
-
return `${sign}${symbol}${space}${formattedString}`;
|
|
221
|
-
}
|
|
222
|
-
return `${sign}${formattedString}${space}${symbol}`;
|
|
223
|
-
}
|
|
224
|
-
//#endregion
|
|
225
|
-
|
|
226
162
|
private computeAverage(num: BigNumber) {
|
|
227
163
|
const powers = {
|
|
228
164
|
// 1t
|
package/src/numbro/shared.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import { LocalesEnum } from "../i18n/enums";
|
|
3
2
|
|
|
4
3
|
export interface Format extends BigNumber.Format {
|
|
5
4
|
output?: "percent";
|
|
@@ -73,30 +72,6 @@ export interface Format extends BigNumber.Format {
|
|
|
73
72
|
absoluteValue?: boolean;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
export interface CurrencyFormat extends Format {
|
|
77
|
-
/**
|
|
78
|
-
* 货币符号
|
|
79
|
-
*/
|
|
80
|
-
symbol?: string;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 货币符号位置
|
|
84
|
-
*/
|
|
85
|
-
position?: "prefix" | "postfix";
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 按哪种语言格式化,会根据传入的语言去 currencies 里获取对应的配置项
|
|
89
|
-
* 一般用在以下情况:
|
|
90
|
-
* - 当前设置的语言是 en,但是需要格式化成 id 的货币
|
|
91
|
-
*/
|
|
92
|
-
locale?: LocalesEnum | (string & {});
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* symbol 和 数字 之间是否需要空格
|
|
96
|
-
*/
|
|
97
|
-
spaceSeparated?: boolean;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
75
|
/**
|
|
101
76
|
* 重新导出 BigNumber.RoundingMode
|
|
102
77
|
* 由于项目不会使用太多的四舍五入模式,所以只导出常用的几个
|
|
@@ -46,7 +46,7 @@ export class RequestBuilder<Req = any, Res = any> {
|
|
|
46
46
|
* useQuery、useMutation 内部会调用这个
|
|
47
47
|
* 另外也可以直接调用这个函数来发送请求
|
|
48
48
|
* @param params 请求参数 默认会根据请求方法来放到 url 上或者 body 里
|
|
49
|
-
* @param config
|
|
49
|
+
* @param config 请求的配置,一般不需要传,内部用
|
|
50
50
|
*/
|
|
51
51
|
request<P extends Req, T = Res>(params?: P, config?: RequestConfig) {
|
|
52
52
|
const method = this.options.method!;
|
package/src/rq/RequestBuilder.ts
CHANGED
|
@@ -77,7 +77,7 @@ export class RequestBuilder<Req = any, Res = any> {
|
|
|
77
77
|
* useQuery、useMutation 内部会调用这个
|
|
78
78
|
* 另外也可以直接调用这个函数来发送请求
|
|
79
79
|
* @param params 请求参数 默认会根据请求方法来放到 url 上或者 body 里
|
|
80
|
-
* @param config
|
|
80
|
+
* @param config 请求的配置,一般不需要传,内部用
|
|
81
81
|
*/
|
|
82
82
|
request<P extends Req, T = Res>(params?: P, config?: RequestConfig) {
|
|
83
83
|
const method = this.options.method!;
|
package/src/rq/createApi.ts
CHANGED
|
@@ -29,7 +29,7 @@ export function createApi<Req, Res>(opts: Options<Req, Res>) {
|
|
|
29
29
|
const { requestFn, ...rest } = opts;
|
|
30
30
|
const api = new RequestBuilder<Req, Res>({
|
|
31
31
|
url: opts.queryKey,
|
|
32
|
-
// 给定 get 则 在 requestFn 中可以通过 params 获取到参数,否则是 data
|
|
32
|
+
// 给定 get 则 在 requestFn 中可以通过 params 获取到参数,否则是 data 字段
|
|
33
33
|
method: "get",
|
|
34
34
|
requestFn: (config) => {
|
|
35
35
|
return requestFn(config.params) as never;
|
package/src/rq/options.ts
CHANGED
|
@@ -5,10 +5,34 @@ import type {
|
|
|
5
5
|
useQuery,
|
|
6
6
|
} from "@tanstack/react-query";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// 定义 HTTP 方法类型
|
|
9
|
+
export type HttpMethod =
|
|
10
|
+
| "get"
|
|
11
|
+
| "post"
|
|
12
|
+
| "put"
|
|
13
|
+
| "delete"
|
|
14
|
+
| "patch"
|
|
15
|
+
| "head"
|
|
16
|
+
| "options";
|
|
9
17
|
// 外部可以重写这个类型
|
|
10
18
|
export interface RequestBuilderMeta {}
|
|
11
19
|
|
|
20
|
+
// 通用的请求配置接口,不依赖于具体的 HTTP 库
|
|
21
|
+
export interface RequestFnParams {
|
|
22
|
+
/** 请求URL */
|
|
23
|
+
url?: string;
|
|
24
|
+
/** HTTP 请求方法 */
|
|
25
|
+
method?: string;
|
|
26
|
+
/** URL 查询参数 */
|
|
27
|
+
params?: any;
|
|
28
|
+
/** 请求体数据 */
|
|
29
|
+
data?: any;
|
|
30
|
+
/** 请求头 */
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
/** 请求取消 */
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
}
|
|
35
|
+
|
|
12
36
|
export interface Basic {
|
|
13
37
|
/**
|
|
14
38
|
* 请求方法
|
|
@@ -16,7 +40,7 @@ export interface Basic {
|
|
|
16
40
|
* 2. 如果在调用`request/useQuery`之类的不想用实例化是传入的`requestFn`,可以在`request/useQuery`的第二个参数传入`requestFn`
|
|
17
41
|
* 一般场景是有些情况需要全局`toast`,有些场景不需要,所以在不同的场景下传入不同实现的`requestFn`
|
|
18
42
|
*/
|
|
19
|
-
requestFn?: <T = unknown>(
|
|
43
|
+
requestFn?: <T = unknown>(params: RequestFnParams) => Promise<T>;
|
|
20
44
|
|
|
21
45
|
meta?: RequestBuilderMeta;
|
|
22
46
|
}
|
|
@@ -45,7 +69,7 @@ export interface RequestBuilderOptions<Req, Res>
|
|
|
45
69
|
* 请求方法
|
|
46
70
|
* @default "get"
|
|
47
71
|
*/
|
|
48
|
-
method?:
|
|
72
|
+
method?: HttpMethod;
|
|
49
73
|
// 请求路径
|
|
50
74
|
url: string;
|
|
51
75
|
// url path 上的参数 , /prefunding-order/{id} 中的 id
|
|
@@ -58,7 +82,7 @@ export interface RequestBuilderOptions<Req, Res>
|
|
|
58
82
|
useMutationOptions?: UseMutationOptions<Res, unknown, Req>;
|
|
59
83
|
}
|
|
60
84
|
|
|
61
|
-
export type RequestConfig = Basic &
|
|
85
|
+
export type RequestConfig = Basic & RequestFnParams;
|
|
62
86
|
|
|
63
87
|
export type PageData<T = any> = {
|
|
64
88
|
total?: number;
|
package/src/logger/Logger.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { noop } from "es-toolkit";
|
|
2
|
-
import store2 from "store2";
|
|
3
|
-
import { Level, type OnLogParams } from "./shared";
|
|
4
|
-
|
|
5
|
-
type StorageState = Record<string, Level>;
|
|
6
|
-
|
|
7
|
-
export type OnLog = (data: OnLogParams) => void;
|
|
8
|
-
|
|
9
|
-
export class Logger {
|
|
10
|
-
constructor(
|
|
11
|
-
public name: string,
|
|
12
|
-
public storageKey?: string,
|
|
13
|
-
/**
|
|
14
|
-
* 当前启用的等级
|
|
15
|
-
* 如果设置为 Silent 则不输出任何日志
|
|
16
|
-
* 只有大于等于当前等级的日志才会输出
|
|
17
|
-
*/
|
|
18
|
-
public level = Level.Debug,
|
|
19
|
-
public onLog: OnLog = noop,
|
|
20
|
-
) {
|
|
21
|
-
this.level = this.getStorageLevel() ?? level;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
private getStorageLevel() {
|
|
25
|
-
if (this.storageKey) {
|
|
26
|
-
const state = store2.get(this.storageKey) as StorageState;
|
|
27
|
-
return state?.[this.name];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
private setStorageLevel(level: Level) {
|
|
31
|
-
if (this.storageKey) {
|
|
32
|
-
const state = store2.get(this.storageKey) as StorageState;
|
|
33
|
-
store2.set(this.storageKey, { ...state, [this.name]: level });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
setLevel(level: Level) {
|
|
37
|
-
this.level = level;
|
|
38
|
-
this.setStorageLevel(level);
|
|
39
|
-
}
|
|
40
|
-
enable() {
|
|
41
|
-
this.setLevel(Level.Debug);
|
|
42
|
-
}
|
|
43
|
-
disable() {
|
|
44
|
-
this.setLevel(Level.Error);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// 是否应该输出日志
|
|
48
|
-
private shouldLog(level: Level) {
|
|
49
|
-
return level >= this.level;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private combineArgs(level: Level, tag: string, args: any[]): OnLogParams {
|
|
53
|
-
const data = {
|
|
54
|
-
name: this.name,
|
|
55
|
-
level,
|
|
56
|
-
msg: args,
|
|
57
|
-
tag,
|
|
58
|
-
time: Date.now(),
|
|
59
|
-
shouldLog: this.shouldLog(level),
|
|
60
|
-
};
|
|
61
|
-
return data;
|
|
62
|
-
}
|
|
63
|
-
private formatArgs(data: OnLogParams) {
|
|
64
|
-
const time = new Date(data.time).toLocaleTimeString("zh-CN");
|
|
65
|
-
const prefix = `[${time}] ${data.tag} ${data.name}: `;
|
|
66
|
-
|
|
67
|
-
const first = data.msg[0];
|
|
68
|
-
|
|
69
|
-
if (typeof first === "string") {
|
|
70
|
-
// 确保 %o %O 等占位符正常工作
|
|
71
|
-
return [`${prefix}${first}`, ...data.msg.slice(1)];
|
|
72
|
-
}
|
|
73
|
-
return [`${prefix}`, ...data.msg];
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
debug(...args: any[]) {
|
|
77
|
-
const data = this.combineArgs(Level.Debug, "DEBUG", args);
|
|
78
|
-
this.onLog(data);
|
|
79
|
-
if (data.shouldLog) {
|
|
80
|
-
console.debug(...this.formatArgs(data));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
info(...args: any[]) {
|
|
84
|
-
const data = this.combineArgs(Level.Info, "INFO", args);
|
|
85
|
-
this.onLog(data);
|
|
86
|
-
if (data.shouldLog) {
|
|
87
|
-
console.log(...this.formatArgs(data));
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
warn(...args: any[]) {
|
|
91
|
-
const data = this.combineArgs(Level.Warn, "WARN", args);
|
|
92
|
-
this.onLog(data);
|
|
93
|
-
if (data.shouldLog) {
|
|
94
|
-
console.warn(...this.formatArgs(data));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
error(...args: any[]) {
|
|
98
|
-
const data = this.combineArgs(Level.Error, "ERROR", args);
|
|
99
|
-
this.onLog(data);
|
|
100
|
-
if (data.shouldLog) {
|
|
101
|
-
console.error(...this.formatArgs(data));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
package/src/logger/index.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { camelCase } from "es-toolkit";
|
|
2
|
-
import { forEach } from "es-toolkit/compat";
|
|
3
|
-
import { Logger, type OnLog } from "./Logger";
|
|
4
|
-
import { Level } from "./shared";
|
|
5
|
-
|
|
6
|
-
interface Config<Name extends string = string> {
|
|
7
|
-
// 创建的 logger 名称
|
|
8
|
-
loggers: Name[];
|
|
9
|
-
// 默认日志级别
|
|
10
|
-
level?: Level;
|
|
11
|
-
// 日志回调,用于上报日志
|
|
12
|
-
onLog?: OnLog;
|
|
13
|
-
// 存储到本地的 key,用于存储日志级别
|
|
14
|
-
storageKey?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type NormalizeName<T extends string> = T extends `${infer A}.${infer B}`
|
|
18
|
-
? `${A}${Capitalize<NormalizeName<B>>}`
|
|
19
|
-
: T;
|
|
20
|
-
|
|
21
|
-
export function createLogger<Name extends string>(config: Config<Name>) {
|
|
22
|
-
type Key = NormalizeName<Name>;
|
|
23
|
-
|
|
24
|
-
// 内置关键字
|
|
25
|
-
const keywords = ["debug", "info", "warn", "error", "enable", "disable"];
|
|
26
|
-
|
|
27
|
-
const loggerMap = {} as Record<Key, Logger>;
|
|
28
|
-
config.loggers.forEach((name) => {
|
|
29
|
-
if (keywords.includes(name)) {
|
|
30
|
-
throw new Error(`logger name can't be ${name}`);
|
|
31
|
-
}
|
|
32
|
-
// 输入:foo.login
|
|
33
|
-
// 输出:fooLogin
|
|
34
|
-
const key = (name.includes(".") ? camelCase(name) : name) as Key;
|
|
35
|
-
|
|
36
|
-
if (loggerMap[key]) {
|
|
37
|
-
throw new Error(`logger name "${name}" is duplicated`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const logger = new Logger(
|
|
41
|
-
name,
|
|
42
|
-
config.storageKey,
|
|
43
|
-
config.level ?? Level.Debug,
|
|
44
|
-
config.onLog,
|
|
45
|
-
);
|
|
46
|
-
loggerMap[key] = logger;
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const method = {
|
|
50
|
-
enable() {
|
|
51
|
-
forEach(loggerMap, (v) => {
|
|
52
|
-
v.enable();
|
|
53
|
-
});
|
|
54
|
-
},
|
|
55
|
-
disable() {
|
|
56
|
-
forEach(loggerMap, (v) => {
|
|
57
|
-
v.disable();
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
setLevel(level: Level) {
|
|
61
|
-
forEach(loggerMap, (v) => {
|
|
62
|
-
v.setLevel(level);
|
|
63
|
-
});
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
...method,
|
|
69
|
-
...loggerMap,
|
|
70
|
-
};
|
|
71
|
-
}
|
package/src/logger/shared.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export enum Level {
|
|
2
|
-
Debug,
|
|
3
|
-
Info,
|
|
4
|
-
Warn,
|
|
5
|
-
Error,
|
|
6
|
-
Silent,
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export type OnLogParams = {
|
|
10
|
-
// 日志等级
|
|
11
|
-
level: Level;
|
|
12
|
-
// 可读的日志等级
|
|
13
|
-
tag: string;
|
|
14
|
-
// 用于标识日志的名称
|
|
15
|
-
name: string;
|
|
16
|
-
// 日志输出时间
|
|
17
|
-
time: number;
|
|
18
|
-
// 是否应该输出日志
|
|
19
|
-
shouldLog: boolean;
|
|
20
|
-
// 日志内容
|
|
21
|
-
msg: any[];
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// 让 vite 能识别成 es-module
|
|
25
|
-
export default {};
|
package/src/numbro/currencies.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { LocalesEnum } from "../i18n/enums";
|
|
2
|
-
import type { CurrencyFormat } from "./shared";
|
|
3
|
-
|
|
4
|
-
export const defaultCurrencies: Record<
|
|
5
|
-
string,
|
|
6
|
-
Omit<CurrencyFormat, "locale">
|
|
7
|
-
> = {
|
|
8
|
-
[LocalesEnum.en]: {
|
|
9
|
-
symbol: "$",
|
|
10
|
-
position: "prefix",
|
|
11
|
-
mantissa: 2,
|
|
12
|
-
},
|
|
13
|
-
[LocalesEnum.id]: {
|
|
14
|
-
symbol: "Rp",
|
|
15
|
-
position: "prefix",
|
|
16
|
-
mantissa: 2,
|
|
17
|
-
},
|
|
18
|
-
[LocalesEnum.zh]: {
|
|
19
|
-
symbol: "¥",
|
|
20
|
-
position: "prefix",
|
|
21
|
-
mantissa: 2,
|
|
22
|
-
},
|
|
23
|
-
};
|