@bettergi/utils 0.0.4 → 0.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/README.md +58 -3
- package/dist/flow.d.ts +10 -0
- package/dist/flow.js +20 -0
- package/dist/game.d.ts +38 -0
- package/dist/game.js +103 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/mouse.d.ts +22 -0
- package/dist/mouse.js +34 -0
- package/dist/ocr.d.ts +18 -0
- package/dist/ocr.js +39 -0
- package/dist/time.d.ts +0 -0
- package/dist/time.js +0 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,9 +8,27 @@ npm install @bettergi/utils
|
|
|
8
8
|
|
|
9
9
|
## 函数清单
|
|
10
10
|
|
|
11
|
+
### 游戏内操作
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { openMenu, openMenuPage, openPaimonMenu, setTime } from "@bettergi/utils";
|
|
15
|
+
|
|
16
|
+
// 打开派蒙菜单
|
|
17
|
+
await openPaimonMenu();
|
|
18
|
+
|
|
19
|
+
// 打开菜单
|
|
20
|
+
await openMenu("邮件");
|
|
21
|
+
|
|
22
|
+
// 打开菜单页面
|
|
23
|
+
await openMenuPage("问卷");
|
|
24
|
+
|
|
25
|
+
// 调整游戏时间
|
|
26
|
+
await setTime("evening");
|
|
27
|
+
```
|
|
28
|
+
|
|
11
29
|
### 图文识别
|
|
12
30
|
|
|
13
|
-
> 对 RecognitionObject
|
|
31
|
+
> 对 RecognitionObject 代码的封装,对于简单的找图、找字操作,不再需要编写复杂的代码。
|
|
14
32
|
|
|
15
33
|
```ts
|
|
16
34
|
import {
|
|
@@ -41,7 +59,7 @@ const t2 = findTextInDirection("师傅", true, true, "east");
|
|
|
41
59
|
const t3 = findTextWithinBounds("确认", false, true, 960, 540, 960, 540);
|
|
42
60
|
```
|
|
43
61
|
|
|
44
|
-
###
|
|
62
|
+
### 行为流程
|
|
45
63
|
|
|
46
64
|
> 对脚本开发过程中常见工作流的抽象,例如:等待 XXX 完成/出现/消失。
|
|
47
65
|
|
|
@@ -58,7 +76,44 @@ const done = await waitUntil(
|
|
|
58
76
|
if (!done) throw new Error("关闭页面超时");
|
|
59
77
|
```
|
|
60
78
|
|
|
61
|
-
###
|
|
79
|
+
### 鼠标操作
|
|
80
|
+
|
|
81
|
+
> 对常见鼠标操作的封装,如鼠标滚动、拖拽等。
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import {
|
|
85
|
+
mouseScrollDown,
|
|
86
|
+
mouseScrollDownLines,
|
|
87
|
+
mouseScrollUp,
|
|
88
|
+
mouseScrollUpLines,
|
|
89
|
+
mouseSlide,
|
|
90
|
+
mouseSlideX,
|
|
91
|
+
mouseSlideY
|
|
92
|
+
} from "@bettergi/utils";
|
|
93
|
+
|
|
94
|
+
// 鼠标滚轮向上滚动 175 像素
|
|
95
|
+
await mouseScrollUp(175);
|
|
96
|
+
|
|
97
|
+
// 鼠标滚轮向下滚动 175 像素
|
|
98
|
+
await mouseScrollDown(175);
|
|
99
|
+
|
|
100
|
+
// 鼠标滚轮向上滚动 99 行,行高 175(默认:背包物品行高)
|
|
101
|
+
await mouseScrollUpLines(99);
|
|
102
|
+
|
|
103
|
+
// 鼠标滚轮向下滚动 1 行,行高 115(自定义:商店物品行高)
|
|
104
|
+
await mouseScrollDownLines(1, 115);
|
|
105
|
+
|
|
106
|
+
// 鼠标从 (745, 610) 拖拽到 (1280, 610)
|
|
107
|
+
await mouseSlide(745, 610, 1280, 610);
|
|
108
|
+
|
|
109
|
+
// 鼠标从 (745, 610) 向右拖拽 435 像素
|
|
110
|
+
await mouseSlideX(745, 610, 435);
|
|
111
|
+
|
|
112
|
+
// 鼠标从 (1290, 140) 向下拖拽 175 像素
|
|
113
|
+
await mouseSlideY(1290, 140, 175);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 数据存储
|
|
62
117
|
|
|
63
118
|
> 对象数据持久化,通过 Proxy 实现自动存储。从而可以无感知地读取/更新数据,而无需考虑如何持久化。
|
|
64
119
|
|
package/dist/flow.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 等待直到条件满足或超时
|
|
3
|
+
* @param condition 等待的条件判断函数,返回 true 表示条件满足
|
|
4
|
+
* @param timeout 超时时间(毫秒),默认 3000 毫秒
|
|
5
|
+
* @param interval 等待间隔(毫秒),默认 300 毫秒
|
|
6
|
+
* @param action 每次等待循环中执行的操作(可选)
|
|
7
|
+
* @returns - true 在超时前条件已满足
|
|
8
|
+
* - false 在超时后条件仍未满足
|
|
9
|
+
*/
|
|
10
|
+
export declare const waitUntil: (condition: (context: Record<string, any>) => boolean, timeout?: number, interval?: number, action?: (context: Record<string, any>) => void) => Promise<boolean>;
|
package/dist/flow.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 等待直到条件满足或超时
|
|
3
|
+
* @param condition 等待的条件判断函数,返回 true 表示条件满足
|
|
4
|
+
* @param timeout 超时时间(毫秒),默认 3000 毫秒
|
|
5
|
+
* @param interval 等待间隔(毫秒),默认 300 毫秒
|
|
6
|
+
* @param action 每次等待循环中执行的操作(可选)
|
|
7
|
+
* @returns - true 在超时前条件已满足
|
|
8
|
+
* - false 在超时后条件仍未满足
|
|
9
|
+
*/
|
|
10
|
+
export const waitUntil = async (condition, timeout, interval, action) => {
|
|
11
|
+
const context = {};
|
|
12
|
+
const deadline = Date.now() + (timeout ?? 3 * 1000);
|
|
13
|
+
while (Date.now() < deadline) {
|
|
14
|
+
if (condition(context))
|
|
15
|
+
return true;
|
|
16
|
+
action?.(context);
|
|
17
|
+
await sleep(interval ?? 300);
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
};
|
package/dist/game.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 打开派蒙菜单
|
|
3
|
+
*/
|
|
4
|
+
export declare const openPaimonMenu: () => Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* 打开游戏菜单(左侧按钮)
|
|
7
|
+
* @param name 菜单名称
|
|
8
|
+
* @param reverse 是否反向搜索(可选)
|
|
9
|
+
* @param config 搜索参数(可选)
|
|
10
|
+
*/
|
|
11
|
+
export declare const openMenu: (name: "\u62CD\u7167" | "\u516C\u544A" | "\u90AE\u4EF6" | "\u65F6\u95F4" | "\u8BBE\u7F6E" | (string & {}), reverse?: boolean, config?: {
|
|
12
|
+
x?: number;
|
|
13
|
+
step?: number;
|
|
14
|
+
timeout?: number;
|
|
15
|
+
}) => Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* 打开游戏菜单页面(菜单按钮列表)
|
|
18
|
+
* @param name 菜单页面名称
|
|
19
|
+
* @param config 菜单页面视图参数
|
|
20
|
+
*/
|
|
21
|
+
export declare const openMenuPage: (name: string, config?: {
|
|
22
|
+
x?: number;
|
|
23
|
+
y?: number;
|
|
24
|
+
w?: number;
|
|
25
|
+
h?: number;
|
|
26
|
+
lineHeight?: number;
|
|
27
|
+
}) => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* 调整游戏时间
|
|
30
|
+
* @param period 时间段
|
|
31
|
+
* @param config 时钟参数
|
|
32
|
+
*/
|
|
33
|
+
export declare const setTime: (period: "night" | "morning" | "noon" | "evening", config?: {
|
|
34
|
+
centerX?: number;
|
|
35
|
+
centerY?: number;
|
|
36
|
+
radius?: number;
|
|
37
|
+
offset?: number;
|
|
38
|
+
}) => Promise<void>;
|
package/dist/game.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { waitUntil } from "./flow";
|
|
2
|
+
import { mouseSlide } from "./mouse";
|
|
3
|
+
import { findTextInDirection, findTextWithinBounds, findTextWithinListView } from "./ocr";
|
|
4
|
+
/**
|
|
5
|
+
* 打开派蒙菜单
|
|
6
|
+
*/
|
|
7
|
+
export const openPaimonMenu = async () => {
|
|
8
|
+
// 1.返回主界面
|
|
9
|
+
await genshin.returnMainUi();
|
|
10
|
+
// 2.打开派蒙菜单
|
|
11
|
+
const findWorldLevel = () => findTextInDirection("世界等级", false, true, "north-west");
|
|
12
|
+
const ok = await waitUntil(() => findWorldLevel() !== undefined, 5000, 1000, () => keyPress("ESCAPE"));
|
|
13
|
+
if (!ok)
|
|
14
|
+
throw new Error("打开派蒙菜单超时");
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 打开游戏菜单(左侧按钮)
|
|
18
|
+
* @param name 菜单名称
|
|
19
|
+
* @param reverse 是否反向搜索(可选)
|
|
20
|
+
* @param config 搜索参数(可选)
|
|
21
|
+
*/
|
|
22
|
+
export const openMenu = async (name, reverse, config) => {
|
|
23
|
+
// 1.打开派蒙菜单
|
|
24
|
+
await openPaimonMenu();
|
|
25
|
+
// 2.搜索菜单按钮
|
|
26
|
+
const { x = 50, step = 30, timeout = 3000 } = config || {};
|
|
27
|
+
const findTooltip = () => findTextWithinBounds(name, false, true, 0, 0, x + 150, genshin.height);
|
|
28
|
+
let result = undefined;
|
|
29
|
+
const steps = Math.ceil(genshin.height / step);
|
|
30
|
+
for (let i = 0; i < steps; i++) {
|
|
31
|
+
const o = i * step;
|
|
32
|
+
const y = reverse ? genshin.height - o : o;
|
|
33
|
+
moveMouseTo(x, y);
|
|
34
|
+
await sleep(30);
|
|
35
|
+
if ((result = findTooltip()) !== undefined)
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
// 3.点击菜单按钮
|
|
39
|
+
if (result != undefined) {
|
|
40
|
+
const ok = await waitUntil(() => findTooltip() === undefined, timeout, 1000, () => {
|
|
41
|
+
click(x, result.y);
|
|
42
|
+
});
|
|
43
|
+
if (!ok)
|
|
44
|
+
throw new Error(`打开菜单 ${name} 超时`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error(`打开菜单 ${name} 失败`);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* 打开游戏菜单页面(菜单按钮列表)
|
|
52
|
+
* @param name 菜单页面名称
|
|
53
|
+
* @param config 菜单页面视图参数
|
|
54
|
+
*/
|
|
55
|
+
export const openMenuPage = async (name, config) => {
|
|
56
|
+
// 1.打开派蒙菜单
|
|
57
|
+
await openPaimonMenu();
|
|
58
|
+
// 2.搜索菜单页面
|
|
59
|
+
const { x = 100, y = 330, w = 670, h = 730, lineHeight = 142 } = config || {};
|
|
60
|
+
const pageButton = await findTextWithinListView(name, false, true, {
|
|
61
|
+
x,
|
|
62
|
+
y,
|
|
63
|
+
w,
|
|
64
|
+
h,
|
|
65
|
+
maxListItems: 5,
|
|
66
|
+
lineHeight
|
|
67
|
+
});
|
|
68
|
+
if (!pageButton)
|
|
69
|
+
throw new Error(`搜索菜单页面 ${name} 失败`);
|
|
70
|
+
// 3.点击菜单页面
|
|
71
|
+
pageButton.click();
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* 调整游戏时间
|
|
75
|
+
* @param period 时间段
|
|
76
|
+
* @param config 时钟参数
|
|
77
|
+
*/
|
|
78
|
+
export const setTime = async (period, config) => {
|
|
79
|
+
// 1.打开时间页面
|
|
80
|
+
await openMenu("时间", true);
|
|
81
|
+
// 2.拨动指针
|
|
82
|
+
const { centerX = 1440, centerY = 502, radius = 400, offset = 5 } = config || {};
|
|
83
|
+
const index = ["night", "morning", "noon", "evening"].indexOf(period);
|
|
84
|
+
const periodsDirections = [
|
|
85
|
+
() => mouseSlide(centerX, centerY, centerX - offset, centerY + radius),
|
|
86
|
+
() => mouseSlide(centerX, centerY, centerX - radius, centerY - offset),
|
|
87
|
+
() => mouseSlide(centerX, centerY, centerX + offset, centerY - radius),
|
|
88
|
+
() => mouseSlide(centerX, centerY, centerX + radius, centerY + offset)
|
|
89
|
+
];
|
|
90
|
+
const jobs = Array.from({ length: 4 }, (_, i) => periodsDirections[(index + i + 1) % periodsDirections.length]);
|
|
91
|
+
for (const job of jobs)
|
|
92
|
+
await job();
|
|
93
|
+
// 3.点击确认按钮,等待调整结束
|
|
94
|
+
const findTooShort = () => findTextInDirection("时间少于", true, true, "south-east");
|
|
95
|
+
const findConfirmButton = () => findTextInDirection("确认", false, true, "south-east");
|
|
96
|
+
const ok = await waitUntil(() => findTooShort() !== undefined, 20 * 1000, 1000, () => {
|
|
97
|
+
findConfirmButton()?.click();
|
|
98
|
+
});
|
|
99
|
+
if (!ok)
|
|
100
|
+
throw new Error("调整时间超时");
|
|
101
|
+
// 4.返回主界面
|
|
102
|
+
await genshin.returnMainUi();
|
|
103
|
+
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/mouse.d.ts
CHANGED
|
@@ -22,3 +22,25 @@ export declare const mouseScrollUpLines: (lines: number, lineHeight?: number) =>
|
|
|
22
22
|
* @param lineHeight 行高(默认值为175像素)
|
|
23
23
|
*/
|
|
24
24
|
export declare const mouseScrollDownLines: (lines: number, lineHeight?: number) => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* 鼠标拖拽滑动到指定位置
|
|
27
|
+
* @param x1 起始水平方向偏移量(像素)
|
|
28
|
+
* @param y1 起始垂直方向偏移量(像素)
|
|
29
|
+
* @param x2 终止水平方向偏移量(像素)
|
|
30
|
+
* @param y2 终止垂直方向偏移量(像素)
|
|
31
|
+
*/
|
|
32
|
+
export declare const mouseSlide: (x1: number, y1: number, x2: number, y2: number) => Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* 鼠标水平拖拽滑动指定距离
|
|
35
|
+
* @param x 起始水平方向偏移量(像素)
|
|
36
|
+
* @param y 起始垂直方向偏移量(像素)
|
|
37
|
+
* @param distance 水平拖拽滑动距离(像素) 正数向右,负数向左
|
|
38
|
+
*/
|
|
39
|
+
export declare const mouseSlideX: (x: number, y: number, distance: number) => Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* 鼠标垂直拖拽滑动指定距离
|
|
42
|
+
* @param x 起始水平方向偏移量(像素)
|
|
43
|
+
* @param y 起始垂直方向偏移量(像素)
|
|
44
|
+
* @param distance 垂直拖拽滑动距离(像素) 正数向下,负数向上
|
|
45
|
+
*/
|
|
46
|
+
export declare const mouseSlideY: (x: number, y: number, distance: number) => Promise<void>;
|
package/dist/mouse.js
CHANGED
|
@@ -41,3 +41,37 @@ export const mouseScrollUpLines = (lines, lineHeight) => {
|
|
|
41
41
|
export const mouseScrollDownLines = (lines, lineHeight) => {
|
|
42
42
|
return mouseScrollDown(lines * (lineHeight ?? 175));
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* 鼠标拖拽滑动到指定位置
|
|
46
|
+
* @param x1 起始水平方向偏移量(像素)
|
|
47
|
+
* @param y1 起始垂直方向偏移量(像素)
|
|
48
|
+
* @param x2 终止水平方向偏移量(像素)
|
|
49
|
+
* @param y2 终止垂直方向偏移量(像素)
|
|
50
|
+
*/
|
|
51
|
+
export const mouseSlide = async (x1, y1, x2, y2) => {
|
|
52
|
+
moveMouseTo(x1, y1);
|
|
53
|
+
await sleep(50);
|
|
54
|
+
leftButtonDown();
|
|
55
|
+
await sleep(50);
|
|
56
|
+
moveMouseTo(x2, y2);
|
|
57
|
+
await sleep(50);
|
|
58
|
+
leftButtonUp();
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* 鼠标水平拖拽滑动指定距离
|
|
62
|
+
* @param x 起始水平方向偏移量(像素)
|
|
63
|
+
* @param y 起始垂直方向偏移量(像素)
|
|
64
|
+
* @param distance 水平拖拽滑动距离(像素) 正数向右,负数向左
|
|
65
|
+
*/
|
|
66
|
+
export const mouseSlideX = (x, y, distance) => {
|
|
67
|
+
return mouseSlide(x, y, x + distance, y);
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* 鼠标垂直拖拽滑动指定距离
|
|
71
|
+
* @param x 起始水平方向偏移量(像素)
|
|
72
|
+
* @param y 起始垂直方向偏移量(像素)
|
|
73
|
+
* @param distance 垂直拖拽滑动距离(像素) 正数向下,负数向上
|
|
74
|
+
*/
|
|
75
|
+
export const mouseSlideY = (x, y, distance) => {
|
|
76
|
+
return mouseSlide(x, y, x, y + distance);
|
|
77
|
+
};
|
package/dist/ocr.d.ts
CHANGED
|
@@ -53,4 +53,22 @@ export declare const findTextWithinBounds: (text: string, contains: boolean, ign
|
|
|
53
53
|
* @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
|
|
54
54
|
*/
|
|
55
55
|
export declare const findTextInDirection: (text: string, contains: boolean, ignoreCase: boolean, direction: Direction) => Region | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* 在列表视图中滚动搜索文本
|
|
58
|
+
* @param text 待搜索文本
|
|
59
|
+
* @param contains 是否包含
|
|
60
|
+
* @param ignoreCase 是否忽略大小写
|
|
61
|
+
* @param listView 列表视图参数
|
|
62
|
+
* @param timeout 搜索超时
|
|
63
|
+
* @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
|
|
64
|
+
*/
|
|
65
|
+
export declare const findTextWithinListView: (text: string, contains: boolean, ignoreCase: boolean, listView: {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
w: number;
|
|
69
|
+
h: number;
|
|
70
|
+
maxListItems: number;
|
|
71
|
+
lineHeight: number;
|
|
72
|
+
padding?: number;
|
|
73
|
+
}, timeout?: number) => Promise<Region | undefined>;
|
|
56
74
|
export {};
|
package/dist/ocr.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { waitUntil } from "./flow";
|
|
2
|
+
import { mouseScrollDownLines } from "./mouse";
|
|
1
3
|
const findFirst = (ir, ro, predicate) => {
|
|
2
4
|
const candidates = ir.findMulti(ro);
|
|
3
5
|
for (let i = 0; i < candidates.count; i++) {
|
|
@@ -108,3 +110,40 @@ export const findTextInDirection = (text, contains, ignoreCase, direction) => {
|
|
|
108
110
|
const { x, y, w, h } = directionToBounds(direction);
|
|
109
111
|
return findTextWithinBounds(text, contains, ignoreCase, x, y, w, h);
|
|
110
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* 在列表视图中滚动搜索文本
|
|
115
|
+
* @param text 待搜索文本
|
|
116
|
+
* @param contains 是否包含
|
|
117
|
+
* @param ignoreCase 是否忽略大小写
|
|
118
|
+
* @param listView 列表视图参数
|
|
119
|
+
* @param timeout 搜索超时
|
|
120
|
+
* @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
|
|
121
|
+
*/
|
|
122
|
+
export const findTextWithinListView = async (text, contains, ignoreCase, listView, timeout) => {
|
|
123
|
+
const { x, y, w, h, maxListItems, lineHeight, padding = 10 } = listView;
|
|
124
|
+
const find = () => {
|
|
125
|
+
return findTextWithinBounds(text, contains, ignoreCase, x, y, w, h);
|
|
126
|
+
};
|
|
127
|
+
let firstRegion;
|
|
128
|
+
const isBottomTouched = () => {
|
|
129
|
+
const ro = RecognitionObject.ocr(x, y, w, h);
|
|
130
|
+
const list = captureGameRegion().findMulti(ro);
|
|
131
|
+
if (list.count > 0) {
|
|
132
|
+
if (firstRegion?.text === list[0].text && Math.abs(list[0].y - firstRegion.y) < lineHeight) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
firstRegion = list[0];
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const ok = await waitUntil(() => find() != undefined || isBottomTouched(), timeout ?? 30 * 1000, 1000, async () => {
|
|
145
|
+
moveMouseTo(x + w - padding, y + padding);
|
|
146
|
+
await mouseScrollDownLines(maxListItems, lineHeight);
|
|
147
|
+
});
|
|
148
|
+
return ok ? find() : undefined;
|
|
149
|
+
};
|
package/dist/time.d.ts
ADDED
|
File without changes
|
package/dist/time.js
ADDED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bettergi/utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Utils for BetterGI JavaScript Development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Bread Grocery<https://github.com/breadgrocery>",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"build": "tsc"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@bettergi/types": "^0.0.
|
|
37
|
-
"typescript": "
|
|
36
|
+
"@bettergi/types": "^0.0.10",
|
|
37
|
+
"typescript": "5.6.3"
|
|
38
38
|
}
|
|
39
39
|
}
|