diff --git a/api/dataset.ts b/api/dataset.ts new file mode 100644 index 0000000..e1d260b --- /dev/null +++ b/api/dataset.ts @@ -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, +}; diff --git a/commands/dataset/create/mod.ts b/commands/dataset/create/mod.ts new file mode 100644 index 0000000..b786130 --- /dev/null +++ b/commands/dataset/create/mod.ts @@ -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[] = []; + +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; + } + } + }, +); diff --git a/commands/dataset/delete/mod.ts b/commands/dataset/delete/mod.ts new file mode 100644 index 0000000..407902f --- /dev/null +++ b/commands/dataset/delete/mod.ts @@ -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[] = []; + +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; + } + } + }, +); diff --git a/commands/dataset/get/mod.ts b/commands/dataset/get/mod.ts new file mode 100644 index 0000000..33df9a5 --- /dev/null +++ b/commands/dataset/get/mod.ts @@ -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[] = []; + +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; + } + } + }, +); diff --git a/commands/dataset/list/mod.ts b/commands/dataset/list/mod.ts new file mode 100644 index 0000000..9786539 --- /dev/null +++ b/commands/dataset/list/mod.ts @@ -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[] = []; + +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); + } + }, +); diff --git a/commands/dataset/mod.ts b/commands/dataset/mod.ts new file mode 100644 index 0000000..46a0ac3 --- /dev/null +++ b/commands/dataset/mod.ts @@ -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[] = [ + 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; + } +}); diff --git a/commands/dataset/update/mod.ts b/commands/dataset/update/mod.ts new file mode 100644 index 0000000..1b88da2 --- /dev/null +++ b/commands/dataset/update/mod.ts @@ -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[] = []; + +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; + } + } + }, +); diff --git a/commands/mod.ts b/commands/mod.ts index f33b1e8..bb51e09 100644 --- a/commands/mod.ts +++ b/commands/mod.ts @@ -1,36 +1,36 @@ -import { app, completion, fmt, version } from "../zcli.ts"; +import { billingAccountStanding } from "../api/billing.ts"; +import { config as appConfig } from "../config.ts"; +import { credentials } from "../credentials.ts"; import { semver } from "../deps.ts"; -import { VERSION } from "../version.ts"; +import { env } from "../env.ts"; import { AppError } from "../errors.ts"; +import { asserts } from "../lib/asserts.ts"; import { logger } from "../logger.ts"; -import { env } from "../env.ts"; -import { config as appConfig } from "../config.ts"; -import { credentials } from "../credentials.ts"; -import { getLatestVersion } from "./upgrade/mod.ts"; -import { project } from "./project/mod.ts"; -import { deployment } from "./deployment/mod.ts"; +import { VERSION } from "../version.ts"; +import { app, completion, fmt, version } from "../zcli.ts"; +import { autoscalingGroup } from "./autoscaling-group/mod.ts"; import { config } from "./config/mod.ts"; -import { upgrade } from "./upgrade/mod.ts"; -import { signup } from "./signup/mod.ts"; import { console } from "./console/mod.ts"; +import { dataset } from "./dataset/mod.ts"; +import { deployment } from "./deployment/mod.ts"; import { docs } from "./docs/mod.ts"; -import { logout } from "./logout/mod.ts"; -import { login } from "./login/mod.ts"; import { init } from "./init/mod.ts"; -import { up } from "./up/mod.ts"; -import { secret } from "./secret/mod.ts"; -import { sharedDrive } from "./shared-drive/mod.ts"; -import { privateNetwork } from "./private-network/mod.ts"; -import { publicIp } from "./public-ip/mod.ts"; +import { login } from "./login/mod.ts"; +import { logout } from "./logout/mod.ts"; import { machineEvent } from "./machine-event/mod.ts"; import { machine } from "./machine/mod.ts"; +import { model } from "./model/mod.ts"; +import { privateNetwork } from "./private-network/mod.ts"; +import { project } from "./project/mod.ts"; +import { publicIp } from "./public-ip/mod.ts"; +import { secret } from "./secret/mod.ts"; +import { sharedDrive } from "./shared-drive/mod.ts"; +import { signup } from "./signup/mod.ts"; import { snapshot } from "./snapshot/mod.ts"; -import { template } from "./template/mod.ts"; import { startupScript } from "./startup-script/mod.ts"; -import { autoscalingGroup } from "./autoscaling-group/mod.ts"; -import { model } from "./model/mod.ts"; -import { billingAccountStanding } from "../api/billing.ts"; -import { asserts } from "../lib/asserts.ts"; +import { template } from "./template/mod.ts"; +import { up } from "./up/mod.ts"; +import { getLatestVersion, upgrade } from "./upgrade/mod.ts"; /** * This variable is automatically generated by `zcli add`. Do not remove this @@ -40,6 +40,7 @@ export const commands = [ autoscalingGroup, config, console, + dataset, deployment, docs, init,