mirror of
https://github.com/chenasraf/simple-scaffold.git
synced 2026-05-17 17:28:09 +00:00
update docs
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -42,6 +42,9 @@ typings/
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# NPM
|
||||
.npmrc
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
"typedocplugin"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
"build": "tsc && yarn copy-files && yarn post-build",
|
||||
"copy-files": "cp package.json build/",
|
||||
"postbuild": "rimraf node_modules"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
"cmd": "node --trace-warnings dist/cmd.js",
|
||||
"build-test": "yarn build && yarn test",
|
||||
"build-cmd": "yarn build && yarn cmd",
|
||||
"build-docs": "yarn build && yarn typedoc",
|
||||
"watch-docs": "yarn typedoc --watch",
|
||||
"audit-fix": "npm_config_yes=true npx yarn-audit-fix --flow=convert"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -54,4 +56,4 @@
|
||||
"typedoc": "^0.22.15",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +47,13 @@ import { LogLevel, ScaffoldConfig } from "./types"
|
||||
* Any functions you provide in `helpers` option will also be available to you to make custom formatting as you see fit
|
||||
* (for example, formatting a date)
|
||||
*
|
||||
* For available default values, see {@link DefaultHelperKeys}.
|
||||
* For available default values, see {@link DefaultHelpers}.
|
||||
*
|
||||
* @param {ScaffoldConfig} config The main configuration object
|
||||
*
|
||||
* @see {@link DefaultHelperKeys}
|
||||
* @see {@link DefaultHelpers}
|
||||
* @see {@link CaseHelpers}
|
||||
* @see {@link DateHelpers}
|
||||
*
|
||||
* @category Main
|
||||
*/
|
||||
@@ -66,7 +68,7 @@ export async function Scaffold(config: ScaffoldConfig): Promise<void> {
|
||||
try {
|
||||
const { nonGlobTemplate, origTemplate, isDirOrGlob, isGlob, template } = await getTemplateGlobInfo(
|
||||
config,
|
||||
_template
|
||||
_template,
|
||||
)
|
||||
const files = await getFileList(config, template)
|
||||
for (const inputFilePath of files) {
|
||||
@@ -101,7 +103,7 @@ export async function Scaffold(config: ScaffoldConfig): Promise<void> {
|
||||
}
|
||||
async function handleTemplateFile(
|
||||
config: ScaffoldConfig,
|
||||
{ templatePath, basePath }: { templatePath: string; basePath: string }
|
||||
{ templatePath, basePath }: { templatePath: string; basePath: string },
|
||||
): Promise<void> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
@@ -120,7 +122,7 @@ async function handleTemplateFile(
|
||||
`\nOutput Path Opt: ${outputPathOpt}`,
|
||||
`\nFull output dir: ${outputDir}`,
|
||||
`\nFull output path: ${outputPath}`,
|
||||
`\n`
|
||||
`\n`,
|
||||
)
|
||||
|
||||
await createDirIfNotExists(path.dirname(outputPath), config)
|
||||
|
||||
86
src/types.ts
86
src/types.ts
@@ -4,7 +4,9 @@ import { HelperDelegate } from "handlebars/runtime"
|
||||
* The config object for defining a scaffolding group.
|
||||
*
|
||||
* @see https://github.com/chenasraf/simple-scaffold#readme
|
||||
* @see {@link DefaultHelperKeys}
|
||||
* @see {@link DefaultHelpers}
|
||||
* @see {@link CaseHelpers}
|
||||
* @see {@link DateHelpers}
|
||||
*
|
||||
* @category Config
|
||||
*/
|
||||
@@ -95,7 +97,7 @@ export interface ScaffoldConfig {
|
||||
* 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
|
||||
* (text: string, ...args: any[]) => string
|
||||
* ```
|
||||
*
|
||||
* A full example might be:
|
||||
@@ -104,27 +106,47 @@ export interface ScaffoldConfig {
|
||||
* Scaffold({
|
||||
* //...
|
||||
* helpers: {
|
||||
* upperCamelCase: (text) => camelCase(text).toUpperCase()
|
||||
* upperKebabCase: (text) => kebabCase(text).toUpperCase()
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* See {@link DefaultHelperKeys} for a list of all the built-in available helpers.
|
||||
* Which will allow:
|
||||
*
|
||||
* @see https://github.com/chenasraf/simple-scaffold#helpers
|
||||
* @see https://github.com/chenasraf/simple-scaffold#built-in-helpers
|
||||
* ```
|
||||
* {{ upperKebabCase "my value" }}
|
||||
* ```
|
||||
*
|
||||
* To transform to:
|
||||
*
|
||||
* ```
|
||||
* MY-VALUE
|
||||
* ```
|
||||
*
|
||||
* See {@link DefaultHelpers} for a list of all the built-in available helpers.
|
||||
*
|
||||
* Simple Scaffold uses Handlebars.js, so all the syntax from there is supported. See
|
||||
* [their docs](https://handlebarsjs.com/guide/#custom-helpers) for more information.
|
||||
*
|
||||
* @see {@link DefaultHelpers}
|
||||
* @see {@link CaseHelpers}
|
||||
* @see {@link DateHelpers}
|
||||
* @see https://casraf.blog/simple-scaffold#helpers
|
||||
* @see https://casraf.blog/simple-scaffold#built-in-helpers
|
||||
* @see https://handlebarsjs.com/guide/#custom-helpers
|
||||
*/
|
||||
helpers?: Record<string, Helper>
|
||||
|
||||
/**
|
||||
* Default transformer to apply to subfolder name when using `createSubFolder: true`. Can be one of the default
|
||||
* capitalization helpers, or a custom one you provide to `helpers`. Defaults to `undefined`, which means no transformation is done.
|
||||
* capitalization helpers, or a custom one you provide to `helpers`. Defaults to `undefined`, which means no
|
||||
* transformation is done.
|
||||
*
|
||||
* @see {@link createSubFolder}
|
||||
* @see {@link CapitalizationHelperKeys}
|
||||
* @see {@link DefaultHelperKeys}
|
||||
* @see {@link CaseHelpers}
|
||||
* @see {@link DefaultHelpers}
|
||||
*/
|
||||
subFolderNameHelper?: DefaultHelperKeys | string
|
||||
subFolderNameHelper?: DefaultHelpers | string
|
||||
|
||||
/**
|
||||
* This callback runs right before content is being written to the disk. If you supply this function, you may return
|
||||
@@ -137,13 +159,13 @@ export interface ScaffoldConfig {
|
||||
* @param rawContent The original template before token replacement
|
||||
* @param outputPath The final output path of the processed file
|
||||
*
|
||||
* @returns {Promise<String | Buffer | undefined> | String | Buffer | undefined} The final output of the file contents-only, after further modifications -
|
||||
* or `undefined` to use the original content (i.e. `content.toString()`)
|
||||
* @returns {Promise<String | Buffer | undefined> | String | Buffer | undefined} The final output of the file
|
||||
* contents-only, after further modifications - or `undefined` to use the original content (i.e. `content.toString()`)
|
||||
*/
|
||||
beforeWrite?(
|
||||
content: Buffer,
|
||||
rawContent: Buffer,
|
||||
outputPath: string
|
||||
outputPath: string,
|
||||
): string | Buffer | undefined | Promise<string | Buffer | undefined>
|
||||
}
|
||||
|
||||
@@ -164,13 +186,14 @@ export interface ScaffoldConfig {
|
||||
* | `upperCase` | `{{ upperCase name }}` | MY NAME |
|
||||
* | `lowerCase` | `{{ lowerCase name }}` | my name |
|
||||
*
|
||||
* @see {@link DefaultHelpers}
|
||||
* @see {@link DateHelpers}
|
||||
* @see {@link ScaffoldConfig}
|
||||
* @see {@link subFolderNameHelper}
|
||||
* @see {@link DefaultHelperKeys}
|
||||
*
|
||||
* @category Helpers
|
||||
*/
|
||||
export type CapitalizationHelperKeys =
|
||||
export type CaseHelpers =
|
||||
| "camelCase"
|
||||
| "hyphenCase"
|
||||
| "kebabCase"
|
||||
@@ -191,11 +214,33 @@ export type CapitalizationHelperKeys =
|
||||
* | `date` (with offset) | Custom date with format, and with offset | `{{ date "2042-01-01T15:00:00Z" "yyyy-MM-dd HH:mm" -1 "days" }}` | `2041-31-12 15:00` |
|
||||
* | `date` (with date from `--data`) | Custom date with format, with data from the `data` config option | `{{ date myCustomDate "yyyy-MM-dd HH:mm" }}` | `2042-01-01 12:00` |
|
||||
*
|
||||
* @see {@link DefaultHelperKeys}
|
||||
* Further details:
|
||||
*
|
||||
* - We use [`date-fns`](https://date-fns.org/docs/) for parsing/manipulating the dates. If you want
|
||||
* more information on the date tokens to use, refer to
|
||||
* [their format documentation](https://date-fns.org/docs/format).
|
||||
*
|
||||
* - The date helper format takes the following arguments:
|
||||
*
|
||||
* ```typescript
|
||||
* (
|
||||
* date: string,
|
||||
* format: string,
|
||||
* offsetAmount?: number,
|
||||
* offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds"
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* - **The now helper** (for current time) takes the same arguments, minus the first one (`date`) as it is implicitly
|
||||
* the current date.
|
||||
*
|
||||
* @see {@link DefaultHelpers}
|
||||
* @see {@link CaseHelpers}
|
||||
* @see {@link ScaffoldConfig}
|
||||
*
|
||||
* @category Helpers
|
||||
*/
|
||||
export type DateHelperKeys = "date" | "now"
|
||||
export type DateHelpers = "date" | "now"
|
||||
|
||||
/**
|
||||
* The names of all the available helper functions in templates.
|
||||
@@ -204,12 +249,13 @@ export type DateHelperKeys = "date" | "now"
|
||||
* For example, you may use `{{ snakeCase name }}` inside a template file or filename, and it will
|
||||
* replace `My Name` with `my_name` when producing the final value.
|
||||
*
|
||||
* @see {@link CapitalizationHelperKeys}
|
||||
* @see {@link DateHelperKeys}
|
||||
* @see {@link CaseHelpers}
|
||||
* @see {@link DateHelpers}
|
||||
* @see {@link ScaffoldConfig}
|
||||
*
|
||||
* @category Helpers
|
||||
*/
|
||||
export type DefaultHelperKeys = CapitalizationHelperKeys | DateHelperKeys
|
||||
export type DefaultHelpers = CaseHelpers | DateHelpers
|
||||
|
||||
/**
|
||||
* Helper function, see https://handlebarsjs.com/guide/#custom-helpers
|
||||
|
||||
34
src/utils.ts
34
src/utils.ts
@@ -1,6 +1,6 @@
|
||||
import path from "path"
|
||||
import { F_OK } from "constants"
|
||||
import { DefaultHelperKeys, FileResponse, FileResponseHandler, Helper, LogLevel, ScaffoldConfig } from "./types"
|
||||
import { DefaultHelpers, FileResponse, FileResponseHandler, Helper, LogLevel, ScaffoldConfig } from "./types"
|
||||
import camelCase from "lodash/camelCase"
|
||||
import snakeCase from "lodash/snakeCase"
|
||||
import kebabCase from "lodash/kebabCase"
|
||||
@@ -23,7 +23,7 @@ import { glob } from "glob"
|
||||
import { promisify } from "util"
|
||||
const { readFile, writeFile } = fsPromises
|
||||
|
||||
export const defaultHelpers: Record<DefaultHelperKeys, Helper> = {
|
||||
export const defaultHelpers: Record<DefaultHelpers, Helper> = {
|
||||
camelCase,
|
||||
snakeCase,
|
||||
startCase,
|
||||
@@ -41,13 +41,13 @@ export function _dateHelper(
|
||||
date: Date,
|
||||
formatString: string,
|
||||
durationDifference: number,
|
||||
durationType: keyof Duration
|
||||
durationType: keyof Duration,
|
||||
): string
|
||||
export function _dateHelper(
|
||||
date: Date,
|
||||
formatString: string,
|
||||
durationDifference?: number,
|
||||
durationType?: keyof Duration
|
||||
durationType?: keyof Duration,
|
||||
): string {
|
||||
if (durationType && durationDifference !== undefined) {
|
||||
return dateFns.format(dateFns.add(date, { [durationType]: durationDifference }), formatString)
|
||||
@@ -66,14 +66,14 @@ export function dateHelper(
|
||||
date: string,
|
||||
formatString: string,
|
||||
durationDifference: number,
|
||||
durationType: keyof Duration
|
||||
durationType: keyof Duration,
|
||||
): string
|
||||
|
||||
export function dateHelper(
|
||||
date: string,
|
||||
formatString: string,
|
||||
durationDifference?: number,
|
||||
durationType?: keyof Duration
|
||||
durationType?: keyof Duration,
|
||||
): string {
|
||||
return _dateHelper(dateFns.parseISO(date), formatString, durationDifference!, durationType!)
|
||||
}
|
||||
@@ -110,8 +110,8 @@ export function log(config: ScaffoldConfig, level: LogLevel, ...obj: any[]): voi
|
||||
? chalkFn(i, JSON.stringify(i, undefined, 1), i.stack)
|
||||
: typeof i === "object"
|
||||
? chalkFn(JSON.stringify(i, undefined, 1))
|
||||
: chalkFn(i)
|
||||
)
|
||||
: chalkFn(i),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ export function getOptionValueForFile<T>(
|
||||
config: ScaffoldConfig,
|
||||
filePath: string,
|
||||
fn: FileResponse<T>,
|
||||
defaultValue?: T
|
||||
defaultValue?: T,
|
||||
): T {
|
||||
if (typeof fn !== "function") {
|
||||
return defaultValue ?? (fn as T)
|
||||
@@ -148,14 +148,14 @@ export function getOptionValueForFile<T>(
|
||||
return (fn as FileResponseHandler<T>)(
|
||||
filePath,
|
||||
path.dirname(handlebarsParse(config, filePath, { isPath: true }).toString()),
|
||||
path.basename(handlebarsParse(config, filePath, { isPath: true }).toString())
|
||||
path.basename(handlebarsParse(config, filePath, { isPath: true }).toString()),
|
||||
)
|
||||
}
|
||||
|
||||
export function handlebarsParse(
|
||||
config: ScaffoldConfig,
|
||||
templateBuffer: Buffer | string,
|
||||
{ isPath = false }: { isPath?: boolean } = {}
|
||||
{ isPath = false }: { isPath?: boolean } = {},
|
||||
): Buffer {
|
||||
const { data } = config
|
||||
try {
|
||||
@@ -255,7 +255,7 @@ export interface OutputFileInfo {
|
||||
|
||||
export async function getTemplateFileInfo(
|
||||
config: ScaffoldConfig,
|
||||
{ templatePath, basePath }: { templatePath: string; basePath: string }
|
||||
{ templatePath, basePath }: { templatePath: string; basePath: string },
|
||||
): Promise<OutputFileInfo> {
|
||||
const inputPath = path.resolve(process.cwd(), templatePath)
|
||||
const outputPathOpt = getOptionValueForFile(config, inputPath, config.output)
|
||||
@@ -279,7 +279,7 @@ export async function copyFileTransformed(
|
||||
overwrite: boolean
|
||||
outputPath: string
|
||||
inputPath: string
|
||||
}
|
||||
},
|
||||
): Promise<void> {
|
||||
if (!exists || overwrite) {
|
||||
if (exists && overwrite) {
|
||||
@@ -313,7 +313,7 @@ export function getOutputDir(config: ScaffoldConfig, outputPathOpt: string, base
|
||||
? handlebarsParse(config, `{{ ${config.subFolderNameHelper} name }}`).toString()
|
||||
: config.name
|
||||
: undefined,
|
||||
].filter(Boolean) as string[])
|
||||
].filter(Boolean) as string[]),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ export function logInputFile(
|
||||
basePath: string
|
||||
isDirOrGlob: boolean
|
||||
isGlob: boolean
|
||||
}
|
||||
},
|
||||
): void {
|
||||
log(
|
||||
config,
|
||||
@@ -351,7 +351,7 @@ export function logInputFile(
|
||||
`\nbasePath: ${basePath}`,
|
||||
`\nisDirOrGlob: ${isDirOrGlob}`,
|
||||
`\nisGlob: ${isGlob}`,
|
||||
`\n`
|
||||
`\n`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ export function logInitStep(config: ScaffoldConfig): void {
|
||||
subFolderTransformHelper: config.subFolderNameHelper,
|
||||
helpers: Object.keys(config.helpers ?? {}),
|
||||
verbose: `${config.verbose} (${Object.keys(LogLevel).find(
|
||||
(k) => (LogLevel[k as any] as unknown as number) === config.verbose!
|
||||
(k) => (LogLevel[k as any] as unknown as number) === config.verbose!,
|
||||
)})`,
|
||||
})
|
||||
log(config, LogLevel.Info, "Data:", config.data)
|
||||
|
||||
Reference in New Issue
Block a user