From 05865eb04e5434168481756d867a1c155ebb986e Mon Sep 17 00:00:00 2001 From: nrslib <38722970+nrslib@users.noreply.github.com> Date: Sun, 22 Feb 2026 02:07:32 +0900 Subject: [PATCH] refactor: centralize ensemble manifest filename constant --- src/commands/ensemble/add.ts | 3 ++- src/features/ensemble/constants.ts | 6 ++++++ src/features/ensemble/list.ts | 3 ++- src/features/ensemble/takt-pack-config.ts | 17 ++++++++++------- 4 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 src/features/ensemble/constants.ts diff --git a/src/commands/ensemble/add.ts b/src/commands/ensemble/add.ts index 60a0b52..bf8af2d 100644 --- a/src/commands/ensemble/add.ts +++ b/src/commands/ensemble/add.ts @@ -27,6 +27,7 @@ import { parseTarVerboseListing } from '../../features/ensemble/tar-parser.js'; import { resolveRef } from '../../features/ensemble/github-ref-resolver.js'; import { atomicReplace, cleanupResiduals } from '../../features/ensemble/atomic-update.js'; import { generateLockFile, extractCommitSha } from '../../features/ensemble/lock-file.js'; +import { TAKT_PACKAGE_MANIFEST_FILENAME } from '../../features/ensemble/constants.js'; import { summarizeFacetsByType, detectEditPieces, formatEditPieceWarnings } from '../../features/ensemble/pack-summary.js'; import { confirm } from '../../shared/prompt/index.js'; import { info, success } from '../../shared/ui/index.js'; @@ -176,7 +177,7 @@ export async function ensembleAddCommand(spec: string): Promise { mkdirSync(dirname(destFile), { recursive: true }); copyFileSync(target.absolutePath, destFile); } - copyFileSync(packConfigPath, join(packageDir, 'takt-package.yaml')); + copyFileSync(packConfigPath, join(packageDir, TAKT_PACKAGE_MANIFEST_FILENAME)); const lock = generateLockFile({ source: `github:${owner}/${repo}`, diff --git a/src/features/ensemble/constants.ts b/src/features/ensemble/constants.ts new file mode 100644 index 0000000..74ca440 --- /dev/null +++ b/src/features/ensemble/constants.ts @@ -0,0 +1,6 @@ +/** + * Shared constants for ensemble package manifest handling. + */ + +/** Manifest filename inside a package repository and installed package directory. */ +export const TAKT_PACKAGE_MANIFEST_FILENAME = 'takt-package.yaml'; diff --git a/src/features/ensemble/list.ts b/src/features/ensemble/list.ts index 0679ead..bacbb6d 100644 --- a/src/features/ensemble/list.ts +++ b/src/features/ensemble/list.ts @@ -9,6 +9,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; import { join } from 'node:path'; import { parseTaktPackConfig } from './takt-pack-config.js'; import { parseLockFile } from './lock-file.js'; +import { TAKT_PACKAGE_MANIFEST_FILENAME } from './constants.js'; import { createLogger, getErrorMessage } from '../../shared/utils/index.js'; const log = createLogger('ensemble-list'); @@ -29,7 +30,7 @@ export interface PackageInfo { * @param scope - e.g. "@nrslib/takt-fullstack" */ export function readPackageInfo(packageDir: string, scope: string): PackageInfo { - const packConfigPath = join(packageDir, 'takt-package.yaml'); + const packConfigPath = join(packageDir, TAKT_PACKAGE_MANIFEST_FILENAME); const lockPath = join(packageDir, '.takt-pack-lock.yaml'); const configYaml = existsSync(packConfigPath) diff --git a/src/features/ensemble/takt-pack-config.ts b/src/features/ensemble/takt-pack-config.ts index 596e668..cb488ce 100644 --- a/src/features/ensemble/takt-pack-config.ts +++ b/src/features/ensemble/takt-pack-config.ts @@ -13,6 +13,7 @@ import { existsSync, realpathSync } from 'node:fs'; import { join } from 'node:path'; import { parse as parseYaml } from 'yaml'; +import { TAKT_PACKAGE_MANIFEST_FILENAME } from './constants.js'; export interface TaktPackConfig { description?: string; @@ -52,14 +53,14 @@ export function parseTaktPackConfig(yaml: string): TaktPackConfig { */ export function validateTaktPackPath(path: string): void { if (path.startsWith('/')) { - throw new Error(`takt-package.yaml: path must not be absolute, got "${path}"`); + throw new Error(`${TAKT_PACKAGE_MANIFEST_FILENAME}: path must not be absolute, got "${path}"`); } if (path.startsWith('~')) { - throw new Error(`takt-package.yaml: path must not start with "~", got "${path}"`); + throw new Error(`${TAKT_PACKAGE_MANIFEST_FILENAME}: path must not start with "~", got "${path}"`); } const segments = path.split('/'); if (segments.includes('..')) { - throw new Error(`takt-package.yaml: path must not contain ".." segments, got "${path}"`); + throw new Error(`${TAKT_PACKAGE_MANIFEST_FILENAME}: path must not contain ".." segments, got "${path}"`); } } @@ -72,7 +73,7 @@ export function validateTaktPackPath(path: string): void { export function validateMinVersion(version: string): void { if (!SEMVER_PATTERN.test(version)) { throw new Error( - `takt-package.yaml: takt.min_version must match X.Y.Z (no "v" prefix, no pre-release), got "${version}"`, + `${TAKT_PACKAGE_MANIFEST_FILENAME}: takt.min_version must match X.Y.Z (no "v" prefix, no pre-release), got "${version}"`, ); } } @@ -123,13 +124,15 @@ export function checkPackageHasContent(packageRoot: string): void { * @throws if neither candidate exists */ export function resolvePackConfigPath(extractDir: string): string { - const taktDirPath = join(extractDir, '.takt', 'takt-package.yaml'); + const taktDirPath = join(extractDir, '.takt', TAKT_PACKAGE_MANIFEST_FILENAME); if (existsSync(taktDirPath)) return taktDirPath; - const rootPath = join(extractDir, 'takt-package.yaml'); + const rootPath = join(extractDir, TAKT_PACKAGE_MANIFEST_FILENAME); if (existsSync(rootPath)) return rootPath; - throw new Error(`takt-package.yaml not found in "${extractDir}": checked .takt/takt-package.yaml and takt-package.yaml`); + throw new Error( + `${TAKT_PACKAGE_MANIFEST_FILENAME} not found in "${extractDir}": checked .takt/${TAKT_PACKAGE_MANIFEST_FILENAME} and ${TAKT_PACKAGE_MANIFEST_FILENAME}`, + ); } /**