Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/core/src/frontend/ensure-buffer-dependency.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,36 @@ describe("ensureBufferDependency", () => {
expect(result?.added).toBe(false);
});

// #98: presence is not enough — an out-of-range version must be corrected.
it("should_update_buffer_when_the_declared_version_is_out_of_range", async () => {
const cwd = await scaffold({ name: "app", dependencies: { buffer: "^1.0.0" } });

const result = await ensureBufferDependency(cwd, "./frontend/src/contracts");

expect(result?.added).toBe(true);
const pkg = JSON.parse(await readFile(path.join(cwd, "frontend", "package.json"), "utf8"));
expect(pkg.dependencies.buffer).toBe("^6.0.3");
});

it("should_update_an_out_of_range_buffer_in_devDependencies_in_place", async () => {
const cwd = await scaffold({ name: "app", devDependencies: { buffer: "5.0.0" } });

const result = await ensureBufferDependency(cwd, "./frontend/src/contracts");

expect(result?.added).toBe(true);
const pkg = JSON.parse(await readFile(path.join(cwd, "frontend", "package.json"), "utf8"));
expect(pkg.devDependencies.buffer).toBe("^6.0.3");
expect(pkg.dependencies?.buffer).toBeUndefined();
});

it("should_be_a_noop_when_a_higher_in_range_version_is_declared", async () => {
const cwd = await scaffold({ name: "app", dependencies: { buffer: "^6.1.0" } });

const result = await ensureBufferDependency(cwd, "./frontend/src/contracts");

expect(result?.added).toBe(false);
});

it("should_return_undefined_when_no_package_json_is_found", async () => {
tmpDir = await mkdtemp(path.join(os.tmpdir(), "caatinga-buffer-dep-none-"));
await mkdir(path.join(tmpDir, "frontend", "src", "contracts"), { recursive: true });
Expand Down
22 changes: 20 additions & 2 deletions packages/core/src/frontend/ensure-buffer-dependency.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import semver from "semver";

// Backs the Buffer polyfill that every generated binding imports. Pinned to the
// same major the templates ship so behaviour matches across init and adoption.
Expand Down Expand Up @@ -75,8 +76,25 @@ export async function ensureBufferDependency(
return undefined;
}

if (pkg.dependencies?.buffer ?? pkg.devDependencies?.buffer) {
return { packageJsonPath, added: false };
const existing = pkg.dependencies?.buffer ?? pkg.devDependencies?.buffer;
if (existing) {
// #98: presence alone isn't enough — the templates pin `buffer` to a major
// (^6). If the declared range already resolves within the supported range,
// leave it; otherwise pin it, so a stale `buffer: "^1.0.0"` gets corrected
// instead of silently kept.
const minVersion = semver.minVersion(existing);
if (minVersion && semver.satisfies(minVersion, BUFFER_DEPENDENCY_RANGE)) {
return { packageJsonPath, added: false };
}

// Out of range (or unparseable) — update it in the section it already lives.
if (pkg.dependencies?.buffer) {
pkg.dependencies.buffer = BUFFER_DEPENDENCY_RANGE;
} else {
(pkg.devDependencies as Record<string, string>).buffer = BUFFER_DEPENDENCY_RANGE;
}
await writeFile(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf8");
return { packageJsonPath, added: true };
}

pkg.dependencies = { ...(pkg.dependencies ?? {}), buffer: BUFFER_DEPENDENCY_RANGE };
Expand Down