Skip to content
Merged
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
28 changes: 22 additions & 6 deletions apps/hub/src/builds/import-scan.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { readFile } from "node:fs/promises";
import { builtinModules } from "node:module";
import { dirname, join, relative, resolve } from "node:path";
import { type } from "arktype";
import { hasCode } from "@intx/types/has-code";
import { DEPENDENCY_FIELDS, Manifest } from "./package-install.ts";

const LOADERS: Record<string, "ts" | "tsx" | "js" | "jsx"> = {
Expand All @@ -25,11 +27,19 @@ const packageOf = (specifier: string) => {
};

async function manifest(path: string) {
let parsed: unknown;
try {
return Manifest.assert(JSON.parse(await readFile(path, "utf8")));
} catch {
return undefined;
parsed = JSON.parse(await readFile(path, "utf8"));
} catch (error) {
if (
(hasCode(error) && error.code === "ENOENT") ||
error instanceof SyntaxError
)
return undefined;
throw error;
}
const found = Manifest(parsed);
return found instanceof type.errors ? undefined : found;
}

const declared = (found: typeof Manifest.infer | undefined) => [
Expand All @@ -47,11 +57,17 @@ export async function undeclaredImports(workspace: string, path: string) {
if (!loader || relative(workspace, file).startsWith("..")) return undefined;
let imported: string[];
try {
const source = await readFile(file, "utf8");
imported = new Bun.Transpiler({ loader })
.scanImports(await readFile(file, "utf8"))
.scanImports(source)
.map((entry) => entry.path);
} catch {
// A file that does not parse yet has no imports to check; check-app says why.
} catch (error) {
const expected =
error instanceof BuildMessage ||
error instanceof AggregateError ||
(hasCode(error) && error.code === "ENOENT");
if (!expected) throw error;
// A file that does not parse yet, or was deleted mid-turn, has no imports to check; check-app says why.
return undefined;
}
let directory = dirname(file);
Expand Down
35 changes: 24 additions & 11 deletions apps/hub/src/builds/package-install.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { type } from "arktype";
import { hasCode } from "@intx/types/has-code";
import type { ToolCall, ToolResult, ToolRunner } from "@intx/types/runtime";
import {
PACKAGE_INSTALL_TOOL,
Expand Down Expand Up @@ -42,14 +43,21 @@ const Lockfile = type({ "workspaces?": type({ "[string]": Manifest }) });
/** The packages bun.lock records as installed for some package of the workspace. */
export async function installedPackages(workspace: string) {
const names = new Set<string>();
let lock: typeof Lockfile.infer;
let parsed: unknown;
try {
lock = Lockfile.assert(
Bun.JSONC.parse(await readFile(join(workspace, "bun.lock"), "utf8")),
parsed = Bun.JSONC.parse(
await readFile(join(workspace, "bun.lock"), "utf8"),
);
} catch {
return names;
} catch (error) {
if (
(hasCode(error) && error.code === "ENOENT") ||
error instanceof SyntaxError
)
return names;
throw error;
}
const lock = Lockfile(parsed);
if (lock instanceof type.errors) return names;
for (const manifest of Object.values(lock.workspaces ?? {}))
for (const field of DEPENDENCY_FIELDS)
for (const name of Object.keys(manifest[field] ?? {})) names.add(name);
Expand Down Expand Up @@ -89,14 +97,19 @@ export function createPackageGate(workspace: string, executor: ToolRunner) {
)
).flat();
for (const path of manifests) {
let manifest: typeof Manifest.infer;
let parsed: unknown;
try {
manifest = Manifest.assert(
JSON.parse(await readFile(join(workspace, path), "utf8")),
);
} catch {
continue;
parsed = JSON.parse(await readFile(join(workspace, path), "utf8"));
} catch (error) {
if (
(hasCode(error) && error.code === "ENOENT") ||
error instanceof SyntaxError
)
continue;
throw error;
}
const manifest = Manifest(parsed);
if (manifest instanceof type.errors) continue;
for (const field of DEPENDENCY_FIELDS)
for (const [name, spec] of Object.entries(manifest[field] ?? {}))
if (spec.startsWith("workspace:")) continue;
Expand Down
4 changes: 1 addition & 3 deletions apps/hub/src/builds/posix-child.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ export async function runHostGate(
outputLimited = false,
total = 0;
const stop = () => {
try {
child.kill("SIGKILL");
} catch {}
child.kill("SIGKILL");
};
const timer = setTimeout(() => {
timedOut = true;
Expand Down
Loading