Skip to content

Commit 0200995

Browse files
committed
refactor(plapi): allow null active_domain and guard in deploy wizard
1 parent 05eff4c commit 0200995

4 files changed

Lines changed: 48 additions & 2 deletions

File tree

packages/cli-core/src/commands/deploy/api.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ describe("deploy api adapter", () => {
6363
});
6464

6565
expect(production.instance_id).toBe("MOCKED_NOT_REAL_FIXME");
66-
expect(production.active_domain.name).toBe("example.com");
66+
expect(production.active_domain?.name).toBe("example.com");
6767
expect(production.cname_targets).toHaveLength(3);
6868
expect(mockPlapiCreateProductionInstance).not.toHaveBeenCalled();
6969
expect(mockPlapiValidateCloning).not.toHaveBeenCalled();

packages/cli-core/src/commands/deploy/index.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,43 @@ describe("deploy", () => {
14931493
expect(err).toContain("Configure them from the Clerk Dashboard before going live");
14941494
});
14951495

1496+
test("throws a CliError when createProductionInstance returns no active_domain", async () => {
1497+
_modeOverride = "human";
1498+
await linkedProject({
1499+
appId: "app_test",
1500+
appName: "Test App",
1501+
instances: { development: "ins_dev" },
1502+
});
1503+
mockFetchApplication.mockResolvedValue({
1504+
application_id: "app_test",
1505+
name: "Test App",
1506+
instances: [
1507+
{ instance_id: "ins_dev", environment_type: "development", publishable_key: "pk_test" },
1508+
],
1509+
});
1510+
mockFetchInstanceConfig.mockResolvedValue({});
1511+
mockConfirm.mockResolvedValue(true);
1512+
mockInput.mockResolvedValue("https://example.com");
1513+
1514+
mockCreateProductionInstance.mockResolvedValue({
1515+
instance_id: "ins_prod",
1516+
environment_type: "production",
1517+
active_domain: null,
1518+
secret_key: "sk_live_x",
1519+
publishable_key: "pk_live_x",
1520+
cname_targets: [],
1521+
});
1522+
1523+
let thrown: unknown;
1524+
try {
1525+
await runDeploy({});
1526+
} catch (e) {
1527+
thrown = e;
1528+
}
1529+
expect(thrown).toBeInstanceOf(CliError);
1530+
expect((thrown as CliError).message).toContain("did not return a domain");
1531+
});
1532+
14961533
test("recovers from production_instance_exists by resuming reconcileExistingDeploy", async () => {
14971534
_modeOverride = "human";
14981535
await linkedProject({

packages/cli-core/src/commands/deploy/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,14 @@ async function startNewDeploy(ctx: DeployContext): Promise<void> {
278278
throw error;
279279
}
280280
await persistProductionInstance(ctx, production.instance_id);
281+
282+
if (!production.active_domain) {
283+
throw new CliError(
284+
"Production instance was created but Clerk did not return a domain. " +
285+
"Run `clerk deploy` again to retry domain provisioning.",
286+
);
287+
}
288+
281289
log.blank();
282290

283291
const productionDomain = production.active_domain.name;

packages/cli-core/src/lib/plapi.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ export type ListApplicationDomainsResponse = {
174174
export type ProductionInstanceResponse = {
175175
instance_id: string;
176176
environment_type: "production";
177-
active_domain: DomainSummary;
177+
/** Server contract permits null; CLI currently throws if the server omits it. */
178+
active_domain: DomainSummary | null;
178179
secret_key?: string;
179180
publishable_key: string;
180181
cname_targets: CnameTarget[];

0 commit comments

Comments
 (0)