@agiflowai/aicode-utils 1.0.15 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +86 -35
- package/dist/index.d.cts +297 -21
- package/dist/index.d.mts +297 -21
- package/dist/index.mjs +130 -79
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import * as path
|
|
3
|
-
import
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import nodePath from "node:path";
|
|
4
4
|
import * as fs from "node:fs/promises";
|
|
5
5
|
import { accessSync, mkdirSync, readFileSync, readFileSync as readFileSync$1, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import * as os from "node:os";
|
|
@@ -84,7 +84,7 @@ async function copy(src, dest) {
|
|
|
84
84
|
* Move a file or directory
|
|
85
85
|
*/
|
|
86
86
|
async function move(src, dest) {
|
|
87
|
-
await ensureDir(
|
|
87
|
+
await ensureDir(nodePath.dirname(dest));
|
|
88
88
|
await fs.rename(src, dest);
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
@@ -120,12 +120,12 @@ const cp = fs.cp;
|
|
|
120
120
|
|
|
121
121
|
//#endregion
|
|
122
122
|
//#region src/utils/logger.ts
|
|
123
|
-
const logsDir = path
|
|
123
|
+
const logsDir = path.join(os.tmpdir(), "scaffold-mcp-logs");
|
|
124
124
|
const logger = pino({
|
|
125
125
|
level: process.env.LOG_LEVEL || "debug",
|
|
126
126
|
timestamp: pino.stdTimeFunctions.isoTime
|
|
127
127
|
}, pino.destination({
|
|
128
|
-
dest: path
|
|
128
|
+
dest: path.join(logsDir, "scaffold-mcp.log"),
|
|
129
129
|
mkdir: true,
|
|
130
130
|
sync: true
|
|
131
131
|
}));
|
|
@@ -164,16 +164,41 @@ const log = {
|
|
|
164
164
|
var TemplatesManagerService = class TemplatesManagerService {
|
|
165
165
|
static SCAFFOLD_CONFIG_FILE = "scaffold.yaml";
|
|
166
166
|
static TEMPLATES_FOLDER = "templates";
|
|
167
|
+
static TOOLKIT_FOLDER = ".toolkit";
|
|
168
|
+
static SETTINGS_FILE = "settings.yaml";
|
|
169
|
+
static SETTINGS_LOCAL_FILE = "settings.local.yaml";
|
|
167
170
|
static TOOLKIT_CONFIG_FILE = "toolkit.yaml";
|
|
168
171
|
/**
|
|
172
|
+
* Recursively merge two plain objects. Primitive and array values in `local`
|
|
173
|
+
* replace those in `base`; plain-object values are merged recursively.
|
|
174
|
+
*/
|
|
175
|
+
static deepMerge(base, local) {
|
|
176
|
+
const result = { ...base };
|
|
177
|
+
for (const [key, localValue] of Object.entries(local)) {
|
|
178
|
+
const baseValue = result[key];
|
|
179
|
+
if (localValue !== null && typeof localValue === "object" && !Array.isArray(localValue) && baseValue !== null && typeof baseValue === "object" && !Array.isArray(baseValue)) result[key] = TemplatesManagerService.deepMerge(baseValue, localValue);
|
|
180
|
+
else result[key] = localValue;
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Deep-merge two ToolkitConfig objects. Plain-object values are merged
|
|
186
|
+
* recursively; primitives and arrays in `local` replace those in `base`.
|
|
187
|
+
* This allows settings.local.yaml to override a single leaf key (e.g.
|
|
188
|
+
* scaffold-mcp.mcp-serve.fallbackTool) without wiping sibling keys.
|
|
189
|
+
*/
|
|
190
|
+
static mergeToolkitConfigs(base, local) {
|
|
191
|
+
return TemplatesManagerService.deepMerge(base, local);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
169
194
|
* Find the templates directory by searching upwards from the starting path.
|
|
170
195
|
*
|
|
171
196
|
* Algorithm:
|
|
172
197
|
* 1. Start from the provided path (default: current working directory)
|
|
173
198
|
* 2. Search upwards to find the workspace root (where .git exists or filesystem root)
|
|
174
|
-
* 3.
|
|
175
|
-
* - If
|
|
176
|
-
* - If no, default to 'templates' folder in workspace root
|
|
199
|
+
* 3. Read toolkit config (checks .toolkit/settings.yaml, then toolkit.yaml)
|
|
200
|
+
* - If config has templatesPath, use it
|
|
201
|
+
* - If no config, default to 'templates' folder in workspace root
|
|
177
202
|
* 4. Verify the templates directory exists
|
|
178
203
|
*
|
|
179
204
|
* @param startPath - The path to start searching from (defaults to process.cwd())
|
|
@@ -181,18 +206,13 @@ var TemplatesManagerService = class TemplatesManagerService {
|
|
|
181
206
|
*/
|
|
182
207
|
static async findTemplatesPath(startPath = process.cwd()) {
|
|
183
208
|
const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
|
|
184
|
-
const
|
|
185
|
-
if (
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (config?.templatesPath) {
|
|
190
|
-
const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
|
|
191
|
-
if (await pathExists(templatesPath$1)) return templatesPath$1;
|
|
192
|
-
else return null;
|
|
193
|
-
}
|
|
209
|
+
const config = await TemplatesManagerService.readToolkitConfig(startPath);
|
|
210
|
+
if (config?.templatesPath) {
|
|
211
|
+
const templatesPath$1 = nodePath.isAbsolute(config.templatesPath) ? config.templatesPath : nodePath.join(workspaceRoot, config.templatesPath);
|
|
212
|
+
if (await pathExists(templatesPath$1)) return templatesPath$1;
|
|
213
|
+
return null;
|
|
194
214
|
}
|
|
195
|
-
const templatesPath =
|
|
215
|
+
const templatesPath = nodePath.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
|
|
196
216
|
if (await pathExists(templatesPath)) return templatesPath;
|
|
197
217
|
return null;
|
|
198
218
|
}
|
|
@@ -200,12 +220,12 @@ var TemplatesManagerService = class TemplatesManagerService {
|
|
|
200
220
|
* Find the workspace root by searching upwards for .git folder
|
|
201
221
|
*/
|
|
202
222
|
static async findWorkspaceRoot(startPath) {
|
|
203
|
-
let currentPath =
|
|
204
|
-
const rootPath =
|
|
223
|
+
let currentPath = nodePath.resolve(startPath);
|
|
224
|
+
const rootPath = nodePath.parse(currentPath).root;
|
|
205
225
|
while (true) {
|
|
206
|
-
if (await pathExists(
|
|
226
|
+
if (await pathExists(nodePath.join(currentPath, ".git"))) return currentPath;
|
|
207
227
|
if (currentPath === rootPath) return process.cwd();
|
|
208
|
-
currentPath =
|
|
228
|
+
currentPath = nodePath.dirname(currentPath);
|
|
209
229
|
}
|
|
210
230
|
}
|
|
211
231
|
/**
|
|
@@ -217,18 +237,13 @@ var TemplatesManagerService = class TemplatesManagerService {
|
|
|
217
237
|
*/
|
|
218
238
|
static findTemplatesPathSync(startPath = process.cwd()) {
|
|
219
239
|
const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
|
|
220
|
-
const
|
|
221
|
-
if (
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (config?.templatesPath) {
|
|
226
|
-
const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
|
|
227
|
-
if (pathExistsSync(templatesPath$1)) return templatesPath$1;
|
|
228
|
-
else return null;
|
|
229
|
-
}
|
|
240
|
+
const config = TemplatesManagerService.readToolkitConfigSync(startPath);
|
|
241
|
+
if (config?.templatesPath) {
|
|
242
|
+
const templatesPath$1 = nodePath.isAbsolute(config.templatesPath) ? config.templatesPath : nodePath.join(workspaceRoot, config.templatesPath);
|
|
243
|
+
if (pathExistsSync(templatesPath$1)) return templatesPath$1;
|
|
244
|
+
return null;
|
|
230
245
|
}
|
|
231
|
-
const templatesPath =
|
|
246
|
+
const templatesPath = nodePath.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
|
|
232
247
|
if (pathExistsSync(templatesPath)) return templatesPath;
|
|
233
248
|
return null;
|
|
234
249
|
}
|
|
@@ -236,12 +251,12 @@ var TemplatesManagerService = class TemplatesManagerService {
|
|
|
236
251
|
* Find the workspace root synchronously by searching upwards for .git folder
|
|
237
252
|
*/
|
|
238
253
|
static findWorkspaceRootSync(startPath) {
|
|
239
|
-
let currentPath =
|
|
240
|
-
const rootPath =
|
|
254
|
+
let currentPath = nodePath.resolve(startPath);
|
|
255
|
+
const rootPath = nodePath.parse(currentPath).root;
|
|
241
256
|
while (true) {
|
|
242
|
-
if (pathExistsSync(
|
|
257
|
+
if (pathExistsSync(nodePath.join(currentPath, ".git"))) return currentPath;
|
|
243
258
|
if (currentPath === rootPath) return process.cwd();
|
|
244
|
-
currentPath =
|
|
259
|
+
currentPath = nodePath.dirname(currentPath);
|
|
245
260
|
}
|
|
246
261
|
}
|
|
247
262
|
/**
|
|
@@ -267,44 +282,80 @@ var TemplatesManagerService = class TemplatesManagerService {
|
|
|
267
282
|
return TemplatesManagerService.TEMPLATES_FOLDER;
|
|
268
283
|
}
|
|
269
284
|
/**
|
|
270
|
-
* Read toolkit
|
|
285
|
+
* Read toolkit configuration from workspace root.
|
|
286
|
+
*
|
|
287
|
+
* Priority order:
|
|
288
|
+
* 1. .toolkit/settings.yaml (new location)
|
|
289
|
+
* 2. Shallow-merge .toolkit/settings.local.yaml over settings.yaml if present
|
|
290
|
+
* 3. Fallback to root toolkit.yaml (deprecated, backward-compat)
|
|
271
291
|
*
|
|
272
292
|
* @param startPath - The path to start searching from (defaults to process.cwd())
|
|
273
293
|
* @returns The toolkit configuration object or null if not found
|
|
274
294
|
*/
|
|
275
295
|
static async readToolkitConfig(startPath = process.cwd()) {
|
|
276
296
|
const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
|
|
277
|
-
const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
|
|
278
|
-
if (!await pathExists(toolkitConfigPath)) return null;
|
|
279
297
|
const yaml$1 = await import("js-yaml");
|
|
280
|
-
const
|
|
298
|
+
const toolkitFolder = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_FOLDER);
|
|
299
|
+
const settingsPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_FILE);
|
|
300
|
+
const settingsLocalPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_LOCAL_FILE);
|
|
301
|
+
if (await pathExists(settingsPath)) {
|
|
302
|
+
const baseContent = await fs.readFile(settingsPath, "utf-8");
|
|
303
|
+
const base = yaml$1.load(baseContent);
|
|
304
|
+
if (await pathExists(settingsLocalPath)) {
|
|
305
|
+
const localContent = await fs.readFile(settingsLocalPath, "utf-8");
|
|
306
|
+
const local = yaml$1.load(localContent);
|
|
307
|
+
return TemplatesManagerService.mergeToolkitConfigs(base, local);
|
|
308
|
+
}
|
|
309
|
+
return base;
|
|
310
|
+
}
|
|
311
|
+
const legacyConfigPath = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
|
|
312
|
+
if (!await pathExists(legacyConfigPath)) return null;
|
|
313
|
+
const content = await fs.readFile(legacyConfigPath, "utf-8");
|
|
281
314
|
return yaml$1.load(content);
|
|
282
315
|
}
|
|
283
316
|
/**
|
|
284
|
-
* Read toolkit
|
|
317
|
+
* Read toolkit configuration from workspace root (sync).
|
|
318
|
+
*
|
|
319
|
+
* Priority order:
|
|
320
|
+
* 1. .toolkit/settings.yaml (new location)
|
|
321
|
+
* 2. Shallow-merge .toolkit/settings.local.yaml over settings.yaml if present
|
|
322
|
+
* 3. Fallback to root toolkit.yaml (deprecated, backward-compat)
|
|
285
323
|
*
|
|
286
324
|
* @param startPath - The path to start searching from (defaults to process.cwd())
|
|
287
325
|
* @returns The toolkit configuration object or null if not found
|
|
288
326
|
*/
|
|
289
327
|
static readToolkitConfigSync(startPath = process.cwd()) {
|
|
290
328
|
const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
|
|
291
|
-
const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
|
|
292
|
-
if (!pathExistsSync(toolkitConfigPath)) return null;
|
|
293
329
|
const yaml$1 = __require("js-yaml");
|
|
294
|
-
const
|
|
295
|
-
|
|
330
|
+
const toolkitFolder = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_FOLDER);
|
|
331
|
+
const settingsPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_FILE);
|
|
332
|
+
const settingsLocalPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_LOCAL_FILE);
|
|
333
|
+
if (pathExistsSync(settingsPath)) {
|
|
334
|
+
const base = yaml$1.load(readFileSync$1(settingsPath, "utf-8"));
|
|
335
|
+
if (pathExistsSync(settingsLocalPath)) {
|
|
336
|
+
const local = yaml$1.load(readFileSync$1(settingsLocalPath, "utf-8"));
|
|
337
|
+
return TemplatesManagerService.mergeToolkitConfigs(base, local);
|
|
338
|
+
}
|
|
339
|
+
return base;
|
|
340
|
+
}
|
|
341
|
+
const legacyConfigPath = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
|
|
342
|
+
if (!pathExistsSync(legacyConfigPath)) return null;
|
|
343
|
+
return yaml$1.load(readFileSync$1(legacyConfigPath, "utf-8"));
|
|
296
344
|
}
|
|
297
345
|
/**
|
|
298
|
-
* Write toolkit
|
|
346
|
+
* Write toolkit configuration to .toolkit/settings.yaml.
|
|
347
|
+
* Creates the .toolkit directory if it does not exist.
|
|
299
348
|
*
|
|
300
349
|
* @param config - The toolkit configuration to write
|
|
301
350
|
* @param startPath - The path to start searching from (defaults to process.cwd())
|
|
302
351
|
*/
|
|
303
352
|
static async writeToolkitConfig(config, startPath = process.cwd()) {
|
|
304
353
|
const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
|
|
305
|
-
const
|
|
354
|
+
const toolkitFolder = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_FOLDER);
|
|
355
|
+
const settingsPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_FILE);
|
|
356
|
+
await fs.mkdir(toolkitFolder, { recursive: true });
|
|
306
357
|
const content = (await import("js-yaml")).dump(config, { indent: 2 });
|
|
307
|
-
await fs.writeFile(
|
|
358
|
+
await fs.writeFile(settingsPath, content, "utf-8");
|
|
308
359
|
}
|
|
309
360
|
/**
|
|
310
361
|
* Get the workspace root directory
|
|
@@ -373,13 +424,13 @@ var ProjectConfigResolver = class ProjectConfigResolver {
|
|
|
373
424
|
*/
|
|
374
425
|
static async resolveProjectConfig(projectPath, explicitTemplate) {
|
|
375
426
|
try {
|
|
376
|
-
const absolutePath =
|
|
427
|
+
const absolutePath = nodePath.resolve(projectPath);
|
|
377
428
|
if (explicitTemplate) return {
|
|
378
429
|
type: ProjectType.MONOLITH,
|
|
379
430
|
sourceTemplate: explicitTemplate,
|
|
380
431
|
configSource: ConfigSource.TOOLKIT_YAML
|
|
381
432
|
};
|
|
382
|
-
const projectJsonPath =
|
|
433
|
+
const projectJsonPath = nodePath.join(absolutePath, "project.json");
|
|
383
434
|
if (await pathExists(projectJsonPath)) {
|
|
384
435
|
const projectJson = await readJson(projectJsonPath);
|
|
385
436
|
if (projectJson.sourceTemplate && typeof projectJson.sourceTemplate === "string" && projectJson.sourceTemplate.trim()) return {
|
|
@@ -470,12 +521,12 @@ Run 'scaffold-mcp scaffold list --help' for more info.`;
|
|
|
470
521
|
* @param sourceTemplate - The template identifier
|
|
471
522
|
*/
|
|
472
523
|
static async createProjectJson(projectPath, projectName, sourceTemplate) {
|
|
473
|
-
const projectJsonPath =
|
|
524
|
+
const projectJsonPath = nodePath.join(projectPath, "project.json");
|
|
474
525
|
try {
|
|
475
526
|
let projectJson;
|
|
476
527
|
if (await pathExists(projectJsonPath)) projectJson = await readJson(projectJsonPath);
|
|
477
528
|
else {
|
|
478
|
-
const relativePath =
|
|
529
|
+
const relativePath = nodePath.relative(projectPath, process.cwd());
|
|
479
530
|
projectJson = {
|
|
480
531
|
name: projectName,
|
|
481
532
|
$schema: relativePath ? `${relativePath}/node_modules/nx/schemas/project-schema.json` : "node_modules/nx/schemas/project-schema.json",
|
|
@@ -527,15 +578,15 @@ var ProjectFinderService = class {
|
|
|
527
578
|
* @returns Project configuration or null if not found
|
|
528
579
|
*/
|
|
529
580
|
async findProjectForFile(filePath) {
|
|
530
|
-
const normalizedPath =
|
|
531
|
-
let currentDir =
|
|
581
|
+
const normalizedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.join(this.workspaceRoot, filePath);
|
|
582
|
+
let currentDir = nodePath.dirname(normalizedPath);
|
|
532
583
|
while (currentDir !== "/" && currentDir.startsWith(this.workspaceRoot)) {
|
|
533
|
-
const projectJsonPath =
|
|
584
|
+
const projectJsonPath = nodePath.join(currentDir, "project.json");
|
|
534
585
|
try {
|
|
535
586
|
const project = await this.loadProjectConfig(projectJsonPath);
|
|
536
587
|
if (project) return project;
|
|
537
588
|
} catch {}
|
|
538
|
-
currentDir =
|
|
589
|
+
currentDir = nodePath.dirname(currentDir);
|
|
539
590
|
}
|
|
540
591
|
return null;
|
|
541
592
|
}
|
|
@@ -546,15 +597,15 @@ var ProjectFinderService = class {
|
|
|
546
597
|
* @returns Project configuration or null if not found
|
|
547
598
|
*/
|
|
548
599
|
findProjectForFileSync(filePath) {
|
|
549
|
-
const normalizedPath =
|
|
550
|
-
let currentDir =
|
|
600
|
+
const normalizedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.join(this.workspaceRoot, filePath);
|
|
601
|
+
let currentDir = nodePath.dirname(normalizedPath);
|
|
551
602
|
while (currentDir !== "/" && currentDir.startsWith(this.workspaceRoot)) {
|
|
552
|
-
const projectJsonPath =
|
|
603
|
+
const projectJsonPath = nodePath.join(currentDir, "project.json");
|
|
553
604
|
try {
|
|
554
605
|
const project = this.loadProjectConfigSync(projectJsonPath);
|
|
555
606
|
if (project) return project;
|
|
556
607
|
} catch {}
|
|
557
|
-
currentDir =
|
|
608
|
+
currentDir = nodePath.dirname(currentDir);
|
|
558
609
|
}
|
|
559
610
|
return null;
|
|
560
611
|
}
|
|
@@ -567,8 +618,8 @@ var ProjectFinderService = class {
|
|
|
567
618
|
const content = await fs.readFile(projectJsonPath, "utf-8");
|
|
568
619
|
const config = JSON.parse(content);
|
|
569
620
|
const projectConfig = {
|
|
570
|
-
name: config.name ||
|
|
571
|
-
root:
|
|
621
|
+
name: config.name || nodePath.basename(nodePath.dirname(projectJsonPath)),
|
|
622
|
+
root: nodePath.dirname(projectJsonPath),
|
|
572
623
|
sourceTemplate: config.sourceTemplate,
|
|
573
624
|
projectType: config.projectType
|
|
574
625
|
};
|
|
@@ -587,8 +638,8 @@ var ProjectFinderService = class {
|
|
|
587
638
|
const content = readFileSync$1(projectJsonPath, "utf-8");
|
|
588
639
|
const config = JSON.parse(content);
|
|
589
640
|
const projectConfig = {
|
|
590
|
-
name: config.name ||
|
|
591
|
-
root:
|
|
641
|
+
name: config.name || nodePath.basename(nodePath.dirname(projectJsonPath)),
|
|
642
|
+
root: nodePath.dirname(projectJsonPath),
|
|
592
643
|
sourceTemplate: config.sourceTemplate,
|
|
593
644
|
projectType: config.projectType
|
|
594
645
|
};
|
|
@@ -648,7 +699,7 @@ var ScaffoldProcessingService = class {
|
|
|
648
699
|
* Now supports tracking existing files separately from created files
|
|
649
700
|
*/
|
|
650
701
|
async copyAndProcess(sourcePath, targetPath, variables, createdFiles, existingFiles) {
|
|
651
|
-
await this.fileSystem.ensureDir(
|
|
702
|
+
await this.fileSystem.ensureDir(nodePath.dirname(targetPath));
|
|
652
703
|
if (await this.fileSystem.pathExists(targetPath) && existingFiles) {
|
|
653
704
|
await this.trackExistingFiles(targetPath, existingFiles);
|
|
654
705
|
return;
|
|
@@ -670,7 +721,7 @@ var ScaffoldProcessingService = class {
|
|
|
670
721
|
}
|
|
671
722
|
for (const item of items) {
|
|
672
723
|
if (!item) continue;
|
|
673
|
-
const itemPath =
|
|
724
|
+
const itemPath = nodePath.join(dirPath, item);
|
|
674
725
|
try {
|
|
675
726
|
const stat$1 = await this.fileSystem.stat(itemPath);
|
|
676
727
|
if (stat$1.isDirectory()) await this.trackCreatedFilesRecursive(itemPath, createdFiles);
|
|
@@ -693,7 +744,7 @@ var ScaffoldProcessingService = class {
|
|
|
693
744
|
}
|
|
694
745
|
for (const item of items) {
|
|
695
746
|
if (!item) continue;
|
|
696
|
-
const itemPath =
|
|
747
|
+
const itemPath = nodePath.join(dirPath, item);
|
|
697
748
|
try {
|
|
698
749
|
const stat$1 = await this.fileSystem.stat(itemPath);
|
|
699
750
|
if (stat$1.isDirectory()) await this.trackExistingFilesRecursive(itemPath, existingFiles);
|
|
@@ -820,12 +871,12 @@ async function gitInit(projectPath) {
|
|
|
820
871
|
* }
|
|
821
872
|
*/
|
|
822
873
|
async function findWorkspaceRoot(startPath = process.cwd()) {
|
|
823
|
-
let currentPath =
|
|
824
|
-
const rootPath =
|
|
874
|
+
let currentPath = nodePath.resolve(startPath);
|
|
875
|
+
const rootPath = nodePath.parse(currentPath).root;
|
|
825
876
|
while (true) {
|
|
826
|
-
if (await pathExists(
|
|
877
|
+
if (await pathExists(nodePath.join(currentPath, ".git"))) return currentPath;
|
|
827
878
|
if (currentPath === rootPath) return null;
|
|
828
|
-
currentPath =
|
|
879
|
+
currentPath = nodePath.dirname(currentPath);
|
|
829
880
|
}
|
|
830
881
|
}
|
|
831
882
|
/**
|
|
@@ -907,7 +958,7 @@ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
|
|
|
907
958
|
"core.sparseCheckout",
|
|
908
959
|
"true"
|
|
909
960
|
], tempFolder);
|
|
910
|
-
await writeFile(
|
|
961
|
+
await writeFile(nodePath.join(tempFolder, ".git", "info", "sparse-checkout"), `${subdirectory}\n`);
|
|
911
962
|
await execGit([
|
|
912
963
|
"pull",
|
|
913
964
|
"--depth=1",
|
|
@@ -915,7 +966,7 @@ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
|
|
|
915
966
|
"--",
|
|
916
967
|
branch
|
|
917
968
|
], tempFolder);
|
|
918
|
-
const sourceDir =
|
|
969
|
+
const sourceDir = nodePath.join(tempFolder, subdirectory);
|
|
919
970
|
if (!await pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
|
|
920
971
|
if (await pathExists(targetFolder)) throw new Error(`Target folder already exists: ${targetFolder}`);
|
|
921
972
|
await move(sourceDir, targetFolder);
|
|
@@ -942,7 +993,7 @@ async function cloneRepository(repoUrl, targetFolder) {
|
|
|
942
993
|
repoUrl,
|
|
943
994
|
targetFolder
|
|
944
995
|
]);
|
|
945
|
-
const gitFolder =
|
|
996
|
+
const gitFolder = nodePath.join(targetFolder, ".git");
|
|
946
997
|
if (await pathExists(gitFolder)) await remove(gitFolder);
|
|
947
998
|
}
|
|
948
999
|
/**
|
|
@@ -1159,7 +1210,7 @@ const MONOREPO_INDICATOR_FILES = [
|
|
|
1159
1210
|
*/
|
|
1160
1211
|
async function detectProjectType(workspaceRoot) {
|
|
1161
1212
|
const indicators = [];
|
|
1162
|
-
const toolkitYamlPath =
|
|
1213
|
+
const toolkitYamlPath = nodePath.join(workspaceRoot, "toolkit.yaml");
|
|
1163
1214
|
if (await pathExists(toolkitYamlPath)) try {
|
|
1164
1215
|
const content = await fs.readFile(toolkitYamlPath, "utf-8");
|
|
1165
1216
|
const config = yaml.load(content);
|
|
@@ -1171,14 +1222,14 @@ async function detectProjectType(workspaceRoot) {
|
|
|
1171
1222
|
};
|
|
1172
1223
|
}
|
|
1173
1224
|
} catch {}
|
|
1174
|
-
for (const filename of MONOREPO_INDICATOR_FILES) if (await pathExists(
|
|
1225
|
+
for (const filename of MONOREPO_INDICATOR_FILES) if (await pathExists(nodePath.join(workspaceRoot, filename))) {
|
|
1175
1226
|
indicators.push(`${filename} found`);
|
|
1176
1227
|
return {
|
|
1177
1228
|
projectType: ProjectType.MONOREPO,
|
|
1178
1229
|
indicators
|
|
1179
1230
|
};
|
|
1180
1231
|
}
|
|
1181
|
-
const packageJsonPath =
|
|
1232
|
+
const packageJsonPath = nodePath.join(workspaceRoot, "package.json");
|
|
1182
1233
|
if (await pathExists(packageJsonPath)) try {
|
|
1183
1234
|
if ((await readJson(packageJsonPath)).workspaces) {
|
|
1184
1235
|
indicators.push("package.json with workspaces found");
|
package/package.json
CHANGED