@akanjs/devkit 3.0.0-beta.15 → 3.0.0-beta.16
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/executors.ts +5 -0
- package/package.json +5 -2
- package/piDependencyPins.test.ts +55 -0
- package/types.ts +1 -0
package/executors.ts
CHANGED
|
@@ -1832,6 +1832,11 @@ export class PkgExecutor extends Executor {
|
|
|
1832
1832
|
};
|
|
1833
1833
|
const rootVersion = rootDeps[dep];
|
|
1834
1834
|
if (rootVersion) return rootVersion;
|
|
1835
|
+
// A transitive dependency the workspace pins rather than imports is only ever written as an override, and
|
|
1836
|
+
// that pin has to reach the published package: neither an override nor a dependency's own shrinkwrap is
|
|
1837
|
+
// applied to a consumer's install, so the version has to be a dependency of what we publish.
|
|
1838
|
+
const overrideVersion = rootPackageJson.overrides?.[dep];
|
|
1839
|
+
if (typeof overrideVersion === "string") return overrideVersion;
|
|
1835
1840
|
|
|
1836
1841
|
try {
|
|
1837
1842
|
const packageJsonPath = `pkgs/${dep}/package.json`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/devkit",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.16",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -39,11 +39,14 @@
|
|
|
39
39
|
"./*": "./*.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
+
"@earendil-works/pi-agent-core": "0.80.6",
|
|
43
|
+
"@earendil-works/pi-ai": "0.80.6",
|
|
42
44
|
"@earendil-works/pi-coding-agent": "0.80.6",
|
|
45
|
+
"@earendil-works/pi-tui": "0.80.6",
|
|
43
46
|
"@inquirer/prompts": "^8.4.3",
|
|
44
47
|
"@tailwindcss/node": "^4.3.0",
|
|
45
48
|
"@trapezedev/project": "^7.1.4",
|
|
46
|
-
"akanjs": "3.0.0-beta.
|
|
49
|
+
"akanjs": "3.0.0-beta.16",
|
|
47
50
|
"chalk": "^5.6.2",
|
|
48
51
|
"commander": "^14.0.3",
|
|
49
52
|
"dayjs": "^1.11.20",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import type { PackageJson } from "@akanjs/devkit/types";
|
|
4
|
+
|
|
5
|
+
// Guards the published dependency closure of the code agent, which the monorepo cannot exercise on its own.
|
|
6
|
+
//
|
|
7
|
+
// `@earendil-works/pi-coding-agent` asks for `^0.80.6` of its three sibling packages and ships an
|
|
8
|
+
// `npm-shrinkwrap.json` pinning them to the exact version it was built against. Bun reads neither that file nor
|
|
9
|
+
// this workspace's `overrides` when somebody installs the published CLI, so `^0.80.6` resolved to the newest
|
|
10
|
+
// 0.80.x — 0.80.10, which dropped `getOAuthApiKey` from `pi-ai/oauth` while the pinned coding agent still
|
|
11
|
+
// imports it. A global install died on its first import:
|
|
12
|
+
//
|
|
13
|
+
// Export named 'getOAuthApiKey' not found in module '.../@earendil-works/pi-ai/dist/oauth.js'.
|
|
14
|
+
//
|
|
15
|
+
// `PackageRunner` therefore re-declares pi's own pins as dependencies of what we publish; this keeps the two
|
|
16
|
+
// equal, so bumping the coding agent without moving the pins fails here rather than at a user's first run.
|
|
17
|
+
|
|
18
|
+
const repoRoot = path.resolve(import.meta.dir, "../../..");
|
|
19
|
+
const piName = "@earendil-works/pi-coding-agent";
|
|
20
|
+
const piDir = `${repoRoot}/node_modules/${piName}`;
|
|
21
|
+
const publishedPackages = ["pkgs/@akanjs/devkit/package.json", "pkgs/@akanjs/cli/package.json"];
|
|
22
|
+
|
|
23
|
+
interface Shrinkwrap {
|
|
24
|
+
packages: Record<string, { version?: string }>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const readJson = async <T>(file: string) => (await Bun.file(file).json()) as T;
|
|
28
|
+
|
|
29
|
+
const shrinkwrappedPins = async () => {
|
|
30
|
+
const { packages } = await readJson<Shrinkwrap>(`${piDir}/npm-shrinkwrap.json`);
|
|
31
|
+
const entries = Object.entries(packages)
|
|
32
|
+
.map(([key, entry]) => [key.replace(/^node_modules\//, ""), entry.version ?? ""] as const)
|
|
33
|
+
.filter(([name]) => name.startsWith("@earendil-works/"));
|
|
34
|
+
return Object.fromEntries(entries);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
describe("pi dependency pins", () => {
|
|
38
|
+
test("the shrinkwrap read here belongs to the coding agent we publish", async () => {
|
|
39
|
+
const installed = await readJson<PackageJson>(`${piDir}/package.json`);
|
|
40
|
+
for (const file of publishedPackages) {
|
|
41
|
+
const { dependencies = {} } = await readJson<PackageJson>(`${repoRoot}/${file}`);
|
|
42
|
+
expect({ file, [piName]: dependencies[piName] }).toEqual({ file, [piName]: installed.version });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("every sibling pi package is published at the version the coding agent shrinkwrapped", async () => {
|
|
47
|
+
const pins = await shrinkwrappedPins();
|
|
48
|
+
expect(Object.keys(pins).length).toBeGreaterThan(0);
|
|
49
|
+
for (const file of publishedPackages) {
|
|
50
|
+
const { dependencies = {} } = await readJson<PackageJson>(`${repoRoot}/${file}`);
|
|
51
|
+
const declared = Object.fromEntries(Object.keys(pins).map((name) => [name, dependencies[name]]));
|
|
52
|
+
expect({ file, ...declared }).toEqual({ file, ...pins });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
package/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface PackageJson {
|
|
|
10
10
|
peerDependencies?: Record<string, string>;
|
|
11
11
|
peerDependenciesMeta?: Record<string, { optional?: boolean }>;
|
|
12
12
|
optionalDependencies?: Record<string, string>;
|
|
13
|
+
overrides?: Record<string, string>;
|
|
13
14
|
engines?: Record<string, string>;
|
|
14
15
|
exports?: Record<string, string | Record<string, string>>;
|
|
15
16
|
bun?: {
|