toolcraft-openapi 0.0.101 → 0.0.103
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/dist/composition.json +1 -1
- package/node_modules/toolcraft-design/dist/explorer/jobs.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/explorer/jobs.js +28 -0
- package/node_modules/toolcraft-design/dist/explorer/reducer.js +14 -2
- package/node_modules/toolcraft-design/dist/explorer/render/detail.js +1 -1
- package/node_modules/toolcraft-design/dist/explorer/render/list.js +1 -1
- package/package.json +2 -2
package/dist/composition.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ExplorerEvent } from "./events.js";
|
|
2
2
|
import type { DetailCtx, DetailItem } from "./state.js";
|
|
3
3
|
export declare const LOADING_INDICATOR_MS = 150;
|
|
4
|
+
export declare const DETAIL_DEBOUNCE_MS = 100;
|
|
4
5
|
export declare function createDetailJobs(emit: (event: ExplorerEvent) => void): {
|
|
5
6
|
schedule: (rowId: string, items: (ctx: DetailCtx) => Promise<DetailItem[]>, ctx: DetailCtx) => Promise<void>;
|
|
6
7
|
abort: () => void;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const LOADING_INDICATOR_MS = 150;
|
|
2
|
+
export const DETAIL_DEBOUNCE_MS = 100;
|
|
2
3
|
export function createDetailJobs(emit) {
|
|
3
4
|
let token = 0;
|
|
5
|
+
let lastScheduleAt = 0;
|
|
4
6
|
let current = null;
|
|
5
7
|
const abortedTokens = new Set();
|
|
6
8
|
return {
|
|
@@ -9,6 +11,9 @@ export function createDetailJobs(emit) {
|
|
|
9
11
|
current.controller.abort();
|
|
10
12
|
clearTimeout(current.loadingTimer);
|
|
11
13
|
}
|
|
14
|
+
const scheduledAt = Date.now();
|
|
15
|
+
const debounce = scheduledAt - lastScheduleAt < DETAIL_DEBOUNCE_MS;
|
|
16
|
+
lastScheduleAt = scheduledAt;
|
|
12
17
|
const nextToken = ++token;
|
|
13
18
|
const controller = new AbortController();
|
|
14
19
|
let finished = false;
|
|
@@ -19,6 +24,12 @@ export function createDetailJobs(emit) {
|
|
|
19
24
|
}, LOADING_INDICATOR_MS);
|
|
20
25
|
current = { controller, loadingTimer, token: nextToken };
|
|
21
26
|
try {
|
|
27
|
+
if (debounce) {
|
|
28
|
+
await waitUnlessAborted(DETAIL_DEBOUNCE_MS, controller.signal);
|
|
29
|
+
if (controller.signal.aborted || nextToken !== token) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
22
33
|
const loadedItems = await items({ ...ctx, signal: controller.signal });
|
|
23
34
|
finished = true;
|
|
24
35
|
if (!abortedTokens.has(nextToken)) {
|
|
@@ -51,6 +62,23 @@ export function createDetailJobs(emit) {
|
|
|
51
62
|
}
|
|
52
63
|
};
|
|
53
64
|
}
|
|
65
|
+
function waitUnlessAborted(ms, signal) {
|
|
66
|
+
return new Promise((resolve) => {
|
|
67
|
+
if (signal.aborted) {
|
|
68
|
+
resolve();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const onAbort = () => {
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
resolve();
|
|
74
|
+
};
|
|
75
|
+
const timer = setTimeout(() => {
|
|
76
|
+
signal.removeEventListener("abort", onAbort);
|
|
77
|
+
resolve();
|
|
78
|
+
}, ms);
|
|
79
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
54
82
|
function toError(error) {
|
|
55
83
|
if (error instanceof Error) {
|
|
56
84
|
return error;
|
|
@@ -77,9 +77,13 @@ function stepKey(state, key, runtimeHandles) {
|
|
|
77
77
|
case "bottom":
|
|
78
78
|
return setCursor(state, state.filtered.length - 1);
|
|
79
79
|
case "pageUp":
|
|
80
|
-
return
|
|
80
|
+
return isDetailBlobFocused(state)
|
|
81
|
+
? detailScroll(state, -detailBodyHeight(state))
|
|
82
|
+
: moveCursor(state, -pageSize(state));
|
|
81
83
|
case "pageDown":
|
|
82
|
-
return
|
|
84
|
+
return isDetailBlobFocused(state)
|
|
85
|
+
? detailScroll(state, detailBodyHeight(state))
|
|
86
|
+
: moveCursor(state, pageSize(state));
|
|
83
87
|
case "focusNext":
|
|
84
88
|
return focusNext(state);
|
|
85
89
|
case "escape":
|
|
@@ -328,8 +332,16 @@ function moveCursor(state, delta) {
|
|
|
328
332
|
if (state.focused === "detail" && hasDetailCursor(state)) {
|
|
329
333
|
return moveDetailCursor(state, delta);
|
|
330
334
|
}
|
|
335
|
+
if (isDetailBlobFocused(state)) {
|
|
336
|
+
return detailScroll(state, delta);
|
|
337
|
+
}
|
|
331
338
|
return setCursor(state, state.cursor + delta);
|
|
332
339
|
}
|
|
340
|
+
function isDetailBlobFocused(state) {
|
|
341
|
+
return (state.focused === "detail" &&
|
|
342
|
+
!hasDetailCursor(state) &&
|
|
343
|
+
(state.detail.items?.length ?? 0) > 0);
|
|
344
|
+
}
|
|
333
345
|
function moveDetailCursor(state, delta) {
|
|
334
346
|
const max = Math.max(0, (state.detail.items?.length ?? 0) - 1);
|
|
335
347
|
const cursor = clamp(state.detail.cursor + delta, 0, max);
|
|
@@ -26,7 +26,7 @@ function renderDetailBody(state, screen, rect, row) {
|
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
if (items === null) {
|
|
29
|
-
writeLine(screen, rect, 0, state.
|
|
29
|
+
writeLine(screen, rect, 0, row === null ? state.emptyHint : "Loading detail...", styles.muted);
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
if (items.length === 0) {
|
|
@@ -13,7 +13,7 @@ export function renderList(state, screen, layout) {
|
|
|
13
13
|
writeLine(screen, rect, 0, "Terminal too narrow", styles.muted);
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
-
drawPaneFrame(screen, rect,
|
|
16
|
+
drawPaneFrame(screen, rect, state.title, state.focused === "list" ? styles.borderFocused : styles.border);
|
|
17
17
|
const bodyRect = paneBodyRect(rect);
|
|
18
18
|
if (bodyRect.width <= 0 || bodyRect.height <= 0) {
|
|
19
19
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft-openapi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.103",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"toolcraft-openapi-generate": "dist/bin/generate.js"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"toolcraft": "0.0.
|
|
33
|
+
"toolcraft": "0.0.103",
|
|
34
34
|
"auth-store": "^0.0.1",
|
|
35
35
|
"fast-string-width": "^3.0.2",
|
|
36
36
|
"fast-wrap-ansi": "^0.2.0",
|