Skip to content

Commit

Permalink
Add fauna schema commit and abandon (#357)
Browse files Browse the repository at this point in the history
  • Loading branch information
macmv authored Sep 17, 2024
1 parent 534e88f commit 9e4afd6
Show file tree
Hide file tree
Showing 5 changed files with 440 additions and 3 deletions.
96 changes: 96 additions & 0 deletions src/commands/schema/abandon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { confirm } from "@inquirer/prompts";
import SchemaCommand from "../../lib/schema-command";
import { Flags } from "@oclif/core";

export default class CommitSchemaCommand extends SchemaCommand {
static flags = {
...SchemaCommand.flags,
force: Flags.boolean({
description: "Push the change without a diff or schema version check",
default: false,
}),
};

static description = "Abandons the currently staged schema.";

static examples = ["$ fauna schema abandon"];

async run() {
try {
const { url, secret } = await this.fetchsetup();
if (this.flags?.force) {
const params = new URLSearchParams({
force: "true", // Just abandon, don't pass a schema version through.
});

const path = new URL(`/schema/1/staged/abandon?${params}`, url);
const res = await fetch(path, {
method: "POST",
headers: { AUTHORIZATION: `Bearer ${secret}` },
// https://github.com/nodejs/node/issues/46221
// https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1483
// @ts-expect-error-next-line
duplex: "half",
});

const json = await res.json();
if (json.error) {
this.error(json.error?.message ?? json.error);
}

this.log("Schema has been abandonded");
} else {
// Show status to confirm.
const { url, secret } = await this.fetchsetup();
const res = await fetch(
new URL("/schema/1/staged/status?diff=true", url),
{
method: "GET",
headers: { AUTHORIZATION: `Bearer ${secret}` },
// @ts-expect-error-next-line
duplex: "half",
}
);

const json = await res.json();
if (json.error) {
this.error(json.error.message);
}

if (json.status === "none") {
this.error("There is no staged schema to abandon");
}

this.log(json.diff);

const confirmed = await confirm({
message: "Abandon these changes?",
default: false,
});

if (confirmed) {
const params = new URLSearchParams({ version: json.version });

const path = new URL(`/schema/1/staged/abandon?${params}`, url);
const res = await fetch(path, {
method: "POST",
headers: { AUTHORIZATION: `Bearer ${secret}` },
// @ts-expect-error-next-line
duplex: "half",
});

const json0 = await res.json();
if (json0.error) {
this.error(json0.error.message);
}

this.log("Schema has been abandoned");
} else {
this.log("Abandon cancelled");
}
}
} catch (err) {
this.error(err);
}
}
}
100 changes: 100 additions & 0 deletions src/commands/schema/commit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { confirm } from "@inquirer/prompts";
import SchemaCommand from "../../lib/schema-command";
import { Flags } from "@oclif/core";

export default class CommitSchemaCommand extends SchemaCommand {
static flags = {
...SchemaCommand.flags,
force: Flags.boolean({
description: "Push the change without a diff or schema version check",
default: false,
}),
};

static description = "Commits the currently staged schema.";

static examples = ["$ fauna schema commit"];

async run() {
try {
const { url, secret } = await this.fetchsetup();
if (this.flags?.force) {
const params = new URLSearchParams({
force: "true", // Just commit, don't pass a schema version through.
});

const path = new URL(`/schema/1/staged/commit?${params}`, url);
const res = await fetch(path, {
method: "POST",
headers: { AUTHORIZATION: `Bearer ${secret}` },
// https://github.com/nodejs/node/issues/46221
// https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1483
// @ts-expect-error-next-line
duplex: "half",
});

const json = await res.json();
if (json.error) {
this.error(json.error?.message ?? json.error);
}

this.log("Schema has been committed");
} else {
// Show status to confirm.
const { url, secret } = await this.fetchsetup();
const res = await fetch(
new URL("/schema/1/staged/status?diff=true", url),
{
method: "GET",
headers: { AUTHORIZATION: `Bearer ${secret}` },
// @ts-expect-error-next-line
duplex: "half",
}
);

const json = await res.json();
if (json.error) {
this.error(json.error.message);
}

if (json.status === "none") {
this.error("There is no staged schema to commit");
}

this.log(json.diff);

if (json.status !== "ready") {
this.error("Schema is not ready to be committed");
}

const confirmed = await confirm({
message: "Accept and commit these changes?",
default: false,
});

if (confirmed) {
const params = new URLSearchParams({ version: json.version });

const path = new URL(`/schema/1/staged/commit?${params}`, url);
const res = await fetch(path, {
method: "POST",
headers: { AUTHORIZATION: `Bearer ${secret}` },
// @ts-expect-error-next-line
duplex: "half",
});

const json0 = await res.json();
if (json0.error) {
this.error(json0.error.message);
}

this.log("Schema has been committed");
} else {
this.log("Commit cancelled");
}
}
} catch (err) {
this.error(err);
}
}
}
95 changes: 95 additions & 0 deletions test/commands/schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,101 @@ describe("fauna schema push test", () => {
);
expect(stdout).to.contain(`${diff.diff}`);
});

it("runs schema commit", async () => {
nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(q.Now()))
.reply(200, new Date())
.get("/schema/1/staged/status?diff=true")
.reply(200, {
version: 3,
status: "ready",
diff: diff.diff,
})
.post("/schema/1/staged/commit?version=3")
.reply(200, { version: 0 });

// Stubbing the confirmation to always return true
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);
const { stdout } = await runCommand(
withOpts(["schema commit", "--dir=test/testdata"])
);
expect(stdout).to.contain(`Schema has been committed`);
// Restore the stub after the test
stubConfirm.restore();
});

it("won't commit when schema isn't ready", async () => {
nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(q.Now()))
.reply(200, new Date())
.get("/schema/1/staged/status?diff=true")
.reply(200, {
version: 3,
status: "pending",
diff: diff.diff,
});

// Stubbing the confirmation to always return true
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);
const { stdout, error } = await runCommand(
withOpts(["schema commit", "--dir=test/testdata"])
);
expect(stdout).to.contain(diff.diff);
expect(error.message).to.equal("Schema is not ready to be committed");
// Restore the stub after the test
stubConfirm.restore();
});

it("runs schema abandon", async () => {
nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(q.Now()))
.reply(200, new Date())
.get("/schema/1/staged/status?diff=true")
.reply(200, {
version: 3,
status: "ready",
diff: diff.diff,
})
.post("/schema/1/staged/abandon?version=3")
.reply(200, { version: 0 });

// Stubbing the confirmation to always return true
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);
const { stdout } = await runCommand(
withOpts(["schema abandon", "--dir=test/testdata"])
);
expect(stdout).to.contain(`Schema has been abandoned`);
// Restore the stub after the test
stubConfirm.restore();
});

it("will abandon even when schema isn't ready", async () => {
nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(q.Now()))
.reply(200, new Date())
.get("/schema/1/staged/status?diff=true")
.reply(200, {
version: 3,
status: "pending",
diff: diff.diff,
})
.post("/schema/1/staged/abandon?version=3")
.reply(200, { version: 0 });

// Stubbing the confirmation to always return true
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);
const { stdout } = await runCommand(
withOpts(["schema abandon", "--dir=test/testdata"])
);
expect(stdout).to.contain(`Schema has been abandoned`);
// Restore the stub after the test
stubConfirm.restore();
});
});

const testdir = "test/testdata";
Expand Down
7 changes: 5 additions & 2 deletions test/integ/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ export const shellOk = async (
return res.stdout;
};

export const shellErr = async (cmd: string): Promise<string> => {
const res = await shell(cmd);
export const shellErr = async (
cmd: string,
secret?: string
): Promise<string> => {
const res = await shell(cmd, secret);
if (res.ok) {
fail(`Command should not have exitted succesfully:\n${res.stdout}`);
}
Expand Down
Loading

0 comments on commit 9e4afd6

Please sign in to comment.