From cdd816787d936298cf55fe964a89d8ce92d8e1c9 Mon Sep 17 00:00:00 2001 From: Kevin Deng Date: Thu, 21 May 2026 19:58:52 +0900 Subject: [PATCH] refactor: inline trivial helper functions --- src/commands.ts | 43 +++++++++++++----------------------- src/optimizer.ts | 6 +---- src/scan.ts | 8 ------- src/utils/expression.ts | 15 +++++-------- src/utils/fs.ts | 37 +++++++++---------------------- src/utils/github.ts | 7 ++---- src/utils/ref.ts | 11 ++++----- src/utils/substitute.ts | 9 +------- src/utils/workflow-parser.ts | 13 ++--------- src/utils/yaml.ts | 6 +---- 10 files changed, 41 insertions(+), 114 deletions(-) diff --git a/src/commands.ts b/src/commands.ts index 983eb0a..180325a 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -2,12 +2,7 @@ import { execFile } from 'node:child_process' import { promisify } from 'node:util' import { pack, packScanned, verify } from './pack.ts' import { scan } from './scan.ts' -import { - discoverConfig, - LOCKFILE_PATH, - readLockfile, - resolveCwd, -} from './utils/fs.ts' +import { LOCKFILE_PATH, readLockfile, resolveCwd } from './utils/fs.ts' import { matchesPackageSelector } from './utils/ref.ts' import { stringifyYaml } from './utils/yaml.ts' import type { @@ -66,10 +61,20 @@ export async function why( } } - const output = - paths.length === 0 - ? `${packageName} is not reachable\n` - : `${packageName} is used by:\n\n${paths.map(formatPath).join('\n\n')}\n` + let output = `${packageName} is not reachable\n` + if (paths.length > 0) { + const formattedPaths = paths + .map((path) => + path + .map( + (item, index) => + `${' '.repeat(index)}${index === 0 ? item : `└─ ${item}`}`, + ) + .join('\n'), + ) + .join('\n\n') + output = `${packageName} is used by:\n\n${formattedPaths}\n` + } options.stdout?.write(output) return output } @@ -90,15 +95,6 @@ export async function diff( return output } -export async function verifyEntryConfig( - options: ActionspackOptions = {}, -): Promise { - const config = await discoverConfig(options.cwd) - if (config.entries.length === 0) { - throw new Error('No workflow entries found in .github/workflows/src') - } -} - function selectRefreshPackages( lockfile: Lockfile, selector?: string, @@ -172,15 +168,6 @@ function collectWhyPaths( ) } -function formatPath(path: string[]): string { - return path - .map( - (item, index) => - `${' '.repeat(index)}${index === 0 ? item : `└─ ${item}`}`, - ) - .join('\n') -} - async function readHeadLockfile(cwd: string): Promise { try { const { stdout } = await execFileAsync( diff --git a/src/optimizer.ts b/src/optimizer.ts index 1b026c9..6851d19 100644 --- a/src/optimizer.ts +++ b/src/optimizer.ts @@ -9,7 +9,7 @@ export function optimizeJob( job: Record, ): Record { const next = { ...job } - if (isEmptyNeeds(next.needs)) { + if (Array.isArray(next.needs) && next.needs.length === 0) { delete next.needs } if (staticIfValue(next.if) === true) { @@ -56,7 +56,3 @@ function staticIfValue(value: unknown): StaticIfValue | undefined { const trimmed = value.trim() return staticIfExpression(expressionBody(trimmed) ?? trimmed) } - -function isEmptyNeeds(value: unknown): boolean { - return Array.isArray(value) && value.length === 0 -} diff --git a/src/scan.ts b/src/scan.ts index 73bcfb7..b00018c 100644 --- a/src/scan.ts +++ b/src/scan.ts @@ -1,5 +1,4 @@ import { createHash } from 'node:crypto' -import path from 'node:path' import { styleText } from 'node:util' import { discoverConfig, @@ -426,10 +425,3 @@ function prunePackages(lockfile: Lockfile): Record { function digest(content: string): string { return `sha256:${createHash('sha256').update(content).digest('hex')}` } - -export function outputForSource(source: string): string { - return path.posix.join( - '.github/workflows', - path.posix.basename(source).replace(/\.ya?ml$/u, '.yml'), - ) -} diff --git a/src/utils/expression.ts b/src/utils/expression.ts index da1b9ad..b1f2ee1 100644 --- a/src/utils/expression.ts +++ b/src/utils/expression.ts @@ -233,7 +233,7 @@ function evaluateStaticExpression( const data = new Evaluator(expr, expressionContext(values)).evaluate() return { data, - text: dataLiteral(data), + text: valueLiteral(dataValue(data)), truthy: truthy(data), value: dataValue(data), } @@ -390,10 +390,6 @@ function dataValue(value: ExpressionData): unknown { return null } -function dataLiteral(value: ExpressionData): string { - return valueLiteral(dataValue(value)) -} - function replacementForIndexAccess( expr: IndexAccess, values: Record, @@ -517,7 +513,10 @@ function simplifyFormatString( return } if (arg.static) { - nextFormat += escapeFormatLiteral(arg.static.data.coerceString()) + nextFormat += arg.static.data + .coerceString() + .replaceAll('{', '{{') + .replaceAll('}', '}}') } else { const nextIndex = nextArgs.push(arg.text) - 1 nextFormat += `{${nextIndex}}` @@ -528,7 +527,3 @@ function simplifyFormatString( nextFormat = nextFormat.trim() return { args: nextArgs, format: nextFormat } } - -function escapeFormatLiteral(value: string): string { - return value.replaceAll('{', '{{').replaceAll('}', '}}') -} diff --git a/src/utils/fs.ts b/src/utils/fs.ts index fb2aa72..3ac30ee 100644 --- a/src/utils/fs.ts +++ b/src/utils/fs.ts @@ -38,12 +38,6 @@ export async function readYamlFile( return parseYamlMap(await readFile(file, 'utf8'), file) } -export async function readWorkflowFile( - file: string, -): Promise> { - return parseWorkflowMap(await readFile(file, 'utf8'), file) -} - export async function discoverConfig( cwd?: string, overrides: Pick = {}, @@ -76,7 +70,8 @@ export async function discoverConfig( return { ...config, - ...normalizeConfigOverrides(overrides), + ...(overrides.entries ? { entries: overrides.entries } : {}), + ...(overrides.external ? { external: overrides.external } : {}), } } @@ -102,15 +97,6 @@ async function discoverDefaultConfig(root: string): Promise { } } -function normalizeConfigOverrides( - overrides: Pick, -): Partial { - return { - ...(overrides.entries ? { entries: overrides.entries } : {}), - ...(overrides.external ? { external: overrides.external } : {}), - } -} - function normalizeStringList(value: unknown): string[] { if (typeof value === 'string') { return [value] @@ -121,26 +107,23 @@ function normalizeStringList(value: unknown): string[] { return value.filter((item) => typeof item === 'string') } -export function readWorkflowEntry( +export async function readWorkflowEntry( root: string, entry: WorkflowEntry, ): Promise> { - return readWorkflowFile(path.join(root, entry.source)) -} - -export function emptyLockfile(): Lockfile { - return { - lockfileVersion: 1, - entries: {}, - packages: {}, - } + const file = path.join(root, entry.source) + return parseWorkflowMap(await readFile(file, 'utf8'), file) } export async function readLockfile(cwd?: string): Promise { const root = resolveCwd(cwd) const file = path.join(root, LOCKFILE_PATH) if (!(await fileExists(file))) { - return emptyLockfile() + return { + lockfileVersion: 1, + entries: {}, + packages: {}, + } } const value = await readYamlFile(file) return { diff --git a/src/utils/github.ts b/src/utils/github.ts index 143c663..2428778 100644 --- a/src/utils/github.ts +++ b/src/utils/github.ts @@ -69,8 +69,9 @@ export class HttpGitHubClient implements GitHubClient { return cached } + const encodedPath = filePath.split('/').map(encodeURIComponent).join('/') const response = await this.#request( - `/repos/${owner}/${repo}/contents/${encodeURIComponentPath(filePath)}?ref=${ref}`, + `/repos/${owner}/${repo}/contents/${encodedPath}?ref=${ref}`, true, ) @@ -127,7 +128,3 @@ export class HttpGitHubClient implements GitHubClient { return (await response.json()) as T } } - -function encodeURIComponentPath(filePath: string): string { - return filePath.split('/').map(encodeURIComponent).join('/') -} diff --git a/src/utils/ref.ts b/src/utils/ref.ts index 2c32d57..5d3602b 100644 --- a/src/utils/ref.ts +++ b/src/utils/ref.ts @@ -2,12 +2,6 @@ import type { RemoteRef } from '../types.ts' const REMOTE_USES_RE = /^[\w.-]+\/[\w.-]+(?:\/[^@\s]+)?@[^@\s]+$/ -export function packageKey(owner: string, repo: string, path: string): string { - return path && path !== '.' - ? `github:${owner}/${repo}/${path}` - : `github:${owner}/${repo}` -} - export function isRemoteUses(value: unknown): value is string { return typeof value === 'string' && REMOTE_USES_RE.test(value) } @@ -44,7 +38,10 @@ export function parseRemoteUses( repo, path, ref, - package: packageKey(owner, repo, path), + package: + path && path !== '.' + ? `github:${owner}/${repo}/${path}` + : `github:${owner}/${repo}`, kind: inferredKind, } } diff --git a/src/utils/substitute.ts b/src/utils/substitute.ts index e597630..fe91342 100644 --- a/src/utils/substitute.ts +++ b/src/utils/substitute.ts @@ -50,7 +50,7 @@ export function substituteString( } try { const expr = parseExpression(expression) - const replacement = directReplacement(expr, values) + const replacement = valueForIndexAccess(expr, values) if (replacement !== undefined) { return replacement } @@ -115,10 +115,3 @@ function findToken( } return } - -function directReplacement( - expr: ReturnType, - values: Record, -): unknown { - return valueForIndexAccess(expr, values) -} diff --git a/src/utils/workflow-parser.ts b/src/utils/workflow-parser.ts index 355c4e2..e9a5f1e 100644 --- a/src/utils/workflow-parser.ts +++ b/src/utils/workflow-parser.ts @@ -34,12 +34,8 @@ export function parseWorkflowMap( source: string, file: string, ): Record { - return parseTemplateMap( - WORKFLOW_ROOT, - workflowSchemaForParser(), - source, - file, - ) + workflowSchema ??= loadSchema('workflow-v1.0.min.json') + return parseTemplateMap(WORKFLOW_ROOT, workflowSchema, source, file) } export function parseActionMap( @@ -132,11 +128,6 @@ export function templateTokenToValue(token: TemplateToken): unknown { return token.toJSON() } -function workflowSchemaForParser(): TemplateSchema { - workflowSchema ??= loadSchema('workflow-v1.0.min.json') - return workflowSchema -} - function actionSchemaForParser(): TemplateSchema { actionSchema ??= loadSchema('action-v1.0.min.json') return actionSchema diff --git a/src/utils/yaml.ts b/src/utils/yaml.ts index d6729d8..fb4cee8 100644 --- a/src/utils/yaml.ts +++ b/src/utils/yaml.ts @@ -46,7 +46,7 @@ function formatWorkflowYaml(source: string): string { let stepItemIndent: number | undefined for (const line of lines) { - const indent = leadingSpaces(line) + const indent = line.length - line.trimStart().length const trimmed = line.trim() const isTopLevelKey = indent === 0 && /^[\w-]+:/u.test(line) @@ -88,10 +88,6 @@ function formatWorkflowYaml(source: string): string { return `${output.join('\n')}\n` } -function leadingSpaces(value: string): number { - return value.length - value.trimStart().length -} - function pushBlankLine(lines: string[]): void { if (lines.length > 0 && lines.at(-1) !== '') { lines.push('') -- 2.51.2