From dcba30689b81406a2319df6f11a5b96e754f52b9 Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Thu, 19 Jun 2025 01:28:15 +0300 Subject: [PATCH] chore: update formatting & lints --- eslint.config.mjs | 2 +- src/cmd.ts | 2 +- src/file.ts | 59 ++++++++++++++++++++---------------------- src/logger.ts | 4 +-- src/scaffold.ts | 10 +++---- src/types.ts | 4 +-- tests/config.test.ts | 4 +++ tests/parser.test.ts | 15 ++++++++++- tests/scaffold.test.ts | 7 +++-- tests/utils.test.ts | 13 +++++----- 10 files changed, 69 insertions(+), 51 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 06298dd..c8671af 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,7 @@ export default [ ...tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended), { rules: { - 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': [ 'warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, diff --git a/src/cmd.ts b/src/cmd.ts index b2dc594..3226329 100644 --- a/src/cmd.ts +++ b/src/cmd.ts @@ -188,7 +188,7 @@ export async function parseCliArgs(args = process.argv.slice(2)) { console.log(colorize.underline`Available templates:\n`) console.log(Object.keys(file).join("\n")) } catch (e) { - const message = "message" in (e as any) ? (e as any).message : e?.toString() + const message = "message" in (e as object) ? (e as Error).message : e?.toString() log(config, LogLevel.error, message) } finally { log(config, LogLevel.debug, "Cleaning up temporary files...", config.tmpDir) diff --git a/src/file.ts b/src/file.ts index 3a25a41..7776a5d 100644 --- a/src/file.ts +++ b/src/file.ts @@ -30,8 +30,8 @@ export async function createDirIfNotExists( log(config, LogLevel.debug, `Creating dir ${dir}`) await mkdir(dir) return - } catch (e: any) { - if (e.code !== "EEXIST") { + } catch (e: unknown) { + if (e && (e as NodeJS.ErrnoException).code !== "EEXIST") { throw e } return @@ -43,8 +43,8 @@ export async function pathExists(filePath: string): Promise { try { await access(filePath, F_OK) return true - } catch (e: any) { - if (e.code === "ENOENT") { + } catch (e: unknown) { + if (e && (e as NodeJS.ErrnoException).code === "ENOENT") { return false } throw e @@ -181,36 +181,33 @@ export async function handleTemplateFile( config: ScaffoldConfig, { templatePath, basePath }: { templatePath: string; basePath: string }, ): Promise { - return new Promise(async (resolve, reject) => { - try { - const { inputPath, outputPathOpt, outputDir, outputPath, exists } = await getTemplateFileInfo(config, { - templatePath, - basePath, - }) - const overwrite = getOptionValueForFile(config, inputPath, config.overwrite ?? false) + try { + const { inputPath, outputPathOpt, outputDir, outputPath, exists } = await getTemplateFileInfo(config, { + templatePath, + basePath, + }) + const overwrite = getOptionValueForFile(config, inputPath, config.overwrite ?? false) - log( - config, - LogLevel.debug, - `\nParsing ${templatePath}`, - `\nBase path: ${basePath}`, - `\nFull input path: ${inputPath}`, - `\nOutput Path Opt: ${outputPathOpt}`, - `\nFull output dir: ${outputDir}`, - `\nFull output path: ${outputPath}`, - `\n`, - ) + log( + config, + LogLevel.debug, + `\nParsing ${templatePath}`, + `\nBase path: ${basePath}`, + `\nFull input path: ${inputPath}`, + `\nOutput Path Opt: ${outputPathOpt}`, + `\nFull output dir: ${outputDir}`, + `\nFull output path: ${outputPath}`, + `\n`, + ) - await createDirIfNotExists(path.dirname(outputPath), config) + await createDirIfNotExists(path.dirname(outputPath), config) - log(config, LogLevel.info, `Writing to ${outputPath}`) - await copyFileTransformed(config, { exists, overwrite, outputPath, inputPath }) - resolve() - } catch (e: any) { - handleErr(e) - reject(e) - } - }) + log(config, LogLevel.info, `Writing to ${outputPath}`) + await copyFileTransformed(config, { exists, overwrite, outputPath, inputPath }) + } catch (e: unknown) { + handleErr(e as NodeJS.ErrnoException) + throw e + } } /** @internal */ diff --git a/src/logger.ts b/src/logger.ts index 2014608..ca155fd 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -2,7 +2,7 @@ import util from "util" import { LogConfig, LogLevel, ScaffoldConfig } from "./types" import { colorize, TermColor } from "./utils" -export function log(config: LogConfig, level: LogLevel, ...obj: any[]): void { +export function log(config: LogConfig, level: LogLevel, ...obj: unknown[]): void { const priority: Record = { [LogLevel.none]: 0, [LogLevel.debug]: 1, @@ -25,7 +25,7 @@ export function log(config: LogConfig, level: LogLevel, ...obj: any[]): void { const colorFn = colorize[levelColor[level]] const key: "log" | "warn" | "error" = level === LogLevel.error ? "error" : level === LogLevel.warning ? "warn" : "log" - const logFn: any = console[key] + const logFn: (..._args: unknown[]) => void = console[key] logFn( ...obj.map((i) => i instanceof Error diff --git a/src/scaffold.ts b/src/scaffold.ts index 7ac6f64..e50ca8d 100644 --- a/src/scaffold.ts +++ b/src/scaffold.ts @@ -65,15 +65,15 @@ export async function Scaffold(config: ScaffoldConfig): Promise { const excludes = config.templates.filter((t) => t.startsWith("!")) const includes = config.templates.filter((t) => !t.startsWith("!")) const templates: GlobInfo[] = [] - for (let _template of includes) { + for (const includedTemplate of includes) { try { const { nonGlobTemplate, origTemplate, isDirOrGlob, isGlob, template } = await getTemplateGlobInfo( config, - _template, + includedTemplate, ) templates.push({ nonGlobTemplate, origTemplate, isDirOrGlob, isGlob, template }) - } catch (e: any) { - handleErr(e) + } catch (e: unknown) { + handleErr(e as NodeJS.ErrnoException) } } for (const tpl of templates) { @@ -101,7 +101,7 @@ export async function Scaffold(config: ScaffoldConfig): Promise { }) } } - } catch (e: any) { + } catch (e: unknown) { log(config, LogLevel.error, e) throw e } diff --git a/src/types.ts b/src/types.ts index 3421b27..ea13df2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -56,7 +56,7 @@ export interface ScaffoldConfig { * * This can be any object that will be usable by Handlebars. */ - data?: Record + data?: Record /** * Enable to override output files, even if they already exist. @@ -411,7 +411,7 @@ export type ScaffoldConfigMap = Record export type ScaffoldConfigFile = AsyncResolver /** @internal */ -export type Resolver = R | ((value: T) => R) +export type Resolver = R | ((_value: T) => R) /** @internal */ export type AsyncResolver = Resolver | R> diff --git a/tests/config.test.ts b/tests/config.test.ts index 60148d4..5161400 100644 --- a/tests/config.test.ts +++ b/tests/config.test.ts @@ -78,6 +78,7 @@ describe("config", () => { }), ).toEqual({ ...conf, name: "-", tmpDir, subdirHelper: undefined, beforeWrite: undefined }) }) + describe("appendData", () => { test("appends", async () => { const result = await parseConfigFile({ @@ -88,6 +89,7 @@ describe("config", () => { }) expect(result?.data?.key).toEqual("value") }) + test("overwrites existing value", async () => { const result = await parseConfigFile({ ...blankCliConf, @@ -98,6 +100,7 @@ describe("config", () => { }) expect(result?.data?.num).toEqual("1234") }) + test("CLI output overrides config file output", async () => { const tmpDir = `/tmp/scaffold-config-${Date.now()}` @@ -171,6 +174,7 @@ describe("config", () => { for (const struct of [struct1, struct2, struct3, struct4]) { const [k] = Object.keys(struct) + describe(`finds config file ${k}`, () => { withMock(struct, async () => { const result = await findConfigFile(process.cwd()) diff --git a/tests/parser.test.ts b/tests/parser.test.ts index dc6afc0..732fdbe 100644 --- a/tests/parser.test.ts +++ b/tests/parser.test.ts @@ -13,35 +13,43 @@ const blankConf: ScaffoldConfig = { describe("parser", () => { describe("handlebarsParse", () => { - let origSep: any + let origSep: string + describe("windows paths", () => { beforeAll(() => { origSep = path.sep Object.defineProperty(path, "sep", { value: "\\" }) }) + afterAll(() => { Object.defineProperty(path, "sep", { value: origSep }) }) + test("should work for windows paths", async () => { expect(handlebarsParse(blankConf, "C:\\exports\\{{name}}.txt", { asPath: true }).toString()).toEqual( "C:\\exports\\test.txt", ) }) }) + describe("non-windows paths", () => { + beforeAll(() => { origSep = path.sep Object.defineProperty(path, "sep", { value: "/" }) }) + afterAll(() => { Object.defineProperty(path, "sep", { value: origSep }) }) + test("should work for non-windows paths", async () => { expect(handlebarsParse(blankConf, "/home/test/{{name}}.txt", { asPath: true })).toEqual( Buffer.from("/home/test/test.txt"), ) }) }) + test("should not do path escaping on non-path compiles", async () => { expect( handlebarsParse( @@ -65,6 +73,7 @@ describe("parser", () => { expect(defaultHelpers.camelCase("TestString")).toEqual("testString") expect(defaultHelpers.camelCase("Test____String")).toEqual("testString") }) + test("pascalCase", () => { expect(defaultHelpers.pascalCase("test string")).toEqual("TestString") expect(defaultHelpers.pascalCase("test_string")).toEqual("TestString") @@ -73,6 +82,7 @@ describe("parser", () => { expect(defaultHelpers.pascalCase("TestString")).toEqual("TestString") expect(defaultHelpers.pascalCase("Test____String")).toEqual("TestString") }) + test("snakeCase", () => { expect(defaultHelpers.snakeCase("test string")).toEqual("test_string") expect(defaultHelpers.snakeCase("test_string")).toEqual("test_string") @@ -81,6 +91,7 @@ describe("parser", () => { expect(defaultHelpers.snakeCase("TestString")).toEqual("test_string") expect(defaultHelpers.snakeCase("Test____String")).toEqual("test_string") }) + test("kebabCase", () => { expect(defaultHelpers.kebabCase("test string")).toEqual("test-string") expect(defaultHelpers.kebabCase("test_string")).toEqual("test-string") @@ -89,6 +100,7 @@ describe("parser", () => { expect(defaultHelpers.kebabCase("TestString")).toEqual("test-string") expect(defaultHelpers.kebabCase("Test____String")).toEqual("test-string") }) + test("startCase", () => { expect(defaultHelpers.startCase("test string")).toEqual("Test String") expect(defaultHelpers.startCase("test_string")).toEqual("Test String") @@ -98,6 +110,7 @@ describe("parser", () => { expect(defaultHelpers.startCase("Test____String")).toEqual("Test String") }) }) + describe("date helpers", () => { describe("now", () => { test("should work without extra params", () => { diff --git a/tests/scaffold.test.ts b/tests/scaffold.test.ts index 3ae1d82..0b4d352 100644 --- a/tests/scaffold.test.ts +++ b/tests/scaffold.test.ts @@ -99,8 +99,10 @@ function withMock(fileStruct: FileSystem.DirectoryItems, testFn: jest.EmptyFunct } describe("Scaffold", () => { + describe( "create subdir", + withMock(fileStructNormal, () => { test("should not create by default", async () => { await Scaffold({ @@ -130,6 +132,7 @@ describe("Scaffold", () => { describe( "binary files", + withMock(fileStructWithBinary, () => { test("should copy as-is", async () => { await Scaffold({ @@ -322,7 +325,7 @@ describe("Scaffold", () => { describe( "capitalization helpers", withMock(fileStructHelpers, () => { - const _helpers: Record string> = { + const _helpers: Record string> = { add1: (text) => text + " 1", } @@ -394,7 +397,7 @@ describe("Scaffold", () => { describe( "custom helpers", withMock(fileStructHelpers, () => { - const _helpers: Record string> = { + const _helpers: Record string> = { add1: (text) => text + " 1", } test("should work", async () => { diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 30ee2b2..ef2b1eb 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -5,6 +5,7 @@ describe("utils", () => { expect(resolve(() => 1, null)).toBe(1) expect(resolve((x) => x, 2)).toBe(2) }) + test("should resolve value", () => { expect(resolve(1, null)).toBe(1) expect(resolve(2, 1)).toBe(2) @@ -20,22 +21,22 @@ describe("utils", () => { }) describe("colorize", () => { - it("should colorize text with red color", () => { + test("should colorize text with red color", () => { const result = colorize("Hello", "red") expect(result).toBe("\x1b[31mHello\x1b[0m") }) - it("should colorize text with bold", () => { + test("should colorize text with bold", () => { const result = colorize("Hello", "bold") expect(result).toBe("\x1b[1mHello\x1b[23m") }) - it("should reset color", () => { + test("should reset color", () => { const result = colorize("Hello", "reset") expect(result).toBe("\x1b[0mHello\x1b[0m") }) - it("should have all color functions", () => { + test("should have all color functions", () => { const colors: TermColor[] = [ "reset", "dim", @@ -56,12 +57,12 @@ describe("colorize", () => { }) }) - it("should colorize text using colorize.red", () => { + test("should colorize text using colorize.red", () => { const result = colorize.red("Hello") expect(result).toBe("\x1b[31mHello\x1b[0m") }) - it("should colorize text using template strings with colorize.blue", () => { + test("should colorize text using template strings with colorize.blue", () => { const result = colorize.blue`Hello ${"World"}` expect(result).toBe("\x1b[34mHello World\x1b[0m") })