scaffoldrite 2.0.7 → 2.1.0
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/cli.js +4 -1
- package/dist/library/commandHandler.js +90 -39
- package/dist/library/fsToAst.js +31 -11
- package/dist/library/plot/ai.js +148 -0
- package/dist/library/plot/aiClient.js +36 -0
- package/dist/library/plot/generateStructure.js +30 -0
- package/dist/library/plot/lis.js +158 -0
- package/dist/library/validateFS.js +16 -7
- package/dist/utils/index.js +16 -8
- package/package.json +2 -2
- package/readme.md +272 -386
|
@@ -10,6 +10,7 @@ const index_1 = require("../utils/index");
|
|
|
10
10
|
const index_2 = require("../data/index");
|
|
11
11
|
function validateFS(root, dir, options = {}) {
|
|
12
12
|
const { ignoreList = [], allowExtra = false, allowExtraPaths = [], currentPath = "", } = options;
|
|
13
|
+
const effectiveIgnoreList = [...ignoreList, ".scaffoldrite"];
|
|
13
14
|
if (!fs_1.default.existsSync(dir)) {
|
|
14
15
|
throw new Error(`${index_2.icons.error} ${index_2.theme.error('Folder does not exist:')} ${index_2.theme.highlight(dir)}\n` +
|
|
15
16
|
`${index_2.theme.muted('Expected folder according to')} ${index_2.theme.secondary('structure.sr')} ${index_2.theme.muted('at:')} ${index_2.theme.primary(currentPath || "root")}`);
|
|
@@ -17,7 +18,7 @@ function validateFS(root, dir, options = {}) {
|
|
|
17
18
|
const actualItems = fs_1.default.readdirSync(dir);
|
|
18
19
|
// Check missing items in filesystem
|
|
19
20
|
for (const child of root.children) {
|
|
20
|
-
if ((0, index_1.isIgnored)(child.name,
|
|
21
|
+
if ((0, index_1.isIgnored)(child.name, effectiveIgnoreList))
|
|
21
22
|
continue;
|
|
22
23
|
const expectedPath = path_1.default.join(dir, child.name);
|
|
23
24
|
const expectedSrPath = path_1.default.join(currentPath, child.name);
|
|
@@ -27,8 +28,12 @@ function validateFS(root, dir, options = {}) {
|
|
|
27
28
|
return (expectedSrPath === normalized ||
|
|
28
29
|
expectedSrPath.endsWith(normalized));
|
|
29
30
|
});
|
|
30
|
-
if (allowExtra || allowedExplicitly)
|
|
31
|
+
if (allowExtra || allowedExplicitly) {
|
|
32
|
+
// Print info about allowed missing item
|
|
33
|
+
console.log(`${index_2.icons.info} ${index_2.theme.info('Allowed missing:')} ${index_2.theme.muted(expectedSrPath)} ` +
|
|
34
|
+
`${index_2.theme.muted(allowedExplicitly ? '(explicitly allowed)' : '(via --allow-extra)')}`);
|
|
31
35
|
continue;
|
|
36
|
+
}
|
|
32
37
|
throw new Error(`${index_2.icons.error} ${index_2.theme.error('Missing in filesystem:')} ${index_2.theme.highlight(expectedPath)}\n` +
|
|
33
38
|
`${index_2.theme.muted('Expected according to')} ${index_2.theme.secondary('structure.sr')} ${index_2.theme.muted('at:')} ${index_2.theme.primary(expectedSrPath)}\n` +
|
|
34
39
|
`${index_2.theme.info('Fix:')} Run ${index_2.theme.primary('scaffoldrite generate')} to recreate missing files. This does not restore file contents.`);
|
|
@@ -56,26 +61,30 @@ function validateFS(root, dir, options = {}) {
|
|
|
56
61
|
}
|
|
57
62
|
// Check extra items in filesystem not in .sr
|
|
58
63
|
for (const item of actualItems) {
|
|
59
|
-
if ((0, index_1.isIgnored)(item,
|
|
64
|
+
if ((0, index_1.isIgnored)(item, effectiveIgnoreList))
|
|
60
65
|
continue;
|
|
61
66
|
const existsInSr = root.children.some((c) => c.name === item);
|
|
62
67
|
if (!existsInSr) {
|
|
63
68
|
const extraPath = path_1.default.join(dir, item);
|
|
69
|
+
const extraRel = path_1.default.relative(process.cwd(), extraPath);
|
|
70
|
+
const extraBasename = path_1.default.basename(extraPath);
|
|
64
71
|
const allowedExplicitly = allowExtraPaths.some((p) => {
|
|
65
72
|
const normalized = path_1.default.normalize(p);
|
|
66
|
-
const extraRel = path_1.default.relative(dir, extraPath);
|
|
67
|
-
const extraBasename = path_1.default.basename(extraPath);
|
|
68
73
|
return (extraBasename === normalized ||
|
|
69
74
|
extraRel === normalized ||
|
|
70
75
|
extraRel.endsWith(normalized));
|
|
71
76
|
});
|
|
72
|
-
if (allowExtra || allowedExplicitly)
|
|
77
|
+
if (allowExtra || allowedExplicitly) {
|
|
78
|
+
// Print info about allowed extra item
|
|
79
|
+
console.log(`${index_2.icons.info} ${index_2.theme.info('Allowed extra:')} ${index_2.theme.highlight(extraRel)} ` +
|
|
80
|
+
`${index_2.theme.muted(allowedExplicitly ? '(explicitly allowed)' : '(via --allow-extra)')}`);
|
|
73
81
|
continue;
|
|
82
|
+
}
|
|
74
83
|
throw new Error(`${index_2.icons.error} ${index_2.theme.error('Extra file/folder found in filesystem:')} ${index_2.theme.highlight(extraPath)}\n` +
|
|
75
84
|
`${index_2.theme.muted('Not defined in')} ${index_2.theme.secondary('structure.sr')} ${index_2.theme.muted('at:')} ${index_2.theme.primary(currentPath || "root")}\n` +
|
|
76
85
|
`${index_2.theme.info('Options:')}\n` +
|
|
77
86
|
` • ${index_2.theme.primary('--allow-extra')} to allow all extra files\n` +
|
|
78
|
-
` • ${index_2.theme.primary('--allow-extra ' +
|
|
87
|
+
` • ${index_2.theme.primary('--allow-extra ' + extraRel)} to allow this specific file\n` +
|
|
79
88
|
` • Delete or move the file to resolve`);
|
|
80
89
|
}
|
|
81
90
|
}
|
package/dist/utils/index.js
CHANGED
|
@@ -150,10 +150,10 @@ function loadAST() {
|
|
|
150
150
|
return (0, parser_1.parseStructure)(content);
|
|
151
151
|
}
|
|
152
152
|
function printTree(node, prefix = "", isLast = true) {
|
|
153
|
-
const connector = isLast ? "└── " : "├── ";
|
|
154
|
-
const nextPrefix = prefix + (isLast ? " " : "│ ");
|
|
155
153
|
node.children.forEach((child, index) => {
|
|
156
154
|
const last = index === node.children.length - 1;
|
|
155
|
+
const connector = last ? "└── " : "├── ";
|
|
156
|
+
const nextPrefix = prefix + (last ? " " : "│ ");
|
|
157
157
|
if (child.type === "folder") {
|
|
158
158
|
console.log(`${prefix}${connector}${data_1.theme.secondary(child.name)}`);
|
|
159
159
|
printTree(child, nextPrefix, last);
|
|
@@ -164,10 +164,10 @@ function printTree(node, prefix = "", isLast = true) {
|
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
function printTreeWithIcons(node, prefix = "", isLast = true) {
|
|
167
|
-
const connector = isLast ? "└── " : "├── ";
|
|
168
|
-
const nextPrefix = prefix + (isLast ? " " : "│ ");
|
|
169
167
|
node.children.forEach((child, index) => {
|
|
170
168
|
const last = index === node.children.length - 1;
|
|
169
|
+
const connector = last ? "└── " : "├── ";
|
|
170
|
+
const nextPrefix = prefix + (last ? " " : "│ ");
|
|
171
171
|
if (child.type === "folder") {
|
|
172
172
|
console.log(`${prefix}${connector}${data_1.icons.folder} ${data_1.theme.secondary(child.name)}`);
|
|
173
173
|
printTreeWithIcons(child, nextPrefix, last);
|
|
@@ -233,14 +233,15 @@ exports.ALLOWED_FLAGS = {
|
|
|
233
233
|
"--verbose",
|
|
234
234
|
"--summary",
|
|
235
235
|
"--ignore-tooling",
|
|
236
|
-
"--copy"
|
|
236
|
+
"--copy",
|
|
237
237
|
],
|
|
238
238
|
create: ["--force", "--if-not-exists", "--yes", "--dry-run", "--verbose", "--summary"],
|
|
239
239
|
delete: ["--yes", "--dry-run", "--verbose", "--summary"],
|
|
240
240
|
rename: ["--yes", "--dry-run", "--verbose", "--summary"],
|
|
241
241
|
list: ["--structure", "--sr", "--fs", "--diff", "--with-icon"],
|
|
242
|
+
find: ["--structure", "--sr", "--fs"], // ✅ updated
|
|
242
243
|
version: [],
|
|
243
|
-
"check-packages": ["--validate"]
|
|
244
|
+
"check-packages": ["--validate"],
|
|
244
245
|
};
|
|
245
246
|
function printUsage(cmd) {
|
|
246
247
|
if (cmd && exports.ALLOWED_FLAGS[cmd]) {
|
|
@@ -254,8 +255,9 @@ function printUsage(cmd) {
|
|
|
254
255
|
create: "<path> <file|folder> [--force | --if-not-exists] [--yes | -y] [--dry-run] [--verbose | --summary]",
|
|
255
256
|
delete: "<path> [--yes | -y] [--dry-run] [--verbose | --summary]",
|
|
256
257
|
rename: "<path> <newName> [--yes | -y] [--dry-run] [--verbose | --summary]",
|
|
258
|
+
find: "<query> [--structure | --sr | --fs]",
|
|
257
259
|
version: "",
|
|
258
|
-
"check-packages": "[--validate]"
|
|
260
|
+
"check-packages": "[--validate]",
|
|
259
261
|
};
|
|
260
262
|
const args = argsMap[cmd] ? ` ${argsMap[cmd]}` : "";
|
|
261
263
|
console.log(data_1.theme.primary.bold(`Usage for '${cmd}':`) +
|
|
@@ -272,8 +274,9 @@ Usage:
|
|
|
272
274
|
scaffoldrite update [--from-fs [dir]] [--yes | -y]
|
|
273
275
|
scaffoldrite merge [--from-fs [dir]] [--yes | -y]
|
|
274
276
|
scaffoldrite validate [--allow-extra] [--allow-extra <path1> <path2> ...]
|
|
275
|
-
scaffoldrite generate [dir] [--yes | -y] [--dry-run] [--verbose | --summary]
|
|
277
|
+
scaffoldrite generate [dir] [--yes | -y] [--dry-run] [--verbose | --summary] [--ignore-tooling]
|
|
276
278
|
scaffoldrite list [[--structure | --sr] | --fs | --diff] [--with-icon]
|
|
279
|
+
scaffoldrite find <query> [--structure | --sr | --fs]
|
|
277
280
|
scaffoldrite create <path> <file|folder> [--force | --if-not-exists] [--yes | -y] [--dry-run] [--verbose | --summary]
|
|
278
281
|
scaffoldrite delete <path> [--yes | -y] [--dry-run] [--verbose | --summary]
|
|
279
282
|
scaffoldrite rename <path> <newName> [--yes | -y] [--dry-run] [--verbose | --summary]
|
|
@@ -346,6 +349,11 @@ function runRequirements(ctx) {
|
|
|
346
349
|
if (fromFs && !arg3)
|
|
347
350
|
fail("init");
|
|
348
351
|
},
|
|
352
|
+
// ✅ New requirement for find
|
|
353
|
+
find() {
|
|
354
|
+
if (!arg3)
|
|
355
|
+
fail("find"); // arg3 is the search query
|
|
356
|
+
},
|
|
349
357
|
};
|
|
350
358
|
requirements[command]?.();
|
|
351
359
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scaffoldrite",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A project structure validator and generator CLI tool.",
|
|
5
5
|
"author": "Isaac Anasonye",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"validate": "npm run type-check && npm run build",
|
|
39
39
|
"test": "jest",
|
|
40
40
|
"prepublishOnly": "npm run build && node dist/cli.js --help npm pack --dry-run",
|
|
41
|
-
"release:test": "npm run build && node -e \"const { execSync } = require('child_process'); const name=require('./package.json').name; const version=require('./package.json').version; const file=`${name}-${version}.tgz`; execSync('npm pack', { stdio: 'inherit' }); execSync(`npm install -g ${file}`, { stdio: 'inherit' }); execSync('sr --help', { stdio: 'inherit' }); execSync('npm uninstall -g
|
|
41
|
+
"release:test": "npm run build && node -e \"const { execSync } = require('child_process'); const name=require('./package.json').name; const version=require('./package.json').version; const file=`${name}-${version}.tgz`; execSync('npm pack', { stdio: 'inherit' }); execSync(`npm install -g ${file}`, { stdio: 'inherit' }); execSync('sr --help', { stdio: 'inherit' }); execSync('npm uninstall -g ${name}-${version}', { stdio: 'inherit' });\""
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/cli-progress": "^3.11.6",
|