Skip to content

Commit

Permalink
feat(datasets): add dataset create/delete/get/list commands (#59)
Browse files Browse the repository at this point in the history
Co-authored-by: Carlos Duarte Do Nascimento (Chester) <[email protected]>
  • Loading branch information
ps-kwang and chesterbr authored Apr 5, 2024
1 parent 9f6203a commit aff5856
Show file tree
Hide file tree
Showing 8 changed files with 410 additions and 22 deletions.
9 changes: 9 additions & 0 deletions api/dataset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { client } from "./client.ts";

export const datasets = {
create: client("/datasets").post,
get: client("/datasets/{id}").get,
list: client("/datasets").get,
delete: client("/datasets/{id}").delete,
update: client("/datasets/{id}").put,
};
70 changes: 70 additions & 0 deletions commands/dataset/create/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { datasets } from "../../../api/dataset.ts";
import { fields } from "../../../flags.ts";
import { asserts } from "../../../lib/asserts.ts";
import { dataTable } from "../../../lib/data-table.ts";
import { loading } from "../../../lib/loading.ts";
import { pickJson } from "../../../lib/pick-json.ts";
import { command, flag, flags } from "../../../zcli.ts";
import { defaultFields } from "../mod.ts";

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [];

export const create = command("create", {
short: "Create a dataset",
long: `
Create a dataset.
`,
commands: subCommands,
flags: flags({
fields,
}).merge(flags({
"name": flag({
aliases: ["n"],
short: "The name of the dataset",
}).string(),
"description": flag({
short: "The description of the dataset",
}).ostring(),
"storage-provider-id": flag({
short: "The ID of the storage provider to use for the dataset",
}).ostring(),
"is-public": flag({
short: "Whether the dataset is public",
}).oboolean(),
})),
// We use command metadata in the `persistentPreRun` function to check if a
// command requires an API key. If it does, we'll check to see if one is
// set. If not, we'll throw an error.
meta: {
requireApiKey: true,
requireInGoodStanding: true,
},
}).run(
async function* ({ flags }) {
const response = await loading(
datasets.create({
name: flags.name,
description: flags.description,
storageProviderId: flags["storage-provider-id"],
isPublic: flags["is-public"] ?? false,
}),
);

asserts(response.ok, response);
const result = response.data;

if (flags.json) {
yield pickJson(result, flags.fields);
} else {
for await (
const line of dataTable([result], flags.fields ?? defaultFields)
) {
yield line;
}
}
},
);
63 changes: 63 additions & 0 deletions commands/dataset/delete/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { datasets } from "../../../api/dataset.ts";
import { fields } from "../../../flags.ts";
import { asserts } from "../../../lib/asserts.ts";
import { dataTable } from "../../../lib/data-table.ts";
import { loading } from "../../../lib/loading.ts";
import { pickJson } from "../../../lib/pick-json.ts";
import { input } from "../../../prompts/input.ts";
import { args, command, flags, z } from "../../../zcli.ts";
import { defaultFields } from "../mod.ts";

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [];

export const del = command("delete", {
short: "Delete a dataset",
long: `
Delete a dataset from a team.
`,
commands: subCommands,
args: args().tuple([
z.string().describe("The ID of the dataset to delete"),
]).optional(),
flags: flags({
fields,
}),
// We use command metadata in the `persistentPreRun` function to check if a
// command requires an API key. If it does, we'll check to see if one is
// set. If not, we'll throw an error.
meta: {
requireApiKey: true,
},
}).run(
async function* ({ args, flags }) {
let [id] = args;

if (!id) {
id = await input("ID:", {
filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_-]/),
});
asserts(id, "A dataset ID is required");
}

const response = await loading(
datasets.delete({ id }),
);

asserts(response.ok, response);
const result = response.data;

if (flags.json) {
yield pickJson(result, flags.fields);
} else {
for await (
const line of dataTable([result], flags.fields ?? defaultFields)
) {
yield line;
}
}
},
);
63 changes: 63 additions & 0 deletions commands/dataset/get/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { datasets } from "../../../api/dataset.ts";
import { fields } from "../../../flags.ts";
import { asserts } from "../../../lib/asserts.ts";
import { dataTable } from "../../../lib/data-table.ts";
import { loading } from "../../../lib/loading.ts";
import { pickJson } from "../../../lib/pick-json.ts";
import { input } from "../../../prompts/input.ts";
import { args, command, flags, z } from "../../../zcli.ts";
import { defaultFields } from "../mod.ts";

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [];

export const get = command("get", {
short: "Get a dataset",
long: `
Get a dataset from a team.
`,
commands: subCommands,
args: args().tuple([
z.string().describe("The ID of the dataset to get"),
]).optional(),
flags: flags({
fields,
}),
// We use command metadata in the `persistentPreRun` function to check if a
// command requires an API key. If it does, we'll check to see if one is
// set. If not, we'll throw an error.
meta: {
requireApiKey: true,
},
}).run(
async function* ({ args, flags }) {
let [id] = args;

if (!id) {
id = await input("ID:", {
filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_-]/),
});
asserts(id, "A dataset ID is required");
}

const response = await loading(
datasets.get({ id }),
);

asserts(response.ok, response);
const result = response.data;

if (flags.json) {
yield pickJson(result, flags.fields);
} else {
for await (
const line of dataTable([result], flags.fields ?? defaultFields)
) {
yield line;
}
}
},
);
63 changes: 63 additions & 0 deletions commands/dataset/list/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { datasets } from "../../../api/dataset.ts";
import { config } from "../../../config.ts";
import * as psFlags from "../../../flags.ts";
import { asserts } from "../../../lib/asserts.ts";
import { dataTable } from "../../../lib/data-table.ts";
import { loading } from "../../../lib/loading.ts";
import { pickJson } from "../../../lib/pick-json.ts";
import { command } from "../../../zcli.ts";
import { defaultFields } from "../mod.ts";

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [];

export const list = command("list", {
short: "List datasets.",
long: ({ root }) => `
List datasets in your team or project.
Pick a subset of fields to display:
\`\`\`
${root.name} dataset list -F name -F dtModified
\`\`\`
`,
commands: subCommands,
flags: psFlags.paginator,
// We use command metadata in the `persistentPreRun` function to check if a
// command requires an API key. If it does, we'll check to see if one is
// set. If not, we'll throw an error.
meta: {
requireApiKey: true,
},
}).run(
async function* ({ flags }) {
const team = await config.get("team");
asserts(team, "You must be in a team to list datasets.");
const result = await loading(
datasets.list({
limit: flags.limit,
after: flags.after,
order: flags.asc ? "asc" : undefined,
}),
{ enabled: !flags.json },
);

asserts(result.ok, result);

if (!flags.json) {
for await (
const line of dataTable(
result.data.items,
flags.fields ?? defaultFields,
)
) {
yield line;
}
} else {
yield pickJson(result.data, flags.fields);
}
},
);
44 changes: 44 additions & 0 deletions commands/dataset/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { env } from "../../env.ts";
import { command } from "../../zcli.ts";
import { create } from "./create/mod.ts";
import { del } from "./delete/mod.ts";
import { get } from "./get/mod.ts";
import { list } from "./list/mod.ts";
import { update } from "./update/mod.ts";

export const defaultFields = [
"id",
"name",
"description",
"storageProviderId",
"isPublic",
];

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [
create,
get,
list,
del,
update,
];

export const dataset = command("dataset", {
short: "Manage your datasets",
long: `
Manage your datasets.
For more information, see ${new URL(
"/storage/datasets",
env.get("PAPERSPACE_DOCS_URL"),
)}.
`,
commands: subCommands,
}).run(function* ({ ctx }) {
for (const line of dataset.help(ctx)) {
yield line;
}
});
75 changes: 75 additions & 0 deletions commands/dataset/update/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { datasets } from "../../../api/dataset.ts";
import { fields } from "../../../flags.ts";
import { asserts } from "../../../lib/asserts.ts";
import { dataTable } from "../../../lib/data-table.ts";
import { loading } from "../../../lib/loading.ts";
import { pickJson } from "../../../lib/pick-json.ts";
import { input } from "../../../prompts/input.ts";
import { args, command, flag, flags, z } from "../../../zcli.ts";
import { defaultFields } from "../mod.ts";

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [];

export const update = command("update", {
short: "Update a dataset",
long: `
Update a dataset in a project or team.
`,
commands: subCommands,
args: args().tuple([
z.string().describe("The ID of the dataset to update"),
]).optional(),
flags: flags({
fields,
}).merge(flags({
"name": flag({
aliases: ["n"],
short: "The name of the dataset",
}).string(),
"description": flag({
short: "The description of the dataset",
}).ostring(),
})),
// We use command metadata in the `persistentPreRun` function to check if a
// command requires an API key. If it does, we'll check to see if one is
// set. If not, we'll throw an error.
meta: {
requireApiKey: true,
},
}).run(
async function* ({ args, flags }) {
let [id] = args;

if (!id) {
id = await input("ID:", {
filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_-]/),
});
asserts(id, "A dataset ID is required");
}

const response = await loading(
datasets.update({
id,
name: flags.name,
description: flags.description,
}),
);

asserts(response.ok, response);
const result = response.data;

if (flags.json) {
yield pickJson(result, flags.fields);
} else {
for await (
const line of dataTable([result], flags.fields ?? defaultFields)
) {
yield line;
}
}
},
);
Loading

0 comments on commit aff5856

Please sign in to comment.