scaffoldrite 1.0.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/ast.js +2 -0
- package/dist/cli.js +311 -0
- package/dist/constraints.js +173 -0
- package/dist/data/flags.js +7 -0
- package/dist/data/index.js +18 -0
- package/dist/fsToAst.js +73 -0
- package/dist/generator.js +51 -0
- package/dist/parser.js +101 -0
- package/dist/structure.js +84 -0
- package/dist/validateFS.js +86 -0
- package/dist/validator.js +247 -0
- package/dist/visitor.js +23 -0
- package/package.json +51 -0
- package/readme.md +568 -0
package/readme.md
ADDED
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
# Scaffoldrite
|
|
2
|
+
|
|
3
|
+
**Scaffoldrite** is a **project structure validator & generator**.
|
|
4
|
+
|
|
5
|
+
You define your project structure using a simple `structure.sr` format, then run commands to validate, generate, or modify the structure.
|
|
6
|
+
|
|
7
|
+
> **Note:** The `structure.sr` file is the source of truth β **not the directory itself**.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## π Who should use it?
|
|
12
|
+
|
|
13
|
+
### Framework / Library creators
|
|
14
|
+
Enforce strict project structure for generated projects.
|
|
15
|
+
|
|
16
|
+
### Monorepo maintainers
|
|
17
|
+
Enforce consistent folder rules across multiple packages.
|
|
18
|
+
|
|
19
|
+
### Teams & Bootcamps
|
|
20
|
+
Enforce a standard architecture and reduce mistakes.
|
|
21
|
+
|
|
22
|
+
### Project generators
|
|
23
|
+
Validate output before publishing.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Define folder + file structure using `structure.sr`
|
|
30
|
+
- Validate structure against rules (constraints)
|
|
31
|
+
- Generate filesystem output
|
|
32
|
+
- Create / delete / rename files & folders
|
|
33
|
+
- Enforce rules like:
|
|
34
|
+
- required files
|
|
35
|
+
- max files per folder
|
|
36
|
+
- regex filename checks
|
|
37
|
+
- unique filenames
|
|
38
|
+
- folder depth limit
|
|
39
|
+
- and more
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Supported Actions
|
|
44
|
+
|
|
45
|
+
- Creating starter templates
|
|
46
|
+
- Validating folder/file structure
|
|
47
|
+
- Generating folders and files
|
|
48
|
+
- Modifying the structure file
|
|
49
|
+
- Snapshotting an existing filesystem
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Source of Truth Flow Diagram
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
structure.sr
|
|
57
|
+
|
|
|
58
|
+
v
|
|
59
|
+
Validator
|
|
60
|
+
|
|
|
61
|
+
v
|
|
62
|
+
Constraints Check
|
|
63
|
+
|
|
|
64
|
+
v
|
|
65
|
+
(Valid?) ---- No ---> Error Report
|
|
66
|
+
|
|
|
67
|
+
Yes
|
|
68
|
+
|
|
|
69
|
+
v
|
|
70
|
+
Generator
|
|
71
|
+
|
|
|
72
|
+
v
|
|
73
|
+
Filesystem Output
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install -g scaffoldrite
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
## structure.sr Format
|
|
86
|
+
|
|
87
|
+
A typical structure.sr file looks like:
|
|
88
|
+
|
|
89
|
+
```sr
|
|
90
|
+
folder src {
|
|
91
|
+
folder components {
|
|
92
|
+
file Button.tsx
|
|
93
|
+
}
|
|
94
|
+
file index.ts
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
constraints {
|
|
98
|
+
eachFolderMustContain ** src index.ts
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Command-line rules
|
|
103
|
+
|
|
104
|
+
Scaffoldrite follows simple CLI rules:
|
|
105
|
+
|
|
106
|
+
- The command must come first
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
scaffoldrite <command> [options] [arguments]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- Flags must come after the command.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
scaffoldrite init --force
|
|
116
|
+
scaffoldrite init --from-fs . --force
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- Flags before the command are not supported
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
scaffoldrite --force init β
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- Arguments without -- are positional
|
|
126
|
+
|
|
127
|
+
- Their meaning depends on order
|
|
128
|
+
|
|
129
|
+
- Changing the order changes behavior
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
## Commands
|
|
133
|
+
|
|
134
|
+
- scaffoldrite init: Creates a starter structure.sr template.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
scaffoldrite init
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
### Flags by Command (Authoritative Reference)
|
|
142
|
+
|
|
143
|
+
- `scaffoldrite init`
|
|
144
|
+
|
|
145
|
+
| Flag | Description |
|
|
146
|
+
| ----------- | ------------------------------------------------------------ |
|
|
147
|
+
| `--empty` | Create an empty `structure.sr` with only a constraints block |
|
|
148
|
+
| `--from-fs` | Generate `structure.sr` from the filesystem |
|
|
149
|
+
| `--force` | Overwrite an existing `structure.sr` file |
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
scaffoldrite init
|
|
153
|
+
scaffoldrite init --empty
|
|
154
|
+
scaffoldrite init --from-fs
|
|
155
|
+
scaffoldrite init --from-fs ./src --force
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
- `scaffoldrite validate`
|
|
159
|
+
|
|
160
|
+
| Flag | Description |
|
|
161
|
+
| ------------------------- | ------------------------------------------------------- |
|
|
162
|
+
| `--allow-extra` | Allow extra files/folders not defined in `structure.sr` |
|
|
163
|
+
| `--allow-extra <path...>` | Allow only specific extra files or folders |
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
scaffoldrite validate
|
|
167
|
+
scaffoldrite validate --allow-extra
|
|
168
|
+
scaffoldrite validate --allow-extra index.ts logs
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- `scaffoldrite generate`
|
|
172
|
+
|
|
173
|
+
| Flag | Description |
|
|
174
|
+
| ------- | ------------------------- |
|
|
175
|
+
| `--yes` | Skip confirmation prompts |
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
scaffoldrite generate
|
|
179
|
+
scaffoldrite generate ./output --yes
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- `scaffoldrite create`
|
|
183
|
+
|
|
184
|
+
| Flag | Description |
|
|
185
|
+
| ----------------- | ---------------------------------------- |
|
|
186
|
+
| `--force` | Overwrite existing file or folder |
|
|
187
|
+
| `--if-not-exists` | Skip creation if the path already exists |
|
|
188
|
+
| `--yes` | Skip confirmation prompts |
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
scaffoldrite create src/utils folder
|
|
192
|
+
scaffoldrite create src/index.ts file --force
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
- `scaffoldrite delete`
|
|
196
|
+
|
|
197
|
+
| Flag | Description |
|
|
198
|
+
| ------- | ------------------------- |
|
|
199
|
+
| `--yes` | Skip confirmation prompts |
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
scaffoldrite delete src/utils --yes
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- `scaffoldrite rename`
|
|
206
|
+
|
|
207
|
+
| Flag | Description |
|
|
208
|
+
| ------- | ------------------------- |
|
|
209
|
+
| `--yes` | Skip confirmation prompts |
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
scaffoldrite rename src/index.ts main.ts
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
- `scaffoldrite list`
|
|
216
|
+
|
|
217
|
+
No flags supported.
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
scaffoldrite list
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
## Default Ignore List
|
|
227
|
+
|
|
228
|
+
These folders are ignored by default when running `scaffoldrite init --from-fs`:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
"node_modules",
|
|
232
|
+
".git",
|
|
233
|
+
".next",
|
|
234
|
+
"dist",
|
|
235
|
+
"build",
|
|
236
|
+
"coverage",
|
|
237
|
+
".turbo",
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
## .scaffoldignore
|
|
242
|
+
|
|
243
|
+
scaffoldrite uses a .scaffoldignore file to ignore folders and files when.
|
|
244
|
+
|
|
245
|
+
- Snapshotting a filesystem (`scaffoldrite init --from-fs`)
|
|
246
|
+
|
|
247
|
+
- Validating (`scaffoldrite validate`)
|
|
248
|
+
|
|
249
|
+
This works similarly to .gitignore.
|
|
250
|
+
|
|
251
|
+
This will override the default ingores and if deleted falls back to default ignores except flags are used.
|
|
252
|
+
|
|
253
|
+
### Notes
|
|
254
|
+
|
|
255
|
+
- Lines starting with # are treated as comments
|
|
256
|
+
|
|
257
|
+
- Blank lines are ignored
|
|
258
|
+
|
|
259
|
+
- `.scaffoldignore` is not merged with the default list β it replaces it
|
|
260
|
+
|
|
261
|
+
- It is used for validation and init and not with generation.
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Ignore build output
|
|
265
|
+
dist
|
|
266
|
+
|
|
267
|
+
*.js # Ignore compiled JS
|
|
268
|
+
|
|
269
|
+
# Ignore logs
|
|
270
|
+
*.log
|
|
271
|
+
|
|
272
|
+
node_modules
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
- `scaffoldrite validate`: Validates the structure.sr file against the defined constraints and the actual filesystem.
|
|
279
|
+
This ensures the filesystem matches the structure definition, not just the rules in the .sr file
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
scaffoldrite validate
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
scaffoldrite validate ./output
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
You can use the --allow-extra flag to ignore if there are files or folders in the filesystem not in the structure.sr
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
scaffoldrite validate --allow-extra
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
scaffoldrite validate --allow-extra index.ts math
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
- `scaffoldrite generate`: Generates the filesystem structure based on structure.sr.
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
scaffoldrite generate
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
scaffoldrite generate ./output
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
- `scaffoldrite list`: Lists the current structure defined in structure.sr.
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
scaffoldrite list
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
- `scaffoldrite create <path> <file|folder>`: Creates a file or folder inside the structure and regenerates filesystem.
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
scaffoldrite create src/components folder
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
scaffoldrite create src/index.ts file
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
- `scaffoldrite delete <path>`: Deletes a file or folder from the structure and regenerates filesystem.
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
scaffoldrite delete src/components
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
- `scaffoldrite rename <path> <newName>`: Renames a file or folder inside the structure and regenerates filesystem.
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
scaffoldrite rename src/index.ts main.ts
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
## Constraints (Commands)
|
|
348
|
+
|
|
349
|
+
All constraint rules must be inside the constraints {} block.
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
### Basic Constraints
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
- `require <path>`: Ensures the path exists.
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
require src
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
- `forbid <path>`: Ensures the path does not exist.
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
forbid src/secret.txt
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
- `mustContain <path> <value>`: Ensures folder contains a file/folder.
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
mustContain src index.ts
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
- `mustHaveFile <path> <fileName>`: Ensures folder contains a specific file.
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
mustHaveFile src index.ts
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
- `fileNameRegex <path> <regex>`: Ensures all files in folder match regex.
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
- fileNameRegex src ^[a-z]+\.ts$
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
- `maxFiles <path> <number>`: Limits number of files in folder.
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
maxFiles src 3
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
- `maxFolders <path> <number>`: Limits number of folders in folder.
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
maxFolders src 2
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
- `minFiles <path> <number>`: Requires minimum files.
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
minFiles src 1
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
- `minFolders <path> <number>`: Requires minimum folders.
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
minFolders src 1
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
- `maxDepth <path> <number>`: Limits nesting depth.
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
-maxDepth src 3
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
- `maxFilesRecursive <path> <number>`: Limits files recursively.
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
maxFilesRecursive src 10
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
- `maxFoldersRecursive <path> <number>`: Limits folders recursively.
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
maxFoldersRecursive src 5
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
- `maxFilesByExt <path> <ext> <number>`: Limits files by extension.
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
maxFilesByExt src .ts 3
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
- `maxFilesByExtRecursive <path> <ext> <number>`: Limits files by extension recursively.
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
maxFilesByExtRecursive src .ts 5
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
### βEach Folderβ Constraints
|
|
468
|
+
|
|
469
|
+
These constraints apply a rule to every folder in a given scope.
|
|
470
|
+
|
|
471
|
+
| Scope | Meaning |
|
|
472
|
+
| ---------------- | ---------------------------------------------------------- |
|
|
473
|
+
| `*` | Apply to **every folder in the root** (non-recursive) |
|
|
474
|
+
| `*` with a path | Apply to **every folder inside that path** (non-recursive) |
|
|
475
|
+
| `**` | Apply **recursively** to all nested folders |
|
|
476
|
+
| `**` with a path | Apply recursively to all nested folders inside that path |
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
<path> is optional. If omitted, it defaults to the current directory.
|
|
480
|
+
|
|
481
|
+
- `eachFolderMustContain <scope> <path> <value>`: Ensures every folder in the scope contains a specific file or folder.
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
eachFolderMustContain ** src index.ts
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
- `eachFolderMustContainFile <scope> <path> <fileName>`: Ensures every folder in the scope contains a file.
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
eachFolderMustContainFile * src index.ts
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
- `eachFolderMustContainFolder <scope> <path> <folderName>`: Ensures every folder in the scope contains a folder.
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
eachFolderMustContainFolder * src components
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
- `eachFolderMustHaveExt <scope> <path> <ext>`: Ensures every folder in the scope contains at least one file with the given extension.
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
eachFolderMustHaveExt ** src .ts
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
### Example constraints block
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
constraints {
|
|
513
|
+
require src
|
|
514
|
+
mustContain src index.ts
|
|
515
|
+
maxFiles src 5
|
|
516
|
+
eachFolderMustContain ** src index.ts
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Notes
|
|
521
|
+
|
|
522
|
+
- <path> are relative to the root folder.
|
|
523
|
+
|
|
524
|
+
- For commands that accept a <path>, the path is optional. If omitted, it defaults to the current directory.
|
|
525
|
+
|
|
526
|
+
- The root folder is treated as a virtual folder (__root__) and is ignored in output.
|
|
527
|
+
|
|
528
|
+
- --yes skips all confirmation prompts.
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
## Contributing
|
|
533
|
+
|
|
534
|
+
Found a bug or want to add a feature? Contributions are welcome!
|
|
535
|
+
|
|
536
|
+
1. π΄ Fork it
|
|
537
|
+
2. π Star it (pretty please?)
|
|
538
|
+
3. π§ Fix it
|
|
539
|
+
4. π€ PR it
|
|
540
|
+
5. π Celebrate!
|
|
541
|
+
|
|
542
|
+
Please ensure your code follows the existing style and includes clear commit messages.
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## License
|
|
547
|
+
|
|
548
|
+
This project is licensed under the **MIT License** β see the [LICENSE](LICENSE) file for details.
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
## Credits
|
|
552
|
+
|
|
553
|
+
**Scaffoldrite** is built by **Isaac Anasonye** β a developer tool focused on **scaffolding project structures**, **enforcing constraints**, and **keeping codebases clean and predictable**.
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
<div align="center">
|
|
558
|
+
|
|
559
|
+
### π Using Scaffoldrite in your workflow?
|
|
560
|
+
|
|
561
|
+
**Support the project & join the community**
|
|
562
|
+
|
|
563
|
+
[β Star on GitHub](https://github.com/Isaacprogi/scaffoldrite) Β·
|
|
564
|
+
[π’ Share on Twitter](https://twitter.com/intent/tweet?text=Check%20out%20Scaffoldrite!) Β·
|
|
565
|
+
[π¬ Join the Discussion](https://github.com/Isaacprogi/scaffoldrite/discussions) Β·
|
|
566
|
+
[π Connect on LinkedIn](https://www.linkedin.com/in/isaacanasonye)
|
|
567
|
+
|
|
568
|
+
</div>
|