@danypops/pi-packed 0.1.0 → 0.2.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/src/watcher.ts CHANGED
@@ -5,10 +5,14 @@
5
5
  */
6
6
  import { writeFile, readFile, mkdir } from "node:fs/promises";
7
7
  import { join } from "node:path";
8
- import type { InstalledPkg, Registry, UpdateEntry, UpdatesSnapshot } from "./ports.ts";
8
+ import { UPDATES_FILE } from "./constants.ts";
9
+ import { createLogger } from "./log.ts";
10
+
11
+ const log = createLogger("watcher");
12
+ import type { InstalledPkg, UpdateEntry, UpdatesSnapshot } from "./ports.ts";
9
13
 
10
14
  function updatesPath(dir: string): string {
11
- return join(dir, "updates.json");
15
+ return join(dir, UPDATES_FILE);
12
16
  }
13
17
 
14
18
  export async function saveUpdates(dir: string, snap: UpdatesSnapshot): Promise<void> {
@@ -24,20 +28,18 @@ export async function loadUpdates(dir: string): Promise<UpdatesSnapshot | undefi
24
28
  }
25
29
  }
26
30
 
27
- /** Pure diff: drift = latest what we have (registry latest is authoritative). */
28
- export async function checkUpdates(reg: Registry, installed: InstalledPkg[]): Promise<UpdateEntry[]> {
31
+ /** Pure diff against the local mirror (apt list --upgradable semantics):
32
+ * drift = mirrored latest what we have. The mirror is refreshed by
33
+ * catalogSync; updates are computed offline, exactly like APT. */
34
+ export function checkUpdates(latestOf: (name: string) => string | undefined, installed: InstalledPkg[]): UpdateEntry[] {
29
35
  const now = new Date().toISOString();
30
36
  const updates: UpdateEntry[] = [];
31
37
  for (const p of installed) {
32
38
  const have = p.installed || p.pinned;
33
39
  if (!have) continue;
34
- try {
35
- const info = await reg.info(p.name);
36
- if (info.version && info.version !== have) {
37
- updates.push({ name: p.name, installed: have, latest: info.version, detectedAt: now });
38
- }
39
- } catch (e) {
40
- console.error(`updates: ${p.name}: ${e instanceof Error ? e.message : e}`);
40
+ const latest = latestOf(p.name);
41
+ if (latest && latest !== have) {
42
+ updates.push({ name: p.name, installed: have, latest, detectedAt: now });
41
43
  }
42
44
  }
43
45
  return updates;
@@ -50,16 +52,16 @@ export interface WatcherOptions {
50
52
 
51
53
  /** Producer loop: immediate check, then on a timer. Returns a stop function. */
52
54
  export function startWatcher(
53
- reg: Registry,
55
+ latestOf: (name: string) => string | undefined,
54
56
  stateDir: string,
55
57
  readInstalled: () => InstalledPkg[],
56
58
  opts: WatcherOptions,
57
59
  ): () => void {
58
60
  async function check(): Promise<void> {
59
61
  try {
60
- const updates = await checkUpdates(reg, readInstalled());
62
+ const updates = checkUpdates(latestOf, readInstalled());
61
63
  await saveUpdates(stateDir, { checkedAt: new Date().toISOString(), updates });
62
- if (updates.length > 0) console.error(`[packed] updates available: ${updates.length}`);
64
+ log.info("updates check", { updates: updates.length });
63
65
  } catch (e) {
64
66
  opts.onError?.(e);
65
67
  }