From 04e7e895d7d97e29cf1ded2f2d0ac8e6a237b997 Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Mon, 23 Mar 2026 12:34:48 +0200 Subject: [PATCH] feat: add .scaffold.{ext} as auto-detected file --- README.md | 11 ++-- docs/docs/usage/02-configuration_files.md | 66 +++++++++++++++-------- docs/docs/usage/03-cli.md | 2 +- src/config.ts | 1 + tests/config.test.ts | 52 ++++++++++++++++++ 5 files changed, 106 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 635629d..6e53ea3 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/docs/usage/02-configuration_files.md b/docs/docs/usage/02-configuration_files.md index dae2781..4bd763b 100644 --- a/docs/docs/usage/02-configuration_files.md +++ b/docs/docs/usage/02-configuration_files.md @@ -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 -k @@ -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 diff --git a/docs/docs/usage/03-cli.md b/docs/docs/usage/03-cli.md index 1995306..f754656 100644 --- a/docs/docs/usage/03-cli.md +++ b/docs/docs/usage/03-cli.md @@ -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. | diff --git a/src/config.ts b/src/config.ts index c50c137..45f093c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -174,6 +174,7 @@ export async function findConfigFile(root: string): Promise { 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) { diff --git a/tests/config.test.ts b/tests/config.test.ts index 77a0cdf..1d50a11 100644 --- a/tests/config.test.ts +++ b/tests/config.test.ts @@ -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") + }) + }, + ), + ) }) })