Skip to content

Commit

Permalink
Add fauna schema commit and abandon
Browse files Browse the repository at this point in the history
  • Loading branch information
macmv committed Sep 11, 2024
1 parent d0dc7b1 commit dcfcb9c
Show file tree
Hide file tree
Showing 4 changed files with 335 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 is 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 is abandonded");
} else {
this.log("Commit 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 is comitted");
} 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 is comitted");
} else {
this.log("Commit cancelled");
}
}
} catch (err) {
this.error(err);
}
}
}
7 changes: 5 additions & 2 deletions test/integ/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,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
135 changes: 134 additions & 1 deletion test/integ/schema.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from "chai";
import { evalOk, newDB, shellOk, stripMargin } from "./base";
import { evalOk, newDB, shellErr, shellOk, stripMargin } from "./base";

it("fauna schema push --stage --force works", async () => {
const secret = await newDB();
Expand Down Expand Up @@ -96,3 +96,136 @@ it("fauna schema status works", async () => {
)
);
});

it("fauna schema commit --force works", async () => {
const secret = await newDB();

await shellOk(
"fauna schema push --dir test/integ/schema/start --force",
secret
);

await evalOk(
"User.create({ id: 0, name: 'Alice', email: '[email protected]' })",
secret
);

expect(
await evalOk("Collection.all().map(.name).toArray()", secret)
).to.deep.equal(["User"]);

await shellOk(
"fauna schema push --dir test/integ/schema/staged_index --force --stage",
secret
);

// The index should not be visible on the companion object.
expect(
await evalOk(
stripMargin(
`|let user: Any = User
|user.byName`
),
secret
)
).to.deep.equal(null);

// Commit the schema
await shellOk("fauna schema commit --dir . --force", secret);

// Index should now be available on the companion object.
expect(
await evalOk(stripMargin(`User.byName('Alice').toArray().map(.id)`), secret)
).to.deep.equal(["0"]);

// Status should be blank now.
expect(await status(secret)).to.equal(
stripMargin(
`|Status: none
|`
)
);

// Comitting when there is nothing staged should return an error.
expect(
await shellErr("fauna schema commit --dir . --force", secret)
).to.equal("There is no staged schema to commit");
});

it("fauna schema abandon --force works", async () => {
const secret = await newDB();

await shellOk(
"fauna schema push --dir test/integ/schema/start --force",
secret
);

await evalOk(
"User.create({ id: 0, name: 'Alice', email: '[email protected]' })",
secret
);

expect(
await evalOk("Collection.all().map(.name).toArray()", secret)
).to.deep.equal(["User"]);

await shellOk(
"fauna schema push --dir test/integ/schema/staged_index --force --stage",
secret
);

// The index should be visible on the definition object.
expect(
await evalOk("Collection.byName('User')!.indexes.byName", secret)
).to.deep.equal({
terms: [
{
field: ".name",
mva: false,
},
],
queryable: true,
status: "complete",
});

// But not visible on the companion object.
expect(
await evalOk(
stripMargin(
`|let user: Any = User
|user.byName`
),
secret
)
).to.deep.equal(null);

// Abandon the schema
await shellOk("fauna schema abandon --dir . --force", secret);

// Index should no longer be in the definition object.
expect(
await evalOk("Collection.byName('User')!.indexes.byName", secret)
).to.deep.equal(null);
expect(
await evalOk(
stripMargin(
`|let user: Any = User
|user.byName`
),
secret
)
).to.deep.equal(null);

// Status should be blank now.
expect(await status(secret)).to.equal(
stripMargin(
`|Status: none
|`
)
);

// Abandoning when there is no staged schema should return an error.
expect(
await shellErr("fauna schema abandon --dir . --force", secret)
).to.equal("There is no staged schema to abandon");
});

0 comments on commit dcfcb9c

Please sign in to comment.