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.
@@ -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, ignoreList))
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, ignoreList))
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 ' + path_1.default.relative(process.cwd(), extraPath))} to allow this specific file\n` +
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
  }
@@ -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] [--ignore-tooling]
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.7",
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 scaffoldrite', { stdio: 'inherit' });\""
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",