Skip to content

Commit 363893e

Browse files
committed
Updating the Nexical Core and eliminating rhe redundant projectRoot checks in the commands.
1 parent 8f8da30 commit 363893e

25 files changed

+111
-143
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"test:watch": "vitest"
1717
},
1818
"dependencies": {
19-
"@nexical/cli-core": "^0.1.8",
19+
"@nexical/cli-core": "^0.1.10",
2020
"yaml": "^2.3.4",
2121
"fast-glob": "^3.3.3"
2222
},
@@ -31,4 +31,4 @@
3131
"typescript": "^5.3.3",
3232
"vitest": "^4.0.15"
3333
}
34-
}
34+
}

src/commands/build.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,20 @@ export default class BuildCommand extends BaseCommand {
88
static requiresProject = true;
99

1010
async run(options: any) {
11-
if (!this.projectRoot) {
12-
this.error('Project root not found.');
13-
return;
14-
}
15-
16-
const siteDir = path.resolve(this.projectRoot, 'site');
11+
const projectRoot = this.projectRoot as string;
12+
const siteDir = path.resolve(projectRoot, 'site');
1713

1814
try {
19-
logger.debug(`Preparing environment at: ${this.projectRoot}`);
20-
await copyEnvironment(this.projectRoot);
15+
logger.debug(`Preparing environment at: ${projectRoot}`);
16+
await copyEnvironment(projectRoot);
2117
} catch (error: any) {
2218
this.error(error);
2319
return;
2420
}
2521

2622
this.info('Environment assembled. Running Astro build...');
2723

28-
const astroBin = path.join(this.projectRoot, 'node_modules', '.bin', 'astro');
24+
const astroBin = path.join(projectRoot, 'node_modules', '.bin', 'astro');
2925
logger.debug(`Using astro binary at: ${astroBin}`);
3026

3127
try {

src/commands/clean.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import path from 'path';
55
export default class CleanCommand extends BaseCommand {
66
static usage = 'clean';
77
static description = 'Clean project artifacts and caches.';
8+
static requiresProject = true;
89

910
async run(options: any) {
11+
const projectRoot = this.projectRoot as string;
1012
const coreDir = path.join('src', 'core');
1113

1214
// Core cleaning logic
@@ -22,7 +24,7 @@ export default class CleanCommand extends BaseCommand {
2224
];
2325

2426
for (const target of targets) {
25-
const targetPath = path.resolve(process.cwd(), target);
27+
const targetPath = path.resolve(projectRoot, target);
2628
logger.debug(`Checking clean target: ${targetPath}`);
2729
if (await fs.pathExists(targetPath)) {
2830
await fs.remove(targetPath);

src/commands/dev.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,14 @@ export default class DevCommand extends BaseCommand {
1010
static requiresProject = true;
1111

1212
async run(options: any) {
13-
if (!this.projectRoot) {
14-
this.error('Project root not found.');
15-
return;
16-
}
17-
18-
const siteDir = path.resolve(this.projectRoot, 'site');
13+
const projectRoot = this.projectRoot as string;
14+
const siteDir = path.resolve(projectRoot, 'site');
1915

2016
this.info('Initializing ephemeral build environment...');
2117

2218
try {
23-
logger.debug(`Preparing environment at: ${this.projectRoot}`);
24-
await linkEnvironment(this.projectRoot);
19+
logger.debug(`Preparing environment at: ${projectRoot}`);
20+
await linkEnvironment(projectRoot);
2521
} catch (error: any) {
2622
this.error(error);
2723
return;
@@ -37,7 +33,7 @@ export default class DevCommand extends BaseCommand {
3733

3834
this.success('Environment ready. Starting Astro...');
3935

40-
const astroBin = path.join(this.projectRoot, 'node_modules', '.bin', 'astro');
36+
const astroBin = path.join(projectRoot, 'node_modules', '.bin', 'astro');
4137
logger.debug(`Spawning astro dev from: ${astroBin} in ${siteDir}`);
4238

4339
const child = spawn(astroBin, ['dev'], {

src/commands/init.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import path from 'path';
77
export default class InitCommand extends BaseCommand {
88
static usage = 'init';
99
static description = 'Initialize a new Astrical project.';
10+
static requiresProject = false;
11+
1012
static args: CommandDefinition = {
1113
args: [
1214
{ name: 'directory', required: true, description: 'Directory to initialize the project in' }
@@ -20,8 +22,6 @@ export default class InitCommand extends BaseCommand {
2022
]
2123
};
2224

23-
static requiresProject = false;
24-
2525
async run(options: any) {
2626
const directory = options.directory;
2727
const targetPath = path.resolve(process.cwd(), directory);

src/commands/module/add.ts

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,9 @@ export default class ModuleAddCommand extends BaseCommand {
1919
private visited = new Set<string>();
2020

2121
async run(options: any) {
22-
logger.debug('ModuleAdd Options:', options);
22+
const projectRoot = this.projectRoot as string;
2323
let { url } = options;
2424

25-
if (!this.projectRoot) {
26-
this.error('Project root not found.');
27-
return;
28-
}
29-
3025
if (!url) {
3126
this.error('Please specify a repository URL.');
3227
return;
@@ -36,7 +31,7 @@ export default class ModuleAddCommand extends BaseCommand {
3631
await this.installModule(url);
3732

3833
this.info('Syncing workspace dependencies...');
39-
await runCommand('npm install', this.projectRoot);
34+
await runCommand('npm install', projectRoot);
4035

4136
this.success('All modules installed successfully.');
4237
} catch (e: any) {
@@ -45,35 +40,11 @@ export default class ModuleAddCommand extends BaseCommand {
4540
}
4641

4742
private async installModule(url: string) {
43+
const projectRoot = this.projectRoot as string;
44+
4845
// Resolve URL using utility
4946
url = resolveGitUrl(url);
5047

51-
// Subdirectory support: url.git//path/to/module
52-
// We need to handle this carefully. GIT SUBMODULES don't support partial checkout easily.
53-
// User requirements said: "Support the URL.git//path/to/module syntax. If detected, the 'Clone to Temp' step should perform a sparse checkout or copy only the specified subdirectory to the staging area."
54-
// BUT we are now using `git submodule add` for the final step.
55-
// `git submodule add` will add the WHOLE repo.
56-
// If the user wants a subdirectory, we might have a problem with 'git submodule add'.
57-
// However, the module system seems to rely on the folder structure.
58-
// If we strictly follow "Identity is Internal", we inspect module.yaml.
59-
// If the user provided a subdir, we find module.yaml THERE.
60-
// But `git submodule add` expects a repo URL.
61-
// We can't do sparse submodule add easily.
62-
// I will assume for Phase 1 that if a subdir is given, we warn or we add the whole repo but maybe name it differently?
63-
// Actually, let's look at the instruction: "Support the URL.git//path/to/module syntax... copy only the specified subdirectory to the staging area... Final Placement: Move the validated temporary folder to modules/[Canonical Name]."
64-
// WAIT. The PLAN was updated to use `git submodule add`.
65-
// If we use `git submodule add`, we cannot invoke "copy only subdirectory".
66-
// This is a conflict in requirements vs plan change.
67-
// Plan update said: "Inspect-then-Submodule".
68-
// If I detect a subdir, I can't `submodule add` just the subdir.
69-
// I will implement standard behavior: `submodule add` the specific repo.
70-
// If `//` is present, I'll extract the module name from THAT subdir's yaml during inspection,
71-
// BUT I have to submodule add the ROOT repo.
72-
// This effectively installs the whole repo.
73-
// To strictly support "only the subdirectory", I would have to use the original "Clone & Move" strategy (no submodule).
74-
// Since the user explicitly asked for "git submodule add" in the update, I must prioritize that.
75-
// I will `submodule add` the ROOT repo. I will read module.yaml from the subdir to get the name.
76-
7748
const [repoUrl, subPath] = url.split('.git//');
7849
const cleanUrl = subPath ? repoUrl + '.git' : url;
7950

@@ -86,7 +57,7 @@ export default class ModuleAddCommand extends BaseCommand {
8657
this.info(`Inspecting ${cleanUrl}...`);
8758

8859
// Stage 1: Inspect (Temp Clone)
89-
const stagingDir = path.resolve(this.projectRoot!, '.astrical', 'cache', `staging-${Date.now()}-${Math.random().toString(36).substring(7)}`);
60+
const stagingDir = path.resolve(projectRoot!, '.astrical', 'cache', `staging-${Date.now()}-${Math.random().toString(36).substring(7)}`);
9061
let moduleName = '';
9162
let dependencies: string[] = [];
9263

@@ -119,10 +90,6 @@ export default class ModuleAddCommand extends BaseCommand {
11990

12091
// Normalize dependencies to array if object (though spec says list of strings, defensiveness is good)
12192
if (dependencies && !Array.isArray(dependencies)) {
122-
// If it's an object/map, keys might be URLs? Spec: "map of String keys (Git URLs...)"
123-
// "Input Schema: Expect... dependencies property to be a map of String keys... with the value being the Git reference"
124-
// Example: dependencies: ["https://..."]. Wait, spec says "map of String keys" then example is ARRAY `["..."]`.
125-
// I will handle both Array and Object keys.
12693
dependencies = Object.keys(dependencies);
12794
}
12895

@@ -134,8 +101,8 @@ export default class ModuleAddCommand extends BaseCommand {
134101
}
135102

136103
// Stage 2: Conflict Detection
137-
const targetDir = path.join(this.projectRoot!, 'src', 'modules', moduleName);
138-
const relativeTargetDir = path.relative(this.projectRoot!, targetDir);
104+
const targetDir = path.join(projectRoot!, 'src', 'modules', moduleName);
105+
const relativeTargetDir = path.relative(projectRoot!, targetDir);
139106

140107
if (await fs.pathExists(targetDir)) {
141108
// Check origin
@@ -159,7 +126,7 @@ export default class ModuleAddCommand extends BaseCommand {
159126
// But the CONTENT will be the whole repo.
160127
// If the user meant to only have the subdir, we can't do that with submodule add easily without manual git plumbing.
161128
// Given instructions, I will proceed with submodule add of root repo to target dir.
162-
await runCommand(`git submodule add ${cleanUrl} ${relativeTargetDir}`, this.projectRoot!);
129+
await runCommand(`git submodule add ${cleanUrl} ${relativeTargetDir}`, projectRoot!);
163130
}
164131

165132
// Stage 4: Recurse

src/commands/module/init.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,15 @@ export default class ModuleInitCommand extends BaseCommand {
2424
};
2525

2626
async run(options: any) {
27+
const projectRoot = this.projectRoot as string;
2728
const { module_name, repo } = options;
2829

29-
if (!this.projectRoot) {
30-
this.error('Project root not found. Please run this command inside an Astrical project.');
31-
return;
32-
}
33-
34-
const modulesDir = path.join(this.projectRoot, 'src', 'modules');
30+
const modulesDir = path.join(projectRoot, 'src', 'modules');
3531
const targetDir = path.join(modulesDir, module_name);
3632

3733
if (await fs.pathExists(targetDir)) {
3834
if ((await fs.readdir(targetDir)).length > 0) {
3935
this.error(`Directory ${targetDir} is not empty.`);
40-
process.exit(1);
4136
}
4237
}
4338

@@ -77,7 +72,6 @@ export default class ModuleInitCommand extends BaseCommand {
7772
// Cleanup partial directory
7873
await fs.remove(targetDir);
7974
}
80-
process.exit(1);
8175
}
8276
}
8377

src/commands/module/list.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,8 @@ export default class ModuleListCommand extends BaseCommand {
88
static requiresProject = true;
99

1010
async run() {
11-
if (!this.projectRoot) {
12-
this.error('Project root not found.');
13-
return;
14-
}
15-
16-
const modulesDir = path.resolve(this.projectRoot, 'src', 'modules');
11+
const projectRoot = this.projectRoot as string;
12+
const modulesDir = path.resolve(projectRoot, 'src', 'modules');
1713
logger.debug(`Scanning for modules in: ${modulesDir}`);
1814

1915
if (!(await fs.pathExists(modulesDir))) {

src/commands/module/remove.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,11 @@ export default class ModuleRemoveCommand extends BaseCommand {
1414
};
1515

1616
async run(options: any) {
17-
logger.debug('ModuleRemove Options:', options);
17+
const projectRoot = this.projectRoot as string;
1818
let { name } = options;
1919

20-
if (!this.projectRoot) {
21-
this.error('Project root not found.');
22-
return;
23-
}
24-
2520
const relativePath = `src/modules/${name}`;
26-
const fullPath = path.resolve(this.projectRoot, relativePath);
21+
const fullPath = path.resolve(projectRoot, relativePath);
2722

2823
logger.debug('Removing module at:', fullPath);
2924

@@ -35,17 +30,17 @@ export default class ModuleRemoveCommand extends BaseCommand {
3530
this.info(`Removing module ${name}...`);
3631

3732
try {
38-
await runCommand(`git submodule deinit -f ${relativePath}`, this.projectRoot);
39-
await runCommand(`git rm -f ${relativePath}`, this.projectRoot);
33+
await runCommand(`git submodule deinit -f ${relativePath}`, projectRoot);
34+
await runCommand(`git rm -f ${relativePath}`, projectRoot);
4035

4136
// Clean up .git/modules
42-
const gitModulesDir = path.resolve(this.projectRoot, '.git', 'modules', 'src', 'modules', name);
37+
const gitModulesDir = path.resolve(projectRoot, '.git', 'modules', 'src', 'modules', name);
4338
if (await fs.pathExists(gitModulesDir)) {
4439
await fs.remove(gitModulesDir);
4540
}
4641

4742
this.info('Syncing workspace dependencies...');
48-
await runCommand('npm install', this.projectRoot);
43+
await runCommand('npm install', projectRoot);
4944

5045
this.success(`Module ${name} removed successfully.`);
5146
} catch (e: any) {

src/commands/module/update.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,16 @@ export default class ModuleUpdateCommand extends BaseCommand {
1414
};
1515

1616
async run(options: any) {
17-
logger.debug('ModuleUpdate Options:', options);
17+
const projectRoot = this.projectRoot as string;
1818
let { name } = options;
1919

20-
if (!this.projectRoot) {
21-
this.error('Project root not found.');
22-
return;
23-
}
24-
2520
this.info(name ? `Updating module ${name}...` : 'Updating all modules...');
26-
logger.debug('Update context:', { name, projectRoot: this.projectRoot });
21+
logger.debug('Update context:', { name, projectRoot: projectRoot });
2722

2823
try {
2924
if (name) {
3025
const relativePath = `src/modules/${name}`;
31-
const fullPath = path.resolve(this.projectRoot, relativePath);
26+
const fullPath = path.resolve(projectRoot, relativePath);
3227

3328
if (!(await fs.pathExists(fullPath))) {
3429
this.error(`Module ${name} not found.`);
@@ -38,14 +33,14 @@ export default class ModuleUpdateCommand extends BaseCommand {
3833
// Update specific module
3934
// We enter the directory and pull? Or generic submodule update?
4035
// Generic submodule update --remote src/modules/name
41-
await runCommand(`git submodule update --remote --merge ${relativePath}`, this.projectRoot);
36+
await runCommand(`git submodule update --remote --merge ${relativePath}`, projectRoot);
4237
} else {
4338
// Update all
44-
await runCommand('git submodule update --remote --merge', this.projectRoot);
39+
await runCommand('git submodule update --remote --merge', projectRoot);
4540
}
4641

4742
this.info('Syncing workspace dependencies...');
48-
await runCommand('npm install', this.projectRoot);
43+
await runCommand('npm install', projectRoot);
4944

5045
this.success('Modules updated successfully.');
5146
} catch (e: any) {

0 commit comments

Comments
 (0)