Skip to content

Commit

Permalink
fix(forge): workspace() returns leaf packages only
Browse files Browse the repository at this point in the history
  • Loading branch information
tugrulates committed Feb 28, 2025
1 parent 5d290c0 commit 7f9458d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 31 deletions.
1 change: 0 additions & 1 deletion tool/forge/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { resolve } from "@std/path/resolve";

async function filter(packages: string[]) {
return (await workspace())
.filter((pkg) => pkg.directory !== ".")
.filter((pkg) =>
packages.length === 0 ||
packages.includes(pkg.module) ||
Expand Down
22 changes: 8 additions & 14 deletions tool/forge/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ Deno.test("packageInfo() returns update at initial version", async () => {
});
});

Deno.test("workspace() returns non-workspace package", async () => {
Deno.test("workspace() returns simple package", async () => {
await using directory = await tempDirectory();
await createPackage(directory.path(), { name: "name", version: "version" });
const packages = await workspace({ directories: [directory.path()] });
Expand All @@ -285,12 +285,9 @@ Deno.test("workspace() returns non-workspace package", async () => {
}]);
});

Deno.test("workspace() returns workspace packages", async () => {
Deno.test("workspace() returns monorepo packages", async () => {
await using directory = await tempDirectory();
const root = await createPackage(directory.path(), {
name: "root",
workspace: ["./first", "./second"],
});
await createPackage(directory.path(), { workspace: ["./first", "./second"] });
const pkg1 = await createPackage(directory.path("first"), {
name: "first",
version: "first_version",
Expand All @@ -300,24 +297,21 @@ Deno.test("workspace() returns workspace packages", async () => {
version: "second_version",
});
const packages = await workspace({ directories: [directory.path()] });
assertEquals(packages, [root, pkg1, pkg2]);
assertEquals(packages, [pkg1, pkg2]);
});

Deno.test("workspace() returns nested workspace packages", async () => {
Deno.test("workspace() does not return nested workspace packages", async () => {
await using directory = await tempDirectory();
const root = await createPackage(directory.path(), {
name: "root",
workspace: ["./first"],
});
await createPackage(directory.path(), { workspace: ["./first"] });
const pkg1 = await createPackage(directory.path("first"), {
name: "first",
version: "first_version",
workspace: ["./second"],
});
const pkg2 = await createPackage(directory.path("first", "second"), {
await createPackage(directory.path("first", "second"), {
name: "second",
version: "second_version",
});
const packages = await workspace({ directories: [directory.path()] });
assertEquals(packages, [root, pkg1, pkg2]);
assertEquals(packages, [pkg1]);
});
30 changes: 14 additions & 16 deletions tool/forge/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,31 +186,29 @@ export async function packageInfo(options?: PackageOptions): Promise<Package> {
}

/**
* Returns all packages, recursively traversing workspaces.
* Returns all packages for a workspace.
*
* If a directory is a monorepo, distinguished with the `workspace` field in
* its configuration, this function will return all packages in that monorepo,
* excluding its root. If the directory is not a monorepo, the function will
* return the package in the directory.
*
* @todo Skip root.
* @todo Add a name filter.
*/
export async function workspace(
options?: WorkspaceOptions,
): Promise<Package[]> {
const directories = options?.directories ?? ["."];
const packages = await Promise.all(
directories?.map((directory) => packageInfo({ directory, ...options })),
directories?.map(async (directory) => {
const pkg = await packageInfo({ directory, ...options });
if (pkg.config.workspace === undefined) return pkg;
return await Promise.all(pkg.config.workspace.map(async (child) => {
return await packageInfo({ directory: join(pkg.directory, child) });
}));
}),
);
const all = (await Promise.all(
packages.map(async (pkg) => [
pkg,
...await workspace({
...options,
directories: pkg.config.workspace?.map((child) =>
join(pkg.directory, child)
) ??
[],
}),
]),
)).flat();
return distinctBy(all, (pkg) => pkg.directory);
return distinctBy(packages.flat(), (pkg) => pkg.directory);
}

async function readConfig(directory: string): Promise<Config> {
Expand Down

0 comments on commit 7f9458d

Please sign in to comment.