feat: add .scaffold.{ext} as auto-detected file

This commit is contained in:
2026-03-23 12:34:48 +02:00
parent 68e6d17fa9
commit 04e7e895d7
5 changed files with 106 additions and 26 deletions

View File

@@ -124,7 +124,11 @@ npx simple-scaffold -c scaffold.config.js -k component -D author=John MyComponen
### Configuration Files
You can use a config file to more easily maintain all your scaffold definitions.
You can use a config file to more easily maintain all your scaffold definitions. Simple Scaffold
**auto-detects** config files in the current directory — no `--config` flag needed.
It searches for these files in order: `scaffold.config.{mjs,cjs,js,json}`,
`scaffold.{mjs,cjs,js,json}`, `.scaffold.{mjs,cjs,js,json}`.
`scaffold.config.js`
@@ -142,10 +146,11 @@ module.exports = {
}
```
Then call your scaffold like this:
Then just run from the same directory:
```sh
$ npx simple-scaffold -c scaffold.config.js PageWrapper
$ npx simple-scaffold PageWrapper
# or explicitly: npx simple-scaffold -c scaffold.config.js PageWrapper
```
This will allow you to avoid needing to remember which configs are needed or to store them in a

View File

@@ -79,9 +79,38 @@ default and therefore it will no longer be required in the CLI arguments.
## Using a config file
Once your config is created, you can use it by providing the file name to the `--config` (or `-c`
for brevity), optionally alongside `--key` or `-k`, denoting the key to use as the config object, as
you define in your config:
### Auto-detection
By default, Simple Scaffold automatically searches the current working directory for a config file.
No `--config` flag is needed if your config file uses one of the standard names.
The following files are tried in order:
1. `scaffold.config.mjs`
2. `scaffold.config.cjs`
3. `scaffold.config.js`
4. `scaffold.config.json`
5. `scaffold.mjs`
6. `scaffold.cjs`
7. `scaffold.js`
8. `scaffold.json`
9. `.scaffold.mjs`
10. `.scaffold.cjs`
11. `.scaffold.js`
12. `.scaffold.json`
If a config file is found, it is loaded automatically. If multiple templates are defined and no
`--key` is provided, you'll be prompted to select one interactively.
```sh
# Just run from a directory containing scaffold.config.js — no flags needed
simple-scaffold MyComponentName
```
### Explicit config path
You can also provide a specific file or directory path using `--config` (or `-c`), optionally
alongside `--key` or `-k`:
```sh
simple-scaffold -c <file> -k <template_key>
@@ -93,7 +122,12 @@ For example:
simple-scaffold -c scaffold.json -k component MyComponentName
```
If you don't want to supply a template/config name (e.g. `component`), `default` will be used:
When a directory is given, the same auto-detection order listed above is used to find a config file
within that directory.
### Default template key
If you don't supply a template key (e.g. `component`), `default` will be used:
```js
/** @type {import('simple-scaffold').ScaffoldConfigFile} */
@@ -104,35 +138,23 @@ module.exports = {
}
```
And then:
```sh
# will use 'default' template
simple-scaffold -c scaffold.json MyComponentName
```
- When the a directory is given, the following files in the given directory will be tried in order:
- `scaffold.config.*`
- `scaffold.*`
Where `*` denotes any supported file extension, in the priority listed in
[Supported file types](#supported-file-types)
- When the `template_key` is ommitted, `default` will be used as default.
If multiple keys exist and no key is specified, you'll be prompted to choose one interactively.
### Supported file types
Any importable file is supported, depending on your build process.
Common files include:
Common extensions:
- `*.mjs`
- `*.cjs`
- `*.js`
- `*.json`
When filenames are ommited when loading configs, these are the file extensions that will be
automatically tried, by the specified order of priority.
- `.mjs`
- `.cjs`
- `.js`
- `.json`
Note that you might need to find the correct extension of `.js`, `.cjs` or `.mjs` depending on your
build process and your package type (for example, packages with `"type": "module"` in their

View File

@@ -16,7 +16,7 @@ Options:
| Option/flag \| Alias | Description |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name` \| `-n` | Name to be passed to the generated files. `{{name}}` and other data parameters inside contents and file names will be replaced accordingly. If omitted in an interactive terminal, you will be prompted. |
| `--config` \| `-c` | Filename or directory to load config from |
| `--config` \| `-c` | Filename or directory to load config from. If omitted, the current directory is searched automatically for a config file (see [Auto-detection](configuration_files#auto-detection)). |
| `--git` \| `-g` | Git URL or GitHub path to load a template from. |
| `--key` \| `-k` | Key to load inside the config file. If omitted and multiple templates are available, you will be prompted to select one. |
| `--output` \| `-o` | Path to output to. If `--subdir` is enabled, the subdir will be created inside this path. If omitted in an interactive terminal, you will be prompted. |

View File

@@ -174,6 +174,7 @@ export async function findConfigFile(root: string): Promise<string> {
const allowed = ["mjs", "cjs", "js", "json"].reduce((acc, ext) => {
acc.push(`scaffold.config.${ext}`)
acc.push(`scaffold.${ext}`)
acc.push(`.scaffold.${ext}`)
return acc
}, [] as string[])
for (const file of allowed) {

View File

@@ -474,5 +474,57 @@ describe("config", () => {
})
}),
)
describe(
"finds .scaffold.js",
withMock({ ".scaffold.js": "module.exports = {}" }, () => {
test("finds dotfile config", async () => {
const result = await findConfigFile(process.cwd())
expect(result).toEqual(".scaffold.js")
})
}),
)
describe(
"finds .scaffold.json",
withMock({ ".scaffold.json": "{}" }, () => {
test("finds dotfile json config", async () => {
const result = await findConfigFile(process.cwd())
expect(result).toEqual(".scaffold.json")
})
}),
)
describe(
"prefers scaffold.config over .scaffold",
withMock(
{
"scaffold.config.js": "module.exports = {}",
".scaffold.js": "module.exports = {}",
},
() => {
test("prefers scaffold.config.js over .scaffold.js", async () => {
const result = await findConfigFile(process.cwd())
expect(result).toEqual("scaffold.config.js")
})
},
),
)
describe(
"prefers scaffold over .scaffold",
withMock(
{
"scaffold.js": "module.exports = {}",
".scaffold.js": "module.exports = {}",
},
() => {
test("prefers scaffold.js over .scaffold.js", async () => {
const result = await findConfigFile(process.cwd())
expect(result).toEqual("scaffold.js")
})
},
),
)
})
})