@nickyzj2023/utils 1.0.8 → 1.0.10
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/README.md +35 -35
- package/bun.lock +73 -73
- package/dist/dom.d.ts +8 -8
- package/dist/hoc.d.ts +41 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +6 -2
- package/dist/is.d.ts +6 -6
- package/dist/network.d.ts +40 -32
- package/docs/assets/highlight.css +92 -85
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/functions/fetcher.html +16 -11
- package/docs/functions/isObject.html +7 -3
- package/docs/functions/timeLog.html +5 -5
- package/docs/functions/to.html +11 -7
- package/docs/functions/withCache.html +12 -0
- package/docs/modules.html +1 -1
- package/package.json +22 -22
- package/src/dom.ts +10 -10
- package/src/hoc.ts +109 -0
- package/src/index.ts +4 -3
- package/src/is.ts +8 -8
- package/src/lru-cache.ts +50 -50
- package/src/network.ts +101 -100
- package/tsconfig.json +32 -32
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nickyzj2023/utils",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"module": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"docs": "typedoc src/index.ts",
|
|
9
|
-
"build": "bun build --target=bun --outdir ./dist --minify ./src/index.ts && tsc && bun run docs"
|
|
10
|
-
},
|
|
11
|
-
"devDependencies": {
|
|
12
|
-
"@types/bun": "latest",
|
|
13
|
-
"typedoc": "^0.28.14"
|
|
14
|
-
},
|
|
15
|
-
"peerDependencies": {
|
|
16
|
-
"typescript": "^5"
|
|
17
|
-
},
|
|
18
|
-
"repository": {
|
|
19
|
-
"type": "git",
|
|
20
|
-
"url": "https://github.com/Nickyzj628/utils.git"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@nickyzj2023/utils",
|
|
3
|
+
"version": "1.0.10",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"module": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"docs": "typedoc src/index.ts",
|
|
9
|
+
"build": "bun build --target=bun --outdir ./dist --minify ./src/index.ts && tsc && bun run docs"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@types/bun": "latest",
|
|
13
|
+
"typedoc": "^0.28.14"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"typescript": "^5"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/Nickyzj628/utils.git"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/dom.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 附带时间的 console.log
|
|
3
|
-
* @param args
|
|
4
|
-
*
|
|
5
|
-
* @example
|
|
6
|
-
* timeLog("Hello", "World"); // 14:30:00 Hello World
|
|
7
|
-
*/
|
|
8
|
-
export const timeLog = (...args: any[]) => {
|
|
9
|
-
console.log(`${new Date().toLocaleTimeString()}`, ...args);
|
|
10
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* 附带时间的 console.log
|
|
3
|
+
* @param args
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* timeLog("Hello", "World"); // 14:30:00 Hello World
|
|
7
|
+
*/
|
|
8
|
+
export const timeLog = (...args: any[]) => {
|
|
9
|
+
console.log(`${new Date().toLocaleTimeString()}`, ...args);
|
|
10
|
+
};
|
package/src/hoc.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
type SetTtl = (seconds: number) => void;
|
|
2
|
+
|
|
3
|
+
type CacheEntry = {
|
|
4
|
+
value: any;
|
|
5
|
+
expiresAt: number; // 时间戳(毫秒)
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 创建一个带缓存的高阶函数
|
|
10
|
+
*
|
|
11
|
+
* @template Args 被包装函数的参数类型数组
|
|
12
|
+
* @template Result 被包装函数的返回类型
|
|
13
|
+
*
|
|
14
|
+
* @param fn 需要被缓存的函数,参数里附带的 setTtl 方法用于根据具体情况改写过期时间
|
|
15
|
+
* @param ttlSeconds 以秒为单位的过期时间,-1 表示永不过期,默认 -1,会被回调函数里的 setTtl() 覆盖
|
|
16
|
+
*
|
|
17
|
+
* @returns 返回包装后的函数,以及缓存相关的额外方法
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // 异步函数示例
|
|
21
|
+
* const fetchData = withCache(async (setTtl, url: string) => {
|
|
22
|
+
* const data = await fetch(url).then((res) => res.json());
|
|
23
|
+
* setTtl(data.expiresIn); // 根据实际情况调整过期时间
|
|
24
|
+
* return data;
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* await fetchData(urlA);
|
|
28
|
+
* await fetchData(urlA); // 使用缓存结果
|
|
29
|
+
|
|
30
|
+
* await fetchData(urlB);
|
|
31
|
+
* await fetchData(urlB); // 使用缓存结果
|
|
32
|
+
*
|
|
33
|
+
* fetchData.clear(); // urlA 和 urlB 的缓存都被清除
|
|
34
|
+
* await fetchData(urlA); // 重新请求数据
|
|
35
|
+
* await fetchData(urlB); // 重新请求数据
|
|
36
|
+
*
|
|
37
|
+
* // 缓存过期前
|
|
38
|
+
* fetchData.updateTtl(180); // 更新 ttl 并为所有未过期缓存续期
|
|
39
|
+
* await fetchData(urlA); // 使用缓存结果
|
|
40
|
+
* await fetchData(urlB); // 使用缓存结果
|
|
41
|
+
*/
|
|
42
|
+
export const withCache = <Args extends any[], Result>(
|
|
43
|
+
fn: (setTtl: SetTtl, ...args: Args) => Result,
|
|
44
|
+
ttlSeconds = -1,
|
|
45
|
+
) => {
|
|
46
|
+
const cache = new Map<string, CacheEntry>();
|
|
47
|
+
|
|
48
|
+
const wrapped = (...args: Args): Result => {
|
|
49
|
+
const key = JSON.stringify(args);
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
const entry = cache.get(key);
|
|
52
|
+
|
|
53
|
+
// 命中缓存且未过期
|
|
54
|
+
if (entry && now < entry.expiresAt) {
|
|
55
|
+
return entry.value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const setTtl: SetTtl = (seconds) => (ttlSeconds = seconds);
|
|
59
|
+
const result = fn(setTtl, ...args);
|
|
60
|
+
|
|
61
|
+
// 异步函数:缓存 Promise 的 resolved 值
|
|
62
|
+
if (result instanceof Promise) {
|
|
63
|
+
const promise = result.then((resolved) => {
|
|
64
|
+
cache.set(key, {
|
|
65
|
+
value: resolved,
|
|
66
|
+
expiresAt: Date.now() + ttlSeconds * 1000,
|
|
67
|
+
});
|
|
68
|
+
return resolved;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// 将 promise 先塞进去避免重复请求
|
|
72
|
+
cache.set(key, {
|
|
73
|
+
value: promise,
|
|
74
|
+
expiresAt: now + ttlSeconds * 1000,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return promise as Result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 同步函数缓存
|
|
81
|
+
cache.set(key, {
|
|
82
|
+
value: result,
|
|
83
|
+
expiresAt: now + ttlSeconds * 1000,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** 手动清除缓存 */
|
|
90
|
+
wrapped.clear = () => cache.clear();
|
|
91
|
+
|
|
92
|
+
/** 更新 TTL,同时刷新所有未过期缓存的时间 */
|
|
93
|
+
wrapped.updateTtl = (seconds: number) => {
|
|
94
|
+
// 更新默认 TTL
|
|
95
|
+
ttlSeconds = seconds;
|
|
96
|
+
|
|
97
|
+
// 给未过期缓存续期
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
const newExpiresAt = now + seconds * 1000;
|
|
100
|
+
for (const [key, entry] of cache.entries()) {
|
|
101
|
+
if (entry.expiresAt > now) {
|
|
102
|
+
entry.expiresAt = newExpiresAt;
|
|
103
|
+
cache.set(key, entry);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return wrapped;
|
|
109
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from "./dom";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./dom";
|
|
2
|
+
export * from "./hoc";
|
|
3
|
+
export * from "./is";
|
|
4
|
+
export * from "./network";
|
package/src/is.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 检测传入的值是否为**普通对象**
|
|
3
|
-
* @param value
|
|
4
|
-
* @returns {Boolean} 如果是普通对象,返回 true,否则返回 false
|
|
5
|
-
*/
|
|
6
|
-
export const isObject = (value: any): value is object => {
|
|
7
|
-
return value?.constructor === Object;
|
|
8
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* 检测传入的值是否为**普通对象**
|
|
3
|
+
* @param value
|
|
4
|
+
* @returns {Boolean} 如果是普通对象,返回 true,否则返回 false
|
|
5
|
+
*/
|
|
6
|
+
export const isObject = (value: any): value is object => {
|
|
7
|
+
return value?.constructor === Object;
|
|
8
|
+
};
|
package/src/lru-cache.ts
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 简易 LRU 缓存
|
|
3
|
-
* @example
|
|
4
|
-
* const cache = new LRUCache<string, number>(2);
|
|
5
|
-
* cache.set("a", 1);
|
|
6
|
-
* cache.set("b", 2);
|
|
7
|
-
* cache.set("c", 3); // 缓存已满,a 被淘汰
|
|
8
|
-
* cache.get("a"); // undefined
|
|
9
|
-
*/
|
|
10
|
-
class LRUCache<K, V> {
|
|
11
|
-
private cache: Map<K, V>;
|
|
12
|
-
private maxSize: number;
|
|
13
|
-
|
|
14
|
-
constructor(maxSize = 10) {
|
|
15
|
-
this.cache = new Map();
|
|
16
|
-
this.maxSize = maxSize;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get(key: K): V | undefined {
|
|
20
|
-
const value = this.cache.get(key);
|
|
21
|
-
if (!value) {
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
24
|
-
// 重置缓存顺序
|
|
25
|
-
this.cache.delete(key);
|
|
26
|
-
this.cache.set(key, value);
|
|
27
|
-
return value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
set(key: K, value: V) {
|
|
31
|
-
// 刷新缓存
|
|
32
|
-
if (this.cache.has(key)) {
|
|
33
|
-
this.cache.delete(key);
|
|
34
|
-
}
|
|
35
|
-
// 删除最旧的缓存
|
|
36
|
-
else if (this.cache.size >= this.maxSize) {
|
|
37
|
-
const oldestKey = [...this.cache.keys()][0];
|
|
38
|
-
if (oldestKey) {
|
|
39
|
-
this.cache.delete(oldestKey);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
this.cache.set(key, value);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
has(key: K) {
|
|
46
|
-
return this.cache.has(key);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export default LRUCache;
|
|
1
|
+
/**
|
|
2
|
+
* 简易 LRU 缓存
|
|
3
|
+
* @example
|
|
4
|
+
* const cache = new LRUCache<string, number>(2);
|
|
5
|
+
* cache.set("a", 1);
|
|
6
|
+
* cache.set("b", 2);
|
|
7
|
+
* cache.set("c", 3); // 缓存已满,a 被淘汰
|
|
8
|
+
* cache.get("a"); // undefined
|
|
9
|
+
*/
|
|
10
|
+
class LRUCache<K, V> {
|
|
11
|
+
private cache: Map<K, V>;
|
|
12
|
+
private maxSize: number;
|
|
13
|
+
|
|
14
|
+
constructor(maxSize = 10) {
|
|
15
|
+
this.cache = new Map();
|
|
16
|
+
this.maxSize = maxSize;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get(key: K): V | undefined {
|
|
20
|
+
const value = this.cache.get(key);
|
|
21
|
+
if (!value) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
// 重置缓存顺序
|
|
25
|
+
this.cache.delete(key);
|
|
26
|
+
this.cache.set(key, value);
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set(key: K, value: V) {
|
|
31
|
+
// 刷新缓存
|
|
32
|
+
if (this.cache.has(key)) {
|
|
33
|
+
this.cache.delete(key);
|
|
34
|
+
}
|
|
35
|
+
// 删除最旧的缓存
|
|
36
|
+
else if (this.cache.size >= this.maxSize) {
|
|
37
|
+
const oldestKey = [...this.cache.keys()][0];
|
|
38
|
+
if (oldestKey) {
|
|
39
|
+
this.cache.delete(oldestKey);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this.cache.set(key, value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
has(key: K) {
|
|
46
|
+
return this.cache.has(key);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default LRUCache;
|
package/src/network.ts
CHANGED
|
@@ -1,100 +1,101 @@
|
|
|
1
|
-
import { isObject } from "./is";
|
|
2
|
-
import LRUCache from "./lru-cache";
|
|
3
|
-
|
|
4
|
-
const cachedRequests = new LRUCache<string, Promise<Response>>();
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 基于 Fetch API 的请求客户端
|
|
8
|
-
* @param baseURL 接口前缀,如 https://nickyzj.run:3030,也可以不填
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* const
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
options.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const canCache = options.method === "GET" || !options.method;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
*
|
|
86
|
-
* @
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
1
|
+
import { isObject } from "./is";
|
|
2
|
+
import LRUCache from "./lru-cache";
|
|
3
|
+
|
|
4
|
+
const cachedRequests = new LRUCache<string, Promise<Response>>();
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 基于 Fetch API 的请求客户端
|
|
8
|
+
* @param baseURL 接口前缀,如 https://nickyzj.run:3030,也可以不填
|
|
9
|
+
* @param defaultOptions 客户端级别的请求选项,方法级别的选项会覆盖这里的相同值
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* 特性:
|
|
13
|
+
* - 在 body 里直接传递对象
|
|
14
|
+
* - 能够缓存 GET 请求
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // 用法1:创建客户端
|
|
18
|
+
* const api = fetcher("https://nickyzj.run:3030", { headers: { Authorization: "Bearer token" } });
|
|
19
|
+
* const res = await api.get<Blog>("/blogs/hello-world");
|
|
20
|
+
*
|
|
21
|
+
* // 用法2:直接发送请求
|
|
22
|
+
* const res = await fetcher().get<Blog>("https://nickyzj.run:3030/blogs/hello-world");
|
|
23
|
+
*/
|
|
24
|
+
export const fetcher = (baseURL = "", defaultOptions: RequestInit = {}) => {
|
|
25
|
+
const createRequest = async <T>(path: string, options: RequestInit = {}) => {
|
|
26
|
+
// 构建完整 URL
|
|
27
|
+
const url = baseURL ? `${baseURL}${path}` : path;
|
|
28
|
+
|
|
29
|
+
// 处理 body 为对象的情况
|
|
30
|
+
if (isObject(options.body)) {
|
|
31
|
+
options.body = JSON.stringify(options.body);
|
|
32
|
+
options.headers = {
|
|
33
|
+
...defaultOptions.headers,
|
|
34
|
+
...options.headers,
|
|
35
|
+
"Content-Type": "application/json",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const request = () => fetch(url, options);
|
|
40
|
+
const canCache = options.method === "GET" || !options.method;
|
|
41
|
+
let promise: Promise<Response>;
|
|
42
|
+
if (!canCache) {
|
|
43
|
+
promise = request();
|
|
44
|
+
} else {
|
|
45
|
+
let tempPromise = cachedRequests.get(url);
|
|
46
|
+
if (!tempPromise) {
|
|
47
|
+
tempPromise = request();
|
|
48
|
+
cachedRequests.set(url, tempPromise);
|
|
49
|
+
}
|
|
50
|
+
promise = tempPromise;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 必须使用 clone() 消费一个新的响应体,否则下次从 cache 中获取的响应体会报错(无法被重复消费)
|
|
54
|
+
const response = (await promise).clone();
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
throw new Error(response.statusText);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const data = await response.json();
|
|
60
|
+
return data as T;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
get: <T>(url: string, options: Omit<RequestInit, "method"> = {}) =>
|
|
65
|
+
createRequest<T>(url, { ...options, method: "GET" }),
|
|
66
|
+
|
|
67
|
+
post: <T>(
|
|
68
|
+
url: string,
|
|
69
|
+
body?: any,
|
|
70
|
+
options: Omit<RequestInit, "method" | "body"> = {},
|
|
71
|
+
) => createRequest<T>(url, { ...options, method: "POST", body }),
|
|
72
|
+
|
|
73
|
+
put: <T>(
|
|
74
|
+
url: string,
|
|
75
|
+
body?: any,
|
|
76
|
+
options: Omit<RequestInit, "method" | "body"> = {},
|
|
77
|
+
) => createRequest<T>(url, { ...options, method: "PUT", body }),
|
|
78
|
+
|
|
79
|
+
delete: <T>(url: string, options: Omit<RequestInit, "method"> = {}) =>
|
|
80
|
+
createRequest<T>(url, { ...options, method: "DELETE" }),
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Go 语言风格的异步处理方式
|
|
86
|
+
* @param promise 一个能被 await 的异步函数
|
|
87
|
+
* @returns 如果成功,返回 [null, 异步函数结果],否则返回 [Error, undefined]
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const [error, response] = await to(fetcher().get<Blog>("/blogs/hello-world"));
|
|
91
|
+
*/
|
|
92
|
+
export const to = async <T, U = Error>(
|
|
93
|
+
promise: Promise<T>,
|
|
94
|
+
): Promise<[null, T] | [U, undefined]> => {
|
|
95
|
+
try {
|
|
96
|
+
const response = await promise;
|
|
97
|
+
return [null, response];
|
|
98
|
+
} catch (error) {
|
|
99
|
+
return [error as U, undefined];
|
|
100
|
+
}
|
|
101
|
+
};
|
package/tsconfig.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext", "DOM"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
|
|
11
|
-
// Bundler mode
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
"outDir": "dist",
|
|
16
|
-
"declaration": true,
|
|
17
|
-
"emitDeclarationOnly": true,
|
|
18
|
-
|
|
19
|
-
// Best practices
|
|
20
|
-
"strict": true,
|
|
21
|
-
"skipLibCheck": true,
|
|
22
|
-
"noFallthroughCasesInSwitch": true,
|
|
23
|
-
"noUncheckedIndexedAccess": true,
|
|
24
|
-
"noImplicitOverride": true,
|
|
25
|
-
|
|
26
|
-
// Some stricter flags (disabled by default)
|
|
27
|
-
"noUnusedLocals": false,
|
|
28
|
-
"noUnusedParameters": false,
|
|
29
|
-
"noPropertyAccessFromIndexSignature": false
|
|
30
|
-
},
|
|
31
|
-
"include": ["src"]
|
|
32
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext", "DOM"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"outDir": "dist",
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"emitDeclarationOnly": true,
|
|
18
|
+
|
|
19
|
+
// Best practices
|
|
20
|
+
"strict": true,
|
|
21
|
+
"skipLibCheck": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUncheckedIndexedAccess": true,
|
|
24
|
+
"noImplicitOverride": true,
|
|
25
|
+
|
|
26
|
+
// Some stricter flags (disabled by default)
|
|
27
|
+
"noUnusedLocals": false,
|
|
28
|
+
"noUnusedParameters": false,
|
|
29
|
+
"noPropertyAccessFromIndexSignature": false
|
|
30
|
+
},
|
|
31
|
+
"include": ["src"]
|
|
32
|
+
}
|