Skip to content

Commit e48b832

Browse files
committed
feat: support directory in --config flag
1 parent 06ffa65 commit e48b832

4 files changed

Lines changed: 55 additions & 62 deletions

File tree

docs/docs/usage/01-templates.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,15 @@ Further details:
109109
```
110110

111111
- **The now helper** (for current time) takes the same arguments, minus the first one (`date`) as it
112-
is implicitly the current date.
112+
is implicitly the current date:
113+
114+
```typescript
115+
(
116+
format: string,
117+
offsetAmount?: number,
118+
offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds"
119+
)
120+
```
113121

114122
### Custom Helpers
115123

docs/docs/usage/02-configuration_files.md

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,48 +23,11 @@ module.exports = {
2323
}
2424
```
2525

26-
The configuration contents are identical to the
27-
[Node.js configuration structure](https://chenasraf.github.io/simple-scaffold/docs/usage/node):
28-
29-
```ts
30-
interface ScaffoldConfig {
31-
name: string
32-
templates: string[]
33-
output: FileResponse<string>
34-
subdir?: boolean
35-
git?: string
36-
config?: string
37-
key?: string
38-
data?: Record<string, any>
39-
overwrite?: FileResponse<boolean>
40-
quiet?: boolean
41-
verbose?: LogLevel
42-
dryRun?: boolean
43-
helpers?: Record<string, Helper>
44-
subdirHelper?: DefaultHelpers | string
45-
beforeWrite?(
46-
content: Buffer,
47-
rawContent: Buffer,
48-
outputPath: string,
49-
): string | Buffer | undefined | Promise<string | Buffer | undefined>
50-
}
51-
```
26+
For the full configuration options, see [ScaffoldConfigFile](../api/modules#scaffoldconfigfile).
5227

5328
If you want to supply functions inside the configurations, you must use a `.js`/`.cjs`/`.mjs` file
5429
as JSON does not support non-primitives.
5530

56-
A `.js` file can be just like a `.json` file, make sure to export the final configuration:
57-
58-
```js
59-
/** @type {import('simple-scaffold').ScaffoldConfigFile} */
60-
module.exports = {
61-
component: {
62-
templates: ["templates/component"],
63-
output: "src/components",
64-
},
65-
}
66-
```
67-
6831
Another feature of using a JS file is you can export a function which will be loaded with the CMD
6932
config provided to Simple Scaffold. The `extra` key contains any values not consumed by built-in
7033
flags, so you can pre-process your args before outputting a config:
@@ -116,7 +79,7 @@ And then:
11679
simple-scaffold -c scaffold.json MyComponentName
11780
```
11881

119-
- When the filename is omitted, the following files will be tried in order:
82+
- When the a directory is given, the following files in the given directory will be tried in order:
12083

12184
- `scaffold.config.*`
12285
- `scaffold.*`
@@ -162,6 +125,12 @@ simple-scaffold -g git://gitlab.com/<username>/<project_name> [-c <filename>] [-
162125
simple-scaffold -g https://gitlab.com/<username>/<project_name>.git [-c <filename>] [-k <template_key>]
163126
```
164127

128+
When a config file path is omitted, the files given in the list above will be tried on the root
129+
directory of the git repository.
130+
131+
**Note:** The repository will be cloned to a temporary directory and removed after the scaffolding
132+
has been done.
133+
165134
## Use In Node.js
166135

167136
You can also start a scaffold from Node.js with a remote file or URL config.

src/config.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from "node:path"
2+
import fs from "node:fs/promises"
23
import {
34
ConfigLoadConfig,
45
FileResponse,
@@ -14,6 +15,7 @@ import { handlebarsParse } from "./parser"
1415
import { log } from "./logger"
1516
import { resolve, wrapNoopResolver } from "./utils"
1617
import { getGitConfig } from "./git"
18+
import { isDir, pathExists } from "./file"
1719

1820
/** @internal */
1921
export function getOptionValueForFile<T>(
@@ -68,7 +70,7 @@ export async function parseConfigFile(config: ScaffoldCmdConfig, tmpPath: string
6870
const configFilename = config.config
6971
const configPath = isGit ? config.git : configFilename
7072

71-
log(config, LogLevel.info, `Loading config from ${configFilename} with key ${key}`)
73+
log(config, LogLevel.info, `Loading config from file ${configFilename} with key ${key}`)
7274

7375
const configPromise = await (isGit
7476
? getRemoteConfig({ git: configPath, config: configFilename, logLevel: config.logLevel, tmpPath })
@@ -115,8 +117,22 @@ export function githubPartToUrl(part: string): string {
115117
export async function getLocalConfig(config: ConfigLoadConfig & Partial<LogConfig>): Promise<ScaffoldConfigFile> {
116118
const { config: configFile, ...logConfig } = config as Required<typeof config>
117119

118-
log(logConfig, LogLevel.info, `Loading config from file ${configFile}`)
119120
const absolutePath = path.resolve(process.cwd(), configFile)
121+
122+
const _isDir = await isDir(absolutePath)
123+
124+
if (_isDir) {
125+
log(logConfig, LogLevel.debug, `Resolving config file from directory ${absolutePath}`)
126+
const file = await findConfigFile(absolutePath)
127+
const exists = await pathExists(file)
128+
if (!exists) {
129+
throw new Error(`Could not find config file in directory ${absolutePath}`)
130+
}
131+
log(logConfig, LogLevel.info, `Loading config from: ${path.resolve(absolutePath, file)}`)
132+
return wrapNoopResolver(import(path.resolve(absolutePath, file)))
133+
}
134+
135+
log(logConfig, LogLevel.info, `Loading config from: ${absolutePath}`)
120136
return wrapNoopResolver(import(absolutePath))
121137
}
122138

@@ -138,3 +154,22 @@ export async function getRemoteConfig(
138154

139155
return getGitConfig(url, configFile, tmpPath, logConfig)
140156
}
157+
158+
/** @internal */
159+
export async function findConfigFile(root: string): Promise<string> {
160+
const allowed = ["mjs", "cjs", "js", "json"].reduce((acc, ext) => {
161+
acc.push(`scaffold.config.${ext}`)
162+
acc.push(`scaffold.${ext}`)
163+
return acc
164+
}, [] as string[])
165+
for (const file of allowed) {
166+
const exists = await fs
167+
.stat(path.resolve(root, file))
168+
.then(() => true)
169+
.catch(() => false)
170+
if (exists) {
171+
return file
172+
}
173+
}
174+
throw new Error(`Could not find config file in git repo`)
175+
}

src/git.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import path from "node:path"
2-
import fs from "node:fs/promises"
32
import { log } from "./logger"
43
import { AsyncResolver, LogConfig, LogLevel, ScaffoldCmdConfig, ScaffoldConfigMap } from "./types"
54
import { spawn } from "node:child_process"
65
import { resolve, wrapNoopResolver } from "./utils"
6+
import { findConfigFile } from "./config"
77

88
export async function getGitConfig(
99
url: URL,
@@ -60,22 +60,3 @@ export async function loadGitConfig({
6060
}
6161
return wrapNoopResolver(fixedConfig)
6262
}
63-
64-
/** @internal */
65-
export async function findConfigFile(root: string): Promise<string> {
66-
const allowed = ["mjs", "cjs", "js", "json"].reduce((acc, ext) => {
67-
acc.push(`scaffold.config.${ext}`)
68-
acc.push(`scaffold.${ext}`)
69-
return acc
70-
}, [] as string[])
71-
for (const file of allowed) {
72-
const exists = await fs
73-
.stat(path.resolve(root, file))
74-
.then(() => true)
75-
.catch(() => false)
76-
if (exists) {
77-
return file
78-
}
79-
}
80-
throw new Error(`Could not find config file in git repo`)
81-
}

0 commit comments

Comments
 (0)