Route existing-company CLI imports through safe routes
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
e6df9fa078
commit
f23d611d0c
3 changed files with 77 additions and 7 deletions
|
|
@ -449,7 +449,7 @@ describe("paperclipai company import/export e2e", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(previewExisting.errors).toEqual([]);
|
expect(previewExisting.errors).toEqual([]);
|
||||||
expect(previewExisting.plan.companyAction).toBe("update");
|
expect(previewExisting.plan.companyAction).toBe("none");
|
||||||
expect(previewExisting.plan.agentPlans.some((plan) => plan.action === "create")).toBe(true);
|
expect(previewExisting.plan.agentPlans.some((plan) => plan.action === "create")).toBe(true);
|
||||||
expect(previewExisting.plan.projectPlans.some((plan) => plan.action === "create")).toBe(true);
|
expect(previewExisting.plan.projectPlans.some((plan) => plan.action === "create")).toBe(true);
|
||||||
expect(previewExisting.plan.issuePlans.some((plan) => plan.action === "create")).toBe(true);
|
expect(previewExisting.plan.issuePlans.some((plan) => plan.action === "create")).toBe(true);
|
||||||
|
|
@ -474,7 +474,7 @@ describe("paperclipai company import/export e2e", () => {
|
||||||
{ apiBase, configPath },
|
{ apiBase, configPath },
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(importedExisting.company.action).toBe("updated");
|
expect(importedExisting.company.action).toBe("unchanged");
|
||||||
expect(importedExisting.agents.some((agent) => agent.action === "created")).toBe(true);
|
expect(importedExisting.agents.some((agent) => agent.action === "created")).toBe(true);
|
||||||
|
|
||||||
const twiceImportedAgents = await api<Array<{ id: string; name: string }>>(
|
const twiceImportedAgents = await api<Array<{ id: string; name: string }>>(
|
||||||
|
|
|
||||||
50
cli/src/__tests__/company.test.ts
Normal file
50
cli/src/__tests__/company.test.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { resolveCompanyImportApiPath } from "../commands/client/company.js";
|
||||||
|
|
||||||
|
describe("resolveCompanyImportApiPath", () => {
|
||||||
|
it("uses company-scoped preview route for existing-company dry runs", () => {
|
||||||
|
expect(
|
||||||
|
resolveCompanyImportApiPath({
|
||||||
|
dryRun: true,
|
||||||
|
targetMode: "existing_company",
|
||||||
|
companyId: "company-123",
|
||||||
|
}),
|
||||||
|
).toBe("/api/companies/company-123/imports/preview");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses company-scoped apply route for existing-company imports", () => {
|
||||||
|
expect(
|
||||||
|
resolveCompanyImportApiPath({
|
||||||
|
dryRun: false,
|
||||||
|
targetMode: "existing_company",
|
||||||
|
companyId: "company-123",
|
||||||
|
}),
|
||||||
|
).toBe("/api/companies/company-123/imports/apply");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps global routes for new-company imports", () => {
|
||||||
|
expect(
|
||||||
|
resolveCompanyImportApiPath({
|
||||||
|
dryRun: true,
|
||||||
|
targetMode: "new_company",
|
||||||
|
}),
|
||||||
|
).toBe("/api/companies/import/preview");
|
||||||
|
|
||||||
|
expect(
|
||||||
|
resolveCompanyImportApiPath({
|
||||||
|
dryRun: false,
|
||||||
|
targetMode: "new_company",
|
||||||
|
}),
|
||||||
|
).toBe("/api/companies/import");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws when an existing-company import is missing a company id", () => {
|
||||||
|
expect(() =>
|
||||||
|
resolveCompanyImportApiPath({
|
||||||
|
dryRun: true,
|
||||||
|
targetMode: "existing_company",
|
||||||
|
companyId: " ",
|
||||||
|
})
|
||||||
|
).toThrow(/require a companyId/i);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -114,6 +114,24 @@ function parseCsvValues(input: string | undefined): string[] {
|
||||||
return Array.from(new Set(input.split(",").map((part) => part.trim()).filter(Boolean)));
|
return Array.from(new Set(input.split(",").map((part) => part.trim()).filter(Boolean)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveCompanyImportApiPath(input: {
|
||||||
|
dryRun: boolean;
|
||||||
|
targetMode: "new_company" | "existing_company";
|
||||||
|
companyId?: string | null;
|
||||||
|
}): string {
|
||||||
|
if (input.targetMode === "existing_company") {
|
||||||
|
const companyId = input.companyId?.trim();
|
||||||
|
if (!companyId) {
|
||||||
|
throw new Error("Existing-company imports require a companyId to resolve the API route.");
|
||||||
|
}
|
||||||
|
return input.dryRun
|
||||||
|
? `/api/companies/${companyId}/imports/preview`
|
||||||
|
: `/api/companies/${companyId}/imports/apply`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input.dryRun ? "/api/companies/import/preview" : "/api/companies/import";
|
||||||
|
}
|
||||||
|
|
||||||
export function isHttpUrl(input: string): boolean {
|
export function isHttpUrl(input: string): boolean {
|
||||||
return /^https?:\/\//i.test(input.trim());
|
return /^https?:\/\//i.test(input.trim());
|
||||||
}
|
}
|
||||||
|
|
@ -576,17 +594,19 @@ export function registerCompanyCommands(program: Command): void {
|
||||||
agents,
|
agents,
|
||||||
collisionStrategy: collision,
|
collisionStrategy: collision,
|
||||||
};
|
};
|
||||||
|
const importApiPath = resolveCompanyImportApiPath({
|
||||||
|
dryRun: Boolean(opts.dryRun),
|
||||||
|
targetMode: targetPayload.mode,
|
||||||
|
companyId: targetPayload.mode === "existing_company" ? targetPayload.companyId : null,
|
||||||
|
});
|
||||||
|
|
||||||
if (opts.dryRun) {
|
if (opts.dryRun) {
|
||||||
const preview = await ctx.api.post<CompanyPortabilityPreviewResult>(
|
const preview = await ctx.api.post<CompanyPortabilityPreviewResult>(importApiPath, payload);
|
||||||
"/api/companies/import/preview",
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
printOutput(preview, { json: ctx.json });
|
printOutput(preview, { json: ctx.json });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imported = await ctx.api.post<CompanyPortabilityImportResult>("/api/companies/import", payload);
|
const imported = await ctx.api.post<CompanyPortabilityImportResult>(importApiPath, payload);
|
||||||
printOutput(imported, { json: ctx.json });
|
printOutput(imported, { json: ctx.json });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
handleCommandError(err);
|
handleCommandError(err);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue