mirror of
https://github.com/chenasraf/simple-scaffold.git
synced 2026-05-18 01:29:09 +00:00
Compare commits
2 Commits
v1.0.0-alp
...
v1.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d630e7e62 | ||
|
|
7073add836 |
20
MIGRATION.md
Normal file
20
MIGRATION.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Migrating from 0.x to 1.0
|
||||
|
||||
In Simple Scaffold v1.0, the entire codebase was overhauled, yet usage remains mostly the same
|
||||
between versions. With these notable exceptions:
|
||||
|
||||
- Some of the argument names have changed
|
||||
- Template syntax has been improved
|
||||
|
||||
## Argument changes
|
||||
|
||||
- `locals` has been renamed to `data`. The appropriate command line args have been updated as
|
||||
well to `--data` | `-d`.
|
||||
|
||||
## Template syntax changes
|
||||
|
||||
Simple Scaffold still uses Handlebars.js to handle template content and file names. However, helpers
|
||||
have been added to remove the need for you to pre-process the template data on simple use-cases such
|
||||
as case type manipulation (converting to camel case, snake case, etc)
|
||||
|
||||
See the readme for the full information on how to use these helpers and which are available.
|
||||
40
README.md
40
README.md
@@ -102,18 +102,30 @@ const scaffold = SimpleScaffold({
|
||||
locals: {
|
||||
property: "value",
|
||||
},
|
||||
helpers: {
|
||||
twice: (text) => [text, text].join(" ")
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The exception in the config is that `output`, when used in Node directly, may also be passed a
|
||||
function for each input file to output into a dynamic path:
|
||||
### Additional Node.js options
|
||||
|
||||
```typescript
|
||||
config.output = (fullPath, baseDir, baseName) => {
|
||||
console.log({ fullPath, baseDir, baseName })
|
||||
return path.resolve(baseDir, baseName)
|
||||
}
|
||||
```
|
||||
In addition to all the options available in the command line, there are some JS-specific options
|
||||
available:
|
||||
|
||||
1. When `output` is used in Node directly, it may also be passed a function for each input file to
|
||||
output into a dynamic path:
|
||||
|
||||
```typescript
|
||||
config.output = (fullPath, baseDir, baseName) => {
|
||||
console.log({ fullPath, baseDir, baseName })
|
||||
return path.resolve(baseDir, baseName)
|
||||
}
|
||||
```
|
||||
|
||||
2. You may add custom `helpers` to your scaffolds. Helpers are simple `(string) => string` functions
|
||||
that transform your `data` variables into other values. See [Helpers](#helpers) for the list of
|
||||
default helpers, or add your own to be loaded into the template parser.
|
||||
|
||||
## Preparing files
|
||||
|
||||
@@ -156,9 +168,21 @@ Here are the built-in helpers available for use:
|
||||
| kebabCase | `{{ kebabCase name }}` | my-name |
|
||||
| hyphenCase | `{{ hyphenCase name }}` | my-name |
|
||||
| pascalCase | `{{ pascalCase name }}` | MyName |
|
||||
| upperCase | `{{ upperCase name }}` | MYNAME |
|
||||
| lowerCase | `{{ lowerCase name }}` | myname |
|
||||
|
||||
> These helpers are available for any data property, not exclusive to `name`.
|
||||
|
||||
You may also add your own custom helpers using the `helpers` options when using the JS API (rather
|
||||
than the CLI). The `helpers` option takes an object whose keys are helper names, and values are
|
||||
the transformation functions. For example, `upperCase` is implemented like so:
|
||||
|
||||
```typescript
|
||||
config.helpers = {
|
||||
upperCase: (text) => text.toUpperCase(),
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Command Example
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-scaffold",
|
||||
"version": "1.0.0-alpha.12",
|
||||
"version": "1.0.0-alpha.13",
|
||||
"description": "Create files based on templates",
|
||||
"repository": "https://github.com/chenasraf/simple-scaffold.git",
|
||||
"author": "Chen Asraf <inbox@casraf.com>",
|
||||
@@ -23,7 +23,7 @@
|
||||
"glob": "^7.1.3",
|
||||
"handlebars": "^4.7.7",
|
||||
"lodash": "^4.17.21",
|
||||
"massarg": "^1.0.4",
|
||||
"massarg": "^1.0.5",
|
||||
"util.promisify": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
isDir,
|
||||
removeGlob,
|
||||
makeRelativePath,
|
||||
registerHelpers,
|
||||
} from "./utils"
|
||||
import { LogLevel, ScaffoldConfig } from "./types"
|
||||
|
||||
@@ -30,6 +31,7 @@ export async function Scaffold(config: ScaffoldConfig) {
|
||||
data: options.data,
|
||||
overwrite: options.overwrite,
|
||||
quiet: options.quiet,
|
||||
helpers: Object.keys(options.helpers ?? {}),
|
||||
verbose: `${options.verbose} (${Object.keys(LogLevel).find(
|
||||
(k) => (LogLevel[k as any] as unknown as number) === options.verbose!
|
||||
)})`,
|
||||
@@ -37,6 +39,7 @@ export async function Scaffold(config: ScaffoldConfig) {
|
||||
log(options, LogLevel.Info, "Data:", data)
|
||||
for (let template of config.templates) {
|
||||
try {
|
||||
registerHelpers(options)
|
||||
const _isGlob = template.includes("*")
|
||||
if (!_isGlob && !(await pathExists(template))) {
|
||||
const err: NodeJS.ErrnoException = new Error(`ENOENT, no such file or directory ${template}`)
|
||||
|
||||
20
src/types.ts
20
src/types.ts
@@ -61,6 +61,26 @@ export interface ScaffoldConfig {
|
||||
* actual file contents or create directories. (default: `false`)
|
||||
*/
|
||||
dryRun?: boolean
|
||||
|
||||
/**
|
||||
* Additional helpers to add to the template parser. Provide an object whose keys are the name of the function to add,
|
||||
* and the value is the helper function itself. The signature of helpers is as follows:
|
||||
* ```typescript
|
||||
* (text: string) => string
|
||||
* ```
|
||||
*
|
||||
* A full example might be:
|
||||
*
|
||||
* ```typescript
|
||||
* Scaffold({
|
||||
* //...
|
||||
* helpers: {
|
||||
* upperCamelCase: (text) => camelCase(text).toUpperCase()
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
helpers?: Record<string, (text: string) => string>
|
||||
}
|
||||
export interface ScaffoldCmdConfig {
|
||||
name: string
|
||||
|
||||
12
src/utils.ts
12
src/utils.ts
@@ -10,17 +10,23 @@ import { promises as fsPromises } from "fs"
|
||||
import chalk from "chalk"
|
||||
const { stat, access, mkdir } = fsPromises
|
||||
|
||||
const helpers = {
|
||||
export const defaultHelpers: Exclude<ScaffoldConfig["helpers"], undefined> = {
|
||||
camelCase,
|
||||
snakeCase,
|
||||
startCase,
|
||||
kebabCase,
|
||||
hyphenCase: kebabCase,
|
||||
pascalCase,
|
||||
lowerCase: (text) => text.toLowerCase(),
|
||||
upperCase: (text) => text.toUpperCase(),
|
||||
}
|
||||
|
||||
for (const helperName in helpers) {
|
||||
Handlebars.registerHelper(helperName, helpers[helperName as keyof typeof helpers])
|
||||
export function registerHelpers(options: ScaffoldConfig) {
|
||||
const _helpers = { ...defaultHelpers, ...options.helpers }
|
||||
for (const helperName in _helpers) {
|
||||
log(options, LogLevel.Debug, `Registering helper: ${helperName}`)
|
||||
Handlebars.registerHelper(helperName, _helpers[helperName as keyof typeof _helpers])
|
||||
}
|
||||
}
|
||||
|
||||
export function handleErr(err: NodeJS.ErrnoException | null) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import FileSystem from "mock-fs/lib/filesystem"
|
||||
import Scaffold from "../src/scaffold"
|
||||
import { readdirSync, readFileSync } from "fs"
|
||||
import { Console } from "console"
|
||||
import { defaultHelpers } from "../src/utils"
|
||||
|
||||
const fileStructNormal = {
|
||||
input: {
|
||||
@@ -30,6 +31,20 @@ const fileStructNested = {
|
||||
},
|
||||
output: {},
|
||||
}
|
||||
|
||||
const defaultHelperNames = Object.keys(defaultHelpers)
|
||||
const fileStructHelpers = {
|
||||
input: {
|
||||
defaults: defaultHelperNames.reduce<Record<string, string>>(
|
||||
(all, cur) => ({ ...all, [cur + ".txt"]: `{{ ${cur} name }}` }),
|
||||
{}
|
||||
),
|
||||
custom: {
|
||||
"add1.txt": "{{ add1 name }}",
|
||||
},
|
||||
},
|
||||
output: {},
|
||||
}
|
||||
// let logsTemp: any = []
|
||||
// let logMock: any
|
||||
function withMock(fileStruct: FileSystem.DirectoryItems, testFn: jest.EmptyFunction): jest.EmptyFunction {
|
||||
@@ -202,4 +217,59 @@ describe("Scaffold", () => {
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
describe(
|
||||
"helpers",
|
||||
withMock(fileStructHelpers, () => {
|
||||
const _helpers: Record<string, (text: string) => string> = {
|
||||
add1: (text) => text + " 1",
|
||||
}
|
||||
|
||||
describe("default helpers", () => {
|
||||
test("should work", async () => {
|
||||
await Scaffold({
|
||||
name: "app_name",
|
||||
output: "output",
|
||||
templates: ["input"],
|
||||
verbose: 0,
|
||||
helpers: _helpers,
|
||||
})
|
||||
|
||||
const results = {
|
||||
camelCase: "appName",
|
||||
snakeCase: "app_name",
|
||||
startCase: "App Name",
|
||||
kebabCase: "app-name",
|
||||
hyphenCase: "app-name",
|
||||
pascalCase: "AppName",
|
||||
lowerCase: "app_name",
|
||||
upperCase: "APP_NAME",
|
||||
}
|
||||
for (const key in results) {
|
||||
const file = readFileSync(process.cwd() + `/output/defaults/${key}.txt`)
|
||||
expect(file.toString()).toEqual(results[key as keyof typeof results])
|
||||
}
|
||||
})
|
||||
})
|
||||
describe("custom helpers", () => {
|
||||
test("should work", async () => {
|
||||
await Scaffold({
|
||||
name: "app_name",
|
||||
output: "output",
|
||||
templates: ["input"],
|
||||
verbose: 0,
|
||||
helpers: _helpers,
|
||||
})
|
||||
|
||||
const results = {
|
||||
add1: "app_name 1",
|
||||
}
|
||||
for (const key in results) {
|
||||
const file = readFileSync(process.cwd() + `/output/custom/${key}.txt`)
|
||||
expect(file.toString()).toEqual(results[key as keyof typeof results])
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
12
yarn.lock
12
yarn.lock
@@ -932,7 +932,7 @@ chalk@2.4.2, chalk@^2.0.0:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.1:
|
||||
chalk@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
|
||||
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
|
||||
@@ -2161,12 +2161,12 @@ makeerror@1.0.x:
|
||||
dependencies:
|
||||
tmpl "1.0.x"
|
||||
|
||||
massarg@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/massarg/-/massarg-1.0.4.tgz#8756193bee9bc7331b1f48a8840e86acf808f980"
|
||||
integrity sha512-SakImNzZP8SN6tlcGBoC62z+12yv/To+h7KP8XapnOux5Mjiwprn4KhNHsjh2rbrKCAPqZQWYziAitSzGTkjMw==
|
||||
massarg@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/massarg/-/massarg-1.0.5.tgz#3dfd49bb63bfca4b0371a2f0ffc7580a9a6cc7a0"
|
||||
integrity sha512-gkJHZsNfeMurpVPKojCiT2lnG2cSxHPAXZSg+gCLIgCf5bGn7pKOsoeu4qVAc5mlBxV2l/hA1yojt+ZsJd8SDg==
|
||||
dependencies:
|
||||
chalk "^4.1.1"
|
||||
chalk "^4.1.2"
|
||||
lodash "^4.17.21"
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
|
||||
Reference in New Issue
Block a user