diff --git a/.assets/pspace.json b/.assets/pspace.json index e8494af..bc80fed 100644 --- a/.assets/pspace.json +++ b/.assets/pspace.json @@ -4,7 +4,7 @@ "name": "pspace", "version": "0.1.0-dev", "commit": "development", - "buildDate": "2023-03-10T17:05:17.620Z", + "buildDate": "2023-03-13T13:38:57.799Z", "description": "A CLI for using the Paperspace API. \n\nIt allows you to authenticate, launch deployments, do logging, and more.\n\n* Deploy an ML app with the `deployment` command\n* View a deployed app with the `deployment open` command\n* Check the status of a deployment with the `deployment status` command\n\nRead the full documentation at: https://docs.paperspace.com/", "summary": "A CLI for using the Paperspace API." }, @@ -13,6 +13,7 @@ "name": "pspace", "description": "A CLI for using the Paperspace API. \n\nIt allows you to authenticate, launch deployments, do logging, and more.\n\n* Deploy an ML app with the `deployment` command\n* View a deployed app with the `deployment open` command\n* Check the status of a deployment with the `deployment status` command\n\nRead the full documentation at: https://docs.paperspace.com/", "summary": "A CLI for using the Paperspace API.", + "usage": " pspace [command]\n pspace [flags]", "flags": [ { "name": "log-level", @@ -90,6 +91,7 @@ "name": "completion", "description": "Generate an autocompletion script for pspace in the specified shell.\nSee each sub-command's help for details on how to use the generated script.", "summary": "Generate an autocompletion script for the specified shell", + "usage": " pspace [command]\n pspace [flags]", "flags": [ { "name": "log-level", @@ -165,8 +167,9 @@ "commands": [ { "name": "bash", - "description": "Generate the autocompletion script for the bash shell.\n\nThis script depends on the `bash-completion` package.\nIf it is not installed already, you can install it via your OS's package manager.\n\nTo load completions in your current shell session:\n```\n$ source <(pspace completion bash)\n```\n\nTo load completions for every new session, execute once:\n\nLinux:\n```\n$ pspace completion bash > /etc/bash_completion.d/pspace\n```\n\nMacOS:\n```\n$ pspace completion bash > /usr/local/etc/bash_completion.d/pspace\n```\n\nYou will need to start a new shell for this setup to take effect.", + "description": "Generate the autocompletion script for the bash shell.\n\nThis script depends on the `bash-completion` package.\nIf it is not installed already, you can install it via your OS's package manager.\n\nTo load completions in your current shell session:\n```\n$ source <(pspace completion bash)\n```\n\nTo load completions for every new session, execute once:\n\nLinux:\n```\n$ pspace completion bash > /etc/bash_completion.d/pspace\n```\n\nmacOS:\n```\n$ pspace completion bash > /usr/local/etc/bash_completion.d/pspace\n```\n\nYou will need to start a new shell for this setup to take effect.", "summary": "Generate an autocompletion script for the bash shell", + "usage": " pspace completion [flags]", "flags": [ { "name": "log-level", @@ -245,6 +248,7 @@ "name": "fish", "description": "Generate the autocompletion script for the fish shell.\n\nTo load completions in your current shell session:\n```\n$ pspace completion fish | source\n```\n\nTo load completions for every new session, execute once:\n```\n$ pspace completion fish > ~/.config/fish/completions/pspace.fish\n```\n\nYou will need to start a new shell for this setup to take effect.", "summary": "Generate an autocompletion script for the fish shell", + "usage": " pspace completion [flags]", "flags": [ { "name": "no-descriptions", @@ -338,6 +342,7 @@ "name": "help", "description": "Show help for a completion command", "summary": "Show help for a completion command", + "usage": " pspace completion [command]\n pspace completion [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -436,8 +441,9 @@ "commands": [ { "name": "commands", - "description": "List completion commands", + "description": "List completion commands\n\nExample:\n```\n$ pspace completion help commands\n```", "summary": "List completion commands", + "usage": " pspace completion help [flags]", "flags": [ { "name": "log-level", @@ -535,6 +541,7 @@ "name": "zsh", "description": "Generate the autocompletion script for the zsh shell.\n\nIf shell completion is not already enabled in your environment you will need\nto enable it. You can execute the following once:\n\n```\n$ echo \"autoload -U compinit; compinit\" >> ~/.zshrc\n```\n\nTo load completions for every new session, execute once:\n\nLinux:\n```\n$ pspace completion zsh > \"${fpath[1]}/_pspace\"\n```\n\nmacOS:\n```\n$ pspace completion zsh > /usr/local/share/zsh/site-functions/_pspace\n```\n\nOh My Zsh:\n```\n$ pspace completion zsh > ~/.oh-my-zsh/completions/_pspace\n```\n\nYou will need to start a new shell for this setup to take effect.", "summary": "Generate an autocompletion script for the zsh shell", + "usage": " pspace completion [flags]", "flags": [ { "name": "no-descriptions", @@ -630,6 +637,7 @@ "name": "config", "description": "This command manages your Paperspace configuration. You can use it to set, get, and \ndelete configuration values. Running this command without any subcommands will print \nyour current configuration.\n\nYour configuration is stored in a TOML file at `~/.paperspace/config.toml`. \n\nFor example, to set the current team, run: \n```\npspace config set team \"my-team\"\n```", "summary": "Manage your local Paperspace configuration.", + "usage": " pspace [command]\n pspace [flags]", "flags": [ { "name": "log-level", @@ -707,6 +715,7 @@ "name": "delete", "description": "Delete a configuration value.", "summary": "Delete a configuration value.", + "usage": " pspace config [flags]", "arguments": { "description": "", "summary": "The key to delete.", @@ -807,6 +816,7 @@ "name": "get", "description": "This command gets a configuration value. You can pass a key to get a specific\nvalue, or you can pass no arguments to get all configuration values.\n\nFor example, to get the current team run:\n```\npspace config get team\n```", "summary": "Get a configuration value.", + "usage": " pspace config [arguments] [flags]", "arguments": { "description": "", "summary": "The key to get.", @@ -907,6 +917,7 @@ "name": "help", "description": "Show help for a config command", "summary": "Show help for a config command", + "usage": " pspace config [command]\n pspace config [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -1005,8 +1016,9 @@ "commands": [ { "name": "commands", - "description": "List config commands", + "description": "List config commands\n\nExample:\n```\n$ pspace config help commands\n```", "summary": "List config commands", + "usage": " pspace config help [flags]", "flags": [ { "name": "log-level", @@ -1104,6 +1116,7 @@ "name": "set", "description": "Set a configuration value.", "summary": "Set a configuration value.", + "usage": " pspace config [arguments] [arguments...] [flags]", "arguments": { "description": "", "summary": "The key/value pair to set.", @@ -1217,6 +1230,7 @@ "name": "console", "description": "This command opens the Paperspace web console in your browser.", "summary": "Open the Paperspace web console.", + "usage": " pspace [flags]", "flags": [ { "name": "log-level", @@ -1295,6 +1309,7 @@ "name": "deployment", "description": "Effortlessly deploy ML apps to Paperspace.", "summary": "Effortlessly deploy ML apps to Paperspace.", + "usage": " pspace [command]\n pspace [flags]", "flags": [ { "name": "log-level", @@ -1372,6 +1387,7 @@ "name": "delete", "description": "Delete a deployment by its ID. If you don't provide an ID, this command will\nprompt you for one based on the deployments you have access to.\n\n```\npspace deployment delete 123e4567-e89b-12d3-a456-426614174000\n```", "summary": "Delete a deployment.", + "usage": " pspace deployment [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -1467,6 +1483,7 @@ "name": "get", "description": "Get a deployment by its ID. If you don't provide an ID, this command will\nprompt you for one based on the deployments you have access to.\n\n```\npspace deployment get 123e4567-e89b-12d3-a456-426614174000\n```\n\nPick a subset of fields to display:\n```\npspace deployment get 123e4567-e89b-12d3-a456-426614174000 -F name\n```", "summary": "Get a deployment.", + "usage": " pspace deployment [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -1578,6 +1595,7 @@ "name": "help", "description": "Show help for a deployment command", "summary": "Show help for a deployment command", + "usage": " pspace deployment [command]\n pspace deployment [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -1677,8 +1695,9 @@ "commands": [ { "name": "commands", - "description": "List deployment commands", + "description": "List deployment commands\n\nExample:\n```\n$ pspace deployment help commands\n```", "summary": "List deployment commands", + "usage": " pspace deployment help [flags]", "flags": [ { "name": "log-level", @@ -1774,8 +1793,9 @@ }, { "name": "list", - "description": "List deployments in your team.\n\nExamples:\n\nPick a subset of fields to display:\n```\npspace deployment list -F id -F name\n```", + "description": "List deployments in your team.\n\nPick a subset of fields to display:\n```\npspace deployment list -F id -F name\n```", "summary": "List deployments.", + "usage": " pspace deployment [flags]", "flags": [ { "name": "limit", @@ -1943,13 +1963,14 @@ "name": "up", "description": "This will create a new deployment for your app or update it if it already exists. \nYou can optionally specify a path to a config file. If no config file is specified, \nthe default config file paths will be tried.\n\nCreate a new deployment for the app in the current directory.\n```\n$ pspace deployment create\n```\n\nCreate a new deployment using a config file.\n```\n$ pspace deployment create -c paperspace.json\n```\n\nCreate a new deployment for an app in a different directory.\n```\n$ pspace deployment create --cwd ../my-app\n```\n\nCreate a new deployment for an app in a specific project.\n```\n$ pspace deployment create --project-id 1234\n```", "summary": "Create or update a deployment", + "usage": " pspace deployment [flags]", "flags": [ { "name": "config", "aliases": [ "c" ], - "description": "The path to the config file. Defaults to our default config file paths.\n\nThe default config file paths are in order of precedence:\n\n- `paperspace.yaml`\n- `paperspace.yml`\n- `paperspace.json`\n- `paperspace.toml`\n- `.paperspace/app.yaml`\n- `.paperspace/app.yml`\n- `.paperspace/app.json`\n- `.paperspace/app.toml`", + "description": "The path to the config file. Defaults to our default config file paths.\n\nThe default config file paths are in order of precedence:\n\n- `paperspace.yaml`\n- `paperspace.yml`\n- `paperspace.json`\n- `paperspace.jsonc`\n- `paperspace.toml`\n- `.paperspace/app.yaml`\n- `.paperspace/app.yml`\n- `.paperspace/app.json`\n- `.paperspace/app.jsonc`\n- `.paperspace/app.toml`", "summary": "The path to the config file. Defaults to our default config file paths.", "required": false, "collects": false, @@ -2069,6 +2090,7 @@ "name": "docs", "description": "This command opens the Paperspace documentation in your browser.\nYou can optionally pass an argument that will take you to a specific \ndocs page.\n\nValid pages are:\n - `d`, `deployment`", "summary": "Open Paperspace documention in your default browser.", + "usage": " pspace [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -2168,6 +2190,7 @@ "name": "help", "description": "Show help for a pspace command", "summary": "Show help for a pspace command", + "usage": " pspace [command]\n pspace [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -2191,6 +2214,7 @@ "login", "init", "up", + "secret", "version", "completion", "help" @@ -2276,8 +2300,9 @@ "commands": [ { "name": "commands", - "description": "List pspace commands", + "description": "List pspace commands\n\nExample:\n```\n$ pspace help commands\n```", "summary": "List pspace commands", + "usage": " pspace help [flags]", "flags": [ { "name": "log-level", @@ -2375,6 +2400,7 @@ "name": "init", "description": "Create a new Paperspace app. This will create a new directory with a\ndefault app structure. You can optionally specify a name for the app\nand a template to use. If no template is specified, the default\ntemplate will be used.\n\nCreate a new app in the current directory.\n```\n$ pspace init\n```\n\nCreate a new app named \"my-app\" relative to the current directory.\n```\n$ pspace init my-app\n```\n\nCreate a new app named \"my-app\" relative to the current directory using\na template from the Paperspace GitHub organization.\n```\n$ pspace init my-app -t Paperspace/gradio-demo\n```", "summary": "Create a new Paperspace app", + "usage": " pspace [arguments] [flags]", "arguments": { "description": "", "summary": "The directory to create the app in. Defaults to the current directory.", @@ -2545,6 +2571,7 @@ "name": "login", "description": "Log in to the CLI using your Paperspace API key or by opening the web console.", "summary": "Log in to the CLI.", + "usage": " pspace [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -2640,6 +2667,7 @@ "name": "logout", "description": "Log out of the CLI for the current team, a specific team, or all teams.", "summary": "Log out of the CLI.", + "usage": " pspace [arguments...] [flags]", "arguments": { "description": "", "summary": "The teams to logout of.", @@ -2751,6 +2779,7 @@ "name": "project", "description": "Manage your Paperspace projects.", "summary": "Manage your Paperspace projects.", + "usage": " pspace [command]\n pspace [flags]", "flags": [ { "name": "log-level", @@ -2828,6 +2857,7 @@ "name": "create", "description": "Create a new project. This command will prompt you for a name if you don't\nprovide one.", "summary": "Create a new project", + "usage": " pspace project [arguments] [flags]", "arguments": { "description": "", "summary": "Create a project with these properties.", @@ -2940,6 +2970,7 @@ "name": "get", "description": "Get a project by its ID. If you don't provide an ID, this command will\nprompt you for one based on the projects you have access to.", "summary": "Get a project.", + "usage": " pspace project [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -3051,6 +3082,7 @@ "name": "help", "description": "Show help for a project command", "summary": "Show help for a project command", + "usage": " pspace project [command]\n pspace project [arguments] [flags]", "arguments": { "description": "", "summary": "", @@ -3151,8 +3183,9 @@ "commands": [ { "name": "commands", - "description": "List project commands", + "description": "List project commands\n\nExample:\n```\n$ pspace project help commands\n```", "summary": "List project commands", + "usage": " pspace project help [flags]", "flags": [ { "name": "log-level", @@ -3250,6 +3283,7 @@ "name": "link", "description": "This will link a remote project to a local directory. Commands that\ndepend on a project ID will use the project ID of the linked project\nwhen communicating with the Paperspace API.\n\nLink a project to the current directory.\n```\n$ pspace link\n```\n\nLink a project to a different directory.\n```\n$ pspace link --cwd ../my-app\n```\n\nLink a project and specify a project ID.\n```\n$ pspace link pzwf2g05ubegj\n```", "summary": "Link a remote project to ", + "usage": " pspace project [arguments] [flags]", "arguments": { "description": "", "summary": "A project ID. If not provided, you will be prompted to select one.", @@ -3357,8 +3391,9 @@ }, { "name": "list", - "description": "List projects in your team.\n\nExamples:\n\nPick a subset of fields to display:\n```\npspace project list -F handle -F name -F dtCreated\n```", + "description": "List projects in your team.\n\nPick a subset of fields to display:\n```\npspace project list -F handle -F name -F dtCreated\n```", "summary": "List projects.", + "usage": " pspace project [flags]", "flags": [ { "name": "limit", @@ -3526,6 +3561,7 @@ "name": "update", "description": "Update an existing project.\n\nExample:\n```\npspace project update psukfyemho7 --name my-cool-project\n```", "summary": "Update an existing project.", + "usage": " pspace project update [flags]", "arguments": { "description": "", "summary": "", @@ -3651,10 +3687,1128 @@ } ] }, + { + "name": "secret", + "description": "Manage your Paperspace secrets. Secrets are used to store sensitive\ninformation such as API keys, passwords, and other credentials. Secrets \ncan be safely injected into workloads as environment variables. An environment \nvariable that uses a Secret will not reveal the contents of the secret itself.\n\nSecrets can be created at the following levels:\n\n- Project (default): these secrets are applied to all resources in a project\n- Global: these secrets can be applied to all resources on your current team\n\nFor more information, see https://docs.paperspace.com/secrets.", + "summary": "Manage your Paperspace secrets", + "usage": " pspace [command]\n pspace [flags]", + "flags": [ + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [ + { + "name": "create", + "description": "", + "summary": "", + "usage": " pspace secret [arguments] [arguments] [flags]", + "arguments": { + "description": "", + "summary": "", + "items": [ + { + "position": 0, + "summary": "The name of the secret", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", + "description": "The name of the secret", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "position": 1, + "summary": "The value of the secret", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 8192, + "description": "The value of the secret", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ] + }, + "flags": [ + { + "name": "project-id", + "aliases": [ + "p" + ], + "description": "The ID of the project the secret is in. If not specified, the\nsecret will be created in the project linked to your current working\ndirectory. If you are not in a project directory, you will be prompted\nto select a project.", + "summary": "The ID of the project the secret is in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "global", + "aliases": [ + "g" + ], + "description": "Manage a secret that is available to the entire team you are\ncurrently logged into. By default, secrets are only available to\na project.", + "summary": "Manage a secret that is available to the entire team", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "cwd", + "aliases": [], + "description": "The directory to create the secret in", + "summary": "The directory to create the secret in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [] + }, + { + "name": "delete", + "description": "Delete a secret from a project or team.", + "summary": "Delete a secret", + "usage": " pspace secret [arguments] [flags]", + "arguments": { + "description": "", + "summary": "", + "items": [ + { + "position": 0, + "summary": "The name of the secret to delete", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", + "description": "The name of the secret to delete", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ] + }, + "flags": [ + { + "name": "project-id", + "aliases": [ + "p" + ], + "description": "The ID of the project the secret is in. If not specified, the\nsecret will be created in the project linked to your current working\ndirectory. If you are not in a project directory, you will be prompted\nto select a project.", + "summary": "The ID of the project the secret is in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "global", + "aliases": [ + "g" + ], + "description": "Manage a secret that is available to the entire team you are\ncurrently logged into. By default, secrets are only available to\na project.", + "summary": "Manage a secret that is available to the entire team", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "cwd", + "aliases": [], + "description": "The directory to create the secret in", + "summary": "The directory to create the secret in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [] + }, + { + "name": "get", + "description": "Get a secret from a project or team.", + "summary": "Get a secret", + "usage": " pspace secret [arguments] [flags]", + "arguments": { + "description": "", + "summary": "", + "items": [ + { + "position": 0, + "summary": "The name of the secret to get", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", + "description": "The name of the secret to get", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ] + }, + "flags": [ + { + "name": "project-id", + "aliases": [ + "p" + ], + "description": "The ID of the project the secret is in. If not specified, the\nsecret will be created in the project linked to your current working\ndirectory. If you are not in a project directory, you will be prompted\nto select a project.", + "summary": "The ID of the project the secret is in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "global", + "aliases": [ + "g" + ], + "description": "Manage a secret that is available to the entire team you are\ncurrently logged into. By default, secrets are only available to\na project.", + "summary": "Manage a secret that is available to the entire team", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "cwd", + "aliases": [], + "description": "The directory to create the secret in", + "summary": "The directory to create the secret in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "fields", + "aliases": [ + "F" + ], + "description": "The fields to include in the response.", + "summary": "The fields to include in the response.", + "required": false, + "collects": true, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [] + }, + { + "name": "help", + "description": "Show help for a secret command", + "summary": "Show help for a secret command", + "usage": " pspace secret [command]\n pspace secret [arguments] [flags]", + "arguments": { + "description": "", + "summary": "", + "items": [ + { + "position": 0, + "summary": "The command to show help for.", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "enum": [ + "create", + "get", + "list", + "delete", + "update", + "help" + ], + "description": "The command to show help for.", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ] + }, + "flags": [ + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [ + { + "name": "commands", + "description": "List secret commands\n\nExample:\n```\n$ pspace secret help commands\n```", + "summary": "List secret commands", + "usage": " pspace secret help [flags]", + "flags": [ + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "all", + "aliases": [ + "a" + ], + "description": "Show all commands, including hidden ones", + "summary": "Show all commands, including hidden ones", + "required": false, + "collects": false, + "negatable": false, + "default": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [] + } + ] + }, + { + "name": "list", + "description": "List secrets in your team or project.\n\nPick a subset of fields to display:\n```\npspace secret list -F name -F dtModified\n```", + "summary": "List secrets.", + "usage": " pspace secret [flags]", + "flags": [ + { + "name": "limit", + "aliases": [], + "description": "The number of projects to return in the next page.", + "summary": "The number of projects to return in the next page.", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "number", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "after", + "aliases": [], + "description": "The cursor to fetch the next results from.", + "summary": "The cursor to fetch the next results from.", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "orderBy", + "aliases": [], + "description": "The field to order projects by.", + "summary": "The field to order projects by.", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "enum": [ + "dtCreated" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "asc", + "aliases": [], + "description": "Whether to order projects ascending.", + "summary": "Whether to order projects ascending.", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "desc", + "aliases": [], + "description": "Whether to order projects descending.", + "summary": "Whether to order projects descending.", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "fields", + "aliases": [ + "F" + ], + "description": "The fields to include in the response.", + "summary": "The fields to include in the response.", + "required": false, + "collects": true, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "project-id", + "aliases": [ + "p" + ], + "description": "The ID of the project the secret is in. If not specified, the\nsecret will be created in the project linked to your current working\ndirectory. If you are not in a project directory, you will be prompted\nto select a project.", + "summary": "The ID of the project the secret is in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "global", + "aliases": [ + "g" + ], + "description": "Manage a secret that is available to the entire team you are\ncurrently logged into. By default, secrets are only available to\na project.", + "summary": "Manage a secret that is available to the entire team", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "cwd", + "aliases": [], + "description": "The directory to create the secret in", + "summary": "The directory to create the secret in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [] + }, + { + "name": "update", + "description": "", + "summary": "", + "usage": " pspace secret [arguments] [arguments] [flags]", + "arguments": { + "description": "", + "summary": "", + "items": [ + { + "position": 0, + "summary": "The name of the secret", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", + "description": "The name of the secret", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "position": 1, + "summary": "The value of the secret", + "required": true, + "variadic": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 8192, + "description": "The value of the secret", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ] + }, + "flags": [ + { + "name": "project-id", + "aliases": [ + "p" + ], + "description": "The ID of the project the secret is in. If not specified, the\nsecret will be created in the project linked to your current working\ndirectory. If you are not in a project directory, you will be prompted\nto select a project.", + "summary": "The ID of the project the secret is in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "global", + "aliases": [ + "g" + ], + "description": "Manage a secret that is available to the entire team you are\ncurrently logged into. By default, secrets are only available to\na project.", + "summary": "Manage a secret that is available to the entire team", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "cwd", + "aliases": [], + "description": "The directory to create the secret in", + "summary": "The directory to create the secret in", + "required": false, + "collects": false, + "negatable": false, + "global": false, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "log-level", + "aliases": [ + "l" + ], + "description": "Enable debug logging.", + "summary": "Enable debug logging", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "enum": [ + "debug", + "info", + "warning", + "error", + "critical" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "json", + "aliases": [ + "j" + ], + "description": "Output JSON", + "summary": "Output JSON", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "api-key", + "aliases": [], + "description": "A Paperspace public API Key used for authenticating requests", + "summary": "A Paperspace public API Key used for authenticating requests", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "string", + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "help", + "aliases": [ + "h" + ], + "description": "Show help for a command", + "summary": "Show help for a command", + "required": false, + "collects": false, + "negatable": false, + "global": true, + "schema": { + "type": "boolean", + "default": false, + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + ], + "commands": [] + } + ] + }, { "name": "signup", "description": "This command opens the Paperspace signup page in your browser.", "summary": "Sign up for a Paperspace account.", + "usage": " pspace [flags]", "flags": [ { "name": "log-level", @@ -3733,13 +4887,14 @@ "name": "up", "description": "This will upsert an app config and deploy your app to Paperspace. You can optionally \nspecify a path to a config file. If no config file is specified, the default\nconfig file paths will be tried.\n\nDeploy the app in the current directory.\n```\n$ pspace up\n```\n\nDeploy the app using a config file.\n```\n$ pspace up -c paperspace.json\n```\n\nDeploy an app in a different directory.\n```\n$ pspace up --cwd ../my-app\n```", "summary": "Deploy your app to Paperspace", + "usage": " pspace [flags]", "flags": [ { "name": "config", "aliases": [ "c" ], - "description": "The path to the config file. Defaults to our default config file paths.\n\nThe default config file paths are in order of precedence:\n\n- `paperspace.yaml`\n- `paperspace.yml`\n- `paperspace.json`\n- `paperspace.toml`\n- `.paperspace/app.yaml`\n- `.paperspace/app.yml`\n- `.paperspace/app.json`\n- `.paperspace/app.toml`", + "description": "The path to the config file. Defaults to our default config file paths.\n\nThe default config file paths are in order of precedence:\n\n- `paperspace.yaml`\n- `paperspace.yml`\n- `paperspace.json`\n- `paperspace.jsonc`\n- `paperspace.toml`\n- `.paperspace/app.yaml`\n- `.paperspace/app.yml`\n- `.paperspace/app.json`\n- `.paperspace/app.jsonc`\n- `.paperspace/app.toml`", "summary": "The path to the config file. Defaults to our default config file paths.", "required": false, "collects": false, @@ -3857,6 +5012,7 @@ "name": "upgrade", "description": "This command upgrades \u001b[1mpspace\u001b[22m to the latest version.\n\nIf you used a package manager like `brew` to install `pspace`, \nyou should use that to upgrade in order to avoid potential permissions \nissues. For example, for `brew` you can upgrade by running:\n```\nbrew upgrade pspace\n```\n\nIf you installed `pspace` using the install script, you can upgrade by\nrunning:\n```\npspace upgrade\n```", "summary": "Upgrade \u001b[1mpspace\u001b[22m to the latest version.", + "usage": " pspace [flags]", "flags": [ { "name": "log-level", @@ -3935,6 +5091,7 @@ "name": "version", "description": "Shows version information command, including version number and build date.", "summary": "Show version information", + "usage": " pspace [flags]", "flags": [ { "name": "log-level", diff --git a/.scripts/generate-api.ts b/.scripts/generate-api.ts index 2d048c2..49e419b 100644 --- a/.scripts/generate-api.ts +++ b/.scripts/generate-api.ts @@ -1,6 +1,6 @@ import openapiTS from "npm:openapi-typescript"; import { path } from "../deps.ts"; -import { parse } from "https://deno.land/std@0.178.0/flags/mod.ts"; +import { parse } from "https://deno.land/std@0.179.0/flags/mod.ts"; const flags = parse(Deno.args); const url = flags._[0] ?? "https://api.paperspace.com/v1/openapi.json"; diff --git a/.scripts/generate-docs.ts b/.scripts/generate-docs.ts index 6b60444..e0eaeab 100644 --- a/.scripts/generate-docs.ts +++ b/.scripts/generate-docs.ts @@ -1,6 +1,6 @@ import { app } from "../zcli.ts"; import { root } from "../commands/mod.ts"; -import { zcliJson } from "https://deno.land/x/zcli@1.3.2/zcli-json.ts"; +import { zcliJson } from "https://deno.land/x/zcli@1.3.3/zcli-json.ts"; // Read the markdown file adjacent to this script const json = await zcliJson(app, root); diff --git a/README.md b/README.md index e8cf600..3bab3af 100644 --- a/README.md +++ b/README.md @@ -10,24 +10,6 @@ Using Shell (macOS, Linux, and Windows using WSL): curl -fsSL https://paperspace.com/install.sh | sh ``` -Using Scoop (Windows): - -> **Note** Coming soon -> -> ```sh -> scoop bucket add pspace https://github.com/Paperspace/scoop-bucket.git -> scoop install pspace -> ``` - -Using Homebrew (macOS and Linux): - -> **Note** Coming soon -> -> ```sh -> brew tap paperspace/tap -> brew install pspace -> ``` - ## Usage Run `pspace --help` in your terminal. diff --git a/api/client.ts b/api/client.ts index dde270d..af95b14 100644 --- a/api/client.ts +++ b/api/client.ts @@ -191,7 +191,7 @@ export type ClientMethod< requestInit?: ApiClientRequestInit, ) => Promise | ErrorData> : ( - params: PathParams & PathBody, + params: Prettify & PathBody>, requestInit?: ApiClientRequestInit, ) => Promise | ErrorData>); diff --git a/api/openapi.ts b/api/openapi.ts index 8c6d36f..0876ebf 100644 --- a/api/openapi.ts +++ b/api/openapi.ts @@ -74,6 +74,71 @@ export interface paths { */ put: operations["mutation.projects.update"]; }; + "/projects/{handle}/deployments": { + /** + * List a project's deployments + * @description Fetches a list of deployments for a project. + */ + get: operations["query.projectsDeployments.list"]; + }; + "/projects/{handle}/secrets": { + /** + * List a project's secrets + * @description Fetches a list of secrets for a project. + */ + get: operations["query.projectSecrets.list"]; + /** + * Create a project secret + * @description Creates a new secret for a project. + */ + post: operations["mutation.projectSecrets.create"]; + }; + "/projects/{handle}/secrets/{name}": { + /** + * Get a project secret + * @description Fetches a secret for a project. + */ + get: operations["query.projectSecrets.getProjectSecret"]; + /** + * Delete a project secret + * @description Deletes a secret for a project. + */ + delete: operations["mutation.projectSecrets.delete"]; + /** + * Update a project secret + * @description Update the value of a secret for a project. + */ + patch: operations["mutation.projectSecrets.update"]; + }; + "/teams/{handle}/secrets": { + /** + * List a team's secrets + * @description Fetches a list of secrets for a team. + */ + get: operations["query.teamSecrets.list"]; + /** + * Create a team secret + * @description Creates a new secret for a team. + */ + post: operations["mutation.teamSecrets.create"]; + }; + "/teams/{handle}/secrets/{name}": { + /** + * Get a team secret + * @description Fetches a secret for a team. + */ + get: operations["query.teamSecrets.get"]; + /** + * Delete a team secret + * @description Deletes a secret for a team. + */ + delete: operations["mutation.teamSecrets.delete"]; + /** + * Update a team secret + * @description Update the value of a secret for a team. + */ + patch: operations["mutation.teamSecrets.update"]; + }; } export type webhooks = Record; @@ -384,11 +449,11 @@ export interface operations { }); /** @description The ID of the deployment the spec belongs to */ readonly deploymentId: string; - /** @description The error message for the deployment */ + /** @description The fatal configuration error. Only present if the cluster was unable to apply the entire deployment configuration. This is not the same as an instance error. */ readonly error: string | null; /** * Format: date-time - * @description The date the deployment was applied to the cluster + * @description The date the deployment configuration was applied to the cluster */ readonly externalApplied: Date; /** @description The ID of the deployment spec */ @@ -404,8 +469,10 @@ export interface operations { readonly latestSpecHash: string | null; /** @description The name of the deployment */ readonly name: string; + /** @description The ID of the project the deployment belongs to */ + readonly projectId: string; /** @description The ID of the team the deployment belongs to */ - readonly teamId: number; + readonly teamId: string; })[]; /** @description The cursor required to fetch the next page of results. i.e. `?after=nextPage`. This is `null` when there is no next page. */ readonly nextPage: string | null; @@ -659,6 +726,7 @@ export interface operations { * @description Fetches a single deployment by deployment ID. */ parameters: { + /** @description The ID of the deployment to fetch */ readonly path: { id: string; }; @@ -889,11 +957,11 @@ export interface operations { }); /** @description The ID of the deployment the spec belongs to */ readonly deploymentId: string; - /** @description The error message for the deployment */ + /** @description The fatal configuration error. Only present if the cluster was unable to apply the entire deployment configuration. This is not the same as an instance error. */ readonly error: string | null; /** * Format: date-time - * @description The date the deployment was applied to the cluster + * @description The date the deployment configuration was applied to the cluster */ readonly externalApplied: Date; /** @description The ID of the deployment spec */ @@ -909,8 +977,10 @@ export interface operations { readonly latestSpecHash: string | null; /** @description The name of the deployment */ readonly name: string; + /** @description The ID of the project the deployment belongs to */ + readonly projectId: string; /** @description The ID of the team the deployment belongs to */ - readonly teamId: number; + readonly teamId: string; }; }; }; @@ -923,6 +993,7 @@ export interface operations { * @description Deletes a deployment by deployment ID. */ parameters: { + /** @description The ID of the deployment to delete */ readonly path: { id: string; }; @@ -932,6 +1003,7 @@ export interface operations { 200: { content: { readonly "application/json": { + /** @description The ID of the deleted deployment */ readonly id: string; }; }; @@ -949,6 +1021,7 @@ export interface operations { readonly query: { limit?: number; }; + /** @description The ID of the deployment to fetch */ readonly path: { id: string; }; @@ -1287,4 +1360,676 @@ export interface operations { default: components["responses"]["error"]; }; }; + "query.projectsDeployments.list": { + /** + * List a project's deployments + * @description Fetches a list of deployments for a project. + */ + parameters: { + readonly query: { + name?: string; + }; + /** @description The ID of the project to fetch deployments for */ + readonly path: { + handle: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": readonly ({ + /** + * Format: date-time + * @description The date the deployment was created + */ + readonly dtCreated: Date; + /** @description The unique endpoint for the deployment */ + readonly endpoint: string; + /** @description The ID of the deployment */ + readonly id: string; + /** @description The latest deployment configuration. If invalid, null is returned. */ + readonly latestSpec?: + | ({ + /** @description The data for the deployment spec */ + readonly data: + | ({ + readonly apiVersion: "v0alpha0" | "latest"; + readonly command?: readonly [string, ...(string)[]]; + /** Format: uuid */ + readonly containerRegistry?: string; + /** @default true */ + readonly enabled: boolean; + readonly env?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly healthchecks?: { + readonly liveness?: { + readonly failureThreshold?: number; + readonly headers?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly host?: string; + readonly initialDelaySeconds?: number; + readonly path: string; + readonly periodSeconds?: number; + readonly port?: number; + readonly timeoutSeconds?: number; + } | { + readonly exec: { + readonly command: readonly (string)[]; + }; + readonly failureThreshold?: number; + readonly initialDelaySeconds?: number; + readonly periodSeconds?: number; + readonly timeoutSeconds?: number; + }; + readonly readiness?: { + readonly failureThreshold?: number; + readonly headers?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly host?: string; + readonly initialDelaySeconds?: number; + readonly path: string; + readonly periodSeconds?: number; + readonly port?: number; + readonly timeoutSeconds?: number; + } | { + readonly exec: { + readonly command: readonly (string)[]; + }; + readonly failureThreshold?: number; + readonly initialDelaySeconds?: number; + readonly periodSeconds?: number; + readonly timeoutSeconds?: number; + }; + readonly startup?: { + readonly failureThreshold?: number; + readonly headers?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly host?: string; + readonly initialDelaySeconds?: number; + readonly path: string; + readonly periodSeconds?: number; + readonly port?: number; + readonly timeoutSeconds?: number; + } | { + readonly exec: { + readonly command: readonly (string)[]; + }; + readonly failureThreshold?: number; + readonly initialDelaySeconds?: number; + readonly periodSeconds?: number; + readonly timeoutSeconds?: number; + }; + }; + readonly image: string; + readonly models?: readonly ({ + readonly id: string; + readonly path?: string; + })[]; + readonly name: string; + /** @default 80 */ + readonly port: number; + /** @default null */ + readonly region: string | null; + readonly repositories?: { + readonly dataset: string; + readonly mountPath?: string; + readonly repositories: readonly ({ + readonly name: string; + readonly password?: string; + readonly ref?: string; + readonly url: string; + readonly username?: string; + })[]; + }; + readonly resources: { + readonly autoscaling?: { + readonly enabled?: boolean; + readonly maxReplicas: number; + readonly metrics: readonly ( + | { + /** @enum {string} */ + readonly metric: "requestDuration"; + /** @enum {string} */ + readonly summary: "average"; + readonly value: number; + } + | ({ + /** @enum {string} */ + readonly metric: "cpu" | "memory"; + /** @enum {string} */ + readonly summary: "average"; + readonly value: number; + }) + )[]; + }; + readonly instanceType: string; + /** @default 1 */ + readonly replicas: number; + }; + }) + | ({ + /** @enum {string} */ + readonly apiVersion: "v0alpha1"; + readonly command: readonly [string, ...(string)[]]; + /** Format: uuid */ + readonly containerRegistry?: string; + /** @default true */ + readonly enabled: boolean; + readonly env?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly healthchecks?: { + readonly liveness?: { + readonly failureThreshold?: number; + readonly headers?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly host?: string; + readonly initialDelaySeconds?: number; + readonly path: string; + readonly periodSeconds?: number; + readonly port?: number; + readonly timeoutSeconds?: number; + } | { + readonly exec: { + readonly command: readonly (string)[]; + }; + readonly failureThreshold?: number; + readonly initialDelaySeconds?: number; + readonly periodSeconds?: number; + readonly timeoutSeconds?: number; + }; + readonly readiness?: { + readonly failureThreshold?: number; + readonly headers?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly host?: string; + readonly initialDelaySeconds?: number; + readonly path: string; + readonly periodSeconds?: number; + readonly port?: number; + readonly timeoutSeconds?: number; + } | { + readonly exec: { + readonly command: readonly (string)[]; + }; + readonly failureThreshold?: number; + readonly initialDelaySeconds?: number; + readonly periodSeconds?: number; + readonly timeoutSeconds?: number; + }; + readonly startup?: { + readonly failureThreshold?: number; + readonly headers?: readonly ({ + readonly name: string; + readonly value: string; + })[]; + readonly host?: string; + readonly initialDelaySeconds?: number; + readonly path: string; + readonly periodSeconds?: number; + readonly port?: number; + readonly timeoutSeconds?: number; + } | { + readonly exec: { + readonly command: readonly (string)[]; + }; + readonly failureThreshold?: number; + readonly initialDelaySeconds?: number; + readonly periodSeconds?: number; + readonly timeoutSeconds?: number; + }; + }; + readonly image: string; + readonly name: string; + /** @default null */ + readonly region: string | null; + }); + /** @description The ID of the deployment the spec belongs to */ + readonly deploymentId: string; + /** @description The fatal configuration error. Only present if the cluster was unable to apply the entire deployment configuration. This is not the same as an instance error. */ + readonly error: string | null; + /** + * Format: date-time + * @description The date the deployment configuration was applied to the cluster + */ + readonly externalApplied: Date; + /** @description The ID of the deployment spec */ + readonly id: string; + /** @description The ID of the user the deployment belongs to */ + readonly userId: number; + }) + | null; + /** + * @description The last version hash for the deployment + * @default null + */ + readonly latestSpecHash: string | null; + /** @description The name of the deployment */ + readonly name: string; + /** @description The ID of the project the deployment belongs to */ + readonly projectId: string; + /** @description The ID of the team the deployment belongs to */ + readonly teamId: string; + })[]; + }; + }; + default: components["responses"]["error"]; + }; + }; + "query.projectSecrets.list": { + /** + * List a project's secrets + * @description Fetches a list of secrets for a project. + */ + parameters: { + /** @description Fetch the next page of results after this cursor. */ + /** @description The number of items to fetch after this page. */ + /** @description Order results by one of these fields. */ + /** @description The order to sort the results by. */ + readonly query: { + after?: string; + limit?: number; + orderBy?: "dtCreated"; + order?: "asc" | "desc"; + }; + /** @description The ID of the project where the secret is stored. */ + readonly path: { + handle: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** @description Whether there are more pages of results available. */ + readonly hasMore: boolean; + /** @description The items on this page. */ + readonly items: readonly ({ + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + })[]; + /** @description The cursor required to fetch the next page of results. i.e. `?after=nextPage`. This is `null` when there is no next page. */ + readonly nextPage: string | null; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "mutation.projectSecrets.create": { + /** + * Create a project secret + * @description Creates a new secret for a project. + */ + parameters: { + /** @description The ID of the project where the secret is stored. */ + readonly path: { + handle: string; + }; + }; + readonly requestBody: { + readonly content: { + readonly "application/json": { + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + /** @description The value of the secret, e.g. "password". */ + readonly value: string; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "query.projectSecrets.getProjectSecret": { + /** + * Get a project secret + * @description Fetches a secret for a project. + */ + parameters: { + /** @description The ID of the project where the secret is stored. */ + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly path: { + handle: string; + name: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "mutation.projectSecrets.delete": { + /** + * Delete a project secret + * @description Deletes a secret for a project. + */ + parameters: { + /** @description The ID of the project where the secret is stored. */ + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly path: { + handle: string; + name: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "mutation.projectSecrets.update": { + /** + * Update a project secret + * @description Update the value of a secret for a project. + */ + parameters: { + /** @description The ID of the project where the secret is stored. */ + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly path: { + handle: string; + name: string; + }; + }; + readonly requestBody: { + readonly content: { + readonly "application/json": { + /** @description The value of the secret, e.g. "password". */ + readonly value: string; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "query.teamSecrets.list": { + /** + * List a team's secrets + * @description Fetches a list of secrets for a team. + */ + parameters: { + /** @description Fetch the next page of results after this cursor. */ + /** @description The number of items to fetch after this page. */ + /** @description Order results by one of these fields. */ + /** @description The order to sort the results by. */ + readonly query: { + after?: string; + limit?: number; + orderBy?: "dtCreated"; + order?: "asc" | "desc"; + }; + /** @description The ID of the team where the secret is stored. */ + readonly path: { + handle: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** @description Whether there are more pages of results available. */ + readonly hasMore: boolean; + /** @description The items on this page. */ + readonly items: readonly ({ + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + })[]; + /** @description The cursor required to fetch the next page of results. i.e. `?after=nextPage`. This is `null` when there is no next page. */ + readonly nextPage: string | null; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "mutation.teamSecrets.create": { + /** + * Create a team secret + * @description Creates a new secret for a team. + */ + parameters: { + /** @description The ID of the team where the secret is stored. */ + readonly path: { + handle: string; + }; + }; + readonly requestBody: { + readonly content: { + readonly "application/json": { + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + /** @description The value of the secret, e.g. "password". */ + readonly value: string; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "query.teamSecrets.get": { + /** + * Get a team secret + * @description Fetches a secret for a team. + */ + parameters: { + /** @description The ID of the team where the secret is stored. */ + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly path: { + handle: string; + name: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "mutation.teamSecrets.delete": { + /** + * Delete a team secret + * @description Deletes a secret for a team. + */ + parameters: { + /** @description The ID of the team where the secret is stored. */ + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly path: { + handle: string; + name: string; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; + "mutation.teamSecrets.update": { + /** + * Update a team secret + * @description Update the value of a secret for a team. + */ + parameters: { + /** @description The ID of the team where the secret is stored. */ + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly path: { + handle: string; + name: string; + }; + }; + readonly requestBody: { + readonly content: { + readonly "application/json": { + /** @description The value of the secret, e.g. "password". */ + readonly value: string; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + readonly "application/json": { + /** + * Format: date-time + * @description The date the secret was created. + */ + readonly dtCreated: Date; + /** + * Format: date-time + * @description The date the secret was last modified. + */ + readonly dtModified: Date; + /** @description The name of the secret, e.g. "DB_PASSWORD". */ + readonly name: string; + }; + }; + }; + default: components["responses"]["error"]; + }; + }; } diff --git a/api/projects.ts b/api/projects.ts index 2c65167..1bb9d02 100644 --- a/api/projects.ts +++ b/api/projects.ts @@ -7,3 +7,11 @@ export const projects = { update: client("/projects/{handle}").put, // delete: client("/projects/{handle}").delete, }; + +export const projectSecrets = { + list: client("/projects/{handle}/secrets").get, + create: client("/projects/{handle}/secrets").post, + get: client("/projects/{handle}/secrets/{name}").get, + update: client("/projects/{handle}/secrets/{name}").patch, + delete: client("/projects/{handle}/secrets/{name}").delete, +}; diff --git a/api/teams.ts b/api/teams.ts new file mode 100644 index 0000000..7203145 --- /dev/null +++ b/api/teams.ts @@ -0,0 +1,9 @@ +import { client } from "./client.ts"; + +export const teamSecrets = { + list: client("/teams/{handle}/secrets").get, + create: client("/teams/{handle}/secrets").post, + get: client("/teams/{handle}/secrets/{name}").get, + update: client("/teams/{handle}/secrets/{name}").patch, + delete: client("/teams/{handle}/secrets/{name}").delete, +}; diff --git a/commands/deployment/list/mod.ts b/commands/deployment/list/mod.ts index 86bbd8d..7699342 100644 --- a/commands/deployment/list/mod.ts +++ b/commands/deployment/list/mod.ts @@ -17,8 +17,6 @@ export const list = command("list", { long: ({ root }) => ` List deployments in your team. - Examples: - Pick a subset of fields to display: \`\`\` ${root.name} deployment list -F id -F name diff --git a/commands/mod.ts b/commands/mod.ts index fa06c42..d05b7f2 100644 --- a/commands/mod.ts +++ b/commands/mod.ts @@ -17,6 +17,7 @@ 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"; /** * This variable is automatically generated by `zcli add`. Do not remove this @@ -34,6 +35,7 @@ export const commands = [ login, init, up, + secret, ]; export const root = app diff --git a/commands/project/list/mod.ts b/commands/project/list/mod.ts index fce9414..bfbf4ad 100644 --- a/commands/project/list/mod.ts +++ b/commands/project/list/mod.ts @@ -17,8 +17,6 @@ export const list = command("list", { long: ({ root }) => ` List projects in your team. - Examples: - Pick a subset of fields to display: \`\`\` ${root.name} project list -F handle -F name -F dtCreated diff --git a/commands/secret/create/mod.ts b/commands/secret/create/mod.ts new file mode 100644 index 0000000..63fcb77 --- /dev/null +++ b/commands/secret/create/mod.ts @@ -0,0 +1,113 @@ +import { secretSchema } from "./../schemas.ts"; +import { projectSecrets } from "../../../api/projects.ts"; +import { teamSecrets } from "../../../api/teams.ts"; +import { config } from "../../../config.ts"; +import { asserts } from "../../../lib/asserts.ts"; +import { findProject } from "../../../lib/find-project.ts"; +import { loading } from "../../../lib/loading.ts"; +import { input } from "../../../prompts/input.ts"; +import { confirm } from "../../../prompts/confirm.ts"; +import { secret } from "../../../prompts/secret.ts"; +import { args, command, fmt } from "../../../zcli.ts"; +import { secretFlags } from "../flags.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: "", + commands: subCommands, + args: args().tuple([ + secretSchema.shape.name.describe("The name of the secret"), + secretSchema.shape.value.describe("The value of the secret"), + ]).optional(), + flags: secretFlags, + // 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 [name, value] = args; + + if (!name) { + name = await input("Name:", { + filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_]/), + }); + asserts(name, "A secret name is required"); + } + + const parsedName = secretSchema.shape.name.safeParse(name); + asserts( + parsedName.success, + "error" in parsedName ? parsedName.error : "", + ); + + if (!value) { + value = await secret("Value:"); + asserts(value, "A secret value is required"); + } + + const parsedValue = secretSchema.shape.value.safeParse(name); + asserts( + parsedValue.success, + "error" in parsedValue ? parsedValue.error : "", + ); + + if (flags.global) { + const team = await config.get("team"); + asserts( + team, + "You must be logged into a team to create a secret.", + ); + + if (!flags.json) { + yield fmt.colors.yellow( + `This secret will be available to all resources in the team.`, + ); + asserts( + await confirm( + `Are you sure you want to create a global secret in team "${team}"?`, + ), + "Aborted", + ); + } + + const response = await loading( + teamSecrets.create({ handle: team, name, value }), + ); + + asserts(response.ok, response); + const result = response.data; + + if (flags.json) { + yield JSON.stringify(result, null, 2); + } else { + yield `Created secret "${name}" in team "${team}"`; + } + } else { + const project = await findProject({ + handle: flags["project-id"], + cwd: flags.cwd, + quiet: flags.json, + }); + const response = await loading( + projectSecrets.create({ handle: project.handle, name, value }), + ); + + asserts(response.ok, response); + const result = response.data; + + if (flags.json) { + yield JSON.stringify(result, null, 2); + } else { + yield `Created secret "${name}" in project "${project.name}"`; + } + } + }, +); diff --git a/commands/secret/delete/mod.ts b/commands/secret/delete/mod.ts new file mode 100644 index 0000000..86b8e17 --- /dev/null +++ b/commands/secret/delete/mod.ts @@ -0,0 +1,98 @@ +import { secretSchema } from "./../schemas.ts"; +import { projectSecrets } from "../../../api/projects.ts"; +import { teamSecrets } from "../../../api/teams.ts"; +import { config } from "../../../config.ts"; +import { asserts } from "../../../lib/asserts.ts"; +import { findProject } from "../../../lib/find-project.ts"; +import { loading } from "../../../lib/loading.ts"; +import { input } from "../../../prompts/input.ts"; +import { confirm } from "../../../prompts/confirm.ts"; +import { args, command } from "../../../zcli.ts"; +import { secretFlags } from "../flags.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 delete_ = command("delete", { + short: "Delete a secret", + long: ` + Delete a secret from a project or team. + `, + commands: subCommands, + args: args().tuple([ + secretSchema.shape.name.describe("The name of the secret to delete"), + ]).optional(), + flags: secretFlags, + // 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 [name] = args; + + if (!name) { + name = await input("Name:", { + filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_]/), + }); + asserts(name, "A secret name is required"); + } + + const parsedName = secretSchema.shape.name.safeParse(name); + asserts( + parsedName.success, + "error" in parsedName ? parsedName.error : "", + ); + + if (!flags.global) { + const project = await findProject({ + handle: flags["project-id"], + cwd: flags.cwd, + quiet: flags.json, + }); + + const response = await loading( + projectSecrets.delete({ handle: project.handle, name }), + ); + + asserts(response.ok, response); + const result = response.data; + + if (flags.json) { + yield JSON.stringify(result, null, 2); + } else { + yield `Deleted secret "${name}" in project "${project.name}"`; + } + } else { + const team = await config.get("team"); + asserts(team, "A team is required"); + + if (!flags.json) { + asserts( + await confirm( + `Are you sure you want to delete your global secret "${name}" in team "${team}"?`, + ), + "Aborted", + ); + } + + const response = await loading( + teamSecrets.delete({ handle: team, name }), + ); + + asserts(response.ok, response); + const result = response.data; + + if (flags.json) { + yield JSON.stringify(result, null, 2); + } else { + yield `Deleted secret "${name}" in team "${team}"`; + } + } + }, +); diff --git a/commands/secret/flags.ts b/commands/secret/flags.ts new file mode 100644 index 0000000..4f0b74e --- /dev/null +++ b/commands/secret/flags.ts @@ -0,0 +1,26 @@ +import { flag, flags } from "../../zcli.ts"; + +export const secretFlags = flags({ + "project-id": flag({ + aliases: ["p"], + short: "The ID of the project the secret is in", + long: ` + The ID of the project the secret is in. If not specified, the + secret will be created in the project linked to your current working + directory. If you are not in a project directory, you will be prompted + to select a project. + `, + }).ostring(), + global: flag({ + aliases: ["g"], + short: "Manage a secret that is available to the entire team", + long: ` + Manage a secret that is available to the entire team you are + currently logged into. By default, secrets are only available to + a project. + `, + }).oboolean(), + cwd: flag({ + short: "The directory to create the secret in", + }).ostring(), +}); diff --git a/commands/secret/get/mod.ts b/commands/secret/get/mod.ts new file mode 100644 index 0000000..acbb501 --- /dev/null +++ b/commands/secret/get/mod.ts @@ -0,0 +1,97 @@ +import { secretSchema } from "./../schemas.ts"; +import { projectSecrets } from "../../../api/projects.ts"; +import { teamSecrets } from "../../../api/teams.ts"; +import { config } from "../../../config.ts"; +import { asserts } from "../../../lib/asserts.ts"; +import { findProject } from "../../../lib/find-project.ts"; +import { loading } from "../../../lib/loading.ts"; +import { input } from "../../../prompts/input.ts"; +import { args, command, flags } from "../../../zcli.ts"; +import { secretFlags } from "../flags.ts"; +import { dataTable } from "../../../lib/data-table.ts"; +import { fields } from "../../../flags.ts"; +import { pickJson } from "../../../lib/pick-json.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 secret", + long: ` + Get a secret from a project or team. + `, + commands: subCommands, + args: args().tuple([ + secretSchema.shape.name.describe("The name of the secret to get"), + ]).optional(), + flags: secretFlags.merge(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 [name] = args; + + if (!name) { + name = await input("Name:", { + filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_]/), + }); + asserts(name, "A secret name is required"); + } + + const parsedName = secretSchema.shape.name.safeParse(name); + asserts( + parsedName.success, + "error" in parsedName ? parsedName.error : "", + ); + + if (!flags.global) { + const project = await findProject({ + handle: flags["project-id"], + cwd: flags.cwd, + quiet: flags.json, + }); + + const response = await loading( + projectSecrets.get({ handle: project.handle, name }), + ); + + 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)) { + yield line; + } + } + } else { + const team = await config.get("team"); + asserts(team, "A team is required"); + + const response = await loading( + teamSecrets.get({ handle: team, name }), + ); + + 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)) { + yield line; + } + } + } + }, +); diff --git a/commands/secret/list/mod.ts b/commands/secret/list/mod.ts new file mode 100644 index 0000000..7825ddd --- /dev/null +++ b/commands/secret/list/mod.ts @@ -0,0 +1,90 @@ +import { projectSecrets } from "../../../api/projects.ts"; +import { command } from "../../../zcli.ts"; +import { asserts } from "../../../lib/asserts.ts"; +import { dataTable } from "../../../lib/data-table.ts"; +import { loading } from "../../../lib/loading.ts"; +import * as psFlags from "../../../flags.ts"; +import { pickJson } from "../../../lib/pick-json.ts"; +import { findProject } from "../../../lib/find-project.ts"; +import { secretFlags } from "../flags.ts"; +import { teamSecrets } from "../../../api/teams.ts"; +import { config } from "../../../config.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 secrets.", + long: ({ root }) => ` + List secrets in your team or project. + + Pick a subset of fields to display: + \`\`\` + ${root.name} secret list -F name -F dtModified + \`\`\` + `, + commands: subCommands, + flags: psFlags.paginator.merge(secretFlags), + // 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 }) { + if (!flags.global) { + const project = await findProject({ + handle: flags["project-id"], + cwd: flags.cwd, + quiet: flags.json, + }); + const result = await loading( + projectSecrets.list({ + handle: project.handle, + limit: flags.limit, + after: flags.after, + orderBy: flags.orderBy, + 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)) { + yield line; + } + } else { + yield pickJson(result.data, flags.fields); + } + } else { + const team = await config.get("team"); + asserts(team, "You must be in a team to list secrets."); + const result = await loading( + teamSecrets.list({ + handle: team, + limit: flags.limit, + after: flags.after, + orderBy: flags.orderBy, + 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)) { + yield line; + } + } else { + yield pickJson(result.data, flags.fields); + } + } + }, +); diff --git a/commands/secret/mod.ts b/commands/secret/mod.ts new file mode 100644 index 0000000..5b2415f --- /dev/null +++ b/commands/secret/mod.ts @@ -0,0 +1,40 @@ +import { command } from "../../zcli.ts"; +import { create } from "./create/mod.ts"; +import { get } from "./get/mod.ts"; +import { list } from "./list/mod.ts"; +import { delete_ } from "./delete/mod.ts"; +import { update } from "./update/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[] = [ + create, + get, + list, + delete_, + update, +]; + +export const secret = command("secret", { + short: "Manage your Paperspace secrets", + long: ` + Manage your Paperspace secrets. Secrets are used to store sensitive + information such as API keys, passwords, and other credentials. Secrets + can be safely injected into workloads as environment variables. An environment + variable that uses a Secret will not reveal the contents of the secret itself. + + Secrets can be created at the following levels: + + - Project (default): these secrets are applied to all resources in a project + - Global: these secrets can be applied to all resources on your current team + + For more information, see https://docs.paperspace.com/secrets. + `, + commands: subCommands, +}).run(function* ({ ctx }) { + for (const line of secret.help(ctx)) { + yield line; + } +}); diff --git a/commands/secret/schemas.ts b/commands/secret/schemas.ts new file mode 100644 index 0000000..fbdc80f --- /dev/null +++ b/commands/secret/schemas.ts @@ -0,0 +1,17 @@ +import { z } from "../../zcli.ts"; + +export const secretSchema = z.object({ + name: z.string() + .min(1, "Invalid secret name. Must be at least 1 character.") + .max(128, "Invalid secret name. Must be less than 128 characters.") + .regex( + /^[a-zA-Z][a-zA-Z0-9_]*$/, + 'Invalid secret name. Must start with a letter and only contain letters, numbers, and underscores ("_").', + ) + .describe(`The name of the secret, e.g. "DB_PASSWORD".`), + value: z.string().min( + 1, + "Invalid secret value. Must be at least 1 character.", + ) + .max(8192, "Invalid secret value. Must be less than 8192 characters."), +}); diff --git a/commands/secret/update/mod.ts b/commands/secret/update/mod.ts new file mode 100644 index 0000000..132985e --- /dev/null +++ b/commands/secret/update/mod.ts @@ -0,0 +1,110 @@ +import { secretSchema } from "./../schemas.ts"; +import { projectSecrets } from "../../../api/projects.ts"; +import { teamSecrets } from "../../../api/teams.ts"; +import { config } from "../../../config.ts"; +import { asserts } from "../../../lib/asserts.ts"; +import { findProject } from "../../../lib/find-project.ts"; +import { loading } from "../../../lib/loading.ts"; +import { input } from "../../../prompts/input.ts"; +import { confirm } from "../../../prompts/confirm.ts"; +import { secret } from "../../../prompts/secret.ts"; +import { args, command } from "../../../zcli.ts"; +import { secretFlags } from "../flags.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: "", + commands: subCommands, + args: args().tuple([ + secretSchema.shape.name.describe("The name of the secret"), + secretSchema.shape.value.describe("The value of the secret"), + ]).optional(), + flags: secretFlags, + // 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 [name, value] = args; + + if (!name) { + name = await input("Name:", { + filter: (v) => !!v.sequence.match(/[a-zA-Z0-9_]/), + }); + asserts(name, "A secret name is required"); + } + + const parsedName = secretSchema.shape.name.safeParse(name); + asserts( + parsedName.success, + "error" in parsedName ? parsedName.error : "", + ); + + if (!value) { + value = await secret("Value:"); + asserts(value, "A secret value is required"); + } + + const parsedValue = secretSchema.shape.value.safeParse(name); + asserts( + parsedValue.success, + "error" in parsedValue ? parsedValue.error : "", + ); + + if (flags.global) { + const team = await config.get("team"); + asserts( + team, + "You must be logged into a team to update a secret.", + ); + + if (!flags.json) { + asserts( + await confirm( + `Are you sure you want to update your global secret "${name}" in team "${team}"?`, + ), + "Aborted", + ); + } + + const response = await loading( + teamSecrets.update({ handle: team, name, value }), + ); + + asserts(response.ok, response); + const result = response.data; + + if (flags.json) { + yield JSON.stringify(result, null, 2); + } else { + yield `Updated secret "${name}" in team "${team}"`; + } + } else { + const project = await findProject({ + handle: flags["project-id"], + cwd: flags.cwd, + quiet: flags.json, + }); + const response = await loading( + projectSecrets.update({ handle: project.handle, name, value }), + ); + + asserts(response.ok, response); + const result = response.data; + + if (flags.json) { + yield JSON.stringify(result, null, 2); + } else { + yield `Updated secret "${name}" in project "${project.name}"`; + } + } + }, +); diff --git a/commands/up/mod.ts b/commands/up/mod.ts index c011190..77f5647 100644 --- a/commands/up/mod.ts +++ b/commands/up/mod.ts @@ -1,16 +1,14 @@ import { deploymentRuns, deployments } from "./../../api/deployments.ts"; -import { projects } from "./../../api/projects.ts"; import { command, Context, flag, flags, fmt } from "../../zcli.ts"; import { config } from "../../config.ts"; import { asserts } from "../../lib/asserts.ts"; import { loading } from "../../lib/loading.ts"; import { poll } from "../../lib/poll.ts"; -import { select } from "../../prompts/select.ts"; import { AppError } from "../../errors.ts"; -import { path } from "../../deps.ts"; import { logger } from "../../logger.ts"; import { env } from "../../env.ts"; import * as appConfig from "../../lib/app-config.ts"; +import { findProject } from "../../lib/find-project.ts"; /** * This variable is automatically generated by `zcli add`. Do not remove this @@ -31,10 +29,12 @@ export const upFlags = flags({ - \`paperspace.yaml\` - \`paperspace.yml\` - \`paperspace.json\` + - \`paperspace.jsonc\` - \`paperspace.toml\` - \`.paperspace/app.yaml\` - \`.paperspace/app.yml\` - \`.paperspace/app.json\` + - \`.paperspace/app.jsonc\` - \`.paperspace/app.toml\` `, }).ostring(), @@ -87,7 +87,7 @@ export const up = command("up", { ); export async function* runUp( - { flags, ctx }: { + { flags }: { flags: { cwd?: string; config?: string; @@ -97,45 +97,15 @@ export async function* runUp( ctx: Context; }, ) { - const projectPath = flags.cwd - ? path.isAbsolute(flags.cwd) ? flags.cwd : path.join(Deno.cwd(), flags.cwd) - : Deno.cwd(); - const localProjects = await config.get("projects"); - let handle = flags["project-id"] ?? localProjects[projectPath]?.handle; - const configFile = await appConfig.find(projectPath, flags.config); + const project = await findProject({ + quiet: !flags.json, + cwd: flags.cwd, + handle: flags["project-id"], + }); + const configFile = await appConfig.find(flags); const team = await config.get("team"); - if (!handle) { - const existingProjects = await loading(projects.list({ limit: 50 }), { - enabled: !flags.json, - }); - asserts(existingProjects.ok, existingProjects); - yield fmt.colors.yellow( - `Couldn't find a linked project for ${projectPath}.`, - ); - - yield `Run "${ - fmt.colors.bold(`${ctx.root.name} project link`) - }" in this directory to skip this step in the future.`; - - const selected = await select( - "Select a project:", - existingProjects.data.items, - { - filter(input, option) { - return option.name.toLowerCase().startsWith(input); - }, - renderOption(option, isSelected) { - return `${isSelected ? ">" : " "} ${option.name}`; - }, - }, - ); - - asserts(selected, "No project selected."); - handle = selected.handle; - } - - logger.info({ projectId: handle, config: configFile }); + logger.info({ projectId: project.handle, config: configFile }); const upsert = await loading( // @ts-expect-error: it'll be ok deployments.upsert({ projectId: handle, config: configFile }), @@ -210,7 +180,7 @@ export async function* runUp( yield `✨ ${fmt.colors.bold("Your app is ready")}\n`; yield " " + fmt.colors.bold("Console URL"); yield " " + new URL( - `/${team}/projects/${handle}/gradient-deployments/${deployment.id}`, + `/${team}/projects/${project.handle}/gradient-deployments/${deployment.id}`, env.get("PAPERSPACE_CONSOLE_URL"), ).toString(); yield ""; @@ -220,7 +190,7 @@ export async function* runUp( yield `🌙 ${fmt.colors.bold("Your app was disabled")}\n`; yield " " + fmt.colors.bold("Console URL"); yield " " + new URL( - `/${team}/projects/${handle}/gradient-deployments/${deployment.id}`, + `/${team}/projects/${project.handle}/gradient-deployments/${deployment.id}`, env.get("PAPERSPACE_CONSOLE_URL"), ); } diff --git a/deno.lock b/deno.lock index 9d7eded..90fa522 100644 --- a/deno.lock +++ b/deno.lock @@ -1,112 +1,117 @@ { "version": "2", "remote": { - "https://deno.land/std@0.178.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", - "https://deno.land/std@0.178.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", - "https://deno.land/std@0.178.0/archive/_common.ts": "3fc6974d41f1d2e55edf839a4574db0b5e6f4f62abb6cc3d2c3ca13eb6d08b07", - "https://deno.land/std@0.178.0/archive/mod.ts": "8076e214b461fe214de63960271279bbb8d669f434d512fcc75ab1c787335367", - "https://deno.land/std@0.178.0/archive/tar.ts": "838baf680e545ed780eff41a4a90afff7557f2aec291d0f195d4ab2648b68b5c", - "https://deno.land/std@0.178.0/archive/untar.ts": "b7bd29929ebc819cb5b7265d1e491e4061e31828b6235e8ff5ad17ddfb77d09e", - "https://deno.land/std@0.178.0/async/deferred.ts": "42790112f36a75a57db4a96d33974a936deb7b04d25c6084a9fa8a49f135def8", - "https://deno.land/std@0.178.0/bytes/bytes_list.ts": "b4cbdfd2c263a13e8a904b12d082f6177ea97d9297274a4be134e989450dfa6a", - "https://deno.land/std@0.178.0/bytes/concat.ts": "d26d6f3d7922e6d663dacfcd357563b7bf4a380ce5b9c2bbe0c8586662f25ce2", - "https://deno.land/std@0.178.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219", - "https://deno.land/std@0.178.0/bytes/ends_with.ts": "4228811ebc71615d27f065c54b5e815ec1972538772b0f413c0efe05245b472e", - "https://deno.land/std@0.178.0/bytes/equals.ts": "b87494ce5442dc786db46f91378100028c402f83a14a2f7bbff6bda7810aefe3", - "https://deno.land/std@0.178.0/bytes/includes_needle.ts": "76a8163126fb2f8bf86fd7f22192c3bb04bf6a20b987a095127c2ca08adf3ba6", - "https://deno.land/std@0.178.0/bytes/index_of_needle.ts": "65c939607df609374c4415598fa4dad04a2f14c4d98cd15775216f0aaf597f24", - "https://deno.land/std@0.178.0/bytes/last_index_of_needle.ts": "7181072883cb4908c6ce8f7a5bb1d96787eef2c2ab3aa94fe4268ab326a53cbf", - "https://deno.land/std@0.178.0/bytes/mod.ts": "e869bba1e7a2e3a9cc6c2d55471888429a544e70a840c087672e656e7ba21815", - "https://deno.land/std@0.178.0/bytes/repeat.ts": "6f5e490d8d72bcbf8d84a6bb04690b9b3eb5822c5a11687bca73a2318a842294", - "https://deno.land/std@0.178.0/bytes/starts_with.ts": "3e607a70c9c09f5140b7a7f17a695221abcc7244d20af3eb47ccbb63f5885135", - "https://deno.land/std@0.178.0/collections/_utils.ts": "5114abc026ddef71207a79609b984614e66a63a4bda17d819d56b0e72c51527e", - "https://deno.land/std@0.178.0/collections/deep_merge.ts": "5a8ed29030f4471a5272785c57c3455fa79697b9a8f306013a8feae12bafc99a", - "https://deno.land/std@0.178.0/encoding/_toml/parser.ts": "a932beaf8e65af821c7ff36ff38f6fde3ab8d24a8a79c7ca6fe2e7a920c39804", - "https://deno.land/std@0.178.0/encoding/_yaml/dumper/dumper.ts": "49053c293a2250b33f2efc0ce3973280c6dc3bc0b41397af3863b5f03340e01b", - "https://deno.land/std@0.178.0/encoding/_yaml/dumper/dumper_state.ts": "975a3702752a29251c5746206507dfebbfede60dd2c0dec161dc22633fbc6085", - "https://deno.land/std@0.178.0/encoding/_yaml/error.ts": "e60ab51d7c0253cf0d1cf7d445202e8e3da5c77aae0032071ba7400121c281b4", - "https://deno.land/std@0.178.0/encoding/_yaml/loader/loader.ts": "13ec5aecca06b46105c1ca7053c13ef7ea7ab557893a81bc98338a0a532f27fe", - "https://deno.land/std@0.178.0/encoding/_yaml/loader/loader_state.ts": "fcc82fcdf167acb0e9e5e32b32682e58b45f2d44210bf685794797ccb5621232", - "https://deno.land/std@0.178.0/encoding/_yaml/mark.ts": "0027d6f62a70a6c64b85bd1751ddf1646ea97edcefbf5bea1706d5e519f4e34f", - "https://deno.land/std@0.178.0/encoding/_yaml/parse.ts": "63e79582e07145ca1d3205d1ac72b82bf5ce14159dabae195abe7e36de8111bd", - "https://deno.land/std@0.178.0/encoding/_yaml/schema.ts": "0833c75c59bf72c8a8f96f6c0615bcd98d23fdd9b076657f42b5c1a4f9d972b0", - "https://deno.land/std@0.178.0/encoding/_yaml/schema/core.ts": "366f56673336ba24f5723c04319efcc7471be5f55d5f8d95c9b4a38ec233d4c6", - "https://deno.land/std@0.178.0/encoding/_yaml/schema/default.ts": "96e9ed6ead36f53a0832c542fc9b8cca7f8b4a67c1c8424e1423a39ee7154db7", - "https://deno.land/std@0.178.0/encoding/_yaml/schema/extended.ts": "f9bd75c79ebdfb92a8e167488b6bde7113a31b8fabe20ad7eed0904fba11bcd2", - "https://deno.land/std@0.178.0/encoding/_yaml/schema/failsafe.ts": "cddcbf0258bbe0cd77ca10e2f5aec13439f50d4068f96aab08ca2d64496dabe8", - "https://deno.land/std@0.178.0/encoding/_yaml/schema/json.ts": "c86905dfb1b6c4633750bfbb5bd529a30be5c08287ab7eb6694390b40e276487", - "https://deno.land/std@0.178.0/encoding/_yaml/schema/mod.ts": "051f93dd97a15aaad2da62bd24627e8fd2f02fb026d21567d924b720d606f078", - "https://deno.land/std@0.178.0/encoding/_yaml/state.ts": "ef03d55ec235d48dcfbecc0ab3ade90bfae69a61094846e08003421c2cf5cfc6", - "https://deno.land/std@0.178.0/encoding/_yaml/stringify.ts": "426b73e4dbaeed26ed855add3862786d7e374bd4c59e5e1bd9a6fcd5082be3c7", - "https://deno.land/std@0.178.0/encoding/_yaml/type.ts": "5ded5472a0f17a219ac3b0e90d96dc8472a68654a40258a31e03a6c6297b6788", - "https://deno.land/std@0.178.0/encoding/_yaml/type/binary.ts": "935d39794420ac3718d26716192239de6a53566c6f2ba5010e8ed26936b94a89", - "https://deno.land/std@0.178.0/encoding/_yaml/type/bool.ts": "1c99cfbaa94b022575b636a73e1549569b26fc6bbff2cd5e539aa77b49bdf303", - "https://deno.land/std@0.178.0/encoding/_yaml/type/float.ts": "f60ad19b27050add694bfc255b7efef27103f047861aa657823ff3f6853bad11", - "https://deno.land/std@0.178.0/encoding/_yaml/type/function.ts": "65a37f6bef43ef141854ee48a1058d9c9c4c80ed6eed6cd35608329a6957e27a", - "https://deno.land/std@0.178.0/encoding/_yaml/type/int.ts": "892f59bb7b2dbd64dd9b643c17441af95c0b962ad027e454cb84a68864787b86", - "https://deno.land/std@0.178.0/encoding/_yaml/type/map.ts": "92e647a6aec0dc184ea4b039a77a15883b54da754311189c595b43f6aaa50030", - "https://deno.land/std@0.178.0/encoding/_yaml/type/merge.ts": "8192bf3e4d637f32567917f48bb276043da9cf729cf594e5ec191f7cd229337e", - "https://deno.land/std@0.178.0/encoding/_yaml/type/mod.ts": "060e2b3d38725094b77ea3a3f05fc7e671fced8e67ca18e525be98c4aa8f4bbb", - "https://deno.land/std@0.178.0/encoding/_yaml/type/nil.ts": "606e8f0c44d73117c81abec822f89ef81e40f712258c74f186baa1af659b8887", - "https://deno.land/std@0.178.0/encoding/_yaml/type/omap.ts": "fbd5da9970c211335ff7c8fa11e9c5e9256e568d52418ac237d1538c5cb0d5e6", - "https://deno.land/std@0.178.0/encoding/_yaml/type/pairs.ts": "ea487a44c0ae64d8d952779fa1cb5fa0a12f32a0b5d3d1e8c1f06f446448427c", - "https://deno.land/std@0.178.0/encoding/_yaml/type/regexp.ts": "672000d22a1062d61577d30b218c28f5cb1d039a7a60079fdde6a4e558d5ca51", - "https://deno.land/std@0.178.0/encoding/_yaml/type/seq.ts": "39b28f7c7aa41263c5c42cab9d184f03555e9ba19493766afc0c0c325a9ac49f", - "https://deno.land/std@0.178.0/encoding/_yaml/type/set.ts": "0e30a9f750306b514c8ae9869d1ac2548d57beab55b33e85ea9673ca0a08264c", - "https://deno.land/std@0.178.0/encoding/_yaml/type/str.ts": "a67a3c6e429d95041399e964015511779b1130ea5889fa257c48457bd3446e31", - "https://deno.land/std@0.178.0/encoding/_yaml/type/timestamp.ts": "706ea80a76a73e48efaeb400ace087da1f927647b53ad6f754f4e06d51af087f", - "https://deno.land/std@0.178.0/encoding/_yaml/type/undefined.ts": "94a316ca450597ccbc6750cbd79097ad0d5f3a019797eed3c841a040c29540ba", - "https://deno.land/std@0.178.0/encoding/_yaml/utils.ts": "26b311f0d42a7ce025060bd6320a68b50e52fd24a839581eb31734cd48e20393", - "https://deno.land/std@0.178.0/encoding/jsonc.ts": "02b86115d2b812f26789481ebcf4748171e8ece6514b60243b3733e2c200876a", - "https://deno.land/std@0.178.0/encoding/toml.ts": "d11fc659365218035ec1d92c1dfa206718838954a6de7cfc62d0a07ffb19f582", - "https://deno.land/std@0.178.0/encoding/yaml.ts": "02571d1bbbcfd7c5647789cee872ecf9c1c470e1b1a40948ed219fb661e19d87", - "https://deno.land/std@0.178.0/flags/mod.ts": "d1cdefa18472ef69858a17df5cf7c98445ed27ac10e1460183081303b0ebc270", - "https://deno.land/std@0.178.0/fmt/bytes.ts": "f3cdd34c7a5063c296e198cf9b7000774033283d469716e6b7741f4167bdaf46", - "https://deno.land/std@0.178.0/fmt/colors.ts": "938c5d44d889fb82eff6c358bea8baa7e85950a16c9f6dae3ec3a7a729164471", - "https://deno.land/std@0.178.0/fmt/printf.ts": "e5b426cd6ad13df5d408e9c375c025d59de30e380c5534715bd892df874ab057", - "https://deno.land/std@0.178.0/fs/exists.ts": "b8c8a457b71e9d7f29b9d2f87aad8dba2739cbe637e8926d6ba6e92567875f8e", - "https://deno.land/std@0.178.0/io/buf_reader.ts": "90a7adcb3638d8e1361695cdf844d58bcd97c41711dc6f9f8acc0626ebe097f5", - "https://deno.land/std@0.178.0/io/buf_writer.ts": "2fcaadd9f157970fede6e79c8ea9a58556d8cf3c8a686c3fcaaf3875460092cc", - "https://deno.land/std@0.178.0/io/buffer.ts": "e2b7564f684dad625cab08f5106f33572d325705d19a36822b3272fbdfb8f726", - "https://deno.land/std@0.178.0/io/multi_reader.ts": "5f7ef6e987486322b38c72e206b8fbc8916d55a87fbcdc97a8b2596386c28d44", - "https://deno.land/std@0.178.0/log/handlers.ts": "38871ecbfa67b0d39dc3384210439ac9a13cba6118b912236f9011b5989b9a4d", - "https://deno.land/std@0.178.0/log/levels.ts": "6309147664e9e008cd6671610f2505c4c95f181f6bae4816a84b33e0aec66859", - "https://deno.land/std@0.178.0/log/logger.ts": "257ceb47e3f5f872068073de9809b015a7400e8d86dd40563c1d80169e578f71", - "https://deno.land/std@0.178.0/log/mod.ts": "36d156ad18de3f1806c6ddafa4965129be99ccafc27f1813de528d65b6c528bf", - "https://deno.land/std@0.178.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", - "https://deno.land/std@0.178.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", - "https://deno.land/std@0.178.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0", - "https://deno.land/std@0.178.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", - "https://deno.land/std@0.178.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", - "https://deno.land/std@0.178.0/path/mod.ts": "4b83694ac500d7d31b0cdafc927080a53dc0c3027eb2895790fb155082b0d232", - "https://deno.land/std@0.178.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d", - "https://deno.land/std@0.178.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", - "https://deno.land/std@0.178.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba", - "https://deno.land/std@0.178.0/streams/_common.ts": "f45cba84f0d813de3326466095539602364a9ba521f804cc758f7a475cda692d", - "https://deno.land/std@0.178.0/streams/buffer.ts": "7e7676c29e0e72f6821c3b5fede2540886a216bb91c849bb5db20bb82a01d8a1", - "https://deno.land/std@0.178.0/streams/byte_slice_stream.ts": "cf5785b0d9223ebb51fcf6679d881dfaf614c3b288fb4577b511b6f7801a01aa", - "https://deno.land/std@0.178.0/streams/copy.ts": "de0de21701d8cceba84ca01d9731c77f4b3597bb9de6a1b08f32250353feeae8", - "https://deno.land/std@0.178.0/streams/delimiter_stream.ts": "de8f822a1c394cdb805a97e364400955cd1757cc282d932b4040a0f78fba3b5f", - "https://deno.land/std@0.178.0/streams/early_zip_readable_streams.ts": "64828085be5812ec5f4896c10b59f14e5a322b2c0439be9331dde332ae9c91de", - "https://deno.land/std@0.178.0/streams/iterate_reader.ts": "06491ed8f1bb1c619abbfa04c10b173ff95a93e51fe5037b7c1ad0b5cc01fc7d", - "https://deno.land/std@0.178.0/streams/limited_bytes_transform_stream.ts": "3bc04143b8b91a923f5ee81a3c618b6606ac7da66ccbcde62a67aaa0375cbc71", - "https://deno.land/std@0.178.0/streams/limited_transform_stream.ts": "b336f5d649a06e35e2692849e3682a673bb32531738443eb2ce9f57538722f75", - "https://deno.land/std@0.178.0/streams/merge_readable_streams.ts": "5d6302888f4bb0616dafb5768771be0aec9bedc05fbae6b3d726d05ffbec5b15", - "https://deno.land/std@0.178.0/streams/mod.ts": "c07ec010e700b9ea887dc36ca08729828bc7912f711e4054e24d33fd46282252", - "https://deno.land/std@0.178.0/streams/read_all.ts": "bfa220b0e1d06fa4d0cb5178baba8f8b466019a7411511982bfa2320ca292815", - "https://deno.land/std@0.178.0/streams/readable_stream_from_iterable.ts": "cae337ddafd2abc5e3df699ef2af888ac04091f12732ae658448fba2c7b187e8", - "https://deno.land/std@0.178.0/streams/readable_stream_from_reader.ts": "9aceaeefa9e04b08f56b2d07272baedc3b6432840b66198d72fa2ada3e6608ea", - "https://deno.land/std@0.178.0/streams/reader_from_iterable.ts": "05f7759b9336fd4c233d9daadf92aec9a7d2c07a05986da466a935cec2dd79d9", - "https://deno.land/std@0.178.0/streams/reader_from_stream_reader.ts": "3fda9390ec8520c8a9ea2aba2579208b18880a7663d7a9feec8f193b7af14e41", - "https://deno.land/std@0.178.0/streams/text_delimiter_stream.ts": "ee216316360366c3744197f5665a066a25e6baa8cfe836fbe9a0033e079e089e", - "https://deno.land/std@0.178.0/streams/text_line_stream.ts": "a9dd2636c6b90e626e19df26c97034c5f638bdd957cbd5c531d6278fe1d08e90", - "https://deno.land/std@0.178.0/streams/to_transform_stream.ts": "31c8cce967a2f602be5f164973a5c6cedd4c76e1d2fbc22ae0081b084f73fb0e", - "https://deno.land/std@0.178.0/streams/writable_stream_from_writer.ts": "0320b759aa343f9f4f58b014fe301d9a7abcbfb8413d260502a885995e6a0776", - "https://deno.land/std@0.178.0/streams/write_all.ts": "3b2e1ce44913f966348ce353d02fa5369e94115181037cd8b602510853ec3033", - "https://deno.land/std@0.178.0/streams/writer_from_stream_writer.ts": "31126a6bf2e678c5a718011d4831dbe75dbdbd885965d3dbd5dd105e6f20f976", - "https://deno.land/std@0.178.0/streams/zip_readable_streams.ts": "9eb82070d83055fe6f077192fb204dc7612695a4b330148e9aa376df1a65e708", - "https://deno.land/std@0.178.0/types.d.ts": "220ed56662a0bd393ba5d124aa6ae2ad36a00d2fcbc0e8666a65f4606aaa9784", - "https://deno.land/std@0.51.0/fs/eol.ts": "4a0b2a612e0639b76d9c5fab0392e7bf1a158a7dab191ff7b7564870a1173812", + "https://deno.land/std@0.179.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", + "https://deno.land/std@0.179.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", + "https://deno.land/std@0.179.0/archive/_common.ts": "3fc6974d41f1d2e55edf839a4574db0b5e6f4f62abb6cc3d2c3ca13eb6d08b07", + "https://deno.land/std@0.179.0/archive/mod.ts": "8076e214b461fe214de63960271279bbb8d669f434d512fcc75ab1c787335367", + "https://deno.land/std@0.179.0/archive/tar.ts": "838baf680e545ed780eff41a4a90afff7557f2aec291d0f195d4ab2648b68b5c", + "https://deno.land/std@0.179.0/archive/untar.ts": "b7bd29929ebc819cb5b7265d1e491e4061e31828b6235e8ff5ad17ddfb77d09e", + "https://deno.land/std@0.179.0/async/deferred.ts": "42790112f36a75a57db4a96d33974a936deb7b04d25c6084a9fa8a49f135def8", + "https://deno.land/std@0.179.0/bytes/bytes_list.ts": "b4cbdfd2c263a13e8a904b12d082f6177ea97d9297274a4be134e989450dfa6a", + "https://deno.land/std@0.179.0/bytes/concat.ts": "d26d6f3d7922e6d663dacfcd357563b7bf4a380ce5b9c2bbe0c8586662f25ce2", + "https://deno.land/std@0.179.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219", + "https://deno.land/std@0.179.0/bytes/ends_with.ts": "4228811ebc71615d27f065c54b5e815ec1972538772b0f413c0efe05245b472e", + "https://deno.land/std@0.179.0/bytes/equals.ts": "b87494ce5442dc786db46f91378100028c402f83a14a2f7bbff6bda7810aefe3", + "https://deno.land/std@0.179.0/bytes/includes_needle.ts": "76a8163126fb2f8bf86fd7f22192c3bb04bf6a20b987a095127c2ca08adf3ba6", + "https://deno.land/std@0.179.0/bytes/index_of_needle.ts": "65c939607df609374c4415598fa4dad04a2f14c4d98cd15775216f0aaf597f24", + "https://deno.land/std@0.179.0/bytes/last_index_of_needle.ts": "7181072883cb4908c6ce8f7a5bb1d96787eef2c2ab3aa94fe4268ab326a53cbf", + "https://deno.land/std@0.179.0/bytes/mod.ts": "e869bba1e7a2e3a9cc6c2d55471888429a544e70a840c087672e656e7ba21815", + "https://deno.land/std@0.179.0/bytes/repeat.ts": "6f5e490d8d72bcbf8d84a6bb04690b9b3eb5822c5a11687bca73a2318a842294", + "https://deno.land/std@0.179.0/bytes/starts_with.ts": "3e607a70c9c09f5140b7a7f17a695221abcc7244d20af3eb47ccbb63f5885135", + "https://deno.land/std@0.179.0/collections/_utils.ts": "5114abc026ddef71207a79609b984614e66a63a4bda17d819d56b0e72c51527e", + "https://deno.land/std@0.179.0/collections/deep_merge.ts": "5a8ed29030f4471a5272785c57c3455fa79697b9a8f306013a8feae12bafc99a", + "https://deno.land/std@0.179.0/encoding/_toml/parser.ts": "a932beaf8e65af821c7ff36ff38f6fde3ab8d24a8a79c7ca6fe2e7a920c39804", + "https://deno.land/std@0.179.0/encoding/_yaml/dumper/dumper.ts": "49053c293a2250b33f2efc0ce3973280c6dc3bc0b41397af3863b5f03340e01b", + "https://deno.land/std@0.179.0/encoding/_yaml/dumper/dumper_state.ts": "975a3702752a29251c5746206507dfebbfede60dd2c0dec161dc22633fbc6085", + "https://deno.land/std@0.179.0/encoding/_yaml/error.ts": "e60ab51d7c0253cf0d1cf7d445202e8e3da5c77aae0032071ba7400121c281b4", + "https://deno.land/std@0.179.0/encoding/_yaml/loader/loader.ts": "13ec5aecca06b46105c1ca7053c13ef7ea7ab557893a81bc98338a0a532f27fe", + "https://deno.land/std@0.179.0/encoding/_yaml/loader/loader_state.ts": "fcc82fcdf167acb0e9e5e32b32682e58b45f2d44210bf685794797ccb5621232", + "https://deno.land/std@0.179.0/encoding/_yaml/mark.ts": "0027d6f62a70a6c64b85bd1751ddf1646ea97edcefbf5bea1706d5e519f4e34f", + "https://deno.land/std@0.179.0/encoding/_yaml/parse.ts": "4a4588c93bc4c0216486c8f6c3f44943b73c295e485c2ad060f7ee93bd58d904", + "https://deno.land/std@0.179.0/encoding/_yaml/schema.ts": "0833c75c59bf72c8a8f96f6c0615bcd98d23fdd9b076657f42b5c1a4f9d972b0", + "https://deno.land/std@0.179.0/encoding/_yaml/schema/core.ts": "366f56673336ba24f5723c04319efcc7471be5f55d5f8d95c9b4a38ec233d4c6", + "https://deno.land/std@0.179.0/encoding/_yaml/schema/default.ts": "96e9ed6ead36f53a0832c542fc9b8cca7f8b4a67c1c8424e1423a39ee7154db7", + "https://deno.land/std@0.179.0/encoding/_yaml/schema/extended.ts": "f9bd75c79ebdfb92a8e167488b6bde7113a31b8fabe20ad7eed0904fba11bcd2", + "https://deno.land/std@0.179.0/encoding/_yaml/schema/failsafe.ts": "cddcbf0258bbe0cd77ca10e2f5aec13439f50d4068f96aab08ca2d64496dabe8", + "https://deno.land/std@0.179.0/encoding/_yaml/schema/json.ts": "c86905dfb1b6c4633750bfbb5bd529a30be5c08287ab7eb6694390b40e276487", + "https://deno.land/std@0.179.0/encoding/_yaml/schema/mod.ts": "051f93dd97a15aaad2da62bd24627e8fd2f02fb026d21567d924b720d606f078", + "https://deno.land/std@0.179.0/encoding/_yaml/state.ts": "ef03d55ec235d48dcfbecc0ab3ade90bfae69a61094846e08003421c2cf5cfc6", + "https://deno.land/std@0.179.0/encoding/_yaml/stringify.ts": "426b73e4dbaeed26ed855add3862786d7e374bd4c59e5e1bd9a6fcd5082be3c7", + "https://deno.land/std@0.179.0/encoding/_yaml/type.ts": "5ded5472a0f17a219ac3b0e90d96dc8472a68654a40258a31e03a6c6297b6788", + "https://deno.land/std@0.179.0/encoding/_yaml/type/binary.ts": "935d39794420ac3718d26716192239de6a53566c6f2ba5010e8ed26936b94a89", + "https://deno.land/std@0.179.0/encoding/_yaml/type/bool.ts": "1c99cfbaa94b022575b636a73e1549569b26fc6bbff2cd5e539aa77b49bdf303", + "https://deno.land/std@0.179.0/encoding/_yaml/type/float.ts": "f60ad19b27050add694bfc255b7efef27103f047861aa657823ff3f6853bad11", + "https://deno.land/std@0.179.0/encoding/_yaml/type/function.ts": "65a37f6bef43ef141854ee48a1058d9c9c4c80ed6eed6cd35608329a6957e27a", + "https://deno.land/std@0.179.0/encoding/_yaml/type/int.ts": "892f59bb7b2dbd64dd9b643c17441af95c0b962ad027e454cb84a68864787b86", + "https://deno.land/std@0.179.0/encoding/_yaml/type/map.ts": "92e647a6aec0dc184ea4b039a77a15883b54da754311189c595b43f6aaa50030", + "https://deno.land/std@0.179.0/encoding/_yaml/type/merge.ts": "8192bf3e4d637f32567917f48bb276043da9cf729cf594e5ec191f7cd229337e", + "https://deno.land/std@0.179.0/encoding/_yaml/type/mod.ts": "060e2b3d38725094b77ea3a3f05fc7e671fced8e67ca18e525be98c4aa8f4bbb", + "https://deno.land/std@0.179.0/encoding/_yaml/type/nil.ts": "606e8f0c44d73117c81abec822f89ef81e40f712258c74f186baa1af659b8887", + "https://deno.land/std@0.179.0/encoding/_yaml/type/omap.ts": "fbd5da9970c211335ff7c8fa11e9c5e9256e568d52418ac237d1538c5cb0d5e6", + "https://deno.land/std@0.179.0/encoding/_yaml/type/pairs.ts": "ea487a44c0ae64d8d952779fa1cb5fa0a12f32a0b5d3d1e8c1f06f446448427c", + "https://deno.land/std@0.179.0/encoding/_yaml/type/regexp.ts": "672000d22a1062d61577d30b218c28f5cb1d039a7a60079fdde6a4e558d5ca51", + "https://deno.land/std@0.179.0/encoding/_yaml/type/seq.ts": "39b28f7c7aa41263c5c42cab9d184f03555e9ba19493766afc0c0c325a9ac49f", + "https://deno.land/std@0.179.0/encoding/_yaml/type/set.ts": "0e30a9f750306b514c8ae9869d1ac2548d57beab55b33e85ea9673ca0a08264c", + "https://deno.land/std@0.179.0/encoding/_yaml/type/str.ts": "a67a3c6e429d95041399e964015511779b1130ea5889fa257c48457bd3446e31", + "https://deno.land/std@0.179.0/encoding/_yaml/type/timestamp.ts": "706ea80a76a73e48efaeb400ace087da1f927647b53ad6f754f4e06d51af087f", + "https://deno.land/std@0.179.0/encoding/_yaml/type/undefined.ts": "94a316ca450597ccbc6750cbd79097ad0d5f3a019797eed3c841a040c29540ba", + "https://deno.land/std@0.179.0/encoding/_yaml/utils.ts": "26b311f0d42a7ce025060bd6320a68b50e52fd24a839581eb31734cd48e20393", + "https://deno.land/std@0.179.0/encoding/jsonc.ts": "02b86115d2b812f26789481ebcf4748171e8ece6514b60243b3733e2c200876a", + "https://deno.land/std@0.179.0/encoding/toml.ts": "d11fc659365218035ec1d92c1dfa206718838954a6de7cfc62d0a07ffb19f582", + "https://deno.land/std@0.179.0/encoding/yaml.ts": "02571d1bbbcfd7c5647789cee872ecf9c1c470e1b1a40948ed219fb661e19d87", + "https://deno.land/std@0.179.0/flags/mod.ts": "d1cdefa18472ef69858a17df5cf7c98445ed27ac10e1460183081303b0ebc270", + "https://deno.land/std@0.179.0/fmt/bytes.ts": "f3cdd34c7a5063c296e198cf9b7000774033283d469716e6b7741f4167bdaf46", + "https://deno.land/std@0.179.0/fmt/colors.ts": "938c5d44d889fb82eff6c358bea8baa7e85950a16c9f6dae3ec3a7a729164471", + "https://deno.land/std@0.179.0/fmt/printf.ts": "e5b426cd6ad13df5d408e9c375c025d59de30e380c5534715bd892df874ab057", + "https://deno.land/std@0.179.0/fs/exists.ts": "b8c8a457b71e9d7f29b9d2f87aad8dba2739cbe637e8926d6ba6e92567875f8e", + "https://deno.land/std@0.179.0/io/buf_reader.ts": "90a7adcb3638d8e1361695cdf844d58bcd97c41711dc6f9f8acc0626ebe097f5", + "https://deno.land/std@0.179.0/io/buf_writer.ts": "2fcaadd9f157970fede6e79c8ea9a58556d8cf3c8a686c3fcaaf3875460092cc", + "https://deno.land/std@0.179.0/io/buffer.ts": "e2b7564f684dad625cab08f5106f33572d325705d19a36822b3272fbdfb8f726", + "https://deno.land/std@0.179.0/io/multi_reader.ts": "5f7ef6e987486322b38c72e206b8fbc8916d55a87fbcdc97a8b2596386c28d44", + "https://deno.land/std@0.179.0/log/handlers.ts": "38871ecbfa67b0d39dc3384210439ac9a13cba6118b912236f9011b5989b9a4d", + "https://deno.land/std@0.179.0/log/levels.ts": "6309147664e9e008cd6671610f2505c4c95f181f6bae4816a84b33e0aec66859", + "https://deno.land/std@0.179.0/log/logger.ts": "257ceb47e3f5f872068073de9809b015a7400e8d86dd40563c1d80169e578f71", + "https://deno.land/std@0.179.0/log/mod.ts": "36d156ad18de3f1806c6ddafa4965129be99ccafc27f1813de528d65b6c528bf", + "https://deno.land/std@0.179.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", + "https://deno.land/std@0.179.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", + "https://deno.land/std@0.179.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0", + "https://deno.land/std@0.179.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", + "https://deno.land/std@0.179.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", + "https://deno.land/std@0.179.0/path/mod.ts": "4b83694ac500d7d31b0cdafc927080a53dc0c3027eb2895790fb155082b0d232", + "https://deno.land/std@0.179.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d", + "https://deno.land/std@0.179.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", + "https://deno.land/std@0.179.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba", + "https://deno.land/std@0.179.0/streams/_common.ts": "f45cba84f0d813de3326466095539602364a9ba521f804cc758f7a475cda692d", + "https://deno.land/std@0.179.0/streams/buffer.ts": "7e7676c29e0e72f6821c3b5fede2540886a216bb91c849bb5db20bb82a01d8a1", + "https://deno.land/std@0.179.0/streams/byte_slice_stream.ts": "cf5785b0d9223ebb51fcf6679d881dfaf614c3b288fb4577b511b6f7801a01aa", + "https://deno.land/std@0.179.0/streams/copy.ts": "de0de21701d8cceba84ca01d9731c77f4b3597bb9de6a1b08f32250353feeae8", + "https://deno.land/std@0.179.0/streams/delimiter_stream.ts": "de8f822a1c394cdb805a97e364400955cd1757cc282d932b4040a0f78fba3b5f", + "https://deno.land/std@0.179.0/streams/early_zip_readable_streams.ts": "64828085be5812ec5f4896c10b59f14e5a322b2c0439be9331dde332ae9c91de", + "https://deno.land/std@0.179.0/streams/iterate_reader.ts": "06491ed8f1bb1c619abbfa04c10b173ff95a93e51fe5037b7c1ad0b5cc01fc7d", + "https://deno.land/std@0.179.0/streams/limited_bytes_transform_stream.ts": "3bc04143b8b91a923f5ee81a3c618b6606ac7da66ccbcde62a67aaa0375cbc71", + "https://deno.land/std@0.179.0/streams/limited_transform_stream.ts": "b336f5d649a06e35e2692849e3682a673bb32531738443eb2ce9f57538722f75", + "https://deno.land/std@0.179.0/streams/merge_readable_streams.ts": "5d6302888f4bb0616dafb5768771be0aec9bedc05fbae6b3d726d05ffbec5b15", + "https://deno.land/std@0.179.0/streams/mod.ts": "c07ec010e700b9ea887dc36ca08729828bc7912f711e4054e24d33fd46282252", + "https://deno.land/std@0.179.0/streams/read_all.ts": "bfa220b0e1d06fa4d0cb5178baba8f8b466019a7411511982bfa2320ca292815", + "https://deno.land/std@0.179.0/streams/readable_stream_from_iterable.ts": "cae337ddafd2abc5e3df699ef2af888ac04091f12732ae658448fba2c7b187e8", + "https://deno.land/std@0.179.0/streams/readable_stream_from_reader.ts": "9aceaeefa9e04b08f56b2d07272baedc3b6432840b66198d72fa2ada3e6608ea", + "https://deno.land/std@0.179.0/streams/reader_from_iterable.ts": "05f7759b9336fd4c233d9daadf92aec9a7d2c07a05986da466a935cec2dd79d9", + "https://deno.land/std@0.179.0/streams/reader_from_stream_reader.ts": "3fda9390ec8520c8a9ea2aba2579208b18880a7663d7a9feec8f193b7af14e41", + "https://deno.land/std@0.179.0/streams/text_delimiter_stream.ts": "ee216316360366c3744197f5665a066a25e6baa8cfe836fbe9a0033e079e089e", + "https://deno.land/std@0.179.0/streams/text_line_stream.ts": "a9dd2636c6b90e626e19df26c97034c5f638bdd957cbd5c531d6278fe1d08e90", + "https://deno.land/std@0.179.0/streams/to_transform_stream.ts": "31c8cce967a2f602be5f164973a5c6cedd4c76e1d2fbc22ae0081b084f73fb0e", + "https://deno.land/std@0.179.0/streams/writable_stream_from_writer.ts": "0320b759aa343f9f4f58b014fe301d9a7abcbfb8413d260502a885995e6a0776", + "https://deno.land/std@0.179.0/streams/write_all.ts": "3b2e1ce44913f966348ce353d02fa5369e94115181037cd8b602510853ec3033", + "https://deno.land/std@0.179.0/streams/writer_from_stream_writer.ts": "31126a6bf2e678c5a718011d4831dbe75dbdbd885965d3dbd5dd105e6f20f976", + "https://deno.land/std@0.179.0/streams/zip_readable_streams.ts": "9eb82070d83055fe6f077192fb204dc7612695a4b330148e9aa376df1a65e708", + "https://deno.land/std@0.179.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea", + "https://deno.land/std@0.179.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7", + "https://deno.land/std@0.179.0/testing/_test_suite.ts": "30f018feeb3835f12ab198d8a518f9089b1bcb2e8c838a8b615ab10d5005465c", + "https://deno.land/std@0.179.0/testing/asserts.ts": "984ab0bfb3faeed92ffaa3a6b06536c66811185328c5dd146257c702c41b01ab", + "https://deno.land/std@0.179.0/testing/bdd.ts": "c5ca6d85940dbcc19b4d2bc3608d49ab65d81470aa91306d5efa4b0d5c945731", + "https://deno.land/std@0.179.0/testing/mock.ts": "220ed9b8151cb2cac141043d4cfea7c47673fab5d18d1c1f0943297c8afb5d13", + "https://deno.land/std@0.179.0/types.d.ts": "220ed56662a0bd393ba5d124aa6ae2ad36a00d2fcbc0e8666a65f4606aaa9784", "https://deno.land/x/ansi@1.0.1/clear.ts": "444d83749bd171a38e77a7a7d5d270bbf84fbb0ea21f0a62e60c931a11f2bfc1", "https://deno.land/x/ansi@1.0.1/constants.ts": "aa51274a1402e017e043f544542e895880eadd67cca3e424884ed228813144bb", "https://deno.land/x/ansi@1.0.1/cursor.ts": "cbba999f0f87865401490541e1bf098573491d1c6be411852eaed58f4e39716a", @@ -114,9 +119,6 @@ "https://deno.land/x/ansi@1.0.1/link.ts": "9dff91f666747f09f9c7a58f7d02781142483003bab6fe44612e2081f93dd2ac", "https://deno.land/x/ansi@1.0.1/mod.ts": "10a10101feb7da0e565214f725a3d8e79b3e4a2d8cb22cdeaba1a21a53889945", "https://deno.land/x/ansi@1.0.1/scroll.ts": "071a30cbd84b66de2eb24752ef97ceff475a2fc22aa2f6283baaa904208bda69", - "https://deno.land/x/fastest_levenshtein@1.0.10/mod.ts": "aea49d54b6bb37082b2377da2ea068331da07b2a515621d8eff97538b7157b40", - "https://deno.land/x/ini@v2.1.0/ini.ts": "e63611ed544b8fbd96391b3a6c39d4d7e1867f9f785b75ded2a095c81f4f1da7", - "https://deno.land/x/ini@v2.1.0/mod.ts": "00d31f79fbc3266b2fbe76a1067ba8641c4d57ac2b62aea2e5330e388cd82342", "https://deno.land/x/keypress@0.0.10/mod.ts": "5aad592873a019bd3192b29d41a86105af94acf323acc4b8f48a2d6fb36fef4d", "https://deno.land/x/ms@v0.1.0/ms.ts": "13014fdf12808df48f6e557cc3be22d24db5b8e29b687d710f9012df3428d2c8", "https://deno.land/x/sentry_deno@v0.2.2/main.ts": "c45cc4a347148f89a7a5c574ccfb9802e6c6e807d8f85eb8329e630dbd5ae22b", @@ -223,93 +225,93 @@ "https://deno.land/x/sentry_deno@v0.2.2/packages/utils/src/syncpromise.ts": "5dc2cdf5f0dddeb5e22f6de6e592d2b3f1df20f4df2cba3b51fb0e96894b002a", "https://deno.land/x/sentry_deno@v0.2.2/packages/utils/src/time.ts": "e31dc9398c698f7ca603c390acd7aaeaaf8fc8b992f65628a36a5a8541d9a1bb", "https://deno.land/x/sentry_deno@v0.2.2/packages/utils/src/tracing.ts": "f68ec7c0a76340e3dbaf83cd5d30fb4733260970f8fde66a3b7427a1a98aec93", - "https://deno.land/x/zcli@1.3.2/args.ts": "66cacf5219d207e8af2583d7f947cc1d5f2241130b6e4bb723de2ea208c2f466", - "https://deno.land/x/zcli@1.3.2/command.ts": "013c5ee8087463b134dea81f1b069dd4758fe29faefa9e7ca0b2a5fd64021dcf", - "https://deno.land/x/zcli@1.3.2/completion.ts": "ccc086cc01030da70e8fe5c26313afd2afe0ef85c719622caceadaae60d96ebb", - "https://deno.land/x/zcli@1.3.2/completions/bash.ts": "47097077189ada9b4d9ae445c32a3f07182df4b653f185a8200f1a35020d8933", - "https://deno.land/x/zcli@1.3.2/completions/fish.ts": "60b8316efa97946ee60e0aaf554cf9aecf09c9fafd84b7384118b404076d28e8", - "https://deno.land/x/zcli@1.3.2/completions/shared.ts": "23ac441b008ed1249dd9a80a1cb326184746c5666148c5a3f075412277cb68de", - "https://deno.land/x/zcli@1.3.2/completions/zsh.ts": "2781bbd7c70e9d91b06889ff3599164b2764e79945db62b9d5b173ca206a1e35", - "https://deno.land/x/zcli@1.3.2/config.ts": "b88cc24453cfb4a5824c77d8c1842340800b9218fc7d8bd3e1760b50f22780ae", - "https://deno.land/x/zcli@1.3.2/env.ts": "3a56402620547a7c01e583d3903c991d263bda224cef8ca3113b66a1ecf175b5", - "https://deno.land/x/zcli@1.3.2/flags-parser.ts": "4acc3e80a72ccf2e8e9553abb01daf9d9ba0e767f9df5704ebeca992ba7f0c0e", - "https://deno.land/x/zcli@1.3.2/flags.ts": "5313bf93b3a6b9fc9cb2bd536151f173cf962b51d791afdda1ff4198dcf3fc20", - "https://deno.land/x/zcli@1.3.2/fmt.ts": "d6fbf4a7a86f4da6392e75c0b8d9cce7b53dbbcdacad39a65e1b3a2520e4ddea", - "https://deno.land/x/zcli@1.3.2/help.ts": "8588c14e0eb5aa2e38b786cb6f9016791b0d225d5b885a0c9a00d260dcc7647e", - "https://deno.land/x/zcli@1.3.2/init.ts": "fd3c25367bfa6e0353a321e41d89632982a9be1ebbc69daa2ddd414cb9be4d5d", - "https://deno.land/x/zcli@1.3.2/intl.ts": "ed467959a86265f10e49235f1820d3973e8de6c4a4102514164d570a54685ad2", - "https://deno.land/x/zcli@1.3.2/kv.ts": "0aa4bd91d3321918ecbb00daf19691a3f0f3d309be05cf219e53d49c4743afae", - "https://deno.land/x/zcli@1.3.2/lib/dedent.ts": "0da88eeb519338eec8185ad150dc83b5b37e145b70164ef8c24787563da70158", - "https://deno.land/x/zcli@1.3.2/lib/did-you-mean.ts": "63eca9126c8f18b4d7a6d144b73f5d6b8172ddf159e18a2bd58876a803b831e0", - "https://deno.land/x/zcli@1.3.2/lib/shorten.ts": "a245549ae04c3bf3310ef0be887bdccc89c3d19d3310aac61ffc51bf48bd9cf0", - "https://deno.land/x/zcli@1.3.2/lib/simple-table.ts": "79ecad21cdc43846f9e34c804c38cd34623ed74aa01d3a0fbb08f28f219aa9ba", - "https://deno.land/x/zcli@1.3.2/lib/text-encoder.ts": "ad6e7d6f78778033a1aa96b9f1cc2612e8a938090588bb2b3c0c9e66f5fa1984", - "https://deno.land/x/zcli@1.3.2/lib/types.ts": "3aae439314da2694a8093a55bd4666dfb4505a3abda7b7c989a327ac4b54c314", - "https://deno.land/x/zcli@1.3.2/lib/write-iterable.ts": "942fe1e96f936af6d3c5b6d70cc5272bef0d36fb81e4276282e45b9fa4d97022", - "https://deno.land/x/zcli@1.3.2/locale.ts": "dff20b9968f5d0058a07412e09536c8983520219422e374c5bfd6c366e6d65d3", - "https://deno.land/x/zcli@1.3.2/mod.ts": "bdf98129a4f2d5b9e4d1446e252765f3c0df64289b5094b3c7cc287b42ebee12", - "https://deno.land/x/zcli@1.3.2/version.ts": "793bc7245ccefda0f924017b2d973ec4258519c6b89b75f1f2ad91c3966ce3aa", - "https://deno.land/x/zcli@1.3.2/z.ts": "cf013bc9e7bcba8cefba8b97db188f6373823994a140366ee6125b3b057a4e3b", - "https://deno.land/x/zcli@1.3.2/zcli-json.ts": "183fb19a28a1c20998b25efc6279d004b7ecd4ba52e8806b1f32255986a00574", - "https://deno.land/x/zcli@1.3.2/zod-proxy.ts": "b5cb0c33445e7170c0c021340a6ce45747df76662d0d76ba4eeb6e606ffab115", - "https://deno.land/x/zod@v3.20.5/ZodError.ts": "10bb0d014b0ece532c3bc395c50ae25996315a5897c0216517d9174c2fb570b5", - "https://deno.land/x/zod@v3.20.5/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef", - "https://deno.land/x/zod@v3.20.5/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe", - "https://deno.land/x/zod@v3.20.5/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c", - "https://deno.land/x/zod@v3.20.5/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7", - "https://deno.land/x/zod@v3.20.5/helpers/parseUtil.ts": "51a76c126ee212be86013d53a9d07f87e9ae04bb1496f2558e61b62cb74a6aa8", - "https://deno.land/x/zod@v3.20.5/helpers/partialUtil.ts": "8dc921a02b47384cf52217c7e539268daf619f89319b75bdf13ea178815725df", - "https://deno.land/x/zod@v3.20.5/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e", - "https://deno.land/x/zod@v3.20.5/helpers/util.ts": "0e7366354b1a5070408c1c48d01c7e33d374ca70806f5003b12ff527795c578c", - "https://deno.land/x/zod@v3.20.5/index.ts": "035a7422d9f2be54daa0fe464254b69225b443000673e4794095d672471e8792", - "https://deno.land/x/zod@v3.20.5/locales/en.ts": "ac7210faad6e67ec4f6dbe7062886f04db79ce91ae5ee6c9f64cbdf6221bc80e", - "https://deno.land/x/zod@v3.20.5/mod.ts": "64e55237cb4410e17d968cd08975566059f27638ebb0b86048031b987ba251c4", - "https://deno.land/x/zod@v3.20.5/types.ts": "6ddc4608e70d75f2e06f9cc14aa406df4d80f420c0eef64f2f02d429853c0c38", - "https://esm.sh/v107/@types/json-schema@7.0.11/index.d.ts": "f3e604694b624fa3f83f6684185452992088f5efb2cf136b62474aa106d6f1b6", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/deno/zod-to-json-schema.js": "02074c74c8522a2aab2bbc9de527784087934658e6462761eb5154d53423a248", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/index.d.ts": "6a35cd9a2721b5bc26e2b4fda01d1c56f788a41ba7558fede42340c4a72a97be", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/Options.d.ts": "5272b1cb136171d7f206fdbc2ba501c357ea0f59fcb6908ab629390ddb3ec87e", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/Refs.d.ts": "ee6787259cdcc301d699e79a4a5255fbc6ba1275b781b7a10426b0b8141ae7c6", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/errorMessages.d.ts": "793758266c2149213de4b43f0b923c88da356b2084aed96acb233c9b5791b369", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parseDef.d.ts": "67092b94437034dfcc9c86918d9af9f8bf7d0f3b9a624c7c71ad75f50b9ee35d", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/any.d.ts": "ba739758560a9b3e696095df9b04ac5d9d76acb11e98e06e73b7a86cbffe4207", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/array.d.ts": "2ca6eb061b94616e84a87c47d8da8f983148d1801fefe64f632cc0496a4a9554", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/bigint.d.ts": "8e982f3df4c7b027d54e52cf02acb25f2ccf33cadd27c8a7865c1cd6a1958211", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/boolean.d.ts": "0e8edbe744dfc3ce65e9fa2283f1f0eb2c0aaaec4df19765f51c346e45452cda", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/date.d.ts": "2041c577c7ba7bf4c71d98b79b955c0dae8aec82b800bd403f71416962ebf43a", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/enum.d.ts": "c7702e7129eebc52cdf9a5c00425c01fcfdaf7b2ce54ca2bf952a8f1224c6fa2", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/intersection.d.ts": "ecc9b07a29f727ca765bf642316a7aa4323c6d478280314ba97a04cd7998a040", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/literal.d.ts": "e499c0ec38b85d5acd27c3f110dd89854343f703926345baecc86a089e082b75", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/map.d.ts": "ac95b75fbbb22b16d4e5582522cba9be5913d3fe3a7b7a58b46c1d518a6a0c8a", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/nativeEnum.d.ts": "220458b009a16b5c6ec6be191ede388d8e44d6030c6ec633d48f9d955244abf0", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/never.d.ts": "adb05565c81b408a97cee9201c8539dda075c30dffce0d4ec226e5050f36bfa4", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/null.d.ts": "2007d407fb8742049ecaeac0b4c5a4c78619b64a6abb56250e65f5375ca1bbb1", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/nullable.d.ts": "0233a9167f2c91eece3f256ce55f8953b6867060e67cf17e4c981348b3c41e3d", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/number.d.ts": "ea48ddc2a75e803506e54e35130a18385f00eabb1c26b3e61f3d4fe14b3ca4fe", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/object.d.ts": "cbd01247780ca420f1f2bcad1df8fbb381d0c0d1ec9d0517abeb0f10619aab3b", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/record.d.ts": "bae4a0a7c9ddeae0f1a2d3a35acd7328a2be22f3875215b16ef8aa617a6d9f4b", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/set.d.ts": "3e7d05f4d024a5b2f5911043be573b4f41392afd41717e5ff5176c1d665d3b1b", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/string.d.ts": "cece6e7b359c7d89fbfbb0af76b5999dd5d2fde61e5d4200f85522b775c281d6", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/tuple.d.ts": "8d56e5d52946e12723d3a3ee833f8527cc11b01d437ac316a67b8bb7b8951cbf", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/undefined.d.ts": "3a56da695cfddd03aee7835adf8934e4f357cc9bac59ea534cd282aba668b566", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/union.d.ts": "90d8d9c993b3b1f8bf6e414f91f7785fedf10d05d5cc495a0d00799a45486202", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/parsers/unknown.d.ts": "ba3886b9e5b3bd32588d57421988aeeea94afe40227334edc5d45fb0c5367c9d", - "https://esm.sh/v107/zod-to-json-schema@3.20.2/src/zodToJsonSchema.d.ts": "1ae2d6ed651b2e12c024dcc4ab6ca37290a1bd97fd2c2a41b8e4b217e2cdbdfd", - "https://esm.sh/v107/zod@3.20.6/deno/zod.js": "2d5b4bc60fcf79cc63f09f71c95a8323bfe158e242ca85d03583210163c5d87d", - "https://esm.sh/v107/zod@3.20.6/index.d.ts": "b51c954b9557b1dcb03b2bf34cd136e710cb9aa276e686cac0e291249590a52a", - "https://esm.sh/v107/zod@3.20.6/lib/ZodError.d.ts": "41277322d45d95e8a1b3f28bf7afb5ba1bced52aa5d1915679dac1eb96f62124", - "https://esm.sh/v107/zod@3.20.6/lib/errors.d.ts": "5ec2790f877581637c058eb5bbb72e855a078620d0781d2a6a8f308fe1d5436f", - "https://esm.sh/v107/zod@3.20.6/lib/external.d.ts": "91cec2fe1e1fb2574812a29a57ad2c39a1e69b0fa1179547382c92649fc5c66e", - "https://esm.sh/v107/zod@3.20.6/lib/helpers/enumUtil.d.ts": "f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c", - "https://esm.sh/v107/zod@3.20.6/lib/helpers/errorUtil.d.ts": "98a9cc18f661d28e6bd31c436e1984f3980f35e0f0aa9cf795c54f8ccb667ffe", - "https://esm.sh/v107/zod@3.20.6/lib/helpers/parseUtil.d.ts": "d3dbfc2f2fbf2c1bdea72db72f9f5c95d2ca5b4d32c9e229764ebaba0920203c", - "https://esm.sh/v107/zod@3.20.6/lib/helpers/partialUtil.d.ts": "7da6f1e431746c5364ebe6703f5d3a844ab0495e2a8cedc0a29cced52d6284a1", - "https://esm.sh/v107/zod@3.20.6/lib/helpers/typeAliases.d.ts": "5487b97cfa28b26b4a9ef0770f872bdbebd4c46124858de00f242c3eed7519f4", - "https://esm.sh/v107/zod@3.20.6/lib/helpers/util.d.ts": "bb98c05ae5cb9bd7cb7ad76fe517251a661787a6f24337b842f47faf393f79c7", - "https://esm.sh/v107/zod@3.20.6/lib/index.d.ts": "0f86f053aecd06054359e146b6cd800fee9bf82905f8afb47f1fe774fd37311e", - "https://esm.sh/v107/zod@3.20.6/lib/locales/en.d.ts": "f8ec1611afb8d132c6c71822718805866890cf2071025153af97508eff24e4b6", - "https://esm.sh/v107/zod@3.20.6/lib/types.d.ts": "d3482d1c02b58d90e165efcffae944185b183addd5dd3e287347694655a9102d", - "https://esm.sh/zod-to-json-schema@3.20.2": "ea382caa537539b7fb7c286e680d791d3ab45cb084a91257db686d63d66d7fe4" + "https://deno.land/x/zcli@1.3.3/args.ts": "7b782f670a53b693e6fef1d143513b7e8c08972460e2e78c14fc8f1d75babba6", + "https://deno.land/x/zcli@1.3.3/command.ts": "637cb7ca110a15d59432bc7f10ef66d5bae92d63fd07e80bf59c8c56e86884ab", + "https://deno.land/x/zcli@1.3.3/completion.ts": "db6b47a9b565feb9ed47e1a60150c52ff0c10f34533f12a5387b664c58945d12", + "https://deno.land/x/zcli@1.3.3/completions/bash.ts": "47097077189ada9b4d9ae445c32a3f07182df4b653f185a8200f1a35020d8933", + "https://deno.land/x/zcli@1.3.3/completions/fish.ts": "60b8316efa97946ee60e0aaf554cf9aecf09c9fafd84b7384118b404076d28e8", + "https://deno.land/x/zcli@1.3.3/completions/shared.ts": "23ac441b008ed1249dd9a80a1cb326184746c5666148c5a3f075412277cb68de", + "https://deno.land/x/zcli@1.3.3/completions/zsh.ts": "2781bbd7c70e9d91b06889ff3599164b2764e79945db62b9d5b173ca206a1e35", + "https://deno.land/x/zcli@1.3.3/config.ts": "428a7bdd1d9200be4596622a6a99780e71f0544d4c1a489d6940334295367472", + "https://deno.land/x/zcli@1.3.3/deps.ts": "be1ee730c92a899ca590428239436c84d8150ac9f00dd441e1ec919a7bc860f0", + "https://deno.land/x/zcli@1.3.3/env.ts": "3a56402620547a7c01e583d3903c991d263bda224cef8ca3113b66a1ecf175b5", + "https://deno.land/x/zcli@1.3.3/flags-parser.ts": "4acc3e80a72ccf2e8e9553abb01daf9d9ba0e767f9df5704ebeca992ba7f0c0e", + "https://deno.land/x/zcli@1.3.3/flags.ts": "b52c2242019ade5d50363a686294d6a09c69f8a46c27946faaf9a356f846f03c", + "https://deno.land/x/zcli@1.3.3/fmt.ts": "49110fe4fd9c32c58d751c0a448a8ebcdab459ce48727869b61757dc277d05cc", + "https://deno.land/x/zcli@1.3.3/help.ts": "8588c14e0eb5aa2e38b786cb6f9016791b0d225d5b885a0c9a00d260dcc7647e", + "https://deno.land/x/zcli@1.3.3/init.ts": "68afcc950f75a1902ce60142bfa7e02f673f57290c9e941f8f9085a9288079bd", + "https://deno.land/x/zcli@1.3.3/intl.ts": "ed467959a86265f10e49235f1820d3973e8de6c4a4102514164d570a54685ad2", + "https://deno.land/x/zcli@1.3.3/kv.ts": "9eac138a30c0e2aea8aaa512b0ceb6724a69afaa98f9930cc77e6126ac16c4d1", + "https://deno.land/x/zcli@1.3.3/lib/dedent.ts": "0da88eeb519338eec8185ad150dc83b5b37e145b70164ef8c24787563da70158", + "https://deno.land/x/zcli@1.3.3/lib/did-you-mean.ts": "09ec6cb7684a379cdde456f368d945d00d998b0bcba073b9300e6eca8989cd42", + "https://deno.land/x/zcli@1.3.3/lib/shorten.ts": "a245549ae04c3bf3310ef0be887bdccc89c3d19d3310aac61ffc51bf48bd9cf0", + "https://deno.land/x/zcli@1.3.3/lib/simple-table.ts": "79ecad21cdc43846f9e34c804c38cd34623ed74aa01d3a0fbb08f28f219aa9ba", + "https://deno.land/x/zcli@1.3.3/lib/text-encoder.ts": "ad6e7d6f78778033a1aa96b9f1cc2612e8a938090588bb2b3c0c9e66f5fa1984", + "https://deno.land/x/zcli@1.3.3/lib/types.ts": "3aae439314da2694a8093a55bd4666dfb4505a3abda7b7c989a327ac4b54c314", + "https://deno.land/x/zcli@1.3.3/lib/write-iterable.ts": "942fe1e96f936af6d3c5b6d70cc5272bef0d36fb81e4276282e45b9fa4d97022", + "https://deno.land/x/zcli@1.3.3/locale.ts": "dff20b9968f5d0058a07412e09536c8983520219422e374c5bfd6c366e6d65d3", + "https://deno.land/x/zcli@1.3.3/mod.ts": "bdf98129a4f2d5b9e4d1446e252765f3c0df64289b5094b3c7cc287b42ebee12", + "https://deno.land/x/zcli@1.3.3/version.ts": "793bc7245ccefda0f924017b2d973ec4258519c6b89b75f1f2ad91c3966ce3aa", + "https://deno.land/x/zcli@1.3.3/z.ts": "3ece197424db8241978f2867426ceee02c72a53dc406142cf767b3a33560ebe5", + "https://deno.land/x/zcli@1.3.3/zcli-json.ts": "bf090cbd9c6222ad331ca01382e967e669286b19ea5cd550ebfc7fd2d7384323", + "https://deno.land/x/zcli@1.3.3/zod-proxy.ts": "b5cb0c33445e7170c0c021340a6ce45747df76662d0d76ba4eeb6e606ffab115", + "https://deno.land/x/zod@v3.21.4/ZodError.ts": "4de18ff525e75a0315f2c12066b77b5c2ae18c7c15ef7df7e165d63536fdf2ea", + "https://deno.land/x/zod@v3.21.4/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef", + "https://deno.land/x/zod@v3.21.4/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe", + "https://deno.land/x/zod@v3.21.4/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c", + "https://deno.land/x/zod@v3.21.4/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7", + "https://deno.land/x/zod@v3.21.4/helpers/parseUtil.ts": "51a76c126ee212be86013d53a9d07f87e9ae04bb1496f2558e61b62cb74a6aa8", + "https://deno.land/x/zod@v3.21.4/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7", + "https://deno.land/x/zod@v3.21.4/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e", + "https://deno.land/x/zod@v3.21.4/helpers/util.ts": "8baf19b19b2fca8424380367b90364b32503b6b71780269a6e3e67700bb02774", + "https://deno.land/x/zod@v3.21.4/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268", + "https://deno.land/x/zod@v3.21.4/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c", + "https://deno.land/x/zod@v3.21.4/mod.ts": "64e55237cb4410e17d968cd08975566059f27638ebb0b86048031b987ba251c4", + "https://deno.land/x/zod@v3.21.4/types.ts": "b5d061babea250de14fc63764df5b3afa24f2b088a1d797fc060ba49a0ddff28", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/deno/zod-to-json-schema.js": "52790608b8875080da38adb31db580e95160ea4ad3ee8365790e1acff6387fc2", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/index.d.ts": "6a35cd9a2721b5bc26e2b4fda01d1c56f788a41ba7558fede42340c4a72a97be", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/Options.d.ts": "0f55b75d5866b80bfe80d063fc24b2ce2baa338c459eb316935a27dfb4e5c3bf", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/Refs.d.ts": "d89013b66d577692d30ffbd425fa52dccab992768c2b76d086498dda898c1d94", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/errorMessages.d.ts": "793758266c2149213de4b43f0b923c88da356b2084aed96acb233c9b5791b369", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parseDef.d.ts": "58ab53ae728b36c78ae27eac1d860febfa1af42349478c3f56d425917986820d", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/any.d.ts": "ba739758560a9b3e696095df9b04ac5d9d76acb11e98e06e73b7a86cbffe4207", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/array.d.ts": "3555631748ed9a7c5a43775024c8f8f549db04e82bca3b5416e68ad756791fa7", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/bigint.d.ts": "8e982f3df4c7b027d54e52cf02acb25f2ccf33cadd27c8a7865c1cd6a1958211", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/boolean.d.ts": "0e8edbe744dfc3ce65e9fa2283f1f0eb2c0aaaec4df19765f51c346e45452cda", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/date.d.ts": "2041c577c7ba7bf4c71d98b79b955c0dae8aec82b800bd403f71416962ebf43a", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/enum.d.ts": "c810520a5a5b5885afdfb22e5f24913a680bbf4a6cb3298c7e7926c06fffde14", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/intersection.d.ts": "ddd5dae715ff232033f8fc4a20e993dcb7990fad5a10abdc7c08c23fd105abdf", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/literal.d.ts": "3134d443f1e9e02b2491a5ace19b003ec9a3aa4570b21a3df4a92dcb640ab101", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/map.d.ts": "212a8ae920e91b3aca2f937a9443133e479364516499e39f7dfca66d33200ffe", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/nativeEnum.d.ts": "f0ed791578b81ffe9532f1d7dc69f8042c163da4ce7e17da105cc904e2d5808a", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/never.d.ts": "adb05565c81b408a97cee9201c8539dda075c30dffce0d4ec226e5050f36bfa4", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/null.d.ts": "2007d407fb8742049ecaeac0b4c5a4c78619b64a6abb56250e65f5375ca1bbb1", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/nullable.d.ts": "4247d929e4dbc210e6c4b3a3fadc2fdbe49484cfd39613951120569fd790ff8d", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/number.d.ts": "96068895acb3a0963e466a6a6031d032e0c45fe3cc4fe01d0fb2d1aa599ee151", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/object.d.ts": "95715ae8c783fad3ceba32b20c35981bd872eb8225a3e5bead7178619aec055f", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/record.d.ts": "52ea078ba7248971232a18c994a47de3e95c904ec72c92a09f192790763e4387", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/set.d.ts": "52b4043525e2032ef19ddb7e6fd7ad23ce28285395a4ce9c34851c8fd51e4537", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/string.d.ts": "10f4dbda9b4068de9b42b5005899b68733f7fda316ef8d255f9ccaa10e8d9c94", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/tuple.d.ts": "15a5d7d3848585f5463c8d4281bc807601cd0247abc996ce084c9cb9518ae982", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/undefined.d.ts": "3a56da695cfddd03aee7835adf8934e4f357cc9bac59ea534cd282aba668b566", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/union.d.ts": "54e05b95eef7ec826866f090d7e501354ff9eae89782fabc02954cd7f815bd69", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/parsers/unknown.d.ts": "ba3886b9e5b3bd32588d57421988aeeea94afe40227334edc5d45fb0c5367c9d", + "https://esm.sh/v111/zod-to-json-schema@3.20.4/src/zodToJsonSchema.d.ts": "78eed4b9655aacff0a686884262fcdba7538b49860dd7d8712c107ea7567f0c8", + "https://esm.sh/v111/zod@3.21.4/deno/zod.js": "ef6535dd2aa5c37b49464e9f474f5e59252e3f50f7f03183d43e997be3f62263", + "https://esm.sh/v111/zod@3.21.4/index.d.ts": "b51c954b9557b1dcb03b2bf34cd136e710cb9aa276e686cac0e291249590a52a", + "https://esm.sh/v111/zod@3.21.4/lib/ZodError.d.ts": "1f19511459549a66526d9dcc3b2288e59fa5fd4cf42b390a945d0bdc289806df", + "https://esm.sh/v111/zod@3.21.4/lib/errors.d.ts": "5ec2790f877581637c058eb5bbb72e855a078620d0781d2a6a8f308fe1d5436f", + "https://esm.sh/v111/zod@3.21.4/lib/external.d.ts": "91cec2fe1e1fb2574812a29a57ad2c39a1e69b0fa1179547382c92649fc5c66e", + "https://esm.sh/v111/zod@3.21.4/lib/helpers/enumUtil.d.ts": "f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c", + "https://esm.sh/v111/zod@3.21.4/lib/helpers/errorUtil.d.ts": "98a9cc18f661d28e6bd31c436e1984f3980f35e0f0aa9cf795c54f8ccb667ffe", + "https://esm.sh/v111/zod@3.21.4/lib/helpers/parseUtil.d.ts": "d3dbfc2f2fbf2c1bdea72db72f9f5c95d2ca5b4d32c9e229764ebaba0920203c", + "https://esm.sh/v111/zod@3.21.4/lib/helpers/partialUtil.d.ts": "be2da97df422506d54e0e1727a40f6315c7311931b65a552b3172148db734c43", + "https://esm.sh/v111/zod@3.21.4/lib/helpers/typeAliases.d.ts": "5487b97cfa28b26b4a9ef0770f872bdbebd4c46124858de00f242c3eed7519f4", + "https://esm.sh/v111/zod@3.21.4/lib/helpers/util.d.ts": "7a01f546ace66019156e4232a1bee2fabc2f8eabeb052473d926ee1693956265", + "https://esm.sh/v111/zod@3.21.4/lib/index.d.ts": "e6e0b04af1500398c8840582cce03d8907d6475005eb490f0e07bb33db6da66c", + "https://esm.sh/v111/zod@3.21.4/lib/locales/en.d.ts": "f8ec1611afb8d132c6c71822718805866890cf2071025153af97508eff24e4b6", + "https://esm.sh/v111/zod@3.21.4/lib/types.d.ts": "d7eecca2a9e02b2b2f51eaef95956f490a5780d03b32b9865068a63a26810f01", + "https://esm.sh/zod-to-json-schema@3.20.4": "0d0a0e35307c0904d69c7f265c254245bd738854b5489192bf69f48893e4c137" }, "npm": { "specifiers": { diff --git a/deps.ts b/deps.ts index 6a747bb..32172bf 100644 --- a/deps.ts +++ b/deps.ts @@ -1,21 +1,22 @@ -export * as path from "https://deno.land/std@0.178.0/path/mod.ts"; -export * as log from "https://deno.land/std@0.178.0/log/mod.ts"; -export { getLevelByName } from "https://deno.land/std@0.178.0/log/levels.ts"; -export { deepMerge } from "https://deno.land/std@0.178.0/collections/deep_merge.ts"; -export { stripColor } from "https://deno.land/std@0.178.0/fmt/colors.ts"; +export * as path from "https://deno.land/std@0.179.0/path/mod.ts"; +export * as log from "https://deno.land/std@0.179.0/log/mod.ts"; +export { getLevelByName } from "https://deno.land/std@0.179.0/log/levels.ts"; +export { deepMerge } from "https://deno.land/std@0.179.0/collections/deep_merge.ts"; +export { stripColor } from "https://deno.land/std@0.179.0/fmt/colors.ts"; export { concat, indexOfNeedle, -} from "https://deno.land/std@0.178.0/bytes/mod.ts"; +} from "https://deno.land/std@0.179.0/bytes/mod.ts"; export { copy, iterateReader, readerFromStreamReader, -} from "https://deno.land/std@0.178.0/streams/mod.ts"; -export { TarEntry, Untar } from "https://deno.land/std@0.178.0/archive/mod.ts"; -export { format as formatBytes } from "https://deno.land/std@0.178.0/fmt/bytes.ts"; -export * as YAML from "https://deno.land/std@0.178.0/encoding/yaml.ts"; -export * as TOML from "https://deno.land/std@0.178.0/encoding/toml.ts"; +} from "https://deno.land/std@0.179.0/streams/mod.ts"; +export { TarEntry, Untar } from "https://deno.land/std@0.179.0/archive/mod.ts"; +export { format as formatBytes } from "https://deno.land/std@0.179.0/fmt/bytes.ts"; +export * as YAML from "https://deno.land/std@0.179.0/encoding/yaml.ts"; +export * as TOML from "https://deno.land/std@0.179.0/encoding/toml.ts"; +export * as JSONc from "https://deno.land/std@0.179.0/encoding/jsonc.ts"; export * as Sentry from "https://deno.land/x/sentry_deno@v0.2.2/main.ts"; export { ms } from "https://deno.land/x/ms@v0.1.0/ms.ts"; diff --git a/lib/app-config.ts b/lib/app-config.ts index de166f4..b9de3e7 100644 --- a/lib/app-config.ts +++ b/lib/app-config.ts @@ -1,9 +1,12 @@ import { paths } from "../api/openapi.ts"; -import { path, TOML, YAML } from "../deps.ts"; +import { JSONc, path, TOML, YAML } from "../deps.ts"; import { AppError, DocumentedError } from "../errors.ts"; import { logger } from "../logger.ts"; -export async function find(cwd: string, file?: string) { +export async function find(options: { cwd?: string; config?: string }) { + let { config: file, cwd = Deno.cwd() } = options; + cwd = path.isAbsolute(cwd) ? cwd : path.join(Deno.cwd(), cwd); + if (file) { logger.info(`Using config file: ${file}`); const filePath = path.isAbsolute(file) ? file : path.join(cwd, file); @@ -28,10 +31,12 @@ export async function find(cwd: string, file?: string) { "paperspace.yaml", "paperspace.yml", "paperspace.json", + "paperspace.jsonc", "paperspace.toml", ".paperspace/app.yaml", ".paperspace/app.yml", ".paperspace/app.json", + ".paperspace/app.jsonc", ".paperspace/app.toml", ]; @@ -72,7 +77,8 @@ export function parse( } const parsers = { - ".json": JSON.parse, + ".json": JSONc.parse, + ".jsonc": JSONc.parse, ".yaml": YAML.parse, ".yml": YAML.parse, ".toml": TOML.parse, diff --git a/lib/asserts.ts b/lib/asserts.ts index a55ae41..3af6abb 100644 --- a/lib/asserts.ts +++ b/lib/asserts.ts @@ -1,6 +1,7 @@ // deno-lint-ignore-file no-explicit-any import { ErrorData, SuccessData } from "../api/client.ts"; -import { AppError } from "../errors.ts"; +import { AppError, ValidationError } from "../errors.ts"; +import { z } from "../zcli.ts"; /** * Asserts state we assume to be true. @@ -10,13 +11,21 @@ import { AppError } from "../errors.ts"; */ export function asserts( condition: T, - format: string | Error | (SuccessData | ErrorData), + format: + | string + | Error + | z.ZodError + | (SuccessData | ErrorData), ): asserts condition { if (!condition) { if (typeof format === "object" && "error" in format && "ok" in format) { throw format.error; } + if (format instanceof z.ZodError) { + throw new ValidationError(format.issues[0].message); + } + const error = format instanceof Error ? format : new AppError({ message: typeof format === "string" ? format : "" }); diff --git a/lib/find-project.ts b/lib/find-project.ts new file mode 100644 index 0000000..7349e2b --- /dev/null +++ b/lib/find-project.ts @@ -0,0 +1,63 @@ +import { select } from "../prompts/select.ts"; +import { asserts } from "./asserts.ts"; +import { config } from "../config.ts"; +import { loading } from "./loading.ts"; +import { projects } from "../api/projects.ts"; +import { fmt } from "../zcli.ts"; +import { path } from "../deps.ts"; +import { paths } from "../api/openapi.ts"; +import { printLn } from "./print.ts"; + +export async function findProject( + { handle, cwd, quiet }: { cwd?: string; quiet?: boolean; handle?: string }, +) { + const projectPath = cwd + ? path.isAbsolute(cwd) ? cwd : path.join(Deno.cwd(), cwd) + : Deno.cwd(); + const localProjects = await config.get("projects"); + handle = handle ?? localProjects[projectPath]?.handle; + let project: + paths["/projects/{handle}"]["get"]["responses"]["200"]["content"][ + "application/json" + ]; + + if (!handle) { + const existingProjects = await loading(projects.list({ limit: 50 }), { + enabled: !quiet, + }); + + asserts(existingProjects.ok, existingProjects); + printLn(fmt.colors.yellow( + `Couldn't find a linked project for ${projectPath}.`, + )); + printLn( + `Run "${ + fmt.colors.bold(`pspace project link`) + }" in this directory to skip this step in the future.`, + ); + + const selected = await select( + "Select a project:", + existingProjects.data.items, + { + filter(input, option) { + return option.name.toLowerCase().startsWith(input); + }, + renderOption(option, isSelected) { + return `${isSelected ? ">" : " "} ${option.name}`; + }, + }, + ); + + asserts(selected, "No project selected."); + project = selected; + } else { + const response = await loading(projects.get({ handle }), { + enabled: !quiet, + }); + asserts(response.ok, response); + project = response.data; + } + + return project; +} diff --git a/logger.ts b/logger.ts index f367105..d3ec243 100644 --- a/logger.ts +++ b/logger.ts @@ -1,6 +1,6 @@ import { env } from "./env.ts"; -import { LogRecord } from "https://deno.land/std@0.178.0/log/logger.ts"; -import { HandlerOptions } from "https://deno.land/std@0.178.0/log/handlers.ts"; +import type { LogRecord } from "https://deno.land/std@0.179.0/log/logger.ts"; +import type { HandlerOptions } from "https://deno.land/std@0.179.0/log/handlers.ts"; import { getLevelByName, log, Sentry } from "./deps.ts"; class PaperspaceLogger extends log.handlers.ConsoleHandler { diff --git a/test/deps.ts b/test/deps.ts index 9017ff6..f003867 100644 --- a/test/deps.ts +++ b/test/deps.ts @@ -4,6 +4,6 @@ export { returnsNext, spy, stub, -} from "https://deno.land/std@0.178.0/testing/mock.ts"; -export * as asserts from "https://deno.land/std@0.178.0/testing/asserts.ts"; -export { describe, it } from "https://deno.land/std@0.178.0/testing/bdd.ts"; +} from "https://deno.land/std@0.179.0/testing/mock.ts"; +export * as asserts from "https://deno.land/std@0.179.0/testing/asserts.ts"; +export { describe, it } from "https://deno.land/std@0.179.0/testing/bdd.ts"; diff --git a/zcli.ts b/zcli.ts index 153f394..f77b539 100644 --- a/zcli.ts +++ b/zcli.ts @@ -3,7 +3,7 @@ import { flags, inferContext, init, -} from "https://deno.land/x/zcli@1.3.2/mod.ts"; +} from "https://deno.land/x/zcli@1.3.3/mod.ts"; import { COMMIT, VERSION } from "./version.ts"; @@ -52,11 +52,11 @@ export const app = init({ export type Context = inferContext; export const { command } = app; -export * from "https://deno.land/x/zcli@1.3.2/mod.ts"; +export * from "https://deno.land/x/zcli@1.3.3/mod.ts"; export type { Join, NestedKeys, NestedValue, -} from "https://deno.land/x/zcli@1.3.2/lib/types.ts"; -export { textEncoder } from "https://deno.land/x/zcli@1.3.2/lib/text-encoder.ts"; -export { table } from "https://deno.land/x/zcli@1.3.2/lib/simple-table.ts"; +} from "https://deno.land/x/zcli@1.3.3/lib/types.ts"; +export { textEncoder } from "https://deno.land/x/zcli@1.3.3/lib/text-encoder.ts"; +export { table } from "https://deno.land/x/zcli@1.3.3/lib/simple-table.ts";