mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 18:30:39 +09:00
Refine portability export behavior and skill plans
This commit is contained in:
parent
7e43020a28
commit
b2c0f3f9a5
13 changed files with 1126 additions and 12 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { Command } from "commander";
|
||||
import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import * as p from "@clack/prompts";
|
||||
import type {
|
||||
Company,
|
||||
CompanyPortabilityExportResult,
|
||||
|
|
@ -35,6 +36,7 @@ interface CompanyExportOptions extends BaseClientOptions {
|
|||
projects?: string;
|
||||
issues?: string;
|
||||
projectIssues?: string;
|
||||
expandReferencedSkills?: boolean;
|
||||
}
|
||||
|
||||
interface CompanyImportOptions extends BaseClientOptions {
|
||||
|
|
@ -137,6 +139,31 @@ async function writeExportToFolder(outDir: string, exported: CompanyPortabilityE
|
|||
}
|
||||
}
|
||||
|
||||
async function confirmOverwriteExportDirectory(outDir: string): Promise<void> {
|
||||
const root = path.resolve(outDir);
|
||||
const stats = await stat(root).catch(() => null);
|
||||
if (!stats) return;
|
||||
if (!stats.isDirectory()) {
|
||||
throw new Error(`Export output path ${root} exists and is not a directory.`);
|
||||
}
|
||||
|
||||
const entries = await readdir(root);
|
||||
if (entries.length === 0) return;
|
||||
|
||||
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
||||
throw new Error(`Export output directory ${root} already contains files. Re-run interactively or choose an empty directory.`);
|
||||
}
|
||||
|
||||
const confirmed = await p.confirm({
|
||||
message: `Overwrite existing files in ${root}?`,
|
||||
initialValue: false,
|
||||
});
|
||||
|
||||
if (p.isCancel(confirmed) || !confirmed) {
|
||||
throw new Error("Export cancelled.");
|
||||
}
|
||||
}
|
||||
|
||||
function matchesPrefix(company: Company, selector: string): boolean {
|
||||
return company.issuePrefix.toUpperCase() === selector.toUpperCase();
|
||||
}
|
||||
|
|
@ -278,6 +305,7 @@ export function registerCompanyCommands(program: Command): void {
|
|||
.option("--projects <values>", "Comma-separated project shortnames/ids to export")
|
||||
.option("--issues <values>", "Comma-separated issue identifiers/ids to export")
|
||||
.option("--project-issues <values>", "Comma-separated project shortnames/ids whose issues should be exported")
|
||||
.option("--expand-referenced-skills", "Vendor skill contents instead of exporting upstream references", false)
|
||||
.action(async (companyId: string, opts: CompanyExportOptions) => {
|
||||
try {
|
||||
const ctx = resolveCommandContext(opts);
|
||||
|
|
@ -289,11 +317,13 @@ export function registerCompanyCommands(program: Command): void {
|
|||
projects: parseCsvValues(opts.projects),
|
||||
issues: parseCsvValues(opts.issues),
|
||||
projectIssues: parseCsvValues(opts.projectIssues),
|
||||
expandReferencedSkills: Boolean(opts.expandReferencedSkills),
|
||||
},
|
||||
);
|
||||
if (!exported) {
|
||||
throw new Error("Export request returned no data");
|
||||
}
|
||||
await confirmOverwriteExportDirectory(opts.out!);
|
||||
await writeExportToFolder(opts.out!, exported);
|
||||
printOutput(
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue