fix: simplify package content check and facets label

This commit is contained in:
nrslib 2026-02-22 02:39:25 +09:00
parent 9e6e7e3550
commit 8930688a95
3 changed files with 18 additions and 17 deletions

View File

@ -6,7 +6,7 @@
* - path field defaults, allowed/disallowed values
* - takt.min_version format validation
* - Version comparison (numeric, not lexicographic)
* - Empty package detection (faceted/ and pieces/ presence)
* - Empty package detection (facets/ and pieces/ presence)
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
@ -241,7 +241,7 @@ describe('checkPackageHasContent', () => {
rmSync(tempDir, { recursive: true, force: true });
});
it('should throw when neither faceted/ nor pieces/ exists', () => {
it('should throw when neither facets/ nor pieces/ exists', () => {
// Given: empty package root directory
// When: content check is performed
// Then: throws an error (empty package not allowed)
@ -256,9 +256,9 @@ describe('checkPackageHasContent', () => {
})).toThrow(/path: \.takt/);
});
it('should not throw when only faceted/ exists', () => {
// Given: package with faceted/ only
mkdirSync(join(tempDir, 'faceted'), { recursive: true });
it('should not throw when only facets/ exists', () => {
// Given: package with facets/ only
mkdirSync(join(tempDir, 'facets'), { recursive: true });
// When: content check is performed
// Then: no error (facet-only package is valid)
@ -274,15 +274,16 @@ describe('checkPackageHasContent', () => {
expect(() => checkPackageHasContent(tempDir)).not.toThrow();
});
it('should not throw when both faceted/ and pieces/ exist', () => {
it('should not throw when both facets/ and pieces/ exist', () => {
// Given: package with both directories
mkdirSync(join(tempDir, 'faceted'), { recursive: true });
mkdirSync(join(tempDir, 'facets'), { recursive: true });
mkdirSync(join(tempDir, 'pieces'), { recursive: true });
// When: content check is performed
// Then: no error
expect(() => checkPackageHasContent(tempDir)).not.toThrow();
});
});
// ---------------------------------------------------------------------------

View File

@ -118,7 +118,7 @@ export async function ensembleAddCommand(spec: string): Promise<void> {
});
const targets = collectCopyTargets(packageRoot);
const facetFiles = targets.filter(t => t.relativePath.startsWith('faceted/'));
const facetFiles = targets.filter(t => t.relativePath.startsWith('facets/'));
const pieceFiles = targets.filter(t => t.relativePath.startsWith('pieces/'));
const facetSummary = summarizeFacetsByType(facetFiles.map(t => t.relativePath));
@ -135,7 +135,7 @@ export async function ensembleAddCommand(spec: string): Promise<void> {
const editPieces = detectEditPieces(pieceYamls);
info(`\n📦 ${owner}/${repo} @${ref}`);
info(` faceted: ${facetSummary}`);
info(` facets: ${facetSummary}`);
if (pieceFiles.length > 0) {
const pieceNames = pieceFiles.map(t =>
t.relativePath.replace(/^pieces\//, '').replace(/\.yaml$/, ''),

View File

@ -6,7 +6,7 @@
* - path field validation (no absolute paths, no directory traversal)
* - min_version format validation (strict semver X.Y.Z)
* - Numeric semver comparison
* - Package content presence check (faceted/ or pieces/ must exist)
* - Package content presence check (facets/ or pieces/ must exist)
* - Realpath validation to prevent symlink-based traversal outside root
*/
@ -105,15 +105,15 @@ export function isVersionCompatible(minVersion: string, currentVersion: string):
}
/**
* Check that the package root contains at least one of faceted/ or pieces/.
* Check that the package root contains at least one of facets/ or pieces/.
* Throws if neither exists (empty package).
*/
export function checkPackageHasContent(packageRoot: string): void {
const hasFaceted = existsSync(join(packageRoot, 'faceted'));
const hasFaceted = existsSync(join(packageRoot, 'facets'));
const hasPieces = existsSync(join(packageRoot, 'pieces'));
if (!hasFaceted && !hasPieces) {
throw new Error(
`Package at "${packageRoot}" has neither faceted/ nor pieces/ directory — empty package rejected`,
`Package at "${packageRoot}" has neither facets/ nor pieces/ directory — empty package rejected`,
);
}
}
@ -128,17 +128,17 @@ export function checkPackageHasContentWithContext(
packageRoot: string,
context: PackageContentCheckContext,
): void {
const hasFaceted = existsSync(join(packageRoot, 'faceted'));
const hasFacets = existsSync(join(packageRoot, 'facets'));
const hasPieces = existsSync(join(packageRoot, 'pieces'));
if (hasFaceted || hasPieces) return;
if (hasFacets || hasPieces) return;
const checkedFaceted = join(packageRoot, 'faceted');
const checkedFaceted = join(packageRoot, 'facets');
const checkedPieces = join(packageRoot, 'pieces');
const configuredPath = context.configuredPath ?? '.';
const manifestPath = context.manifestPath ?? '(unknown)';
const hint = configuredPath === '.'
? `hint: If your package content is under ".takt/", set "path: .takt" in ${TAKT_PACKAGE_MANIFEST_FILENAME}.`
: `hint: Verify "path: ${configuredPath}" points to a directory containing faceted/ or pieces/.`;
: `hint: Verify "path: ${configuredPath}" points to a directory containing facets/ or pieces/.`;
throw new Error(
[