@pi-unipi/updater 0.1.2 → 2.0.0
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 +1 -1
- package/src/checker.ts +2 -2
- package/src/commands.ts +6 -6
- package/src/index.ts +12 -10
- package/src/installer.ts +5 -2
- package/src/tui/changelog-overlay.ts +2 -2
- package/src/tui/readme-overlay.ts +4 -4
- package/src/tui/settings-overlay.ts +3 -3
- package/src/tui/update-overlay.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Auto-updater, changelog browser, and readme browser for Unipi — checks npm registry, renders CHANGELOG.md and README.md files in TUI overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/checker.ts
CHANGED
|
@@ -71,14 +71,14 @@ export async function checkForUpdates(): Promise<UpdateCheckResult> {
|
|
|
71
71
|
latestVersion,
|
|
72
72
|
currentVersion,
|
|
73
73
|
};
|
|
74
|
-
} catch (err:
|
|
74
|
+
} catch (err: unknown) {
|
|
75
75
|
// Network error — return cached info if available
|
|
76
76
|
const cache = readLastCheck();
|
|
77
77
|
return {
|
|
78
78
|
updateAvailable: false,
|
|
79
79
|
latestVersion: cache?.latestVersion ?? "",
|
|
80
80
|
currentVersion,
|
|
81
|
-
error: err.message
|
|
81
|
+
error: err instanceof Error ? err.message : String(err) || "Unknown error",
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
}
|
package/src/commands.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Registers /unipi:readme [package], /unipi:changelog, /unipi:updater-settings
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
7
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
|
8
8
|
import { UNIPI_PREFIX, UPDATER_COMMANDS } from "@pi-unipi/core";
|
|
9
9
|
import { renderReadmeOverlay } from "./tui/readme-overlay.js";
|
|
10
10
|
import { renderChangelogOverlay } from "./tui/changelog-overlay.js";
|
|
@@ -14,9 +14,9 @@ import { renderSettingsOverlay } from "./tui/settings-overlay.js";
|
|
|
14
14
|
const OVERLAY_OPTIONS = {
|
|
15
15
|
overlay: true,
|
|
16
16
|
overlayOptions: {
|
|
17
|
-
width: "80%",
|
|
17
|
+
width: "80%" as const,
|
|
18
18
|
minWidth: 60,
|
|
19
|
-
anchor: "center",
|
|
19
|
+
anchor: "center" as const,
|
|
20
20
|
margin: 2,
|
|
21
21
|
},
|
|
22
22
|
};
|
|
@@ -28,7 +28,7 @@ export function registerCommands(pi: ExtensionAPI): void {
|
|
|
28
28
|
`${UNIPI_PREFIX}${UPDATER_COMMANDS.README}`,
|
|
29
29
|
{
|
|
30
30
|
description: "Browse package README files",
|
|
31
|
-
handler: async (args: string, ctx:
|
|
31
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
32
32
|
const packageName = args.trim() || undefined;
|
|
33
33
|
try {
|
|
34
34
|
await ctx.ui.custom(
|
|
@@ -47,7 +47,7 @@ export function registerCommands(pi: ExtensionAPI): void {
|
|
|
47
47
|
`${UNIPI_PREFIX}${UPDATER_COMMANDS.CHANGELOG}`,
|
|
48
48
|
{
|
|
49
49
|
description: "Browse changelog (Keep a Changelog format)",
|
|
50
|
-
handler: async (_args: string, ctx:
|
|
50
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
51
51
|
try {
|
|
52
52
|
await ctx.ui.custom(
|
|
53
53
|
renderChangelogOverlay(),
|
|
@@ -65,7 +65,7 @@ export function registerCommands(pi: ExtensionAPI): void {
|
|
|
65
65
|
`${UNIPI_PREFIX}${UPDATER_COMMANDS.UPDATER_SETTINGS}`,
|
|
66
66
|
{
|
|
67
67
|
description: "Configure updater — check interval and auto-update mode",
|
|
68
|
-
handler: async (_args: string, ctx:
|
|
68
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
69
69
|
try {
|
|
70
70
|
const result = await ctx.ui.custom(
|
|
71
71
|
renderSettingsOverlay(),
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
UNIPI_PREFIX,
|
|
17
17
|
emitEvent,
|
|
18
18
|
getPackageVersion,
|
|
19
|
+
type UnipiUpdateCheckEvent,
|
|
19
20
|
} from "@pi-unipi/core";
|
|
20
21
|
import { registerCommands } from "./commands.js";
|
|
21
22
|
import { loadConfig } from "./settings.js";
|
|
@@ -41,7 +42,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
41
42
|
// Session lifecycle — check for updates and announce module
|
|
42
43
|
pi.on("session_start", async (_event, ctx) => {
|
|
43
44
|
// Emit MODULE_READY
|
|
44
|
-
emitEvent(pi
|
|
45
|
+
emitEvent(pi, UNIPI_EVENTS.MODULE_READY, {
|
|
45
46
|
name: MODULES.UPDATER,
|
|
46
47
|
version: VERSION,
|
|
47
48
|
commands: [
|
|
@@ -53,7 +54,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
53
54
|
});
|
|
54
55
|
|
|
55
56
|
// Register info-screen group
|
|
56
|
-
const infoRegistry =
|
|
57
|
+
const infoRegistry = globalThis.__unipi_info_registry;
|
|
57
58
|
if (infoRegistry) {
|
|
58
59
|
let cachedResult: { currentVersion: string; latestVersion: string; updateAvailable: boolean; lastCheck: string } | null = null;
|
|
59
60
|
|
|
@@ -90,34 +91,35 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
90
91
|
});
|
|
91
92
|
|
|
92
93
|
// Subscribe to events to update cached data
|
|
93
|
-
pi.events.on(UNIPI_EVENTS.UPDATE_CHECK, (
|
|
94
|
+
pi.events.on(UNIPI_EVENTS.UPDATE_CHECK, (data) => {
|
|
95
|
+
const payload = data as UnipiUpdateCheckEvent;
|
|
94
96
|
cachedResult = {
|
|
95
97
|
currentVersion: payload.currentVersion,
|
|
96
98
|
latestVersion: payload.latestVersion,
|
|
97
99
|
updateAvailable: payload.updateAvailable,
|
|
98
100
|
lastCheck: new Date().toLocaleTimeString(),
|
|
99
101
|
};
|
|
100
|
-
emitEvent(pi
|
|
102
|
+
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
101
103
|
groupId: "updater",
|
|
102
104
|
keys: ["current", "latest", "status", "lastCheck"],
|
|
103
105
|
});
|
|
104
106
|
});
|
|
105
107
|
|
|
106
|
-
pi.events.on(UNIPI_EVENTS.UPDATE_AVAILABLE, (
|
|
108
|
+
pi.events.on(UNIPI_EVENTS.UPDATE_AVAILABLE, (_data: unknown) => {
|
|
107
109
|
if (cachedResult) {
|
|
108
110
|
cachedResult.updateAvailable = true;
|
|
109
111
|
}
|
|
110
|
-
emitEvent(pi
|
|
112
|
+
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
111
113
|
groupId: "updater",
|
|
112
114
|
keys: ["status"],
|
|
113
115
|
});
|
|
114
116
|
});
|
|
115
117
|
|
|
116
|
-
pi.events.on(UNIPI_EVENTS.UPDATE_APPLIED, (
|
|
118
|
+
pi.events.on(UNIPI_EVENTS.UPDATE_APPLIED, (_data: unknown) => {
|
|
117
119
|
if (cachedResult) {
|
|
118
120
|
cachedResult.updateAvailable = false;
|
|
119
121
|
}
|
|
120
|
-
emitEvent(pi
|
|
122
|
+
emitEvent(pi, UNIPI_EVENTS.INFO_DATA_UPDATED, {
|
|
121
123
|
groupId: "updater",
|
|
122
124
|
keys: ["status"],
|
|
123
125
|
});
|
|
@@ -132,7 +134,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
132
134
|
const result = await checkForUpdates();
|
|
133
135
|
|
|
134
136
|
// Emit check event
|
|
135
|
-
emitEvent(pi
|
|
137
|
+
emitEvent(pi, UNIPI_EVENTS.UPDATE_CHECK, result);
|
|
136
138
|
|
|
137
139
|
if (!result.updateAvailable || result.error) return;
|
|
138
140
|
|
|
@@ -140,7 +142,7 @@ export default function updaterExtension(pi: ExtensionAPI): void {
|
|
|
140
142
|
if (isVersionSkipped(result.latestVersion)) return;
|
|
141
143
|
|
|
142
144
|
// Emit available event
|
|
143
|
-
emitEvent(pi
|
|
145
|
+
emitEvent(pi, UNIPI_EVENTS.UPDATE_AVAILABLE, {
|
|
144
146
|
currentVersion: result.currentVersion,
|
|
145
147
|
latestVersion: result.latestVersion,
|
|
146
148
|
});
|
package/src/installer.ts
CHANGED
|
@@ -52,8 +52,11 @@ export async function installUpdate(
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
return result;
|
|
55
|
-
} catch (err:
|
|
56
|
-
const errorMessage = err
|
|
55
|
+
} catch (err: unknown) {
|
|
56
|
+
const errorMessage = (err instanceof Error && 'stderr' in err ? String((err as Error & { stderr?: string }).stderr) : undefined)
|
|
57
|
+
|| (err instanceof Error ? err.message : undefined)
|
|
58
|
+
|| String(err)
|
|
59
|
+
|| "Unknown install error";
|
|
57
60
|
|
|
58
61
|
// Emit error event
|
|
59
62
|
if (pi) {
|
|
@@ -39,9 +39,9 @@ function padVisible(content: string, targetWidth: number): string {
|
|
|
39
39
|
*/
|
|
40
40
|
export function renderChangelogOverlay() {
|
|
41
41
|
return (
|
|
42
|
-
tui:
|
|
42
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
43
43
|
theme: Theme,
|
|
44
|
-
_kb:
|
|
44
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
45
45
|
done: (result: { viewed: boolean } | null) => void,
|
|
46
46
|
) => {
|
|
47
47
|
const installedVersion = getInstalledPackageVersion(
|
|
@@ -38,9 +38,9 @@ function padVisible(content: string, targetWidth: number): string {
|
|
|
38
38
|
*/
|
|
39
39
|
export function renderReadmeOverlay(params?: { openDirect?: string }) {
|
|
40
40
|
return (
|
|
41
|
-
tui:
|
|
41
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
42
42
|
theme: Theme,
|
|
43
|
-
_kb:
|
|
43
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
44
44
|
done: (result: { viewed: boolean } | null) => void,
|
|
45
45
|
) => {
|
|
46
46
|
const state: ReadmeState = {
|
|
@@ -61,7 +61,7 @@ export function renderReadmeOverlay(params?: { openDirect?: string }) {
|
|
|
61
61
|
const readmePath = resolveReadmePath(params.openDirect);
|
|
62
62
|
if (readmePath) {
|
|
63
63
|
const content = readFileSync(readmePath, "utf-8");
|
|
64
|
-
state.contentLines = renderMarkdown(content, (tui.
|
|
64
|
+
state.contentLines = renderMarkdown(content, (tui.terminal?.columns ?? 80) - 4, theme);
|
|
65
65
|
state.view = "content";
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -203,7 +203,7 @@ export function renderReadmeOverlay(params?: { openDirect?: string }) {
|
|
|
203
203
|
const entry = state.entries[state.listIndex]!;
|
|
204
204
|
try {
|
|
205
205
|
const content = readFileSync(entry.path, "utf-8");
|
|
206
|
-
state.contentLines = renderMarkdown(content, (tui.
|
|
206
|
+
state.contentLines = renderMarkdown(content, (tui.terminal?.columns ?? 80) - 4, theme);
|
|
207
207
|
state.contentScroll = 0;
|
|
208
208
|
state.view = "content";
|
|
209
209
|
} catch {
|
|
@@ -42,9 +42,9 @@ function trunc(text: string, width: number): string {
|
|
|
42
42
|
*/
|
|
43
43
|
export function renderSettingsOverlay() {
|
|
44
44
|
return (
|
|
45
|
-
tui:
|
|
46
|
-
_theme:
|
|
47
|
-
_kb:
|
|
45
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
46
|
+
_theme: import("@mariozechner/pi-coding-agent").Theme,
|
|
47
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
48
48
|
done: (result: { saved: boolean } | null) => void,
|
|
49
49
|
) => {
|
|
50
50
|
const state = {
|
|
@@ -41,9 +41,9 @@ interface UpdateState {
|
|
|
41
41
|
*/
|
|
42
42
|
export function renderUpdateOverlay(checkResult: UpdateCheckResult) {
|
|
43
43
|
return (
|
|
44
|
-
tui:
|
|
44
|
+
tui: import("@mariozechner/pi-tui").TUI,
|
|
45
45
|
theme: Theme,
|
|
46
|
-
_kb:
|
|
46
|
+
_kb: import("@mariozechner/pi-coding-agent").KeybindingsManager,
|
|
47
47
|
done: (result: { updated: boolean } | null) => void,
|
|
48
48
|
) => {
|
|
49
49
|
const config = loadConfig();
|
|
@@ -66,7 +66,7 @@ export function renderUpdateOverlay(checkResult: UpdateCheckResult) {
|
|
|
66
66
|
: `${theme.bold(entry.version)} — ${theme.fg("muted", "Unreleased")}`;
|
|
67
67
|
contentLines.push(` ${title}`);
|
|
68
68
|
// Use markdown renderer for the body content
|
|
69
|
-
const bodyLines = renderMarkdown(entry.body, (tui.
|
|
69
|
+
const bodyLines = renderMarkdown(entry.body, (tui.terminal?.columns ?? 80) - 6, theme);
|
|
70
70
|
for (const line of bodyLines) {
|
|
71
71
|
contentLines.push(` ${line}`);
|
|
72
72
|
}
|