@henryqw/pi-deps 0.2.0 → 0.3.1
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/extensions/deps.ts +35 -3
- package/package.json +4 -3
package/extensions/deps.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { link, mkdir, readFile, rename, rm, writeFile, chmod } from "node:fs/promises";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import type
|
|
5
|
+
import { type ExtensionAPI, type ExtensionUIContext, type Theme } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { type Component, truncateToWidth, type TUI } from "@earendil-works/pi-tui";
|
|
6
7
|
|
|
7
8
|
const hookSourcePath = fileURLToPath(new URL("../hooks/post-checkout.mjs", import.meta.url));
|
|
8
9
|
const managedHookMarker = "pi-deps-managed-hook";
|
|
@@ -67,6 +68,14 @@ const widgetKey = "pi-deps";
|
|
|
67
68
|
const pollMs = 500;
|
|
68
69
|
const successTtlMs = 5000;
|
|
69
70
|
const waitTimeoutMs = 10 * 60_000;
|
|
71
|
+
const spinnerIntervalMs = 100;
|
|
72
|
+
const spinnerFrames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
73
|
+
|
|
74
|
+
function formatElapsed(startedAt: number, now = Date.now()): string {
|
|
75
|
+
const seconds = Math.max(0, Math.floor((now - startedAt) / 1_000));
|
|
76
|
+
const minutes = Math.floor(seconds / 60);
|
|
77
|
+
return minutes ? `${minutes}m ${seconds % 60}s` : `${seconds}s`;
|
|
78
|
+
}
|
|
70
79
|
|
|
71
80
|
interface InstallStatus {
|
|
72
81
|
state?: string;
|
|
@@ -76,7 +85,7 @@ interface InstallStatus {
|
|
|
76
85
|
export interface InstallWatchContext {
|
|
77
86
|
cwd: string;
|
|
78
87
|
mode?: string;
|
|
79
|
-
ui:
|
|
88
|
+
ui: Pick<ExtensionUIContext, "setWidget">;
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
// Watches the status file written by the background installer spawned by the post-checkout hook.
|
|
@@ -102,7 +111,30 @@ export async function watchDependencyInstallation(
|
|
|
102
111
|
|
|
103
112
|
let status = await readStatus();
|
|
104
113
|
if (!status) return;
|
|
105
|
-
if (status.state === "running")
|
|
114
|
+
if (status.state === "running") {
|
|
115
|
+
const startedAt = Date.now();
|
|
116
|
+
let timer: ReturnType<typeof setInterval> | undefined;
|
|
117
|
+
ctx.ui.setWidget(widgetKey, (tui: TUI, theme: Theme): Component & { dispose?(): void } => {
|
|
118
|
+
timer ??= setInterval(() => tui.requestRender(), spinnerIntervalMs);
|
|
119
|
+
timer.unref();
|
|
120
|
+
return {
|
|
121
|
+
invalidate() {},
|
|
122
|
+
dispose() {
|
|
123
|
+
if (timer) clearInterval(timer);
|
|
124
|
+
timer = undefined;
|
|
125
|
+
},
|
|
126
|
+
render: (width: number) => {
|
|
127
|
+
const frame = spinnerFrames[Math.floor(Date.now() / spinnerIntervalMs) % spinnerFrames.length]!;
|
|
128
|
+
return [
|
|
129
|
+
truncateToWidth(
|
|
130
|
+
`${theme.fg("accent", frame)} pi-deps: installing dependencies… ${theme.fg("dim", formatElapsed(startedAt))}`,
|
|
131
|
+
width,
|
|
132
|
+
),
|
|
133
|
+
];
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
106
138
|
const deadline = Date.now() + waitTimeoutMs;
|
|
107
139
|
while (status.state === "running" && Date.now() < deadline) {
|
|
108
140
|
await new Promise((resolveSleep) => setTimeout(resolveSleep, timing.pollMs ?? pollMs));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-deps",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Prepare Node and uv dependencies when opted-in Git worktrees are created.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"test": "node --test test/*.test.ts",
|
|
25
|
-
"typecheck": "tsc --noEmit --allowImportingTsExtensions --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck extensions/deps.ts
|
|
25
|
+
"typecheck": "tsc --noEmit --allowImportingTsExtensions --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck extensions/deps.ts",
|
|
26
26
|
"pack:check": "npm pack --dry-run"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@earendil-works/pi-coding-agent": "*"
|
|
29
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
30
|
+
"@earendil-works/pi-tui": "*"
|
|
30
31
|
},
|
|
31
32
|
"repository": {
|
|
32
33
|
"type": "git",
|