Skip to content

Commit 8ca6ac7

Browse files
nam-hleclaude
andcommitted
feat: extract @nadle/project package from nadle core (#538)
Create @nadle/project (Layer 2) with project discovery, workspace scanning, and dependency resolution extracted from nadle core. Refactor nadle core to import from the new package. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7327f1a commit 8ca6ac7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1015
-559
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jobs:
6363
name: build-output
6464
path: |
6565
packages/kernel/lib
66+
packages/project/lib
6667
packages/nadle/lib
6768
packages/eslint-plugin/lib
6869
packages/create-nadle/lib
@@ -111,6 +112,9 @@ jobs:
111112
- name: Test kernel
112113
run: pnpm -F @nadle/kernel exec vitest run
113114

115+
- name: Test project
116+
run: pnpm -F @nadle/project exec vitest run
117+
114118
- name: Test nadle
115119
run: pnpm -F nadle exec vitest run
116120

packages/nadle/knip.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"$schema": "https://unpkg.com/knip@latest/schema.json",
33
"ignore": ["src/core/worker.ts", "src/core/file-logger.ts", "test/**", "nadle.config.ts"],
44
"ignoreBinaries": ["nadle"],
5-
"ignoreDependencies": ["@nadle/kernel"]
5+
"ignoreDependencies": ["@nadle/kernel", "@nadle/project"]
66
}

packages/nadle/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,12 @@
2323
"bin": "nadle.mjs",
2424
"types": "lib/index.d.ts",
2525
"dependencies": {
26-
"@manypkg/find-root": "^3.1.0",
27-
"@manypkg/tools": "^2.1.0",
2826
"@nadle/kernel": "workspace:*",
27+
"@nadle/project": "workspace:*",
2928
"consola": "^3.4.2",
3029
"execa": "^9.6.1",
3130
"fast-glob": "^3.3.3",
3231
"fastest-levenshtein": "^1.0.16",
33-
"find-up": "^8.0.0",
3432
"fuzzysort": "^3.1.0",
3533
"glob": "^11.1.0",
3634
"ink": "^6.5.1",

packages/nadle/src/core/engine/worker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import Path from "node:path";
22
import WorkerThreads from "node:worker_threads";
33

44
import c from "tinyrainbow";
5+
import { getWorkspaceById } from "@nadle/project";
56

67
import { Nadle } from "../nadle.js";
78
import { bindObject } from "../utilities/utils.js";
8-
import { Project } from "../models/project/project.js";
99
import { type RunnerContext } from "../interfaces/task.js";
1010
import { CacheValidator } from "../caching/cache-validator.js";
1111
import { type NadleResolvedOptions } from "../options/types.js";
@@ -40,7 +40,7 @@ export default async ({ port, taskId, options, env: originalEnv }: WorkerParams)
4040
const nadle = await getOrCreateNadle(options);
4141
const task = nadle.taskRegistry.getTaskById(taskId);
4242
const taskConfig = task.configResolver();
43-
const workspace = Project.getWorkspaceById(options.project, task.workspaceId);
43+
const workspace = getWorkspaceById(options.project, task.workspaceId);
4444
const workingDir = Path.resolve(workspace.absolutePath, taskConfig.workingDir ?? "");
4545

4646
const context: RunnerContext = {
@@ -68,7 +68,7 @@ interface CacheValidatorParams {
6868

6969
function createCacheValidator(nadle: Nadle, params: CacheValidatorParams) {
7070
const rootConfigFile = nadle.options.project.rootWorkspace.configFilePath;
71-
const workspace = Project.getWorkspaceById(nadle.options.project, params.workspaceId);
71+
const workspace = getWorkspaceById(nadle.options.project, params.workspaceId);
7272
const configFiles = workspace.configFilePath ? [rootConfigFile, workspace.configFilePath] : [rootConfigFile];
7373

7474
return new CacheValidator(params.taskId, params.taskConfig, {

packages/nadle/src/core/handlers/list-handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import c from "tinyrainbow";
22
import { groupBy } from "lodash-es";
3+
import { isRootWorkspaceId } from "@nadle/project";
34

45
import { BaseHandler } from "./base-handler.js";
56
import { DASH } from "../utilities/constants.js";
67
import { capitalize } from "../utilities/utils.js";
78
import { combineComparators } from "../utilities/comparator.js";
8-
import { RootWorkspace } from "../models/project/root-workspace.js";
99
import type { RegisteredTask } from "../interfaces/registered-task.js";
1010

1111
interface DescribedTask extends RegisteredTask {
@@ -69,7 +69,7 @@ export class ListHandler extends BaseHandler {
6969
]);
7070

7171
const taskComparator = combineComparators<DescribedTask>([
72-
(a, b) => Number(RootWorkspace.isRootWorkspaceId(b.workspaceId)) - Number(RootWorkspace.isRootWorkspaceId(a.workspaceId)),
72+
(a, b) => Number(isRootWorkspaceId(b.workspaceId)) - Number(isRootWorkspaceId(a.workspaceId)),
7373
(a, b) => a.label.localeCompare(b.label)
7474
]);
7575

packages/nadle/src/core/handlers/list-workspace-handler.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import c from "tinyrainbow";
2+
import { type Workspace, getAllWorkspaces, isRootWorkspaceId } from "@nadle/project";
23

34
import { BaseHandler } from "./base-handler.js";
45
import { highlight } from "../utilities/utils.js";
5-
import { Project } from "../models/project/project.js";
66
import { createTree } from "../utilities/create-tree.js";
77
import { StringBuilder } from "../utilities/string-builder.js";
8-
import { type Workspace } from "../models/project/workspace.js";
9-
import { RootWorkspace } from "../models/project/root-workspace.js";
108

119
export class ListWorkspacesHandler extends BaseHandler {
1210
public readonly name = "listWorkspaces";
@@ -17,7 +15,7 @@ export class ListWorkspacesHandler extends BaseHandler {
1715
}
1816

1917
public handle() {
20-
const workspaces = Project.getAllWorkspaces(this.context.options.project);
18+
const workspaces = getAllWorkspaces(this.context.options.project);
2119

2220
const parentWorkspaceMap = this.computeParentWorkspaceMap(workspaces);
2321
const childrenWorkspaceMap = Object.fromEntries(
@@ -31,7 +29,7 @@ export class ListWorkspacesHandler extends BaseHandler {
3129
(workspace) => childrenWorkspaceMap[workspace.id],
3230
(workspace) =>
3331
new StringBuilder()
34-
.add(RootWorkspace.isInstance(workspace) ? "Root workspace" : "Workspace")
32+
.add(isRootWorkspaceId(workspace.id) ? "Root workspace" : "Workspace")
3533
.add(highlight(workspace.id))
3634
.addIf(workspace.label !== workspace.id && workspace.label !== "", c.dim(`(alias: ${workspace.label})`))
3735
.build()
@@ -44,7 +42,7 @@ export class ListWorkspacesHandler extends BaseHandler {
4442
const parentWorkspaceMap: Record<string, Workspace | null> = {};
4543

4644
for (const childWorkspace of workspaces) {
47-
if (RootWorkspace.isInstance(childWorkspace)) {
45+
if (isRootWorkspaceId(childWorkspace.id)) {
4846
parentWorkspaceMap[childWorkspace.id] = null;
4947
continue;
5048
}
@@ -68,7 +66,7 @@ export class ListWorkspacesHandler extends BaseHandler {
6866
}
6967

7068
private isParentWorkspace(parentWorkspace: Workspace, childWorkspace: Workspace): boolean {
71-
if (RootWorkspace.isInstance(parentWorkspace)) {
69+
if (isRootWorkspaceId(parentWorkspace.id)) {
7270
return true;
7371
}
7472

packages/nadle/src/core/interfaces/defaults/default-file-reader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import Url from "node:url";
22

33
import { createJiti } from "jiti";
4+
import { SUPPORT_EXTENSIONS } from "@nadle/project";
45

56
import { type FileReader } from "../file-reader.js";
6-
import { SUPPORT_EXTENSIONS } from "../../utilities/constants.js";
77

88
export class DefaultFileReader implements FileReader {
99
private readonly reader = createJiti(import.meta.url, {

packages/nadle/src/core/models/project/alias-resolver.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

packages/nadle/src/core/models/project/dependency-resolver/base-dependency-resolver.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/nadle/src/core/models/project/dependency-resolver/index.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)