Skip to content

Commit c316bba

Browse files
authored
refactor: implement suggested improvements to codebase (#287)
* docs: update code review document with resolved issues and new findings * chore: add copyright notice and license information to `types.ts` file * docs: update code review document to reflect resolution of critical issues * chore: remove unused rule for test files in ESLint configuration * fix: ensure `appName` is a string and handle generation errors in `icons` command * fix: validate `appName` type and improve error handling in splashscreen generation * test: update exit code check in E2E tests for `icons` command completion to reflect generation errors * docs: update status of resolved issues in code review document * refactor: move `CLI_BIN` constant to `constants.ts` file for better organization * refactor: add comment to clarify idempotency of `mkdir` for concurrent execution in Android icon generation * refactor: add JSDoc comments for `extractAppName`, `checkAssetFile`, and `mkdirp` functions for better documentation * docs: update status of resolved issues in code review document for clarity * docs: update code review document with resolved issues and overall assessment
1 parent cd07a16 commit c316bba

10 files changed

Lines changed: 203 additions & 128 deletions

File tree

docs/005-CODE-REVIEW-IMPROVEMENTS.md

Lines changed: 156 additions & 116 deletions
Large diffs are not rendered by default.

eslint.config.mjs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,4 @@ export default [
77
},
88
...tseslint.configs.recommended,
99
prettier,
10-
{
11-
// Test files use Chai's expect().to.be.true style which triggers this rule
12-
files: ["test/**/*.ts"],
13-
rules: {
14-
"@typescript-eslint/no-unused-expressions": "off",
15-
},
16-
},
1710
];

src/cli/help.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
77
*/
88

9+
import { CLI_BIN } from '../constants.js'
910
import type { CommandConfig } from './types.js'
1011

11-
const CLI_BIN = 'rn-toolbox'
12-
1312
/**
1413
* Generates help text for a single command
1514
*/

src/commands/icons.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ The template icon file should be at least 1024x1024px.`,
6262
public async execute(parsed: ParsedArgs): Promise<void> {
6363
const { args, flags } = parsed
6464
const file = args.file!
65-
const appName = flags.appName as string | undefined
65+
const appName = typeof flags.appName === 'string' ? flags.appName : undefined
6666

6767
const sourceFilesExists = checkAssetFile(file)
6868
if (!sourceFilesExists) {
@@ -89,6 +89,10 @@ The template icon file should be at least 1024x1024px.`,
8989
for (const err of this.errors) {
9090
this.log(` - ${err}`)
9191
}
92+
this.error(
93+
`Failed to generate ${this.errors.length} asset(s)`,
94+
ExitCode.GENERATION_ERROR
95+
)
9296
}
9397

9498
this.log(green('✔'), `Generated icons for '${cyan(appName)}' app.`)
@@ -145,6 +149,7 @@ The template icon file should be at least 1024x1024px.`,
145149
private async generateAndroidIconsWithDensity(inputPath: string, outputDir: string, density: string, size: number) {
146150
const densityFolderPath = join(outputDir, `mipmap-${density}`)
147151

152+
// Safe for concurrent execution - mkdir with recursive:true is idempotent
148153
await mkdirp(densityFolderPath)
149154

150155
this.logVerbose(yellow('≈'), cyan('Android'), `Generating icons for density '${density}'...`)

src/commands/splash.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ The template splashscreen file should be at least 1242x2208px.`,
6161
public async execute(parsed: ParsedArgs): Promise<void> {
6262
const { args, flags } = parsed
6363
const file = args.file!
64-
const appName = flags.appName as string | undefined
64+
const appName = typeof flags.appName === 'string' ? flags.appName : undefined
6565

6666
const sourceFilesExists = checkAssetFile(file)
6767
if (!sourceFilesExists) {
@@ -88,6 +88,10 @@ The template splashscreen file should be at least 1242x2208px.`,
8888
for (const err of this.errors) {
8989
this.log(` - ${err}`)
9090
}
91+
this.error(
92+
`Failed to generate ${this.errors.length} asset(s)`,
93+
ExitCode.GENERATION_ERROR
94+
)
9195
}
9296

9397
this.log(green('✔'), `Generated splashscreens for '${cyan(appName)}' app.`)

src/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
import type { IconSizeAndroid, IconSizeIOS, SplashscreenSize } from "./types.js"
1010

11+
/**
12+
* CLI binary name
13+
*/
14+
export const CLI_BIN = 'rn-toolbox'
15+
1116
/**
1217
* Android Assets Sizes
1318
*/

src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
/*
2+
* Copyright (c) 2025 ForWarD Software (https://forwardsoftware.solutions/)
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
19
export interface SplashscreenSize {
210
density?: string;
311
height: number;

src/utils/app.utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88

99
import {readFile} from 'node:fs/promises'
1010

11+
/**
12+
* Extracts the app name from app.json in the current directory.
13+
*
14+
* @returns The app name if found and valid, undefined otherwise
15+
* @example
16+
* const name = await extractAppName()
17+
* if (name) {
18+
* console.log(`Found app: ${name}`)
19+
* }
20+
*/
1121
export async function extractAppName(): Promise<string | undefined> {
1222
try {
1323
const content = await readFile('./app.json', {encoding: 'utf8'})

src/utils/file-utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,21 @@
99
import { existsSync } from 'node:fs'
1010
import { mkdir } from 'node:fs/promises'
1111

12+
/**
13+
* Checks if an asset file exists at the specified path.
14+
*
15+
* @param filePath - The path to the asset file
16+
* @returns true if the file exists, false otherwise
17+
*/
1218
export function checkAssetFile(filePath: string): boolean {
1319
return existsSync(filePath)
1420
}
1521

22+
/**
23+
* Creates a directory and all necessary parent directories.
24+
*
25+
* @param path - The path to create
26+
*/
1627
export async function mkdirp(path: string): Promise<void> {
1728
await mkdir(path, { recursive: true })
1829
}

test/e2e/cli.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ describe('CLI E2E', () => {
267267
})
268268

269269
// Command completes but reports failures
270-
assert.equal(exitCode, ExitCode.SUCCESS)
270+
assert.equal(exitCode, ExitCode.GENERATION_ERROR)
271271
assert.ok(stdout.includes('Warning') || stdout.includes('Failed'))
272272
assert.ok(stdout.includes('asset') || stdout.includes('generate'))
273273
})

0 commit comments

Comments
 (0)