@danypops/pi-packed 0.22.4 → 0.22.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-packed",
3
- "version": "0.22.4",
3
+ "version": "0.22.6",
4
4
  "description": "Pi package lifecycle, validation, daemon, tools, profiles, and TUI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  "@danypops/packed": "^0.7.0",
32
32
  "@danypops/pi-extension-harness": "^0.7.0",
33
33
  "@danypops/vehicle-client": "^0.8.1",
34
- "@danypops/vehicle-client-pi": "^0.31.2",
34
+ "@danypops/vehicle-client-pi": "^0.39.0",
35
35
  "@danypops/vehicle-core": "^0.15.0",
36
36
  "@danypops/vehicle-server": "^0.22.0",
37
37
  "jiti": "^2.7.0",
@@ -9,12 +9,18 @@ import {
9
9
  } from "@danypops/vehicle-server/daemon";
10
10
  import { ensureAuthToken } from "@danypops/vehicle-server/paths";
11
11
  import { captureLoadedModules, checkModuleFreshnessAll, ownRuntimeDependencyNames } from "../adoption/module-freshness.ts";
12
- import { type DaemonServiceInstaller, PACKED_VEHICLE_NAME, RealDaemonServiceInstaller, reconcileAllDaemonServices } from "./daemon-service.ts";
12
+ import {
13
+ type DaemonServiceInstaller,
14
+ listManagedPackages,
15
+ PACKED_VEHICLE_NAME,
16
+ RealDaemonServiceInstaller,
17
+ reconcileAllDaemonServices,
18
+ } from "./daemon-service.ts";
13
19
  import { generateIndex, indexPath, indexStatus } from "../index/build-index.ts";
14
20
  import { catalogStatus, syncCatalog } from "../packages/catalog.ts";
15
21
  import { latestVersion, openDb } from "../packages/db.ts";
16
22
  import { ExecInstaller } from "../packages/install.ts";
17
- import { defaultPiHome, readInstalledPackages } from "../packages/installed.ts";
23
+ import { defaultPiHome } from "../packages/installed.ts";
18
24
  import type { Installer, Registry } from "../packages/package.ts";
19
25
  import { HttpRegistry } from "../registry/registry.ts";
20
26
  import {
@@ -87,7 +93,10 @@ export function daemonOptions(options: StartPackedDaemonOptions): StartDaemonOpt
87
93
  name: "package-update-check",
88
94
  intervalMs: envMs(ENV.WATCH_SECS, WATCH_INTERVAL_DEFAULT_MS),
89
95
  run: async () => {
90
- const updates = checkUpdates((name) => latestVersion(database, name), readInstalledPackages(piHome));
96
+ // listManagedPackages(), not readInstalledPackages() -- also catches a physically
97
+ // installed daemon-dependency that isn't itself pi:-configured (e.g. papyrus via
98
+ // pi-papyrus). readInstalledPackages() alone silently missed every such stale package.
99
+ const updates = checkUpdates((name) => latestVersion(database, name), listManagedPackages(piHome));
91
100
  await saveUpdates(paths.stateDirectory, { checkedAt: new Date().toISOString(), updates });
92
101
  },
93
102
  },
@@ -11,9 +11,11 @@ import {
11
11
  RealDaemonServiceInstaller,
12
12
  reconcileAllDaemonServices,
13
13
  } from "../src/daemon/daemon-service.ts";
14
+ import { openDb, replaceAll } from "../src/packages/db.ts";
14
15
  import type { Installer, Registry } from "../src/packages/package.ts";
15
16
  import { RECONCILE_INTERVAL_DEFAULT_MS } from "../src/shared/constants.ts";
16
17
  import { resolvePackedPaths } from "../src/shared/paths.ts";
18
+ import { loadUpdates } from "../src/daemon/watcher.ts";
17
19
 
18
20
  const roots: string[] = [];
19
21
  afterEach(() => {
@@ -57,6 +59,24 @@ function installMockDaemon(piHome: string, name: string): void {
57
59
  writeFileSync(join(directory, "cli.ts"), "// Mock Vehicle entry point; Armada's test controller never executes it.\n");
58
60
  }
59
61
 
62
+ /** A Vehicle-shaped daemon-dependency (real bin + vehicle-server dependency), not declared in
63
+ * settings.json's packages[] -- e.g. papyrus, resolved only via pi-papyrus. */
64
+ function installUnconfiguredDaemonDependency(piHome: string, name: string, version: string): void {
65
+ const directory = join(piHome, "npm", "node_modules", name);
66
+ mkdirSync(directory, { recursive: true });
67
+ writeFileSync(
68
+ join(directory, "package.json"),
69
+ JSON.stringify({ name, version, bin: { probe: "cli.ts" }, dependencies: { "@danypops/vehicle-server": "^0.1.0" } }),
70
+ );
71
+ writeFileSync(join(directory, "cli.ts"), "// Mock Vehicle entry point.\n");
72
+ }
73
+
74
+ function installConfiguredExtension(piHome: string, name: string, version: string): void {
75
+ const directory = join(piHome, "npm", "node_modules", name);
76
+ mkdirSync(directory, { recursive: true });
77
+ writeFileSync(join(directory, "package.json"), JSON.stringify({ name, version }));
78
+ }
79
+
60
80
  const registry: Registry = {
61
81
  async search() {
62
82
  return { total: 0, results: [] };
@@ -252,4 +272,40 @@ describe("startPackedDaemon's own maintenance-task wiring (self-heals Vehicle dr
252
272
  await harness.dispose();
253
273
  }
254
274
  });
275
+
276
+ describe("package-update-check (feeds package.updates / pkg_updates)", () => {
277
+ it("reports a stale pi:-configured extension", async () => {
278
+ const piHome = fakePiHome(["npm:@danypops/probe-ext"]);
279
+ installConfiguredExtension(piHome, "@danypops/probe-ext", "1.0.0");
280
+ const paths = fakePaths();
281
+ const db = openDb(paths.database);
282
+ replaceAll(db, [{ name: "@danypops/probe-ext", version: "2.0.0" }], "test");
283
+ db.close();
284
+
285
+ const options = daemonOptions({ paths, reg: registry, inst: installer, piHome });
286
+ const task = options.maintenanceTasks?.find((t) => t.name === "package-update-check");
287
+ expect(task).toBeDefined();
288
+ await task?.run();
289
+
290
+ const snapshot = await loadUpdates(paths.stateDirectory);
291
+ expect(snapshot?.updates.map((u) => u.name)).toContain("@danypops/probe-ext");
292
+ });
293
+
294
+ it("also reports a stale daemon-dependency package (e.g. papyrus via pi-papyrus)", async () => {
295
+ const piHome = fakePiHome([]); // deliberately NOT declaring probe-daemon in settings.json
296
+ installUnconfiguredDaemonDependency(piHome, "@danypops/probe-daemon", "1.0.0");
297
+ const paths = fakePaths();
298
+ const db = openDb(paths.database);
299
+ replaceAll(db, [{ name: "@danypops/probe-daemon", version: "9.9.9" }], "test");
300
+ db.close();
301
+
302
+ const options = daemonOptions({ paths, reg: registry, inst: installer, piHome });
303
+ const task = options.maintenanceTasks?.find((t) => t.name === "package-update-check");
304
+ expect(task).toBeDefined();
305
+ await task?.run();
306
+
307
+ const snapshot = await loadUpdates(paths.stateDirectory);
308
+ expect(snapshot?.updates.map((u) => u.name)).toContain("@danypops/probe-daemon");
309
+ });
310
+ });
255
311
  });