From 549042dae1ec26cbc446790cc236170bc5365158 Mon Sep 17 00:00:00 2001 From: Nikita Klimin Date: Tue, 20 Aug 2024 14:35:29 +0300 Subject: [PATCH 01/15] Update to lastest manifest (#91) * fix: update cli to newest manifest * bump: version --- package.json | 9 +++------ src/commands/deploy.ts | 4 ++-- src/hooks/command_not_found.ts | 7 ++++--- src/manifest/manifest.ts | 26 +++++++++++--------------- yarn.lock | 11 ++++++----- 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index c5303a7..da8d8e4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.1", + "version": "2.13.0", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { @@ -58,8 +58,7 @@ "tsc": "tsc --noEmit", "pkg:build": "./bin/pkg-build.sh", "pkg:compress": "./bin/pkg-compress.sh", - "upg": "yarn upgrade-interactive", - "codegen": "npx openapi-typescript http://localhost:3001/docs/swagger.json -o ./src/api/schema.d.ts --enum --empty-objects-unknown" + "upg": "yarn upgrade-interactive" }, "jest": { "moduleFileExtensions": [ @@ -78,7 +77,7 @@ "@oclif/plugin-autocomplete": "3.0.13", "@oclif/plugin-warn-if-update-available": "^3.1.6", "@subsquid/commands": "^2.3.1", - "@subsquid/manifest": "^0.0.1-beta.17", + "@subsquid/manifest": "^1.0.0-beta.11", "@subsquid/manifest-expr": "^0.0.1", "@types/fast-levenshtein": "^0.0.4", "@types/lodash": "^4.17.0", @@ -138,12 +137,10 @@ "eslint-plugin-promise": "^6.1.1", "eslint-plugin-standard": "^4.1.0", "jest": "^29.7.0", - "openapi-typescript": "^7.3.0", "pkg": "^5.8.1", "prettier": "^3.2.5", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", - "type-fest": "^4.24.0", "typescript": "~5.4.3" }, "packageManager": "yarn@4.1.1" diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index cd1f0b7..14a2b31 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -3,7 +3,7 @@ import path from 'node:path'; import { promisify } from 'util'; import { Args, Flags, ux as CliUx } from '@oclif/core'; -import { ManifestValue } from '@subsquid/manifest'; +import { Manifest } from '@subsquid/manifest'; import chalk from 'chalk'; import { globSync } from 'glob'; import ignore from 'ignore'; @@ -33,7 +33,7 @@ export const DELETE_COLOR = 'red'; export function resolveManifest( localPath: string, manifestPath: string, -): { error: string } | { buildDir: string; squidDir: string; manifest: ManifestValue } { +): { error: string } | { buildDir: string; squidDir: string; manifest: Manifest } { try { const { squidDir, manifest } = loadManifestFile(localPath, manifestPath); diff --git a/src/hooks/command_not_found.ts b/src/hooks/command_not_found.ts index f3110f1..8138d1a 100644 --- a/src/hooks/command_not_found.ts +++ b/src/hooks/command_not_found.ts @@ -1,16 +1,17 @@ import { Hook, toConfiguredId } from '@oclif/core'; -import { getSquidCommands } from '../utils'; import { run as squidCommandRun } from '@subsquid/commands/lib/run'; import chalk from 'chalk'; -import { minBy } from 'lodash'; import Levenshtein from 'fast-levenshtein'; +import { minBy } from 'lodash'; + import Help from '../help'; +import { getSquidCommands } from '../utils'; function closestCommand(cmd: string, commands: string[]) { return minBy(commands, (c) => Levenshtein.get(cmd, c))!; } -const hook: Hook<'command_not_found'> = async function ({ id, argv, config}) { +const hook: Hook<'command_not_found'> = async function ({ id, argv, config }) { const squidCmdConfig = await getSquidCommands(); if (squidCmdConfig?.commands?.[id]) { process.exit(await squidCommandRun(squidCmdConfig, id, (argv || []).slice(1))); diff --git a/src/manifest/manifest.ts b/src/manifest/manifest.ts index 63bf2ff..d6d2aa3 100644 --- a/src/manifest/manifest.ts +++ b/src/manifest/manifest.ts @@ -1,20 +1,20 @@ import fs from 'fs'; import path from 'path'; -import { Manifest, ManifestValue } from '@subsquid/manifest'; +import { Manifest } from '@subsquid/manifest'; import { Expression, Parser } from '@subsquid/manifest-expr'; import yaml from 'js-yaml'; import { mapValues } from 'lodash'; export function readManifest(path: string) { - return yaml.load(fs.readFileSync(path).toString()) as Partial; + return yaml.load(fs.readFileSync(path).toString()) as Partial; } -export function saveManifest(path: string, manifest: Partial) { +export function saveManifest(path: string, manifest: Partial) { fs.writeFileSync(path, formatManifest(manifest)); } -export function formatManifest(manifest: Partial): string { +export function formatManifest(manifest: Partial): string { return yaml.dump(manifest, { styles: { 'tag:yaml.org,2002:null': 'empty', @@ -34,10 +34,7 @@ export function parseManifestEnv(env: Record) { return mapValues(env, (value) => (typeof value === 'string' ? parser.parse(value) : value)); } -export function loadManifestFile( - localPath: string, - manifestPath: string, -): { squidDir: string; manifest: ManifestValue } { +export function loadManifestFile(localPath: string, manifestPath: string): { squidDir: string; manifest: Manifest } { const squidDir = path.resolve(localPath); if (!fs.statSync(squidDir).isDirectory()) { @@ -98,19 +95,18 @@ export function loadManifestFile( let manifest; try { const raw = fs.readFileSync(manifestFullPath).toString(); - manifest = Manifest.parse(raw, { validation: { allowUnknown: true } }); + const { value, error } = Manifest.parse(raw, { validation: { allowUnknown: true } }); + if (error) { + throw error; + } + manifest = value as Manifest; } catch (e: any) { throw new Error( `The manifest file on ${manifestFullPath} can not be parsed: ${e instanceof Error ? e.message : e}`, ); } - - if (manifest.hasError()) { - throw new Error(manifest.getErrors().join('\n')); - } - return { squidDir, - manifest: manifest.values() as ManifestValue, + manifest: manifest, }; } diff --git a/yarn.lock b/yarn.lock index e3ea71e..3731a28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1404,7 +1404,7 @@ __metadata: "@oclif/plugin-autocomplete": "npm:3.0.13" "@oclif/plugin-warn-if-update-available": "npm:^3.1.6" "@subsquid/commands": "npm:^2.3.1" - "@subsquid/manifest": "npm:^0.0.1-beta.17" + "@subsquid/manifest": "npm:^1.0.0-beta.11" "@subsquid/manifest-expr": "npm:^0.0.1" "@types/async-retry": "npm:^1.4.8" "@types/blessed": "npm:^0.1.25" @@ -1505,14 +1505,15 @@ __metadata: languageName: node linkType: hard -"@subsquid/manifest@npm:^0.0.1-beta.17": - version: 0.0.1-beta.17 - resolution: "@subsquid/manifest@npm:0.0.1-beta.17" +"@subsquid/manifest@npm:^1.0.0-beta.11": + version: 1.0.0-beta.11 + resolution: "@subsquid/manifest@npm:1.0.0-beta.11" dependencies: + "@subsquid/manifest-expr": "npm:^0.0.1" joi: "npm:^17.12.0" js-yaml: "npm:^4.1.0" lodash: "npm:^4.17.21" - checksum: 10c0/5ef504f4c2e12c3f4648f46dae7042d8a8c75c90aa35f2aad1ec873eda040ebba9356820f9b2a93908689804ec87b6b50ef9c8933798ad9c2d17b028fb00b8ab + checksum: 10c0/6ced44b1943c90e46557d56654da2dbedf28d83b0d4b0e2201effc33d9a4501ce433320593640ad92e29d9ef1ce381c7542250afd10d9f85b9b3967a50061748 languageName: node linkType: hard From 7201a0a8dab025638ae56ec03536fd4fb710c871 Mon Sep 17 00:00:00 2001 From: Alexander Belopashentsev <61732514+belopash@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:26:01 +0500 Subject: [PATCH 02/15] feat: new deployment flow (#90) Co-authored-by: Eugene Formanenko --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index da8d8e4..485386b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "2.13.0", + "version": "3.0.0-beta.1", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { @@ -58,7 +58,8 @@ "tsc": "tsc --noEmit", "pkg:build": "./bin/pkg-build.sh", "pkg:compress": "./bin/pkg-compress.sh", - "upg": "yarn upgrade-interactive" + "upg": "yarn upgrade-interactive", + "codegen": "npx openapi-typescript http://localhost:3001/docs/swagger.json -o ./src/api/schema.d.ts --enum --empty-objects-unknown" }, "jest": { "moduleFileExtensions": [ @@ -137,10 +138,12 @@ "eslint-plugin-promise": "^6.1.1", "eslint-plugin-standard": "^4.1.0", "jest": "^29.7.0", + "openapi-typescript": "^7.3.0", "pkg": "^5.8.1", "prettier": "^3.2.5", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", + "type-fest": "^4.24.0", "typescript": "~5.4.3" }, "packageManager": "yarn@4.1.1" From 825ed711c9171794e6e9d26431d63f0baca13359 Mon Sep 17 00:00:00 2001 From: Eugene Formanenko Date: Tue, 27 Aug 2024 16:51:38 +0400 Subject: [PATCH 03/15] chore: fix 404 issue --- package.json | 44 +- src/api/api.ts | 9 +- src/api/deploy.ts | 14 +- src/api/schema.d.ts | 8332 ++++-------------------- src/api/squids.ts | 66 +- src/api/types.ts | 20 +- src/command.ts | 89 +- src/commands/deploy.ts | 219 +- src/commands/explorer.ts | 2 +- src/commands/init.ts | 24 +- src/commands/logs.ts | 29 +- src/commands/ls.ts | 30 +- src/commands/prod.ts | 23 + src/commands/restart.ts | 49 +- src/commands/rm.ts | 34 +- src/commands/secrets/ls.ts | 2 +- src/commands/secrets/rm.ts | 2 +- src/commands/secrets/set.ts | 2 +- src/commands/tag.ts | 40 +- src/deploy-command.ts | 64 +- src/help.ts | 2 +- src/manifest/manifest.ts | 15 +- src/manifest/manifest.unit.spec.ts | 15 - src/ui/components/VersionLogsTab.ts | 9 +- src/ui/components/VersionSummaryTab.ts | 5 +- src/utils.ts | 28 +- yarn.lock | 503 +- 27 files changed, 1935 insertions(+), 7736 deletions(-) create mode 100644 src/commands/prod.ts delete mode 100644 src/manifest/manifest.unit.spec.ts diff --git a/package.json b/package.json index 485386b..2310f0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.1", + "version": "3.0.0-beta.3", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { @@ -74,20 +74,21 @@ "testEnvironment": "node" }, "dependencies": { - "@oclif/core": "3.26.0", - "@oclif/plugin-autocomplete": "3.0.13", - "@oclif/plugin-warn-if-update-available": "^3.1.6", + "@oclif/core": "3.27.0", + "@oclif/plugin-autocomplete": "3.2.2", + "@oclif/plugin-warn-if-update-available": "^3.1.13", "@subsquid/commands": "^2.3.1", - "@subsquid/manifest": "^1.0.0-beta.11", + "@subsquid/manifest": "^1.0.0-beta.12", "@subsquid/manifest-expr": "^0.0.1", "@types/fast-levenshtein": "^0.0.4", - "@types/lodash": "^4.17.0", + "@types/lodash": "^4.17.7", "@types/targz": "^1.0.4", "async-retry": "^1.3.3", - "axios": "^1.6.8", - "axios-retry": "^4.1.0", + "axios": "^1.7.5", + "axios-retry": "^4.5.0", "blessed-contrib": "^4.11.0", "chalk": "^4.1.2", + "cli-diff": "^1.0.0", "cli-select": "^1.1.2", "cross-spawn": "^7.0.3", "date-fns": "^3.6.0", @@ -95,8 +96,8 @@ "fast-levenshtein": "^3.0.0", "figlet": "^1.7.0", "form-data": "^4.0.0", - "glob": "^10.3.12", - "ignore": "^5.3.1", + "glob": "^10.4.5", + "ignore": "^5.3.2", "inquirer": "^8.2.6", "js-yaml": "^4.1.0", "lodash": "^4.17.21", @@ -104,13 +105,12 @@ "neo-blessed": "^0.2.0", "open": "^8.1.0", "pretty-bytes": "^5.6.0", - "qs": "^6.12.0", + "qs": "^6.13.0", "reblessed": "^0.2.1", - "simple-git": "^3.24.0", + "simple-git": "^3.25.0", "split2": "^4.2.0", "targz": "^1.0.1", - "tree-kill": "^1.2.2", - "unique-names-generator": "^4.7.1" + "tree-kill": "^1.2.2" }, "devDependencies": { "@oclif/dev-cli": "^1.26.10", @@ -123,12 +123,12 @@ "@types/jest": "^29.5.12", "@types/js-yaml": "^4.0.9", "@types/ms": "^0.7.34", - "@types/node": "^20.12.3", - "@types/qs": "^6.9.14", + "@types/node": "^20.16.2", + "@types/qs": "^6.9.15", "@types/split2": "^3.2.1", - "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/eslint-plugin-tslint": "^7.0.2", - "@typescript-eslint/parser": "^7.5.0", + "@typescript-eslint/parser": "^7.18.0", "eslint": "8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-config-standard": "^17.1.0", @@ -140,11 +140,11 @@ "jest": "^29.7.0", "openapi-typescript": "^7.3.0", "pkg": "^5.8.1", - "prettier": "^3.2.5", - "ts-jest": "^29.1.2", + "prettier": "^3.3.3", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "type-fest": "^4.24.0", - "typescript": "~5.4.3" + "type-fest": "^4.26.0", + "typescript": "~5.5.4" }, "packageManager": "yarn@4.1.1" } diff --git a/src/api/api.ts b/src/api/api.ts index f38f34f..1493a04 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -3,8 +3,9 @@ import path from 'path'; import axios, { Method } from 'axios'; import axiosRetry, { IAxiosRetryConfig, isNetworkOrIdempotentRequestError } from 'axios-retry'; import chalk from 'chalk'; -import { pickBy } from 'lodash'; +import { isEmpty, pickBy } from 'lodash'; import ms from 'ms'; +import qs from 'qs'; import { getConfig } from '../config'; @@ -58,6 +59,7 @@ export function debugLog(...args: any[]) { } export async function api({ + version = 'v1', method, path, data, @@ -68,6 +70,7 @@ export async function api({ abortController, retry, }: { + version?: 'v1'; method: Method; path: string; query?: Record; @@ -82,7 +85,7 @@ export async function api({ const started = Date.now(); // add the API_URL to the path if it's not a full url - const url = !path.startsWith('https') ? `${config.apiUrl}${path}` : path; + const url = !path.startsWith('https') ? `${config.apiUrl}/${version}${path}` : path; const finalHeaders = { authorization: url.startsWith(config.apiUrl) ? `token ${config.credentials}` : null, @@ -111,7 +114,7 @@ export async function api({ console.log( chalk.dim(new Date().toISOString()), chalk.cyan`[${method.toUpperCase()}]`, - response.config.url, + `${response.config.url}${!isEmpty(query) ? `?${qs.stringify(query)}` : ``}`, chalk.cyan(response.status), ms(Date.now() - started), chalk.dim(JSON.stringify({ headers: response.headers })), diff --git a/src/api/deploy.ts b/src/api/deploy.ts index 795d3f5..e5ad03a 100644 --- a/src/api/deploy.ts +++ b/src/api/deploy.ts @@ -1,19 +1,19 @@ import { api } from './api'; -import { Deploy, DeployRequest, HttpResponse, OrganizationRequest } from './types'; +import { Deployment, DeployRequest, HttpResponse, OrganizationRequest } from './types'; -export async function getDeploy({ organization, deploy }: DeployRequest): Promise { - const { body } = await api>({ +export async function getDeploy({ organization, deploy }: DeployRequest): Promise { + const { body } = await api>({ method: 'get', - path: `/orgs/${organization.code}/deploys/${deploy.id}`, + path: `/orgs/${organization.code}/deployments/${deploy.id}`, }); return body.payload; } -export async function getDeploys({ organization }: OrganizationRequest): Promise { - const { body } = await api>({ +export async function getDeploys({ organization }: OrganizationRequest): Promise { + const { body } = await api>({ method: 'get', - path: `/orgs/${organization.code}/deploys`, + path: `/orgs/${organization.code}/deployments`, }); return body.payload; diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts index 3a846e1..b6fd877 100644 --- a/src/api/schema.d.ts +++ b/src/api/schema.d.ts @@ -4,151 +4,32 @@ */ export interface paths { - "/auth/signin": { + "/v1/orgs/{code}/metrics/ingress": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; - put?: never; - /** Sign in */ - post: operations["signin"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/auth/signin": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Sign in */ - post: operations["signin"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/auth/signup": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Sign up */ - post: operations["signup"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/auth/signup": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Sign up */ - post: operations["signup"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/auth/restore": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Restore */ - post: operations["restore"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/auth/restore": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Restore */ - post: operations["restore"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/auth/restore/confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Confirm restore */ - post: operations["restore-confirm"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/auth/restore/confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; + /** Get all requests count */ + get: operations["SquidMetricsController_dailyRequests"]; put?: never; - /** Confirm restore */ - post: operations["restore-confirm"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/auth/email/confirm": { + "/v1/orgs/{code}/metrics/ingress/{squid_id}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Confirm email */ - get: operations["confirm-email"]; + /** Get full squid ingress metrics */ + get: operations["SquidMetricsController_ingressStats"]; put?: never; post?: never; delete?: never; @@ -157,15 +38,15 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/auth/email/confirm": { + "/v1/orgs/{code}/metrics/usage/{id}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Confirm email */ - get: operations["confirm-email"]; + /** Get squid usage metrics */ + get: operations["SquidMetricsController_usage"]; put?: never; post?: never; delete?: never; @@ -174,32 +55,32 @@ export interface paths { patch?: never; trace?: never; }; - "/oauth/github/url": { + "/v1/orgs/{code}/deployments/upload-url": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get Github OAuth URL */ - get: operations["github"]; + get?: never; put?: never; - post?: never; + /** Create an upload url */ + post: operations["DeploymentController_uploadUrl"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/oauth/github/url": { + "/v1/orgs/{code}/deployments": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get Github OAuth URL */ - get: operations["github"]; + /** Get deployments */ + get: operations["DeploymentController_getAll"]; put?: never; post?: never; delete?: never; @@ -208,24 +89,24 @@ export interface paths { patch?: never; trace?: never; }; - "/oauth/github/auth": { + "/v1/orgs/{code}/deployments/{id}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + /** Retrieve a deployment */ + get: operations["DeploymentController_getOne"]; put?: never; - /** Github auth */ - post: operations["github-auth"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/oauth/github/auth": { + "/v1/orgs/{org}/squids/deploy": { parameters: { query?: never; header?: never; @@ -234,23 +115,23 @@ export interface paths { }; get?: never; put?: never; - /** Github auth */ - post: operations["github-auth"]; + /** Deploy a squid */ + post: operations["SquidController_deploySquid"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/oauth/google/url": { + "/v1/orgs/{org}/squids": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get Google OAuth URL */ - get: operations["google"]; + /** List squids */ + get: operations["SquidController_listSquids"]; put?: never; post?: never; delete?: never; @@ -259,24 +140,25 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/oauth/google/url": { + "/v1/orgs/{org}/squids/{reference}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get Google OAuth URL */ - get: operations["google"]; + /** Retrieve a squid */ + get: operations["SquidController_getSquid"]; put?: never; post?: never; - delete?: never; + /** Delete a squid */ + delete: operations["SquidController_deleteSquid"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/oauth/google/auth": { + "/v1/orgs/{org}/squids/{reference}/restart": { parameters: { query?: never; header?: never; @@ -285,15 +167,15 @@ export interface paths { }; get?: never; put?: never; - /** Google auth */ - post: operations["google-auth"]; + /** Restart a squid */ + post: operations["SquidController_restartSquid"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/oauth/google/auth": { + "/v1/orgs/{org}/squids/{reference}/hibernate": { parameters: { query?: never; header?: never; @@ -302,15 +184,15 @@ export interface paths { }; get?: never; put?: never; - /** Google auth */ - post: operations["google-auth"]; + /** Hibernate a squid */ + post: operations["SquidController_hibernateSquid"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/squids/deploy": { + "/v1/orgs/{org}/squids/{reference}/tag": { parameters: { query?: never; header?: never; @@ -319,23 +201,23 @@ export interface paths { }; get?: never; put?: never; - /** Deploy a squid to organization */ - post: operations["deploy-squid"]; + /** Assign tag to a squid */ + post: operations["SquidController_setTag"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/squids": { + "/v1/orgs/{code}/squids/{reference}/logs/history": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** List organization squids */ - get: operations["list-squids"]; + /** Fetch squid logs */ + get: operations["SquidLogsController_fetchLogsHistory"]; put?: never; post?: never; delete?: never; @@ -344,85 +226,34 @@ export interface paths { patch?: never; trace?: never; }; - "/orgs/{code}/squids/{squid}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get all squid versions */ - get: operations["get-squid"]; - put?: never; - post?: never; - /** Delete all squid versions by name */ - delete: operations["delete-squid"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/squids/{squid}/version/{version}": { + "/v1/orgs/{code}/squids/{reference}/logs/follow": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + /** Stream squid logs */ + get: operations["SquidLogsController_tailLogs"]; put?: never; post?: never; - /** Delete a squid */ - delete: operations["destroy-squid-version"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/squids/{squid}/version/{version}/redeploy": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Restart a squid */ - put: operations["restart-squid-version"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/squids/{squid}/version/{version}/hibernate": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Hibernate a squid */ - post: operations["hibernate-squid"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/squids/metrics/ingress": { + "/v1/user": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get all requests count */ - get: operations["daily-requests"]; - put?: never; + /** Get profile */ + get: operations["UserController_getProfile"]; + /** Update profile */ + put: operations["UserController_updateProfile"]; post?: never; delete?: never; options?: never; @@ -430,15 +261,15 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/orgs/{code}/squids/metrics/ingress": { + "/v1/user/squids": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get all requests count */ - get: operations["daily-requests"]; + /** Get list of squids from all users organizations */ + get: operations["UserController_getSquidsV1"]; put?: never; post?: never; delete?: never; @@ -447,32 +278,33 @@ export interface paths { patch?: never; trace?: never; }; - "/orgs/{code}/squids/metrics/ingress/{id}": { + "/v1/orgs": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get full squid ingress metrics */ - get: operations["ingress-stats"]; + /** List all organizations */ + get: operations["OrganizationController_listOrganizations"]; put?: never; - post?: never; + /** Create new organization */ + post: operations["OrganizationController_create"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{code}/squids/metrics/ingress/{id}": { + "/v1/orgs/{org}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get full squid ingress metrics */ - get: operations["ingress-stats"]; + /** Get an organization */ + get: operations["OrganizationController_getOrganization"]; put?: never; post?: never; delete?: never; @@ -481,49 +313,50 @@ export interface paths { patch?: never; trace?: never; }; - "/orgs/{code}/squids/metrics/usage/{id}": { + "/v1/orgs/{code}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get squid usage metrics */ - get: operations["usage"]; - put?: never; + get?: never; + /** Edit an organization */ + put: operations["OrganizationController_edit"]; post?: never; - delete?: never; + /** Delete an organization */ + delete: operations["OrganizationController_deleteOne"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{code}/squids/metrics/usage/{id}": { + "/v1/orgs/{code}/send-verify-email": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get squid usage metrics */ - get: operations["usage"]; + get?: never; put?: never; - post?: never; + /** Send verification email */ + post: operations["OrganizationController_sendEmailVerification"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/squids/{squidName}/versions/{versionName}/logs/history": { + "/v1/orgs/verify-email": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get squid logs history */ - get: operations["fetch-logs-history"]; + /** Verify organization email by token */ + get: operations["OrganizationController_verifyEmail"]; put?: never; post?: never; delete?: never; @@ -532,24 +365,25 @@ export interface paths { patch?: never; trace?: never; }; - "/orgs/{code}/squids/{squidName}/versions/{versionName}/logs/follow": { + "/v1/orgs/{code}/roles": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Follow the squid logs */ - get: operations["tail-logs"]; + /** Get user roles */ + get: operations["OrganizationController_getOne"]; put?: never; - post?: never; + /** Add user role */ + post: operations["OrganizationController_addUser"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/squids/{squid}/versions/{version}/prod": { + "/v1/orgs/{code}/roles/{id}": { parameters: { query?: never; header?: never; @@ -557,16 +391,17 @@ export interface paths { cookie?: never; }; get?: never; - /** Set alias to a squid */ - put: operations["squid"]; + /** Edit user role */ + put: operations["OrganizationController_editUser"]; post?: never; - delete?: never; + /** Remove user role */ + delete: operations["OrganizationController_deleteUser"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/deploys/upload-url": { + "/v1/orgs/{code}/roles/{id}/accept": { parameters: { query?: never; header?: never; @@ -575,15 +410,15 @@ export interface paths { }; get?: never; put?: never; - /** Get an upload url */ - post: operations["upload-url"]; + /** Accept user role */ + post: operations["OrganizationController_acceptUserRole"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{code}/deploys/upload-url": { + "/v1/orgs/{code}/roles/{id}/reject": { parameters: { query?: never; header?: never; @@ -592,41 +427,43 @@ export interface paths { }; get?: never; put?: never; - /** Get an upload url */ - post: operations["upload-url"]; + /** Reject user role */ + post: operations["OrganizationController_declineUserRole"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/deploys": { + "/v1/orgs/{code}/integrations/neon": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get version deploys */ - get: operations["get-all"]; - put?: never; + get?: never; + /** Setup Neon API integration */ + put: operations["OrganizationController_setNeonApiToken"]; post?: never; - delete?: never; + /** Delete Neon integration */ + delete: operations["OrganizationController_deleteNeonApiToken"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/orgs/{code}/deploys/{id}": { + "/v1/orgs/{code}/billing/settings": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Retrieve a deploy */ - get: operations["get-one"]; - put?: never; + /** Get billing settings */ + get: operations["OrganizationBillingController_getSettings"]; + /** Update billing settings */ + put: operations["OrganizationBillingController_setupIntent"]; post?: never; delete?: never; options?: never; @@ -634,15 +471,15 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/orgs/{code}/deploys": { + "/v1/orgs/{code}/billing/receipts/{year}/{month}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get version deploys */ - get: operations["get-all"]; + /** Get billing month usage total */ + get: operations["OrganizationBillingController_getMonthly"]; put?: never; post?: never; delete?: never; @@ -651,16 +488,17 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/orgs/{code}/deploys/{id}": { + "/v1/orgs/{code}/secrets": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Retrieve a deploy */ - get: operations["get-one"]; - put?: never; + /** List secrets */ + get: operations["SecretController_listSecrets"]; + /** Update secrets */ + put: operations["SecretController_put"]; post?: never; delete?: never; options?: never; @@ -668,49 +506,50 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids/deploy": { + "/v1/orgs/{code}/rpc/chains": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + /** List chains */ + get: operations["RpcController_listChains"]; put?: never; - /** Deploy a squid to organization */ - post: operations["deploy-squid"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids": { + "/v1/orgs/{code}/rpc/token": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** List organization squids */ - get: operations["list-squids"]; + /** Get organization token */ + get: operations["RpcController_getToken"]; put?: never; - post?: never; + /** Refresh organization token */ + post: operations["RpcController_refreshToken"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids/{squid}": { + "/v1/orgs/{code}/quotas": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** List organization squids */ - get: operations["list-squids"]; + /** Get quotas */ + get: operations["QuotaController_get"]; put?: never; post?: never; delete?: never; @@ -719,6180 +558,517 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids/{squid}/slots/{slot}": { + "/v1/orgs/{code}/monitoring/squids/{query}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get a squid deployment */ - get: operations["get-squid"]; + /** Get squids metric */ + get: operations["MonitoringController_squids"]; put?: never; post?: never; - /** Delete a squid deployment */ - delete: operations["delete-squid"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{org}/squids/{squid}/slots/{slot}/restart": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Restart a squid */ - post: operations["restart-squid"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids/{squid}/slots/{slot}/hibernate": { + "/v1/orgs/{code}/monitoring/squids": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + /** Scrape metrics */ + get: operations["MonitoringController_squidsAllProm"]; put?: never; - /** Hibernate a squid deployment */ - post: operations["hibernate-squid"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids/{squid}/slots/{slot}/tag": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; +} +export type webhooks = Record; +export interface components { + schemas: { + UnauthorizedResponse: { + /** @example CREDENTIALS_INVALID */ + error: string; }; - get?: never; - put?: never; - /** Set tag to a squid deployment */ - post: operations["tag-squid"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/squids/{squid}/slots/{slot}/logs/history": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get squid logs history */ - get: operations["fetch-logs-history"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/squids/{squid}/slots/{slot}/logs/history": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + IngressRequestsMetric: { + /** Format: date-time */ + time: string; + squidId: number; + /** @enum {string} */ + res: IngressRequestsMetricRes; }; - /** Get squid logs history */ - get: operations["fetch-logs-history"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/squids/{squid}/slots/{slot}/logs/follow": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + IngressSquidLatency: { + p50: number; + p90: number; + p95: number; + p99: number; }; - /** Follow the squid logs */ - get: operations["tail-logs"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/squids/{squid}/slots/{slot}/logs/follow": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + IngressSquidRequestsStat: { + count: string; + bytesSend: string; + latency: components["schemas"]["IngressSquidLatency"]; }; - /** Follow the squid logs */ - get: operations["tail-logs"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + IngressSquidRequestsMetricValue: { + /** Format: date-time */ + ts: string; + success: components["schemas"]["IngressSquidRequestsStat"]; + error: components["schemas"]["IngressSquidRequestsStat"]; }; - /** Retrieve a user */ - get: operations["get-profile"]; - /** Update a user */ - put: operations["update-profile"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + IngressSquidRequestsMetric: { + /** @enum {string} */ + timeGroup: IngressSquidRequestsMetricTimeGroup; + metrics: components["schemas"]["IngressSquidRequestsMetricValue"][]; }; - /** Retrieve a user */ - get: operations["get-profile"]; - /** Update a user */ - put: operations["update-profile"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/onboarding": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidUsageMetricValue: { + /** Format: date-time */ + ts: string; + apiCpuUsage: number; + apiCpuRequested: number; + apiMemUsageMb: number; + apiMemRequestedMb: number; + processorCpuUsage: number; + processorCpuRequested: number; + processorMemUsageMb: number; + processorMemRequestedMb: number; + dbCpuUsage: number; + dbCpuRequested: number; + dbDiskUsageMb: number; + dbDiskRequestedMb: number; }; - get?: never; - /** Apply user onboarding */ - put: operations["on-boarding-form"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/onboarding": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidUsageMetric: { + /** @enum {string} */ + timeGroup: SquidUsageMetricTimeGroup; + metrics: components["schemas"]["SquidUsageMetricValue"][]; }; - get?: never; - /** Apply user onboarding */ - put: operations["on-boarding-form"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/password/change": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + UploadUrlResponse: { + uploadUrl: string; + uploadFields: Record; + fileUrl: string; + maxUploadBytes: number; }; - get?: never; - put?: never; - /** Change password */ - post: operations["change-password"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/password/change": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + DeployLog: { + severity: string; + message: string; }; - get?: never; - put?: never; - /** Change password */ - post: operations["change-password"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/coinlist/email/confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + DeploymentOrganizationResponse: { + /** @example 550e8400-e29b-41d4-a716-446655440000 */ + id: string; + /** @example Subsquid GmbH */ + name: string; + /** @example subsquid-org */ + code: string; }; - get?: never; - put?: never; - /** Resend Coinlist email confirmation */ - post: operations["resend-coinlist-email-confirm"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/coinlist/email/confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + DeployUserResponse: { + /** @example 90046784-ef9a-42b4-9dcf-ca4e4ed2cf4a */ + id: string; + /** @example user@gmail.com */ + email: string; + /** @example John Doe */ + fullName: string; }; - get?: never; - put?: never; - /** Resend Coinlist email confirmation */ - post: operations["resend-coinlist-email-confirm"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/email/confirm/resend": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + DeploymentSquidResponse: { + /** @example 1 */ + id: number; + /** @example my-squid */ + name: string; + /** @example abc12 */ + hash: string; + /** @example my-squid:abc12 */ + reference: string; }; - get?: never; - put?: never; - /** Resend email confirmation */ - post: operations["resend-email-confirm"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/email/confirm/resend": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + DeploymentOptionsResponse: { + /** @example dev */ + tag: string; + /** @example false */ + hardReset: boolean; }; - get?: never; - put?: never; - /** Resend email confirmation */ - post: operations["resend-email-confirm"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/sqd-key": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Refresh sqd access key */ - post: operations["key"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/sqd-key": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + DeploymentResponse: { + id: number; + /** @enum {string} */ + type: DeploymentResponseType; + /** @enum {string} */ + status: DeploymentResponseStatus; + /** @enum {string} */ + failed: DeploymentResponseFailed; + logs: components["schemas"]["DeployLog"][]; + organization: components["schemas"]["DeploymentOrganizationResponse"]; + user: components["schemas"]["DeployUserResponse"] | null; + squid: components["schemas"]["DeploymentSquidResponse"] | null; + options: components["schemas"]["DeploymentOptionsResponse"]; + /** + * @description Total elapsed time in milliseconds + * @example 50379 + */ + totalElapsedTimeMs: number; + /** Format: date-time */ + updatedAt: string; + /** Format: date-time */ + createdAt: string; }; - get?: never; - put?: never; - /** Refresh sqd access key */ - post: operations["key"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/invites": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidTagResponse: { + /** @example prod */ + name: string; }; - /** Retrieve all invites */ - get: operations["get-invites"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/invites": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + Manifest: Record; + SquidManifestResponse: { + /** @description The actual squid manifest */ + current: components["schemas"]["Manifest"]; + /** @description The unmodified squid manifest */ + raw: string; }; - /** Retrieve all invites */ - get: operations["get-invites"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/squids": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidUrlResponse: { + /** @example tag */ + type: string; + /** @example prod */ + name?: string; + /** @example https://squid.subsquid.io/mysquid/-/a1b2c3/ */ + url: string; }; - /** Get list of squids from all users organizations */ - get: operations["get-squids-v-0"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/squids": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidApiResponse: { + /** @enum {string} */ + status: SquidApiResponseStatus; + urls: components["schemas"]["SquidUrlResponse"][]; }; - /** Get list of squids from all users organizations */ - get: operations["get-squids-v-1"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidSyncStatusResponse: { + /** @example 1 */ + totalBlocks: number; + /** @example 1 */ + currentBlock: number; }; - /** Get list of user tokens */ - get: operations["get-tokens"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidProcessorResponse: { + /** @example processor */ + name: string; + /** @enum {string} */ + status: SquidProcessorResponseStatus; + syncState: components["schemas"]["SquidSyncStatusResponse"]; + metrics: string; }; - /** Get list of user tokens */ - get: operations["get-tokens"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/api-tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidAddonsHasuraResponse: { + replicas: number; + profile: string; + /** @enum {string} */ + status: SquidAddonsHasuraResponseStatus; + urls: components["schemas"]["SquidUrlResponse"][]; }; - /** Get tokens list */ - get: operations["get-tokens"]; - put?: never; - /** Create new token */ - post: operations["create-token"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/api-tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + PostgresConnectionParams: { + /** @example pg.sqd.dev */ + host: string; + /** @example owner */ + user: string; + /** @example dbname */ + database: string; + /** @example random_password */ + password: string; }; - /** Get tokens list */ - get: operations["get-tokens"]; - put?: never; - /** Create new token */ - post: operations["create-token"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/user/api-tokens/{id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + PostgresConnection: { + /** @example postgresql://user:password@host/db?sslmode=require */ + uri: string; + params: components["schemas"]["PostgresConnectionParams"]; }; - get?: never; - put?: never; - post?: never; - /** Delete token */ - delete: operations["deactivate-token"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/user/api-tokens/{id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidDiskResponse: { + /** @enum {string} */ + usageStatus: SquidDiskResponseUsageStatus; + usedBytes: number; + totalBytes: number; }; - get?: never; - put?: never; - post?: never; - /** Delete token */ - delete: operations["deactivate-token"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidAddonsPostgresResponse: { + connections: components["schemas"]["PostgresConnection"][]; + disk: components["schemas"]["SquidDiskResponse"]; }; - /** List all organizations */ - get: operations["list-organizations"]; - put?: never; - /** Create new organization */ - post: operations["create"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidAddonsNeonResponse: { + connections: components["schemas"]["PostgresConnection"][]; }; - /** List all organizations */ - get: operations["list-organizations"]; - put?: never; - /** Create new organization */ - post: operations["create"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + SquidAddonsResponse: { + hasura?: components["schemas"]["SquidAddonsHasuraResponse"]; + postgres?: components["schemas"]["SquidAddonsPostgresResponse"]; + neon?: components["schemas"]["SquidAddonsNeonResponse"]; }; - /** List all organizations */ - get: operations["list-organizations"]; - put?: never; - /** Create new organization */ - post: operations["create"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List all organizations */ - get: operations["list-organizations"]; - put?: never; - /** Create new organization */ - post: operations["create"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{org}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get an organizations */ - get: operations["get-organization"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{org}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get an organizations */ - get: operations["get-organization"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{org}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get an organizations */ - get: operations["get-organization"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{org}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get an organizations */ - get: operations["get-organization"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{code}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit an organization */ - put: operations["edit"]; - post?: never; - /** Delete an organization */ - delete: operations["delete-one"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit an organization */ - put: operations["edit"]; - post?: never; - /** Delete an organization */ - delete: operations["delete-one"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{code}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit an organization */ - put: operations["edit"]; - post?: never; - /** Delete an organization */ - delete: operations["delete-one"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit an organization */ - put: operations["edit"]; - post?: never; - /** Delete an organization */ - delete: operations["delete-one"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{code}/send-verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Send verification email */ - post: operations["send-email-verification"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/send-verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Send verification email */ - post: operations["send-email-verification"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{code}/send-verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Send verification email */ - post: operations["send-email-verification"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/send-verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Send verification email */ - post: operations["send-email-verification"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Verify organization email by token */ - get: operations["verify-email"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Verify organization email by token */ - get: operations["verify-email"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Verify organization email by token */ - get: operations["verify-email"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/verify-email": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Verify organization email by token */ - get: operations["verify-email"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{code}/roles": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get user roles */ - get: operations["get-one"]; - put?: never; - /** Add user role */ - post: operations["add-user"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/roles": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get user roles */ - get: operations["get-one"]; - put?: never; - /** Add user role */ - post: operations["add-user"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{code}/roles": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get user roles */ - get: operations["get-one"]; - put?: never; - /** Add user role */ - post: operations["add-user"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/roles": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get user roles */ - get: operations["get-one"]; - put?: never; - /** Add user role */ - post: operations["add-user"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{code}/roles/{id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit user role */ - put: operations["edit-user"]; - post?: never; - /** Remove user role */ - delete: operations["delete-user"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/roles/{id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit user role */ - put: operations["edit-user"]; - post?: never; - /** Remove user role */ - delete: operations["delete-user"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{code}/roles/{id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit user role */ - put: operations["edit-user"]; - post?: never; - /** Remove user role */ - delete: operations["delete-user"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/roles/{id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** Edit user role */ - put: operations["edit-user"]; - post?: never; - /** Remove user role */ - delete: operations["delete-user"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{code}/roles/{id}/accept": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Accept user role */ - post: operations["accept-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/roles/{id}/accept": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Accept user role */ - post: operations["accept-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{code}/roles/{id}/accept": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Accept user role */ - post: operations["accept-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/roles/{id}/accept": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Accept user role */ - post: operations["accept-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/organizations/{code}/roles/{id}/reject": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Reject user role */ - post: operations["decline-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/roles/{id}/reject": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Reject user role */ - post: operations["decline-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/organizations/{code}/roles/{id}/reject": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Reject user role */ - post: operations["decline-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/roles/{id}/reject": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Reject user role */ - post: operations["decline-user-role"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/billing/settings": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get billing settings */ - get: operations["get-settings"]; - /** Update billing settings */ - put: operations["setup-intent"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/billing/settings": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get billing settings */ - get: operations["get-settings"]; - /** Update billing settings */ - put: operations["setup-intent"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/billing/receipts/{year}/{month}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get billing month usage total */ - get: operations["get-monthly"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/billing/receipts/{year}/{month}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get billing month usage total */ - get: operations["get-monthly"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/secrets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List secrets */ - get: operations["list-secrets"]; - /** Update secrets */ - put: operations["put"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/secrets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List secrets */ - get: operations["list-secrets"]; - /** Update secrets */ - put: operations["put"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/rpc/{code}/chains": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List chains */ - get: operations["list-chains"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/rpc/{code}/chains": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List chains */ - get: operations["list-chains"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/rpc/{code}/token": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get organization token */ - get: operations["get-token"]; - put?: never; - /** Refresh organization token */ - post: operations["refresh-token"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/rpc/{code}/token": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get organization token */ - get: operations["get-token"]; - put?: never; - /** Refresh organization token */ - post: operations["refresh-token"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/quotas/{code}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get quotas */ - get: operations["get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/quotas/{code}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get quotas */ - get: operations["get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/monitoring/squids/{query}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get squids metric */ - get: operations["squids"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/monitoring/squids/{query}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get squids metric */ - get: operations["squids"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/orgs/{code}/monitoring/squids": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Scrape metrics */ - get: operations["squids-all-prom"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/orgs/{code}/monitoring/squids": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Scrape metrics */ - get: operations["squids-all-prom"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; -} -export type webhooks = Record; -export interface components { - schemas: { - AuthResponse: { - /** @example */ - token: string; - }; - ResetPasswordResponse: { - /** @example true */ - success: boolean; - }; - UnauthorizedResponse: { - /** @example CREDENTIALS_INVALID */ - error: string; - }; - DeployLog: { - severity: string; - message: string; - }; - DeployUserResponse: { - /** @example 90046784-ef9a-42b4-9dcf-ca4e4ed2cf4a */ - id: string; - /** @example user@gmail.com */ - email: string; - /** @example John Doe */ - fullName: string; - }; - DeployResponseV0: { - id: number; - /** @enum {string} */ - type: DeployResponseV0Type; - /** @enum {string} */ - status: DeployResponseV0Status; - /** @enum {string} */ - failed: DeployResponseV0Failed; - logs: components["schemas"]["DeployLog"][]; - squidName: string; - versionName: string; - orgCode: string; - deploymentUrl: string; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - createdAt: string; - user: components["schemas"]["DeployUserResponse"]; - }; - SquidOrganizationResponseV0: { - /** @example 550e8400-e29b-41d4-a716-446655440000 */ - id: string; - /** @example Subsquid GmbH */ - name: string; - /** @example subsquid-org */ - code: string; - }; - SquidApiResponseV0: { - /** @example https://squid.subsquid.io/mysquid/graphql */ - url: string; - /** @enum {string} */ - status: SquidApiResponseV0Status; - }; - SquidSyncStatusResponse: { - /** @example 1 */ - totalBlocks: number; - /** @example 1 */ - currentBlock: number; - }; - SquidProcessorResponseV0: { - /** @example processor */ - name: string; - /** @enum {string} */ - status: SquidProcessorResponseV0Status; - syncState: components["schemas"]["SquidSyncStatusResponse"]; - }; - SquidDBResponseV0: Record; - SquidAddonsHasuraResponseV0: { - replicas: number; - profile: string; - }; - SquidDiskResponseV0: { - /** @enum {string} */ - usageStatus: SquidDiskResponseV0UsageStatus; - usedBytes: number; - totalBytes: number; - }; - SquidAddonsPostgresResponseV0: { - connections: string[]; - disk: components["schemas"]["SquidDiskResponseV0"]; - }; - SquidAddonsNeonResponseV0: { - connections: string[]; - }; - SquidAddonsResponseV0: { - hasura?: components["schemas"]["SquidAddonsHasuraResponseV0"]; - postgres?: components["schemas"]["SquidAddonsPostgresResponseV0"]; - neon?: components["schemas"]["SquidAddonsNeonResponseV0"]; - }; - SquidLastDeployV0: { - /** @example 123 */ - id: number; - /** - * @example DEPLOY - * @enum {string} - */ - type: SquidLastDeployV0Type; - /** - * @example UNPACKING - * @enum {string} - */ - status: SquidLastDeployV0Status; - /** - * @example NO - * @enum {string} - */ - failed: SquidLastDeployV0Failed; - /** @example true */ - running: boolean; - }; - SquidRunningDeployV0: { - /** @example 123 */ - id: number; - /** - * @example DELETE - * @enum {string} - */ - type: SquidRunningDeployV0Type; - }; - VersionResponseV0: { - id: number; - name: string; - version: string; - description?: Record; - tags: string[]; - imageUrl?: string; - aliases: string[]; - urls: string[]; - /** @description The unmodified squid manifest */ - manifestYaml?: Record; - /** @description The package.json found in source code */ - packageJson: Record; - /** @example { - * "default for v1": "query { ... }", - * "another query label": "query { ... }" - * } */ - queries: Record; - artifactUrl: string; - api: components["schemas"]["SquidApiResponseV0"]; - processors: components["schemas"]["SquidProcessorResponseV0"][]; - db?: components["schemas"]["SquidDBResponseV0"]; - addons?: components["schemas"]["SquidAddonsResponseV0"]; - spec: string; - /** Format: date-time */ - createdAt: string; - lastDeploy?: components["schemas"]["SquidLastDeployV0"] | null; - /** @enum {string|null} */ - status?: VersionResponseV0Status; - /** - * @deprecated - * @description Use `lastDeploy` fields instead. - */ - runningDeploy?: components["schemas"]["SquidRunningDeployV0"] | null; - /** - * @deprecated - * @description Use `status` fields instead. - */ - deploy: Record; - deployCount: number; - deployedAt?: Record; - hibernatedAt?: Record; - /** @deprecated */ - manifest?: Record; - /** @deprecated */ - deploymentUrl?: string; - }; - SquidResponseV0: { - /** @example 1 */ - id: number; - /** @example my-squid */ - name: string; - organization: components["schemas"]["SquidOrganizationResponseV0"]; - versions: components["schemas"]["VersionResponseV0"][]; - }; - IngressRequestsMetric: { - /** Format: date-time */ - time: string; - squidId: number; - /** @enum {string} */ - res: IngressRequestsMetricRes; - }; - IngressSquidLatency: { - p50: number; - p90: number; - p95: number; - p99: number; - }; - IngressSquidRequestsStat: { - count: string; - bytesSend: string; - latency: components["schemas"]["IngressSquidLatency"]; - }; - IngressSquidRequestsMetricValue: { - /** Format: date-time */ - ts: string; - success: components["schemas"]["IngressSquidRequestsStat"]; - error: components["schemas"]["IngressSquidRequestsStat"]; - }; - IngressSquidRequestsMetric: { - /** @enum {string} */ - timeGroup: IngressSquidRequestsMetricTimeGroup; - metrics: components["schemas"]["IngressSquidRequestsMetricValue"][]; - }; - SquidUsageMetricValue: { - /** Format: date-time */ - ts: string; - apiCpuUsage: number; - apiCpuRequested: number; - apiMemUsageMb: number; - apiMemRequestedMb: number; - processorCpuUsage: number; - processorCpuRequested: number; - processorMemUsageMb: number; - processorMemRequestedMb: number; - dbCpuUsage: number; - dbCpuRequested: number; - dbDiskUsageMb: number; - dbDiskRequestedMb: number; - }; - SquidUsageMetric: { - /** @enum {string} */ - timeGroup: SquidUsageMetricTimeGroup; - metrics: components["schemas"]["SquidUsageMetricValue"][]; - }; - SquidHistoryLogsResponse: { - logs: string[]; - nextPage: Record; - }; - UploadUrlResponse: { - uploadUrl: string; - uploadFields: Record; - fileUrl: string; - maxUploadBytes: number; - }; - DeployOrganizationResponse: { - /** @example 550e8400-e29b-41d4-a716-446655440000 */ - id: string; - /** @example Subsquid GmbH */ - name: string; - /** @example subsquid-org */ - code: string; - }; - DeploySquidResponse: { - /** @example 1 */ - id: number; - /** @example my-squid */ - name: string; - /** @example abc12 */ - slot: string; - }; - DeployResponse: { - id: number; - /** @enum {string} */ - type: DeployResponseType; - /** @enum {string} */ - status: DeployResponseStatus; - /** @enum {string} */ - failed: DeployResponseFailed; - logs: components["schemas"]["DeployLog"][]; - organization: components["schemas"]["DeployOrganizationResponse"]; - deploymentUrl: string; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - createdAt: string; - user: components["schemas"]["DeployUserResponse"] | null; - squid: components["schemas"]["DeploySquidResponse"] | null; - }; - SquidTagResponse: { - name: string; - }; - SquidUrlResponse: { - /** @example api */ - component: string; - /** @example canonical */ - type: string; - /** @example https://squid.subsquid.io/mysquid/graphql */ - url: string; - }; - SquidApiResponse: { - /** @example https://squid.subsquid.io/mysquid/graphql */ - url: string; - /** @enum {string} */ - status: SquidApiResponseStatus; - }; - SquidProcessorResponse: { - /** @example processor */ - name: string; - /** @enum {string} */ - status: SquidProcessorResponseStatus; - syncState: components["schemas"]["SquidSyncStatusResponse"]; - }; - SquidAddonsHasuraResponse: { - replicas: number; - profile: string; - }; - PostgresConnectionParams: { - /** @example pg.sqd.dev */ - host: string; - /** @example owner */ - user: string; - /** @example dbname */ - database: string; - /** @example random_password */ - password: string; - }; - PostgresConnection: { - /** @example postgresql://user:password@host/db?sslmode=require */ - uri: string; - params: components["schemas"]["PostgresConnectionParams"]; - }; - SquidDiskResponse: { - /** @enum {string} */ - usageStatus: SquidDiskResponseUsageStatus; - usedBytes: number; - totalBytes: number; - }; - SquidAddonsPostgresResponse: { - connections: components["schemas"]["PostgresConnection"][]; - disk: components["schemas"]["SquidDiskResponse"]; - }; - SquidAddonsNeonResponse: { - connections: components["schemas"]["PostgresConnection"][]; - }; - SquidAddonsResponse: { - hasura?: components["schemas"]["SquidAddonsHasuraResponse"]; - postgres?: components["schemas"]["SquidAddonsPostgresResponse"]; - neon?: components["schemas"]["SquidAddonsNeonResponse"]; - }; - SquidLastDeploy: { - /** @example 123 */ - id: number; - /** - * @example DEPLOY - * @enum {string} - */ - type: SquidLastDeployType; - /** - * @example UNPACKING - * @enum {string} - */ - status: SquidLastDeployStatus; - /** - * @example NO - * @enum {string} - */ - failed: SquidLastDeployFailed; - /** @example true */ - running: boolean; - }; - SquidOrganizationResponse: { - /** @example 550e8400-e29b-41d4-a716-446655440000 */ - id: string; - /** @example Subsquid GmbH */ - name: string; - /** @example subsquid-org */ - code: string; - }; - SquidResponse: { - id: number; - name: string; - slot: string; - description?: Record; - imageUrl?: string; - tags: components["schemas"]["SquidTagResponse"][]; - urls: components["schemas"]["SquidUrlResponse"][]; - /** @description The unmodified squid manifest */ - manifestYaml?: Record; - /** @description The package.json found in source code */ - packageJson: Record; - artifactUrl: string; - api?: components["schemas"]["SquidApiResponse"]; - processors?: components["schemas"]["SquidProcessorResponse"][]; - addons?: components["schemas"]["SquidAddonsResponse"]; - spec: string; - /** Format: date-time */ - createdAt: string; - lastDeploy?: components["schemas"]["SquidLastDeploy"]; - /** @enum {string} */ - status?: SquidResponseStatus; - deployCount: number; - /** Format: date-time */ - deployedAt?: string; - /** Format: date-time */ - hibernatedAt?: string; - organization: components["schemas"]["SquidOrganizationResponse"]; - }; - EmailResponse: { - /** @example user@gmail.com */ - current: string; - /** @example user_new@gmail.com */ - pendingVerification: string; - }; - UserResponse: { - /** @example 90046784-ef9a-42b4-9dcf-ca4e4ed2cf4a */ - id: string; - /** @example user@gmail.com */ - email: string; - /** @example user@gmail.com */ - coinlistEmail: components["schemas"]["EmailResponse"]; - /** @example John Doe */ - fullName: string; - /** @example user */ - username: string; - /** @example https://gravatar.com/1.jpg */ - avatarUrl: string; - /** @example { - * "occupation": "Backend developer", - * "source": "Twitter", - * "customSource": "", - * "usage": "DeFi", - * "customUsage": "" - * } */ - onboardingForm: Record; - /** @example true */ - policyAccepted: boolean; - /** @example false */ - onboardingFormCompleted: boolean; - /** @example false */ - emailVerified: boolean; - organizations?: string[]; - /** @example false */ - wallet: Record; - /** @example false */ - social: Record; - }; - KeyResponse: { - key: string; - }; - UserInviteProjectResponse: { - /** @example new-project */ - code: string; - /** @example New project */ - name: string; - }; - UserInviteResponse: { - /** @example 90046784-ef9a-42b4-9dcf-ca4e4ed2cf4a */ - id: string; - /** @example admin@subsquid.io */ - invitedBy: string; - organization: components["schemas"]["UserInviteProjectResponse"]; - }; - UserTokenResponse: { - /** @example my-token */ - name: string; - }; - ApiTokenResponse: { - /** @example 50e8400-e29b-41d4-a716-446655440000 */ - id: string; - /** @example my-token */ - name: string; - /** - * Format: date-time - * @example 2024-01-01T11:00:00.000Z - */ - createdAt: string; - /** @example 2039-12-31T11:00:00.000Z */ - expiresAt: Record; - }; - NotificationEmailResponse: { - /** @example current@example.com */ - email: string; - /** @example new@example.com */ - pendingEmail: string; - }; - OrganizationLimitsResponse: { - /** @example 3 */ - squids: number; - /** @example false */ - playground: boolean; - }; - OrganizationBillingsDetails: { - /** @example John Doe */ - name: string; - /** @example Subsquid */ - company: string; - /** @example billing@subsquid.io */ - email: string; - /** @example Mythenquai 2 */ - addressLine1: string; - /** @example Zurich */ - city: string; - /** @example 10004 */ - zipCode: string; - }; - OrganizationResponse: { - /** @example org_DI4wZx0FAJa93tq3iNr1wc7H */ - id: string; - /** @example organization_unique_code */ - code: string; - /** @example My first organization */ - name: string; - email: components["schemas"]["NotificationEmailResponse"]; - /** @example admin */ - roleType: string; - /** - * @example ACTIVE - * @enum {string} - */ - status: OrganizationResponseStatus; - limits: components["schemas"]["OrganizationLimitsResponse"]; - billingDetails: components["schemas"]["OrganizationBillingsDetails"]; - }; - OrganizationRoleResponse: { - /** @example 88a02891-c461-4c1b-b705-13c8e6fdf7c0 */ - id: string; - /** @example test@gmail.com */ - email: string; - /** @example John Doe */ - fullName: string; - /** @example admin */ - type: string; - /** - * @example accepted - * @enum {string} - */ - status: OrganizationRoleResponseStatus; - }; - SecretsResponse: { - /** @example { - * "MY_SECRET": "VALUE" - * } */ - secrets: Record; - }; - ChainResponse: { - /** @example eth */ - id: string; - /** @example Ethereum */ - title: string; - /** @example https://cdn.subsquid.io/images/eth.svg */ - iconUrl: string; - /** @enum {string} */ - type: ChainResponseType; - /** @example 100000000 */ - requests: string; - /** @example false */ - testnet: boolean; - /** @example https://rpc.subsquid.io/eth/{{TOKEN}} */ - url: string; - }; - TokenResponse: { - /** @example sqd_prod_g9FsTC9NXkIPLsIJPZq0 */ - token: string; - }; - QuotaResponse: { - /** @enum {string} */ - id: QuotaResponseId; - /** @example 1.00 */ - usage: string; - /** @example 100.00 */ - capacity: string; - }; - MetricLabelResponse: { - container: string; - squid_id: string; - squid_name: string; - }; - MetricResponse: { - labels: components["schemas"]["MetricLabelResponse"]; - values: string[]; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} -export type $defs = Record; -export interface operations { - signin: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - email: string; - password: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - signin: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - email: string; - password: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - signup: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - fullName: string; - email: string; - password: string; - subscribeToNewsletter?: boolean; - turnstileToken: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - signup: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - fullName: string; - email: string; - password: string; - subscribeToNewsletter?: boolean; - turnstileToken: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - restore: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - email: string; - }; - }; - }; - responses: { - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - restore: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - email: string; - }; - }; - }; - responses: { - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - "restore-confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - token: string; - password: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ResetPasswordResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - "restore-confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - token: string; - password: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ResetPasswordResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - "confirm-email": { - parameters: { - query: { - code: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - "confirm-email": { - parameters: { - query: { - code: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - github: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - github: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - "github-auth": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - "github-auth": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - google: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - google: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - "google-auth": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - "google-auth": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["AuthResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - }; - }; - "deploy-squid": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - hardReset?: boolean; - artifactUrl: string; - /** @default squid.yaml */ - manifestPath?: string; - updateSlot?: string; - tag?: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponseV0"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-squids": { - parameters: { - query?: { - search?: string; - organization?: string; - }; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponseV0"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-squid": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - squid: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponseV0"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "delete-squid": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - squid: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponseV0"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "destroy-squid-version": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - squid: string; - version: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponseV0"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "restart-squid-version": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - squid: string; - version: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponseV0"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "hibernate-squid": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - squid: string; - version: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponseV0"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "daily-requests": { - parameters: { - query: { - organization?: string; - from: string; - to: string; - }; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["IngressRequestsMetric"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "daily-requests": { - parameters: { - query: { - organization?: string; - from: string; - to: string; - }; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["IngressRequestsMetric"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "ingress-stats": { - parameters: { - query: { - organization?: string; - from: string; - to: string; - }; - header?: never; - path: { - code: string; - id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["IngressSquidRequestsMetric"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "ingress-stats": { - parameters: { - query: { - organization?: string; - from: string; - to: string; - }; - header?: never; - path: { - code: string; - id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["IngressSquidRequestsMetric"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - usage: { - parameters: { - query: { - organization?: string; - from: string; - to: string; - }; - header?: never; - path: { - code: string; - id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidUsageMetric"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - usage: { - parameters: { - query: { - organization?: string; - from: string; - to: string; - }; - header?: never; - path: { - code: string; - id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidUsageMetric"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "fetch-logs-history": { - parameters: { - query: { - level?: PathsOrgsCodeSquidsSquidNameVersionsVersionNameLogsHistoryGetParametersQueryLevel[]; - container?: string[]; - search?: string; - nextPage?: string; - from: string; - limit?: number; - }; - header?: never; - path: { - code: string; - squidName: string; - versionName: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["SquidHistoryLogsResponse"]; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "tail-logs": { - parameters: { - query?: { - level?: PathsOrgsCodeSquidsSquidNameVersionsVersionNameLogsFollowGetParametersQueryLevel[]; - container?: string[]; - search?: string; - }; - header?: never; - path: { - code: string; - squidName: string; - versionName: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - squid: { - parameters: { - query?: never; - header?: never; - path: { - code: string; - squid: string; - version: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - allowedOrigins?: string[]; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponseV0"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "upload-url": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UploadUrlResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "upload-url": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UploadUrlResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-all": { - parameters: { - query?: { - squidId?: number; - statusGroup?: PathsOrgsCodeDeploysGetParametersQueryStatusGroup; - }; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponseV0"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponseV0"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-all": { - parameters: { - query?: { - squidId?: number; - statusGroup?: PathsV1OrgsCodeDeploysGetParametersQueryStatusGroup; - }; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "deploy-squid": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - hardReset?: boolean; - artifactUrl: string; - /** @default squid.yaml */ - manifestPath?: string; - updateSlot?: string; - tag?: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-squids": { - parameters: { - query?: { - search?: string; - organization?: string; - }; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponse"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-squids": { - parameters: { - query?: { - search?: string; - organization?: string; - }; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponse"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-squid": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "delete-squid": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "restart-squid": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "hibernate-squid": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "tag-squid": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - tag: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["DeployResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "fetch-logs-history": { - parameters: { - query: { - level?: PathsOrgsCodeSquidsSquidSlotsSlotLogsHistoryGetParametersQueryLevel[]; - container?: string[]; - search?: string; - nextPage?: string; - from: string; - limit?: number; - }; - header?: never; - path: { - code: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidHistoryLogsResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "fetch-logs-history": { - parameters: { - query: { - level?: PathsV1OrgsCodeSquidsSquidSlotsSlotLogsHistoryGetParametersQueryLevel[]; - container?: string[]; - search?: string; - nextPage?: string; - from: string; - limit?: number; - }; - header?: never; - path: { - code: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidHistoryLogsResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "tail-logs": { - parameters: { - query?: { - level?: PathsOrgsCodeSquidsSquidSlotsSlotLogsFollowGetParametersQueryLevel[]; - container?: string[]; - search?: string; - }; - header?: never; - path: { - code: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "tail-logs": { - parameters: { - query?: { - level?: PathsV1OrgsCodeSquidsSquidSlotsSlotLogsFollowGetParametersQueryLevel[]; - container?: string[]; - search?: string; - }; - header?: never; - path: { - code: string; - squid: string; - slot: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-profile": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "update-profile": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - fullName: string; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-profile": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "update-profile": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - fullName: string; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "on-boarding-form": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - policyAccepted?: boolean; - subscribeNewsletter?: boolean; - onboardingForm?: { - occupation: string; - source: string; - usage: string; - }; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "on-boarding-form": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - policyAccepted?: boolean; - subscribeNewsletter?: boolean; - onboardingForm?: { - occupation: string; - source: string; - usage: string; - }; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "change-password": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - oldPassword: string; - newPassword: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "change-password": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - oldPassword: string; - newPassword: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "resend-coinlist-email-confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** Format: email */ - coinlistEmail: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "resend-coinlist-email-confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** Format: email */ - coinlistEmail: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "resend-email-confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "resend-email-confirm": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - key: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["KeyResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - key: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["KeyResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-invites": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserInviteResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-invites": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserInviteResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-squids-v-0": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponseV0"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-squids-v-1": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["SquidResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserTokenResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["UserTokenResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ApiTokenResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "create-token": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name: string; - /** Format: date-time */ - expiresAt?: string | null; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ApiTokenResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-tokens": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ApiTokenResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "create-token": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name: string; - /** Format: date-time */ - expiresAt?: string | null; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ApiTokenResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "deactivate-token": { - parameters: { - query?: never; - header?: never; - path: { - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ApiTokenResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "deactivate-token": { - parameters: { - query?: never; - header?: never; - path: { - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ApiTokenResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-organizations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - create: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-organizations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - create: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-organizations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - create: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "list-organizations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"][]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - create: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - code: string; - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-organization": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-organization": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-organization": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "get-organization": { - parameters: { - query?: never; - header?: never; - path: { - org: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - edit: { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "delete-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - }; - }; - edit: { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "delete-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - }; - }; - edit: { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name: string; - /** Format: email */ - email: string; - }; - }; - }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "delete-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; + SquidLastDeploy: { + /** @example 123 */ + id: number; + /** + * @example DEPLOY + * @enum {string} + */ + type: SquidLastDeployType; + /** + * @example UNPACKING + * @enum {string} + */ + status: SquidLastDeployStatus; + /** + * @example NO + * @enum {string} + */ + failed: SquidLastDeployFailed; + /** @example true */ + running: boolean; }; - }; - edit: { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; + SquidOrganizationResponse: { + /** @example 550e8400-e29b-41d4-a716-446655440000 */ + id: string; + /** @example Subsquid GmbH */ + name: string; + /** @example subsquid-org */ + code: string; }; - requestBody: { - content: { - "application/json": { - name: string; - /** Format: email */ - email: string; - }; - }; + SquidLinks: { + /** @description https://cloud.sqd.dev/squids/test/76zvzw */ + cloudUrl: string; + /** @description eu.gcr.io/bright-meridian-316511/test-13484-76zvzw:8ba4f6c0ad1eb097de435d5458c5365d447fe481 */ + dockerImageUrl: string; }; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; + SquidResponse: { + /** @example 123 */ + id: number; + /** @example my-squid */ + name: string; + /** @example my-squid:4fush9 */ + reference: string; + /** @example 4fush9 */ + hash: string; + description?: string | null; + tags: components["schemas"]["SquidTagResponse"][]; + manifest: components["schemas"]["SquidManifestResponse"]; + /** @description The package.json found in source code */ + packageJson: Record; + api?: components["schemas"]["SquidApiResponse"]; + processors?: components["schemas"]["SquidProcessorResponse"][]; + addons?: components["schemas"]["SquidAddonsResponse"]; + spec: number; + lastDeploy?: components["schemas"]["SquidLastDeploy"]; + /** @enum {string} */ + status?: SquidResponseStatus; + organization: components["schemas"]["SquidOrganizationResponse"]; + /** + * Format: date-time + * @example 2025-01-01T00:00:00.000Z + */ + hibernatedAt?: string; + /** + * Format: date-time + * @example 2025-01-01T00:00:00.000Z + */ + deployedAt?: string; + links: components["schemas"]["SquidLinks"]; + /** + * Format: date-time + * @example 2025-01-01T00:00:00.000Z + */ + createdAt: string; }; - }; - "delete-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; + SquidLogResponse: { + id: string | null; + /** Format: date-time */ + timestamp: string | null; + container: string; + level: string; + payload: Record; }; - requestBody?: never; - responses: { - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; - }; - }; + SquidHistoryLogsResponse: { + logs: components["schemas"]["SquidLogResponse"][]; + nextPage: string | null; }; - }; - "send-email-verification": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; + NotificationEmailResponse: { + /** @example current@example.com */ + email: string; + /** @example new@example.com */ + pendingEmail: string; }; - requestBody: { - content: { - "application/json": { - email: string; - }; - }; + OrganizationLimitsResponse: { + /** @example 3 */ + squids: number; + /** @example false */ + playground: boolean; }; - responses: { - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; + OrganizationBillingsDetails: { + /** @example John Doe */ + name: string; + /** @example Subsquid */ + company: string; + /** @example billing@subsquid.io */ + email: string; + /** @example Mythenquai 2 */ + addressLine1: string; + /** @example Zurich */ + city: string; + /** @example 10004 */ + zipCode: string; }; - }; - "send-email-verification": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; + OrganizationIntegrationsNeon: { + apiTokenMasked: string; }; - requestBody: { - content: { - "application/json": { - email: string; - }; - }; + OrganizationIntegrations: { + neon: components["schemas"]["OrganizationIntegrationsNeon"]; }; - responses: { - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; + OrganizationResponse: { + /** @example org_DI4wZx0FAJa93tq3iNr1wc7H */ + id: string; + /** @example organization_unique_code */ + code: string; + /** @example My first organization */ + name: string; + email: components["schemas"]["NotificationEmailResponse"]; + /** @example admin */ + roleType: string; + /** + * @example ACTIVE + * @enum {string} + */ + status: OrganizationResponseStatus; + limits: components["schemas"]["OrganizationLimitsResponse"]; + billingDetails: components["schemas"]["OrganizationBillingsDetails"]; + integrations: components["schemas"]["OrganizationIntegrations"]; }; - }; - "send-email-verification": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; + UserResponse: { + /** @example 90046784-ef9a-42b4-9dcf-ca4e4ed2cf4a */ + id: string; + /** @example user@gmail.com */ + email: string; + /** @example John Doe */ + fullName: string; + /** @example user */ + username: string; + /** @example https://gravatar.com/1.jpg */ + avatarUrl: string; + /** @example { + * "occupation": "Backend developer", + * "source": "Twitter", + * "customSource": "", + * "usage": "DeFi", + * "customUsage": "" + * } */ + onboardingForm: Record; + /** @example true */ + policyAccepted: boolean; + /** @example false */ + onboardingFormCompleted: boolean; + /** @example false */ + emailVerified: boolean; + organizations?: components["schemas"]["OrganizationResponse"][]; }; - requestBody: { - content: { - "application/json": { - email: string; - }; - }; + OrganizationRoleResponse: { + /** @example 88a02891-c461-4c1b-b705-13c8e6fdf7c0 */ + id: string; + /** @example test@gmail.com */ + email: string; + /** @example John Doe */ + fullName: string; + /** @example admin */ + type: string; + /** + * @example accepted + * @enum {string} + */ + status: OrganizationRoleResponseStatus; }; - responses: { - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; - }; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; + SecretsResponse: { + /** @example { + * "MY_SECRET": "VALUE" + * } */ + secrets: Record; + }; + ChainResponse: { + /** @example eth */ + id: string; + /** @example Ethereum */ + title: string; + /** @example https://cdn.subsquid.io/images/eth.svg */ + iconUrl: string; + /** @enum {string} */ + type: ChainResponseType; + /** @example 100000000 */ + requests: string; + /** @example false */ + testnet: boolean; + /** @example https://rpc.subsquid.io/eth/{{TOKEN}} */ + url: string; + }; + TokenResponse: { + /** @example sqd_prod_g9FsTC9NXkIPLsIJPZq0 */ + token: string; + }; + QuotaResponse: { + /** @enum {string} */ + id: QuotaResponseId; + /** @example 1.00 */ + usage: string; + /** @example 100.00 */ + capacity: string; + }; + MetricLabelResponse: { + container: string; + squid_id: string; + squid_name: string; + }; + MetricResponse: { + labels: components["schemas"]["MetricLabelResponse"]; + values: string[]; }; }; - "send-email-verification": { + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + SquidMetricsController_dailyRequests: { parameters: { - query?: never; + query: { + organization?: string; + from: string; + to: string; + }; header?: never; path: { code: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": { - email: string; + requestBody?: never; + responses: { + /** @description Successful response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["IngressRequestsMetric"][]; + }; }; }; - }; - responses: { + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -6903,127 +1079,80 @@ export interface operations { }; }; }; - "verify-email": { + SquidMetricsController_ingressStats: { parameters: { query: { - code: string; + organization?: string; + from: string; + to: string; }; header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - "verify-email": { - parameters: { - query: { + path: { code: string; + squid_id: number; }; - header?: never; - path?: never; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; }; - content?: never; - }; - }; - }; - "verify-email": { - parameters: { - query: { - code: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["IngressSquidRequestsMetric"]; + }; }; - content?: never; - }; - }; - }; - "verify-email": { - parameters: { - query: { - code: string; }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; - content?: never; - }; - }; - }; - "get-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; + content: { + "application/json": { + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; + }; + }; }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"][]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "add-user": { + SquidMetricsController_usage: { parameters: { - query?: never; + query: { + organization?: string; + from: string; + to: string; + }; header?: never; path: { code: string; + id: number; }; cookie?: never; }; - requestBody: { - content: { - "application/json": { - email: string; - /** @enum {string} */ - roleType: PathsOrganizationsCodeRolesPostRequestBodyApplicationJsonRoleType; - }; - }; - }; + requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -7031,71 +1160,47 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["SquidUsageMetric"]; }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; - }; - }; - "get-one": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"][]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "add-user": { + DeploymentController_uploadUrl: { parameters: { query?: never; header?: never; - path: { - code: string; - }; + path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": { - email: string; - /** @enum {string} */ - roleType: PathsOrgsCodeRolesPostRequestBodyApplicationJsonRoleType; - }; - }; - }; + requestBody?: never; responses: { + /** @description Successful response */ 201: { headers: { [name: string]: unknown; @@ -7104,30 +1209,27 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["UploadUrlResponse"]; }; }; }; - 400: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "get-one": { + DeploymentController_getAll: { parameters: { - query?: never; + query?: { + squidId?: number; + statusGroup?: PathsV1OrgsCodeDeploymentsGetParametersQueryStatusGroup; + }; header?: never; path: { code: string; @@ -7136,6 +1238,7 @@ export interface operations { }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -7144,71 +1247,50 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"][]; + payload?: components["schemas"]["DeploymentResponse"][]; }; }; }; - }; - }; - "add-user": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - email: string; - /** @enum {string} */ - roleType: PathsV1OrganizationsCodeRolesPostRequestBodyApplicationJsonRoleType; - }; - }; - }; - responses: { - 201: { + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; - 400: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "get-one": { + DeploymentController_getOne: { parameters: { query?: never; header?: never; path: { code: string; + id: number; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -7217,31 +1299,48 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"][]; + payload?: components["schemas"]["DeploymentResponse"]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "add-user": { + SquidController_deploySquid: { parameters: { query?: never; header?: never; path: { - code: string; + org: string; }; cookie?: never; }; requestBody: { content: { "application/json": { - email: string; - /** @enum {string} */ - roleType: PathsV1OrgsCodeRolesPostRequestBodyApplicationJsonRoleType; + artifactUrl: string; + /** @default squid.yaml */ + manifestPath?: string; + /** @default {} */ + options?: { + updateByHash?: string; + hardReset?: boolean; + overrideName: string; + tag?: string; + }; }; }; }; responses: { + /** @description Successful response */ 201: { headers: { [name: string]: unknown; @@ -7250,46 +1349,52 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["DeploymentResponse"]; }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "edit-user": { + SquidController_listSquids: { parameters: { - query?: never; + query?: { + search?: string; + name?: string; + }; header?: never; path: { - code: string; - id: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** @enum {string} */ - roleType: PathsOrganizationsCodeRolesIdPutRequestBodyApplicationJsonRoleType; - }; + org: string; }; + cookie?: never; }; + requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -7298,72 +1403,50 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["SquidResponse"][]; }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; - }; - }; - "delete-user": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "edit-user": { + SquidController_getSquid: { parameters: { query?: never; header?: never; path: { - code: string; - id: string; + org: string; + reference: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": { - /** @enum {string} */ - roleType: PathsOrgsCodeRolesIdPutRequestBodyApplicationJsonRoleType; - }; - }; - }; + requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -7372,39 +1455,34 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["SquidResponse"]; }; }; }; - 400: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "delete-user": { + SquidController_deleteSquid: { parameters: { query?: never; header?: never; path: { - code: string; - id: string; + org: string; + reference: string; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 201: { headers: { [name: string]: unknown; @@ -7413,32 +1491,35 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["DeploymentResponse"]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "edit-user": { + SquidController_restartSquid: { parameters: { query?: never; header?: never; path: { - code: string; - id: string; + org: string; + reference: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": { - /** @enum {string} */ - roleType: PathsV1OrganizationsCodeRolesIdPutRequestBodyApplicationJsonRoleType; - }; - }; - }; + requestBody?: never; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; @@ -7446,39 +1527,34 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["DeploymentResponse"]; }; }; }; - 400: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "delete-user": { + SquidController_hibernateSquid: { parameters: { query?: never; header?: never; path: { - code: string; - id: string; + org: string; + reference: string; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 201: { headers: { [name: string]: unknown; @@ -7487,32 +1563,41 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["DeploymentResponse"]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "edit-user": { + SquidController_setTag: { parameters: { query?: never; header?: never; path: { - code: string; - id: string; + org: string; + reference: string; }; cookie?: never; }; requestBody: { content: { "application/json": { - /** @enum {string} */ - roleType: PathsV1OrgsCodeRolesIdPutRequestBodyApplicationJsonRoleType; + tag: string; }; }; }; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; @@ -7520,66 +1605,58 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; + payload?: components["schemas"]["DeploymentResponse"]; }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; - }; - }; - "delete-user": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationRoleResponse"]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "accept-user-role": { + SquidLogsController_fetchLogsHistory: { parameters: { - query?: never; + query: { + level?: PathsV1OrgsCodeSquidsReferenceLogsHistoryGetParametersQueryLevel[]; + container?: string[]; + search?: string; + nextPage?: string; + from: string; + limit?: number; + }; header?: never; path: { code: string; - id: string; + reference: string; }; cookie?: never; }; requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -7587,77 +1664,98 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + payload?: components["schemas"]["SquidHistoryLogsResponse"]; }; }; }; - }; - }; - "accept-user-role": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "accept-user-role": { + SquidLogsController_tailLogs: { parameters: { - query?: never; + query?: { + level?: PathsV1OrgsCodeSquidsReferenceLogsFollowGetParametersQueryLevel[]; + container?: string[]; + search?: string; + }; header?: never; path: { code: string; - id: string; + reference: string; }; cookie?: never; }; requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "accept-user-role": { + UserController_getProfile: { parameters: { query?: never; header?: never; - path: { - code: string; - id: string; - }; + path?: never; cookie?: never; }; requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -7665,25 +1763,38 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + payload?: components["schemas"]["UserResponse"]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "decline-user-role": { + UserController_updateProfile: { parameters: { query?: never; header?: never; - path: { - code: string; - id: string; - }; + path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + fullName: string; + }; + }; + }; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -7691,77 +1802,48 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + payload?: components["schemas"]["UserResponse"]; }; }; }; - }; - }; - "decline-user-role": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; - }; - }; - "decline-user-role": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 201: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["OrganizationResponse"]; - }; + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; }; - "decline-user-role": { + UserController_getSquidsV1: { parameters: { query?: never; header?: never; - path: { - code: string; - id: string; - }; + path?: never; cookie?: never; }; requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -7769,29 +1851,44 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationResponse"]; + payload?: components["schemas"]["SquidResponse"][]; }; }; }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; + }; + }; }; }; - "get-settings": { + OrganizationController_listOrganizations: { parameters: { query?: never; header?: never; - path: { - code: string; - }; + path?: never; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationResponse"][]; + }; + }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -7802,51 +1899,54 @@ export interface operations { }; }; }; - "setup-intent": { + OrganizationController_create: { parameters: { query?: never; header?: never; - path: { - code: string; - }; + path?: never; cookie?: never; }; requestBody: { content: { "application/json": { + code: string; name: string; /** Format: email */ email: string; - country: string; - addressLine1: string; - city: string; - postalCode: string; - vatId?: string; }; }; }; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationResponse"]; + }; + }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -7857,23 +1957,31 @@ export interface operations { }; }; }; - "get-settings": { + OrganizationController_getOrganization: { parameters: { query?: never; header?: never; path: { - code: string; + org: string; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationResponse"]; + }; + }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -7884,7 +1992,7 @@ export interface operations { }; }; }; - "setup-intent": { + OrganizationController_edit: { parameters: { query?: never; header?: never; @@ -7899,36 +2007,40 @@ export interface operations { name: string; /** Format: email */ email: string; - country: string; - addressLine1: string; - city: string; - postalCode: string; - vatId?: string; }; }; }; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationResponse"]; + }; + }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -7939,22 +2051,19 @@ export interface operations { }; }; }; - "get-monthly": { + OrganizationController_deleteOne: { parameters: { - query: { - bySquid: string; - }; + query?: never; header?: never; path: { code: string; - year: string; - month: string; }; cookie?: never; }; requestBody?: never; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; @@ -7962,10 +2071,46 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationResponse"][]; + payload?: components["schemas"]["OrganizationResponse"]; + }; + }; + }; + }; + }; + OrganizationController_sendEmailVerification: { + parameters: { + query?: never; + header?: never; + path: { + code: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + email: string; + }; + }; + }; + responses: { + /** @description Bad user input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -7976,21 +2121,38 @@ export interface operations { }; }; }; - "get-monthly": { + OrganizationController_verifyEmail: { parameters: { query: { - bySquid: string; + code: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful response */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; }; + }; + }; + OrganizationController_getOne: { + parameters: { + query?: never; header?: never; path: { code: string; - year: string; - month: string; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -7999,21 +2161,13 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["OrganizationResponse"][]; + payload?: components["schemas"]["OrganizationRoleResponse"][]; }; }; }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; }; }; - "list-secrets": { + OrganizationController_addUser: { parameters: { query?: never; header?: never; @@ -8022,9 +2176,18 @@ export interface operations { }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + email: string; + /** @enum {string} */ + roleType: PathsV1OrgsCodeRolesPostRequestBodyApplicationJsonRoleType; + }; + }; + }; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; @@ -8032,43 +2195,48 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["SecretsResponse"]; + payload?: components["schemas"]["OrganizationRoleResponse"]; }; }; }; - 401: { + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; + "application/json": { + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; + }; }; }; }; }; - put: { + OrganizationController_editUser: { parameters: { query?: never; header?: never; path: { code: string; + id: string; }; cookie?: never; }; requestBody: { content: { "application/json": { - organization?: string; - secrets: { - name: string; - /** @enum {string} */ - action: PathsOrgsCodeSecretsPutRequestBodyApplicationJsonSecretsAction; - value?: string & unknown; - }[]; + /** @enum {string} */ + roleType: PathsV1OrgsCodeRolesIdPutRequestBodyApplicationJsonRoleType; }; }; }; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8077,47 +2245,69 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["SecretsResponse"]; + payload?: components["schemas"]["OrganizationRoleResponse"]; }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; - 401: { + }; + }; + OrganizationController_deleteUser: { + parameters: { + query?: never; + header?: never; + path: { + code: string; + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationRoleResponse"]; + }; }; }; }; }; - "list-secrets": { + OrganizationController_acceptUserRole: { parameters: { query?: never; header?: never; path: { code: string; + id: string; }; cookie?: never; }; requestBody?: never; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; @@ -8125,21 +2315,40 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["SecretsResponse"]; + payload?: components["schemas"]["OrganizationResponse"]; }; }; }; - 401: { + }; + }; + OrganizationController_declineUserRole: { + parameters: { + query?: never; + header?: never; + path: { + code: string; + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationResponse"]; + }; }; }; }; }; - put: { + OrganizationController_setNeonApiToken: { parameters: { query?: never; header?: never; @@ -8151,17 +2360,12 @@ export interface operations { requestBody: { content: { "application/json": { - organization?: string; - secrets: { - name: string; - /** @enum {string} */ - action: PathsV1OrgsCodeSecretsPutRequestBodyApplicationJsonSecretsAction; - value?: string & unknown; - }[]; + token: string; }; }; }; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8170,36 +2374,55 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["SecretsResponse"]; + payload?: components["schemas"]["OrganizationResponse"]; }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; - 401: { + }; + }; + OrganizationController_deleteNeonApiToken: { + parameters: { + query?: never; + header?: never; + path: { + code: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["OrganizationResponse"]; + }; }; }; }; }; - "list-chains": { + OrganizationBillingController_getSettings: { parameters: { query?: never; header?: never; @@ -8210,18 +2433,14 @@ export interface operations { }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ChainResponse"][]; - }; - }; + content?: never; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8232,7 +2451,7 @@ export interface operations { }; }; }; - "list-chains": { + OrganizationBillingController_setupIntent: { parameters: { query?: never; header?: never; @@ -8241,20 +2460,45 @@ export interface operations { }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + name: string; + /** Format: email */ + email: string; + country: string; + addressLine1: string; + city: string; + postalCode: string; + vatId?: string; + }; + }; + }; responses: { + /** @description Successful response */ 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Bad user input */ + 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - /** @example null */ - error?: string; - payload?: components["schemas"]["ChainResponse"][]; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8265,17 +2509,22 @@ export interface operations { }; }; }; - "get-token": { + OrganizationBillingController_getMonthly: { parameters: { - query?: never; + query: { + bySquid: string; + }; header?: never; path: { code: string; + year: string; + month: string; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8284,10 +2533,11 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["TokenResponse"]; + payload?: components["schemas"]["OrganizationResponse"][]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8298,7 +2548,7 @@ export interface operations { }; }; }; - "refresh-token": { + SecretController_listSecrets: { parameters: { query?: never; header?: never; @@ -8309,7 +2559,8 @@ export interface operations { }; requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -8317,10 +2568,11 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["TokenResponse"]; + payload?: components["schemas"]["SecretsResponse"]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8331,7 +2583,7 @@ export interface operations { }; }; }; - "get-token": { + SecretController_put: { parameters: { query?: never; header?: never; @@ -8340,8 +2592,20 @@ export interface operations { }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + secrets: { + name: string; + /** @enum {string} */ + action: PathsV1OrgsCodeSecretsPutRequestBodyApplicationJsonSecretsAction; + value?: string & unknown; + }[]; + }; + }; + }; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8350,10 +2614,27 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["TokenResponse"]; + payload?: components["schemas"]["SecretsResponse"]; + }; + }; + }; + /** @description Bad user input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8364,7 +2645,7 @@ export interface operations { }; }; }; - "refresh-token": { + RpcController_listChains: { parameters: { query?: never; header?: never; @@ -8375,7 +2656,8 @@ export interface operations { }; requestBody?: never; responses: { - 201: { + /** @description Successful response */ + 200: { headers: { [name: string]: unknown; }; @@ -8383,10 +2665,11 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["TokenResponse"]; + payload?: components["schemas"]["ChainResponse"][]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8397,7 +2680,7 @@ export interface operations { }; }; }; - get: { + RpcController_getToken: { parameters: { query?: never; header?: never; @@ -8408,6 +2691,7 @@ export interface operations { }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8416,10 +2700,11 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["QuotaResponse"][]; + payload?: components["schemas"]["TokenResponse"]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8430,7 +2715,7 @@ export interface operations { }; }; }; - get: { + RpcController_refreshToken: { parameters: { query?: never; header?: never; @@ -8441,7 +2726,8 @@ export interface operations { }; requestBody?: never; responses: { - 200: { + /** @description Successful response */ + 201: { headers: { [name: string]: unknown; }; @@ -8449,10 +2735,11 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["QuotaResponse"][]; + payload?: components["schemas"]["TokenResponse"]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8463,21 +2750,18 @@ export interface operations { }; }; }; - squids: { + QuotaController_get: { parameters: { - query: { - from: string; - to: string; - }; + query?: never; header?: never; path: { code: string; - query: string; }; cookie?: never; }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8486,25 +2770,11 @@ export interface operations { "application/json": { /** @example null */ error?: string; - payload?: components["schemas"]["MetricResponse"][]; - }; - }; - }; - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; - }[]; + payload?: components["schemas"]["QuotaResponse"][]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8515,11 +2785,12 @@ export interface operations { }; }; }; - squids: { + MonitoringController_squids: { parameters: { query: { from: string; to: string; + maxPoints?: number; }; header?: never; path: { @@ -8530,6 +2801,7 @@ export interface operations { }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; @@ -8542,21 +2814,23 @@ export interface operations { }; }; }; + /** @description Bad user input */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; - invalidFields?: { - message?: string; - path?: string[]; - type?: string; + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; }[]; }; }; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8567,34 +2841,7 @@ export interface operations { }; }; }; - "squids-all-prom": { - parameters: { - query?: never; - header?: never; - path: { - code: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["UnauthorizedResponse"]; - }; - }; - }; - }; - "squids-all-prom": { + MonitoringController_squidsAllProm: { parameters: { query?: never; header?: never; @@ -8605,12 +2852,14 @@ export interface operations { }; requestBody?: never; responses: { + /** @description Successful response */ 200: { headers: { [name: string]: unknown; }; content?: never; }; + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; @@ -8622,45 +2871,10 @@ export interface operations { }; }; } -export enum PathsOrgsCodeSquidsSquidNameVersionsVersionNameLogsHistoryGetParametersQueryLevel { - ERROR = "ERROR", - DEBUG = "DEBUG", - INFO = "INFO", - NOTICE = "NOTICE", - WARNING = "WARNING", - CRITICAL = "CRITICAL" -} -export enum PathsOrgsCodeSquidsSquidNameVersionsVersionNameLogsFollowGetParametersQueryLevel { - ERROR = "ERROR", - DEBUG = "DEBUG", - INFO = "INFO", - NOTICE = "NOTICE", - WARNING = "WARNING", - CRITICAL = "CRITICAL" -} -export enum PathsOrgsCodeDeploysGetParametersQueryStatusGroup { - IN_PROGRESS = "IN_PROGRESS" -} -export enum PathsV1OrgsCodeDeploysGetParametersQueryStatusGroup { +export enum PathsV1OrgsCodeDeploymentsGetParametersQueryStatusGroup { IN_PROGRESS = "IN_PROGRESS" } -export enum PathsOrgsCodeSquidsSquidSlotsSlotLogsHistoryGetParametersQueryLevel { - ERROR = "ERROR", - DEBUG = "DEBUG", - INFO = "INFO", - NOTICE = "NOTICE", - WARNING = "WARNING", - CRITICAL = "CRITICAL" -} -export enum PathsV1OrgsCodeSquidsSquidSlotsSlotLogsHistoryGetParametersQueryLevel { - ERROR = "ERROR", - DEBUG = "DEBUG", - INFO = "INFO", - NOTICE = "NOTICE", - WARNING = "WARNING", - CRITICAL = "CRITICAL" -} -export enum PathsOrgsCodeSquidsSquidSlotsSlotLogsFollowGetParametersQueryLevel { +export enum PathsV1OrgsCodeSquidsReferenceLogsHistoryGetParametersQueryLevel { ERROR = "ERROR", DEBUG = "DEBUG", INFO = "INFO", @@ -8668,7 +2882,7 @@ export enum PathsOrgsCodeSquidsSquidSlotsSlotLogsFollowGetParametersQueryLevel { WARNING = "WARNING", CRITICAL = "CRITICAL" } -export enum PathsV1OrgsCodeSquidsSquidSlotsSlotLogsFollowGetParametersQueryLevel { +export enum PathsV1OrgsCodeSquidsReferenceLogsFollowGetParametersQueryLevel { ERROR = "ERROR", DEBUG = "DEBUG", INFO = "INFO", @@ -8676,139 +2890,18 @@ export enum PathsV1OrgsCodeSquidsSquidSlotsSlotLogsFollowGetParametersQueryLevel WARNING = "WARNING", CRITICAL = "CRITICAL" } -export enum PathsOrganizationsCodeRolesPostRequestBodyApplicationJsonRoleType { - admin = "admin", - developer = "developer" -} -export enum PathsOrgsCodeRolesPostRequestBodyApplicationJsonRoleType { - admin = "admin", - developer = "developer" -} -export enum PathsV1OrganizationsCodeRolesPostRequestBodyApplicationJsonRoleType { - admin = "admin", - developer = "developer" -} export enum PathsV1OrgsCodeRolesPostRequestBodyApplicationJsonRoleType { admin = "admin", developer = "developer" } -export enum PathsOrganizationsCodeRolesIdPutRequestBodyApplicationJsonRoleType { - admin = "admin", - developer = "developer" -} -export enum PathsOrgsCodeRolesIdPutRequestBodyApplicationJsonRoleType { - admin = "admin", - developer = "developer" -} -export enum PathsV1OrganizationsCodeRolesIdPutRequestBodyApplicationJsonRoleType { - admin = "admin", - developer = "developer" -} export enum PathsV1OrgsCodeRolesIdPutRequestBodyApplicationJsonRoleType { admin = "admin", developer = "developer" } -export enum PathsOrgsCodeSecretsPutRequestBodyApplicationJsonSecretsAction { - UPDATE = "UPDATE", - DELETE = "DELETE" -} export enum PathsV1OrgsCodeSecretsPutRequestBodyApplicationJsonSecretsAction { UPDATE = "UPDATE", DELETE = "DELETE" } -export enum DeployResponseV0Type { - DEPLOY = "DEPLOY", - DEPLOY_HARD_RESET = "DEPLOY_HARD_RESET", - RESTART = "RESTART", - HIBERNATE = "HIBERNATE", - DELETE = "DELETE", - SCALE = "SCALE", - TAG = "TAG" -} -export enum DeployResponseV0Status { - UNPACKING = "UNPACKING", - IMAGE_BUILDING = "IMAGE_BUILDING", - RESETTING = "RESETTING", - TAGGING = "TAGGING", - SQUID_SYNCING = "SQUID_SYNCING", - SQUID_DELETING = "SQUID_DELETING", - ADDONS_SYNCING = "ADDONS_SYNCING", - ADDONS_DELETING = "ADDONS_DELETING", - OK = "OK", - DEPLOYING = "DEPLOYING" -} -export enum DeployResponseV0Failed { - NO = "NO", - UNEXPECTED = "UNEXPECTED", - PERMISSIONS = "PERMISSIONS", - REQUIREMENTS = "REQUIREMENTS", - REQUIRED_SOURCE_FILE_MISSED = "REQUIRED_SOURCE_FILE_MISSED", - REQUIRED_SOURCE_FILE_INVALID = "REQUIRED_SOURCE_FILE_INVALID", - SOURCE_FILES_BUILD_FAILED = "SOURCE_FILES_BUILD_FAILED" -} -export enum SquidApiResponseV0Status { - AVAILABLE = "AVAILABLE", - NOT_AVAILABLE = "NOT_AVAILABLE" -} -export enum SquidProcessorResponseV0Status { - SYNCING = "SYNCING", - UNKNOWN = "UNKNOWN", - STARTING = "STARTING", - SYNCED = "SYNCED", - STUCK = "STUCK" -} -export enum SquidDiskResponseV0UsageStatus { - LOW = "LOW", - NORMAL = "NORMAL", - WARNING = "WARNING", - CRITICAL = "CRITICAL", - UNKNOWN = "UNKNOWN" -} -export enum SquidLastDeployV0Type { - DEPLOY = "DEPLOY", - DEPLOY_HARD_RESET = "DEPLOY_HARD_RESET", - RESTART = "RESTART", - HIBERNATE = "HIBERNATE", - DELETE = "DELETE", - SCALE = "SCALE", - TAG = "TAG" -} -export enum SquidLastDeployV0Status { - UNPACKING = "UNPACKING", - IMAGE_BUILDING = "IMAGE_BUILDING", - RESETTING = "RESETTING", - TAGGING = "TAGGING", - SQUID_SYNCING = "SQUID_SYNCING", - SQUID_DELETING = "SQUID_DELETING", - ADDONS_SYNCING = "ADDONS_SYNCING", - ADDONS_DELETING = "ADDONS_DELETING", - OK = "OK", - DEPLOYING = "DEPLOYING" -} -export enum SquidLastDeployV0Failed { - NO = "NO", - UNEXPECTED = "UNEXPECTED", - PERMISSIONS = "PERMISSIONS", - REQUIREMENTS = "REQUIREMENTS", - REQUIRED_SOURCE_FILE_MISSED = "REQUIRED_SOURCE_FILE_MISSED", - REQUIRED_SOURCE_FILE_INVALID = "REQUIRED_SOURCE_FILE_INVALID", - SOURCE_FILES_BUILD_FAILED = "SOURCE_FILES_BUILD_FAILED" -} -export enum SquidRunningDeployV0Type { - DEPLOY = "DEPLOY", - DEPLOY_HARD_RESET = "DEPLOY_HARD_RESET", - RESTART = "RESTART", - HIBERNATE = "HIBERNATE", - DELETE = "DELETE", - SCALE = "SCALE", - TAG = "TAG" -} -export enum VersionResponseV0Status { - DEPLOYING = "DEPLOYING", - DEPLOY_ERROR = "DEPLOY_ERROR", - DEPLOYED = "DEPLOYED", - HIBERNATED = "HIBERNATED" -} export enum IngressRequestsMetricRes { error = "error", success = "success" @@ -8825,20 +2918,21 @@ export enum SquidUsageMetricTimeGroup { Day = "Day", Month = "Month" } -export enum DeployResponseType { +export enum DeploymentResponseType { DEPLOY = "DEPLOY", DEPLOY_HARD_RESET = "DEPLOY_HARD_RESET", RESTART = "RESTART", HIBERNATE = "HIBERNATE", DELETE = "DELETE", SCALE = "SCALE", - TAG = "TAG" + SET_TAG = "SET_TAG", + REMOVE_TAG = "REMOVE_TAG" } -export enum DeployResponseStatus { +export enum DeploymentResponseStatus { UNPACKING = "UNPACKING", IMAGE_BUILDING = "IMAGE_BUILDING", RESETTING = "RESETTING", - TAGGING = "TAGGING", + CONFIGURING_INGRESS = "CONFIGURING_INGRESS", SQUID_SYNCING = "SQUID_SYNCING", SQUID_DELETING = "SQUID_DELETING", ADDONS_SYNCING = "ADDONS_SYNCING", @@ -8846,7 +2940,7 @@ export enum DeployResponseStatus { OK = "OK", DEPLOYING = "DEPLOYING" } -export enum DeployResponseFailed { +export enum DeploymentResponseFailed { NO = "NO", UNEXPECTED = "UNEXPECTED", PERMISSIONS = "PERMISSIONS", @@ -8863,8 +2957,11 @@ export enum SquidProcessorResponseStatus { SYNCING = "SYNCING", UNKNOWN = "UNKNOWN", STARTING = "STARTING", - SYNCED = "SYNCED", - STUCK = "STUCK" + SYNCED = "SYNCED" +} +export enum SquidAddonsHasuraResponseStatus { + AVAILABLE = "AVAILABLE", + NOT_AVAILABLE = "NOT_AVAILABLE" } export enum SquidDiskResponseUsageStatus { LOW = "LOW", @@ -8880,13 +2977,14 @@ export enum SquidLastDeployType { HIBERNATE = "HIBERNATE", DELETE = "DELETE", SCALE = "SCALE", - TAG = "TAG" + SET_TAG = "SET_TAG", + REMOVE_TAG = "REMOVE_TAG" } export enum SquidLastDeployStatus { UNPACKING = "UNPACKING", IMAGE_BUILDING = "IMAGE_BUILDING", RESETTING = "RESETTING", - TAGGING = "TAGGING", + CONFIGURING_INGRESS = "CONFIGURING_INGRESS", SQUID_SYNCING = "SQUID_SYNCING", SQUID_DELETING = "SQUID_DELETING", ADDONS_SYNCING = "ADDONS_SYNCING", diff --git a/src/api/squids.ts b/src/api/squids.ts index ec1ad64..315d316 100644 --- a/src/api/squids.ts +++ b/src/api/squids.ts @@ -4,33 +4,30 @@ import { pretty } from '../logs'; import { api, debugLog } from './api'; import { - Deploy, + Deployment, HttpResponse, LogEntry, LogsResponse, + OrganizationRequest, Squid, - UploadUrl, SquidRequest, - OrganizationRequest, + UploadUrl, } from './types'; export async function listSquids({ organization, name }: OrganizationRequest & { name?: string }): Promise { - // return getDemoSquid(orgCode, squidName, tagOrId); - const { body } = await api>({ method: 'get', - path: name ? `/orgs/${organization.code}/squids/${name}` : `/orgs/${organization.code}/squids`, + path: `/orgs/${organization.code}/squids`, + query: { name }, }); return body.payload.sort((a, b) => a.name.localeCompare(b.name)); } -export async function getSquid({ organization, squid }: SquidRequest): Promise { - // return getDemoSquid(orgCode, squidName, tagOrId); - +export async function getSquid({ organization, reference }: SquidRequest): Promise { const { body } = await api>({ method: 'get', - path: `/orgs/${organization.code}/squids/${squid.name}/slots/${squid.slot}`, + path: `/orgs/${organization.code}/squids/${reference}`, }); return body.payload; @@ -38,7 +35,7 @@ export async function getSquid({ organization, squid }: SquidRequest): Promise { - const { body } = await api({ + const { body } = await api>({ method: 'get', - path: `/orgs/${organization.code}/squids/${squid.name}/slots/${squid.slot}/logs/history`, + path: `/orgs/${organization.code}/squids/${reference}/logs/history`, query: { ...query, from: query.from.toISOString(), @@ -64,12 +61,14 @@ export async function squidHistoryLogs({ abortController, }); - return body || { logs: [], nextPage: null }; + const payload = body?.payload; + + return { logs: payload?.logs ?? [], nextPage: payload?.nextPage ?? null }; } export async function squidLogsFollow({ organization, - squid, + reference, query, abortController, }: SquidRequest & { @@ -78,7 +77,7 @@ export async function squidLogsFollow({ }) { const { body } = await api({ method: 'get', - path: `/orgs/${organization.code}/squids/${squid.name}/slots/${squid.slot}/logs/follow`, + path: `/orgs/${organization.code}/squids/${reference}/logs/follow`, query, responseType: 'stream', abortController: abortController, @@ -89,7 +88,7 @@ export async function squidLogsFollow({ export async function streamSquidLogs({ organization, - squid, + reference, abortController, query = {}, onLog, @@ -107,7 +106,7 @@ export async function streamSquidLogs({ try { stream = await squidLogsFollow({ organization, - squid, + reference, query, abortController, }); @@ -171,14 +170,17 @@ export async function deploySquid({ data, }: OrganizationRequest & { data: { - hardReset: boolean; artifactUrl: string; manifestPath: string; - updateSlot?: string; - tag?: string; + options: { + updateByHash?: string; + overrideName?: string; + tag?: string; + hardReset?: boolean; + }; }; -}): Promise { - const { body } = await api>({ +}): Promise { + const { body } = await api>({ method: 'post', path: `/orgs/${organization.code}/squids/deploy`, data, @@ -190,25 +192,25 @@ export async function deploySquid({ export async function getUploadUrl({ organization }: OrganizationRequest): Promise { const { body } = await api>({ method: 'post', - path: `/orgs/${organization.code}/deploys/upload-url`, + path: `/orgs/${organization.code}/deployments/upload-url`, }); return body.payload; } -export async function restartSquid({ organization, squid }: SquidRequest): Promise { - const { body } = await api>({ +export async function restartSquid({ organization, reference }: SquidRequest): Promise { + const { body } = await api>({ method: 'post', - path: `/orgs/${organization.code}/squids/${squid.name}/slots/${squid.slot}/restart`, + path: `/orgs/${organization.code}/squids/${reference}/restart`, }); return body.payload; } -export async function deleteSquid({ organization, squid }: SquidRequest): Promise { - const { body } = await api>({ +export async function deleteSquid({ organization, reference }: SquidRequest): Promise { + const { body } = await api>({ method: 'delete', - path: `/orgs/${organization.code}/squids/${squid.name}/slots/${squid.slot}`, + path: `/orgs/${organization.code}/squids/${reference}`, }); return body.payload; @@ -216,12 +218,12 @@ export async function deleteSquid({ organization, squid }: SquidRequest): Promis export async function tagSquid({ organization, - squid, + reference, data, }: SquidRequest & { data: { tag: string } }): Promise { const { body } = await api>({ method: 'post', - path: `/orgs/${organization.code}/squids/${squid.name}/slots/${squid.slot}/tag`, + path: `/orgs/${organization.code}/squids/${reference}/tag`, data, }); diff --git a/src/api/types.ts b/src/api/types.ts index 7e9f419..2a09afc 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -6,11 +6,9 @@ export type HttpResponse = { payload: T; }; -export type { DeployResponseStatus as DeployStatus } from './schema'; - export type Organization = components['schemas']['OrganizationResponse']; -export type Deploy = components['schemas']['DeployResponse']; +export type Deployment = components['schemas']['DeploymentResponse']; export type UploadUrl = components['schemas']['UploadUrlResponse']; @@ -24,10 +22,6 @@ export type SquidAddonsPostgres = components['schemas']['SquidAddonsPostgresResp export type Squid = components['schemas']['SquidResponse']; -export type SquidNameIsAvailableResponse = { - available: boolean; -}; - export type SecretsListResponse = { secrets: Record; }; @@ -55,16 +49,8 @@ export type LogsResponse = { nextPage: string | null; }; -export type SquidVersionResponse = { - id: number; - name: string; - version: { - deploymentUrl: string; - }; -}; - export type OrganizationRequest = { organization: PickDeep }; -export type SquidRequest = OrganizationRequest & { squid: PickDeep }; +export type SquidRequest = OrganizationRequest & { reference: string }; -export type DeployRequest = OrganizationRequest & { deploy: PickDeep }; +export type DeployRequest = OrganizationRequest & { deploy: PickDeep }; diff --git a/src/command.ts b/src/command.ts index 1a2d047..33e2841 100644 --- a/src/command.ts +++ b/src/command.ts @@ -3,23 +3,15 @@ import chalk from 'chalk'; import inquirer from 'inquirer'; import { isNil, uniqBy } from 'lodash'; -import { ApiError, getOrganization, listOrganizations, listSquids, listUserSquids, OrganizationRequest } from './api'; +import { ApiError, getOrganization, getSquid, listOrganizations, listUserSquids, SquidRequest } from './api'; import { getTTY } from './tty'; -import { formatSquidName } from './utils'; - -export const RELEASE_DEPRECATE = [ - chalk.yellow('*******************************************************'), - chalk.yellow('* *'), - chalk.yellow('* WARNING! This command has been deprecated *'), - chalk.yellow('* Please check the migration guide *'), - chalk.yellow('* https://docs.subsquid.io/deploy-squid/migration/ *'), - chalk.yellow('* *'), - chalk.yellow('*******************************************************'), -].join('\n'); +import { parseSquidReference, SQUID_HASH_SYMBOL, SQUID_TAG_SYMBOL } from './utils'; + +export const SUCCESS_CHECK_MARK = chalk.green('✓'); export abstract class CliCommand extends Command { logSuccess(message: string) { - this.log(chalk.green(`✓ `) + message); + this.log(SUCCESS_CHECK_MARK + message); } logQuestion(message: string) { @@ -83,44 +75,28 @@ export abstract class CliCommand extends Command { throw error; } - async findSquid({ - organization, - name, - tag, - slot, - tagOrSlot, - }: OrganizationRequest & { name: string } & ( - | { tag: string; slot?: undefined; tagOrSlot?: undefined } - | { tag?: undefined; slot: string; tagOrSlot?: undefined } - | { tag?: undefined; slot?: undefined; tagOrSlot: string } - )) { - const squids = await listSquids({ organization, name }); - - if (slot) { - return squids.find((s) => s.slot === slot); - } - - if (tag) { - return squids.find((s) => s.tags.some((t) => t.name === tag)); - } + async findSquid({ organization, reference }: SquidRequest) { + try { + return getSquid({ organization, reference }); + } catch (e) { + if (e instanceof ApiError && e.request.status === 404) { + return null; + } - if (tagOrSlot) { - return squids.find((s) => s.slot === tagOrSlot || s.tags.some((t) => t.name === tagOrSlot)); + throw e; } } - async findOrThrowSquid(opts: Parameters[0]) { - const squid = await this.findSquid(opts); + async findOrThrowSquid({ organization, reference }: SquidRequest) { + const squid = await this.findSquid({ organization, reference }); if (!squid) { - throw new Error( - `The squid ${formatSquidName(opts.tagOrSlot != null ? { name: opts.name, slot: opts.tagOrSlot } : opts)} is not found`, - ); + throw new Error(`The squid "${reference}" is not found`); } return squid; } - async promptOrganization(code: string | null | undefined, using: string) { + async promptOrganization(code: string | null | undefined, using?: string) { if (code) { return await getOrganization({ organization: { code } }); } @@ -132,14 +108,27 @@ export abstract class CliCommand extends Command { return organizations[0]; } - return await this.getOrganizationPromt(organizations, using); + return await this.getOrganizationPrompt(organizations, using); } - async promptSquidOrganization(code: string | null | undefined, name: string, using: string) { + async promptSquidOrganization({ + code, + reference, + using, + }: { + code?: string | null; + reference: string; + using?: string; + }) { if (code) { return await getOrganization({ organization: { code } }); } + const name = + reference.includes(SQUID_TAG_SYMBOL) || reference.includes(SQUID_HASH_SYMBOL) + ? parseSquidReference(reference).name + : reference; + const squids = await listUserSquids({ name }); let organizations = squids.map((s) => s.organization).filter((o) => !isNil(o)); @@ -151,12 +140,12 @@ export abstract class CliCommand extends Command { return organizations[0]; } - return await this.getOrganizationPromt(organizations, using); + return await this.getOrganizationPrompt(organizations, using); } - private async getOrganizationPromt( + private async getOrganizationPrompt( organizations: T[], - using: string, + using: string = 'using "-o" flag', ): Promise { const { stdin, stdout } = getTTY(); if (!stdin || !stdout) { @@ -190,13 +179,13 @@ export abstract class CliCommand extends Command { } } -export const SquidNameArg = Args.string({ - description: ' or ', +export const SquidReferenceArg = Args.string({ + description: ` or `, required: true, parse: async (input) => { input = input.toLowerCase(); - if (!/^[a-z0-9\-]+[#@][a-z0-9\-]+$/.test(input)) { - throw new Error(`Expected a squid name but received: ${input}`); + if (!/^[a-z0-9\-]+[:@][a-z0-9\-]+$/.test(input)) { + throw new Error(`Expected a squid reference but received: ${input}`); } return input; }, diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 14a2b31..69f77e2 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -5,22 +5,23 @@ import { promisify } from 'util'; import { Args, Flags, ux as CliUx } from '@oclif/core'; import { Manifest } from '@subsquid/manifest'; import chalk from 'chalk'; +import diff from 'cli-diff'; import { globSync } from 'glob'; import ignore from 'ignore'; import inquirer from 'inquirer'; import prettyBytes from 'pretty-bytes'; import targz from 'targz'; -import { deploySquid, listSquids, OrganizationRequest, Squid, uploadFile } from '../api'; -// import { buildTable, CREATE_COLOR, deployDemoSquid, listDemoSquids, UPDATE_COLOR } from '../api/demoStore'; +import { deploySquid, OrganizationRequest, uploadFile } from '../api'; +import { SUCCESS_CHECK_MARK } from '../command'; import { DeployCommand } from '../deploy-command'; import { loadManifestFile } from '../manifest'; -import { formatSquidName } from '../utils'; +import { formatSquidName, parseSquidReference, SQUID_HASH_SYMBOL, SQUID_TAG_SYMBOL } from '../utils'; const compressAsync = promisify(targz.compress); -const SQUID_PATH_DESC = [ - `Squid source. Could be:`, +const SQUID_WORKDIR_DESC = [ + `Squid working directory. Could be:`, ` - a relative or absolute path to a local folder (e.g. ".")`, ` - a URL to a .tar.gz archive`, ` - a github URL to a git repo with a branch or commit tag`, @@ -50,39 +51,59 @@ export function resolveManifest( } } -const LIMIT = 10; +function example(command: string, description: string) { + // return [chalk.dim(`// ${description}`), command].join('\r\n'); + return `${command} ${chalk.dim(`// ${description}`)}`; +} export default class Deploy extends DeployCommand { static description = 'Deploy new or update an existing squid in the Cloud'; + static examples = [ + example('sqd deploy', 'Create a new squid with name provided in the manifest file'), + example( + 'sqd deploy my-squid-override', + 'Create a new squid deployment and override it\'s name to "my-squid-override"', + ), + example('sqd deploy my-squid#asmzf5', 'Update the "my-squid" squid with hash "asmzf5"'), + example( + 'sqd deploy -d ./path-to-the-squid -m squid.prod.yaml', + 'Use a manifest file located in ./path-to-the-squid/squid.prod.yaml', + ), + example( + 'sqd deploy -d /Users/dev/path-to-the-squid -m /Users/dev/path-to-the-squid/squid.prod.yaml', + 'Full paths are also fine', + ), + ]; static args = { - source: Args.string({ - description: SQUID_PATH_DESC.join('\n'), - required: true, - default: '.', + squid_name_or_reference: Args.string({ + description: [ + `Reference to squid for the update.`, + `If argument not specified, the squid name will be retrieved from the manifest or prompted and a new squid will be created.`, + ``, + `Alternatively, you can overwrite the name of the squid from the manifest by explicitly providing a new name instead of a reference.`, + ``, + `See Examples section for more information`, + ].join('\n'), + required: false, }), }; static flags = { manifest: Flags.string({ char: 'm', - description: 'Relative local path to a squid manifest file in squid source', + description: 'Relative local path to a squid manifest file in squid working directory', required: false, default: 'squid.yaml', helpValue: '', }), - update: Flags.string({ - char: 'u', - description: [ - 'Reference on a deployment to update in-place. Could be:', - '- "@{tag}" or "{tag}", i.e. the tag assigned to the squid deployment', - '- "#{id}" or "{id}", i.e. the corresponding deployment ID', - 'If it is not provided, a new squid will be created. ', - ].join('\n'), + dir: Flags.string({ + char: 'd', + description: SQUID_WORKDIR_DESC.join('\n'), required: false, - helpValue: '', + default: '.', + helpValue: '', }), - tag: Flags.string({ char: 't', description: [ @@ -91,10 +112,8 @@ export default class Deploy extends DeployCommand { 'Tag must contain only alphanumeric characters, dashes, and underscores', ].join('\n'), required: false, - exclusive: ['update'], helpValue: '', }), - 'hard-reset': Flags.boolean({ char: 'r', description: @@ -108,7 +127,7 @@ export default class Deploy extends DeployCommand { }), org: Flags.string({ char: 'o', - description: 'Organization', + description: 'Organization code', helpValue: '', required: false, }), @@ -116,11 +135,11 @@ export default class Deploy extends DeployCommand { async run(): Promise { const { - args: { source }, - flags: { manifest: manifestPath, 'hard-reset': hardReset, update, 'no-stream-logs': disableStreamLogs, org, tag }, + args: { squid_name_or_reference }, + flags: { dir, manifest: manifestPath, 'hard-reset': hardReset, 'no-stream-logs': disableStreamLogs, org, tag }, } = await this.parse(Deploy); - const isUrl = source.startsWith('http://') || source.startsWith('https://'); + const isUrl = dir.startsWith('http://') || dir.startsWith('https://'); if (isUrl) { // this.log(`🦑 Releasing the squid from remote`); // @@ -137,11 +156,11 @@ export default class Deploy extends DeployCommand { return this.error('Not implemented yet'); } - const organization = await this.promptOrganization(org, 'using "-o" flag'); + const organization = await this.promptOrganization(org); this.log(`🦑 Releasing the squid from local folder`); - const res = resolveManifest(source, manifestPath); + const res = resolveManifest(dir, manifestPath); if ('error' in res) return this.showError(res.error, 'MANIFEST_VALIDATION_FAILED'); const { buildDir, squidDir, manifest } = res; @@ -150,31 +169,42 @@ export default class Deploy extends DeployCommand { this.log(chalk.dim(`Build directory: ${buildDir}`)); this.log(chalk.dim(`Manifest: ${manifestPath}`)); - let target: Squid | undefined; - if (update) { - const filter = update.startsWith('#') - ? { slot: update.slice(1) } - : update.startsWith('@') - ? { tag: update.slice(1) } - : { tagOrSlot: update }; - target = await this.findOrThrowSquid({ organization, name: manifest.name, ...filter }); + let reference = squid_name_or_reference?.trim(); + if (!reference) { + reference = manifest.name; } + const isUpdate = reference.includes(SQUID_HASH_SYMBOL) || reference.includes(SQUID_TAG_SYMBOL); + const overrideName = isUpdate ? parseSquidReference(reference).name : reference; + + await this.checkNameMismatch({ fileName: path.basename(manifestPath), manifest, overrideName }); + + const finalName = await this.getFinalSquidName(manifest, overrideName); + if (tag) { - const normalizedTag = tag.startsWith('@') ? tag.slice(1) : tag; - const oldSquid = await this.findSquid({ organization, name: manifest.name, tag: normalizedTag }); + const oldSquid = await this.findSquid({ + organization, + reference: `${finalName}${tag.padStart(1, SQUID_TAG_SYMBOL)}`, + }); if (oldSquid) { const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', - message: `A squid tag @${normalizedTag} has already been assigned to the previous squid deployment ${formatSquidName(oldSquid)}. Are you sure?`, + message: [ + chalk.reset( + `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidName(oldSquid)}.`, + ), + chalk.reset(`The tag URL will be assigned to the newly created deployment.`), + chalk.bold(`Are you sure?`), + ].join('\n'), }, ]); if (!confirm) return; } } + const target = reference && isUpdate ? await this.findOrThrowSquid({ organization, reference }) : null; if (target) { /** * Squid exists we should check running deploys @@ -184,45 +214,98 @@ export default class Deploy extends DeployCommand { } const archiveName = `${manifest.name}.tar.gz`; - const artifactPath = await this.pack({ buildDir, squidDir, archiveName }); const artifactUrl = await this.upload({ organization, artifactPath }); const deploy = await deploySquid({ organization, data: { - hardReset, artifactUrl, manifestPath, - updateSlot: target?.slot, - tag, + options: { + hardReset, + overrideName: finalName !== manifest.name ? finalName : undefined, + updateByHash: target?.hash, + tag, + }, }, }); - const squid = await this.pollDeploy({ organization, deploy }); - if (squid) { - if (update) { - this.log( - [ - '', - chalk[UPDATE_COLOR](`=================================================`), - `The squid ${squid.name}#${squid.slot} has been successfully updated`, - chalk[UPDATE_COLOR](`=================================================`), - ].join('\n'), - ); - } else { - this.log( - [ - '', - chalk[CREATE_COLOR](`+++++++++++++++++++++++++++++++++++++++++++++++++`), - `A squid deployment ${squid.name}#${squid.slot} was successfully created`, //${tag ? ` using tag ${chalk.bold(tag)} ` : ''} - chalk[CREATE_COLOR](`+++++++++++++++++++++++++++++++++++++++++++++++++`), - ].join('\n'), - ); - } + const deployment = await this.pollDeploy({ organization, deploy }); + if (!deployment || !deployment.squid) return; + + if (isUpdate) { + this.logDeployResult( + UPDATE_COLOR, + `The squid ${formatSquidName(deployment.squid)} has been successfully updated`, + ); + } else { + this.logDeployResult( + CREATE_COLOR, + `A new squid ${formatSquidName(deployment.squid)}${tag ? ` with tag ${chalk.bold(tag)}` : ''} was successfully created`, + ); + } + + if (!disableStreamLogs) { + await this.streamLogs(organization, deployment.squid); } + } + + private async checkNameMismatch({ + fileName, + overrideName, + manifest, + }: { + fileName: string; + manifest: Manifest; + overrideName?: string; + }) { + if (!manifest.name) return; + else if (!overrideName) return; + + if (manifest.name !== overrideName) { + this.log( + [ + chalk.bold('Name conflict detected!'), + + `A manifest squid name ${chalk.bold(manifest.name)} does not match with specified in the argument: ${chalk.bold(overrideName)}.`, + `If it is intended and you'd like to override the name, just skip this message and confirm, the manifest name will be overridden automatically in the Cloud during the deploy.`, + ``, + `Patch:`, + diff( + { name: fileName, content: `name: ${manifest.name}\n` }, + { name: fileName, content: `name: ${overrideName}\n` }, + ), + ].join('\n'), + ); + + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: 'Are you sure?', + }, + ]); + if (!confirm) return; + } + } + + private async getFinalSquidName(manifest: Manifest, overrideName?: string) { + if (overrideName) return overrideName; + else if (manifest.name) return manifest.name; + + const { input } = await inquirer.prompt([ + { + name: 'input', + type: 'input', + message: [ + chalk.reset(`The squid name is not defined either in the manifest or via CLI argument.`), + chalk.reset(`Please enter the name of the squid:`), + ].join('\n'), + }, + ]); - // this.log([buildTable(newSquids, { changes, limit: LIMIT }), '']); + return input.name; } private async pack({ buildDir, squidDir, archiveName }: { buildDir: string; squidDir: string; archiveName: string }) { @@ -260,7 +343,7 @@ export default class Deploy extends DeployCommand { const squidArtifactStats = fs.statSync(squidArtifact); - CliUx.ux.action.stop(`${filesCount} files, ${prettyBytes(squidArtifactStats.size)} ✔️`); + CliUx.ux.action.stop(`${filesCount} files, ${prettyBytes(squidArtifactStats.size)} ${SUCCESS_CHECK_MARK}`); return squidArtifact; } @@ -275,7 +358,7 @@ export default class Deploy extends DeployCommand { return this.showError('The artifact URL is missing', 'UPLOAD_FAILED'); } - CliUx.ux.action.stop('✔️'); + CliUx.ux.action.stop(SUCCESS_CHECK_MARK); return artifactUrl; } diff --git a/src/commands/explorer.ts b/src/commands/explorer.ts index 68b3de2..01669f9 100644 --- a/src/commands/explorer.ts +++ b/src/commands/explorer.ts @@ -21,7 +21,7 @@ export default class Explorer extends CliCommand { flags: { org }, } = await this.parse(Explorer); - const organization = await this.promptOrganization(org, 'using "-o" flag'); + const organization = await this.promptOrganization(org); const screen = blessed.screen({ smartCSR: true, fastCSR: true, diff --git a/src/commands/init.ts b/src/commands/init.ts index 5dff044..a719b9d 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -2,17 +2,16 @@ import { promises as asyncFs } from 'fs'; import path from 'path'; import { Args, Flags, ux as CliUx } from '@oclif/core'; +import { Manifest } from '@subsquid/manifest'; import chalk from 'chalk'; import inquirer from 'inquirer'; import { simpleGit } from 'simple-git'; -import { adjectives, animals, colors, uniqueNamesGenerator } from 'unique-names-generator'; -import { CliCommand } from '../command'; +import { CliCommand, SUCCESS_CHECK_MARK } from '../command'; import { readManifest, saveManifest } from '../manifest'; const SQUID_NAME_DESC = [ `The squid name. It must contain only alphanumeric or dash ("-") symbols and must not start with "-".`, - `Squid names are ${chalk.yellow('globally unique')}.`, ]; const TEMPLATE_ALIASES: Record = { @@ -143,18 +142,6 @@ export default class Init extends CliCommand { ? TEMPLATE_ALIASES[resolvedTemplate].url : resolvedTemplate; - try { - const uniqueNameSuggestion = uniqueNamesGenerator({ - dictionaries: [adjectives, colors, animals], - separator: '-', - length: 2, - }); - return this.error( - `There is already a squid with name "${name}" deployed to the Cloud. Squid names are globally unique. ` + - `Please pick a new memorable name, e.g. "${uniqueNameSuggestion}".`, - ); - } catch (e) {} - CliUx.ux.action.start(`◷ Downloading the template: ${githubRepository}... `); try { // TODO: support branches? @@ -162,7 +149,7 @@ export default class Init extends CliCommand { } catch (e: any) { return this.error(e); } - CliUx.ux.action.stop(`✔`); + CliUx.ux.action.stop(SUCCESS_CHECK_MARK); /** Clean up template **/ await asyncFs.rm(path.resolve(localDir, '.git'), { recursive: true }); @@ -174,10 +161,7 @@ export default class Init extends CliCommand { const manifestPath = path.resolve(localDir, 'squid.yaml'); try { - const manifest = readManifest(manifestPath); - - /** Override name in squid manifest **/ - manifest.name = name; + const manifest = Manifest.replace(readManifest(manifestPath), { name }); saveManifest(manifestPath, manifest); } catch (e: any) { diff --git a/src/commands/logs.ts b/src/commands/logs.ts index a49ac4b..70e217a 100644 --- a/src/commands/logs.ts +++ b/src/commands/logs.ts @@ -1,10 +1,9 @@ -import { Args, ux as CliUx, Flags } from '@oclif/core'; +import { Flags, ux as CliUx } from '@oclif/core'; import ms from 'ms'; -import { debugLog, SquidRequest, streamSquidLogs, squidHistoryLogs } from '../api'; -import { CliCommand, SquidNameArg } from '../command'; +import { debugLog, squidHistoryLogs, SquidRequest, streamSquidLogs } from '../api'; +import { CliCommand, SquidReferenceArg } from '../command'; import { pretty } from '../logs'; -import { parseSquidName } from '../utils'; type LogResult = { hasLogs: boolean; @@ -21,11 +20,9 @@ function parseDate(str: string): Date { } export default class Logs extends CliCommand { - static aliases = ['squid:logs']; - static description = 'Fetch logs from a squid deployed to the Cloud'; static args = { - squidName: SquidNameArg, + squid_reference: SquidReferenceArg, }; static flags = { @@ -75,13 +72,12 @@ export default class Logs extends CliCommand { async run(): Promise { const { - args: { squidName }, + args: { squid_reference: reference }, flags: { follow, pageSize, container, level, since, org, search }, } = await this.parse(Logs); - const filter = parseSquidName(squidName); - const organization = await this.promptSquidOrganization(org, filter.name, 'using "-o" flag'); - const squid = await this.findOrThrowSquid({ organization, ...filter }); + const organization = await this.promptSquidOrganization({ code: org, reference }); + const squid = await this.findOrThrowSquid({ organization, reference }); if (!squid) return; const fromDate = parseDate(since); @@ -89,7 +85,7 @@ export default class Logs extends CliCommand { if (follow) { await this.fetchLogs({ organization, - squid, + reference, reverse: true, query: { limit: 30, @@ -101,7 +97,7 @@ export default class Logs extends CliCommand { }); await streamSquidLogs({ organization, - squid, + reference, onLog: (l) => this.log(l), query: { container, level, search }, }); @@ -112,7 +108,7 @@ export default class Logs extends CliCommand { do { const { hasLogs, nextPage }: LogResult = await this.fetchLogs({ organization, - squid, + reference, query: { limit: pageSize, from: fromDate, @@ -138,7 +134,7 @@ export default class Logs extends CliCommand { async fetchLogs({ organization, - squid, + reference, query, reverse, }: SquidRequest & { @@ -154,7 +150,8 @@ export default class Logs extends CliCommand { }; }): Promise { // eslint-disable-next-line prefer-const - let { logs, nextPage } = await squidHistoryLogs({ organization, squid, query }); + let { logs, nextPage } = await squidHistoryLogs({ organization, reference, query }); + if (reverse) { logs = logs.reverse(); } diff --git a/src/commands/ls.ts b/src/commands/ls.ts index ee868dc..5df1dcc 100644 --- a/src/commands/ls.ts +++ b/src/commands/ls.ts @@ -1,27 +1,27 @@ import { ux as CliUx, Flags } from '@oclif/core'; +import chalk from 'chalk'; import { listSquids } from '../api'; import { CliCommand } from '../command'; export default class Ls extends CliCommand { - static aliases = ['squid:ls']; - static description = 'List squids and squid versions deployed to the Cloud'; + static description = 'List squids deployed to the Cloud'; static flags = { name: Flags.string({ char: 'n', - description: 'squid name', + description: 'Filter by squid name', required: false, }), truncate: Flags.boolean({ char: 't', - description: 'truncate data in columns: false by default', + description: 'Truncate data in columns: false by default', required: false, default: false, }), org: Flags.string({ char: 'o', - description: 'Organization', + description: 'Organization code', required: false, }), }; @@ -33,8 +33,8 @@ export default class Ls extends CliCommand { const noTruncate = !truncate; const organization = name - ? await this.promptSquidOrganization(org, name, 'using "-o" flag') - : await this.promptOrganization(org, 'using "-o" flag'); + ? await this.promptSquidOrganization({ code: org, reference: name }) + : await this.promptOrganization(org); const squids = await listSquids({ organization, name }); if (squids) { @@ -42,31 +42,23 @@ export default class Ls extends CliCommand { squids, { name: { - header: 'Name', - }, - // description: {}, - slot: { - header: 'Deploy ID', - get: (s) => (s.slot ? `#${s.slot}` : `-`), + header: 'Squid', + get: (s) => `${s.name}${chalk.dim(`:${s.hash}`)}`, }, tags: { header: 'Tags', get: (s) => s.tags - .map((t) => `@${t.name}`) + .map((t) => t.name) .sort() .join(', '), }, - // urls: { - // header: 'API Urls', - // get: (s) => s.urls.map((u) => u.url).join('\n'), - // }, status: { header: 'Status', get: (s) => s.status?.toUpperCase(), }, deployedAt: { - header: 'Deployed at', + header: 'Deployed', get: (s) => (s.deployedAt ? new Date(s.deployedAt).toUTCString() : `-`), }, }, diff --git a/src/commands/prod.ts b/src/commands/prod.ts new file mode 100644 index 0000000..8db2c44 --- /dev/null +++ b/src/commands/prod.ts @@ -0,0 +1,23 @@ +import { Command } from '@oclif/core'; +import chalk from 'chalk'; + +export default class Prod extends Command { + static description = 'Assign the canonical production API alias for a squid deployed to the Cloud'; + + async run(): Promise { + await this.parse(Prod); + + // TODO write description + this.log( + [ + chalk.yellow('*******************************************************'), + chalk.yellow('* *'), + chalk.yellow('* WARNING! This command has been deprecated *'), + chalk.yellow('* Please check the migration guide *'), + chalk.yellow('* https://docs.subsquid.io/deploy-squid/migration/ *'), + chalk.yellow('* *'), + chalk.yellow('*******************************************************'), + ].join('\n'), + ); + } +} diff --git a/src/commands/restart.ts b/src/commands/restart.ts index 0c91250..769e48d 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -1,41 +1,18 @@ -import { Args, Flags } from '@oclif/core'; -import chalk from 'chalk'; +import { Flags } from '@oclif/core'; import { restartSquid } from '../api'; -import { SquidNameArg } from '../command'; +import { SquidReferenceArg } from '../command'; import { DeployCommand } from '../deploy-command'; -import { parseSquidName } from '../utils'; import { UPDATE_COLOR } from './deploy'; export default class Restart extends DeployCommand { - static aliases = ['squid:redeploy', 'redeploy']; - static description = 'Restart a squid deployed to the Cloud'; static args = { - squidName: SquidNameArg, + squid_reference: SquidReferenceArg, }; static flags = { - env: Flags.string({ - char: 'e', - description: 'environment variable', - required: false, - deprecated: true, - multiple: true, - hidden: true, - }), - envFile: Flags.string({ - description: 'file with environment variables', - deprecated: true, - required: false, - hidden: true, - }), - 'no-stream-logs': Flags.boolean({ - description: 'Do not attach and stream squid logs after the deploy', - required: false, - default: false, - }), org: Flags.string({ char: 'o', description: 'Organization', @@ -45,25 +22,17 @@ export default class Restart extends DeployCommand { async run(): Promise { const { - flags: { 'no-stream-logs': disableStreamLogs, org }, - args: { squidName }, + flags: { org }, + args: { squid_reference: reference }, } = await this.parse(Restart); - const filter = parseSquidName(squidName); + const organization = await this.promptSquidOrganization({ code: org, reference }); - const organization = await this.promptSquidOrganization(org, filter.name, 'using "-o" flag'); - const squid = await this.findOrThrowSquid({ organization, ...filter }); + await this.findOrThrowSquid({ organization, reference }); - const deploy = await restartSquid({ organization, squid }); + const deploy = await restartSquid({ organization, reference }); await this.pollDeploy({ organization, deploy }); - this.log( - [ - '', - chalk[UPDATE_COLOR](`=================================================`), - `The squid ${squid.name}#${squid.slot} has been successfully restarted`, - chalk[UPDATE_COLOR](`=================================================`), - ].join('\n'), - ); + this.logDeployResult(UPDATE_COLOR, `The squid ${reference} has been successfully restarted`); } } diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 6cbfa15..3dab302 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -1,21 +1,18 @@ -import { Args, ux as CliUx, Flags } from '@oclif/core'; -import chalk from 'chalk'; +import { Flags } from '@oclif/core'; import inquirer from 'inquirer'; import { deleteSquid } from '../api'; -import { SquidNameArg } from '../command'; +import { SquidReferenceArg } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidName, parseSquidName } from '../utils'; +import { formatSquidName } from '../utils'; -import { CREATE_COLOR, DELETE_COLOR } from './deploy'; +import { DELETE_COLOR } from './deploy'; export default class Rm extends DeployCommand { - static aliases = ['squid:kill', 'kill']; - - static description = 'Remove a squid or a squid version deployed to the Cloud'; + static description = 'Remove a squid deployed to the Cloud'; static args = { - squidName: SquidNameArg, + squid_reference: SquidReferenceArg, }; static flags = { @@ -33,14 +30,12 @@ export default class Rm extends DeployCommand { async run(): Promise { const { - args: { squidName }, + args: { squid_reference: reference }, flags: { force, org }, } = await this.parse(Rm); - const filter = parseSquidName(squidName); - - const organization = await this.promptSquidOrganization(org, filter.name, 'using "-o" flag'); - const squid = await this.findOrThrowSquid({ organization, ...filter }); + const organization = await this.promptSquidOrganization({ code: org, reference }); + const squid = await this.findOrThrowSquid({ organization, reference }); if (!force) { const { confirm } = await inquirer.prompt([ @@ -53,16 +48,9 @@ export default class Rm extends DeployCommand { if (!confirm) return; } - const deploy = await deleteSquid({ organization, squid }); + const deploy = await deleteSquid({ organization, reference }); await this.pollDeploy({ organization, deploy }); - this.log( - [ - '', - chalk[DELETE_COLOR](`-------------------------------------------------`), - `A squid deployment ${squid.name}#${squid.slot} was successfully deleted`, - chalk[DELETE_COLOR](`-------------------------------------------------`), - ].join('\n'), - ); + this.logDeployResult(DELETE_COLOR, `A squid deployment ${reference} was successfully deleted`); } } diff --git a/src/commands/secrets/ls.ts b/src/commands/secrets/ls.ts index 2109774..397b753 100644 --- a/src/commands/secrets/ls.ts +++ b/src/commands/secrets/ls.ts @@ -20,7 +20,7 @@ export default class Ls extends CliCommand { args: {}, } = await this.parse(Ls); - const organization = await this.promptOrganization(org, 'using "-o" flag'); + const organization = await this.promptOrganization(org); const response = await listSecrets({ organization }); if (!Object.keys(response.secrets).length) { diff --git a/src/commands/secrets/rm.ts b/src/commands/secrets/rm.ts index c182600..582a376 100644 --- a/src/commands/secrets/rm.ts +++ b/src/commands/secrets/rm.ts @@ -26,7 +26,7 @@ export default class Rm extends CliCommand { args: { name }, } = await this.parse(Rm); - const organization = await this.promptOrganization(org, 'using "-o" flag'); + const organization = await this.promptOrganization(org); await removeSecret({ organization, name }); this.log(`Secret '${name}' removed`); diff --git a/src/commands/secrets/set.ts b/src/commands/secrets/set.ts index 629a887..05f2395 100644 --- a/src/commands/secrets/set.ts +++ b/src/commands/secrets/set.ts @@ -37,7 +37,7 @@ export default class Set extends CliCommand { args: { name, value }, } = await this.parse(Set); - const organization = await this.promptOrganization(org, 'using "-o" flag'); + const organization = await this.promptOrganization(org); let secretValue = value; if (!secretValue) { diff --git a/src/commands/tag.ts b/src/commands/tag.ts index 2bb62c0..1486f72 100644 --- a/src/commands/tag.ts +++ b/src/commands/tag.ts @@ -1,12 +1,11 @@ -// import { buildTable, updateDemoTag } from '../api/demoStore'; import { Args, Flags } from '@oclif/core'; import chalk from 'chalk'; import inquirer from 'inquirer'; import { tagSquid } from '../api'; -import { SquidNameArg } from '../command'; +import { SquidReferenceArg } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidName, parseSquidName } from '../utils'; +import { formatSquidName } from '../utils'; import { UPDATE_COLOR } from './deploy'; @@ -14,7 +13,8 @@ export default class Tag extends DeployCommand { static description = 'Set a tag for squid'; static args = { - squid: SquidNameArg, + squid_reference: SquidReferenceArg, + tag: Args.string({ description: `New tag to assign`, required: true, @@ -31,23 +31,30 @@ export default class Tag extends DeployCommand { async run(): Promise { const { - args: { squid: squidName, tag }, + args: { squid_reference: reference, tag }, flags: { org }, } = await this.parse(Tag); - const filter = parseSquidName(squidName); + const organization = await this.promptSquidOrganization({ code: org, reference }); + const squid = await this.findOrThrowSquid({ organization, reference }); - const organization = await this.promptSquidOrganization(org, filter.name, 'using "-o" flag'); - const squid = await this.findOrThrowSquid({ organization, ...filter }); + if (squid.tags.find((t) => t.name === tag)) { + return this.log(`Tag ${tag} is already assigned to the squid ${formatSquidName(squid)}`); + } - const normalizedTag = tag.startsWith('@') ? tag.slice(1) : tag; - const oldSquid = await this.findSquid({ organization, name: filter.name, tag: normalizedTag }); + const oldSquid = await this.findSquid({ organization, reference: `${squid.name}@${tag}` }); if (oldSquid) { const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', - message: `A squid tag @${normalizedTag} has already been assigned to the previous squid deployment ${formatSquidName(oldSquid)}. Are you sure?`, + message: [ + chalk.reset( + `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidName(oldSquid)}.`, + ), + chalk.reset(`The tag URL will be assigned to the newly created deployment.`), + chalk.bold(`Are you sure?`), + ].join('\n'), }, ]); if (!confirm) return; @@ -55,20 +62,13 @@ export default class Tag extends DeployCommand { const deploy = await tagSquid({ organization, - squid, + reference, data: { tag, }, }); await this.pollDeploy({ organization, deploy }); - this.log( - [ - '', - chalk[UPDATE_COLOR](`=================================================`), - `The squid ${squid.name}#${squid.slot} has been successfully updated`, - chalk[UPDATE_COLOR](`=================================================`), - ].join('\n'), - ); + this.logDeployResult(UPDATE_COLOR, `The squid ${squid.name}#${squid.hash} has been successfully updated`); } } diff --git a/src/deploy-command.ts b/src/deploy-command.ts index 83ec241..b57df64 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -1,24 +1,13 @@ import { ux as CliUx } from '@oclif/core'; -import chalk from 'chalk'; +import chalk, { ForegroundColor } from 'chalk'; import inquirer from 'inquirer'; -import { - ApiError, - Deploy, - DeployRequest, - DeployStatus, - getDeploy, - getSquid, - listSquids, - OrganizationRequest, - Squid, - streamSquidLogs, -} from './api'; -import { CliCommand } from './command'; +import { Deployment, DeployRequest, getDeploy, Organization, Squid, streamSquidLogs } from './api'; +import { CliCommand, SUCCESS_CHECK_MARK } from './command'; import { doUntil } from './utils'; export abstract class DeployCommand extends CliCommand { - deploy: Deploy | undefined; + deploy: Deployment | undefined; logsPrinted = 0; async attachToParallelDeploy(squid: Squid) { @@ -32,7 +21,7 @@ export abstract class DeployCommand extends CliCommand { { name: 'confirm', type: 'confirm', - message: `Squid "${squid.name}#${squid.slot}" is being deploying. + message: `Squid "${squid.name}#${squid.hash}" is being deploying. You can not run deploys on the same squid in parallel. Do you want to attach to the running deploy process?`, }, @@ -43,6 +32,7 @@ Do you want to attach to the running deploy process?`, await this.pollDeploy({ organization: squid.organization, deploy: squid.lastDeploy, + streamLogs: true, }); } @@ -50,7 +40,10 @@ Do you want to attach to the running deploy process?`, } } - async pollDeploy({ deploy, organization }: DeployRequest): Promise { + async pollDeploy({ + deploy, + organization, + }: DeployRequest & { streamLogs?: boolean }): Promise { let lastStatus: string; let validatedPrinted = false; @@ -65,7 +58,7 @@ Do you want to attach to the running deploy process?`, if (this.isFailed()) return this.showError(`An error occurred while deploying the squid`); if (this.deploy.status === lastStatus) return false; lastStatus = this.deploy.status; - CliUx.ux.action.stop('✔️'); + CliUx.ux.action.stop(SUCCESS_CHECK_MARK); switch (this.deploy.status) { case 'UNPACKING': @@ -105,12 +98,12 @@ Do you want to attach to the running deploy process?`, CliUx.ux.action.start('◷ Syncing the squid addons'); return false; - case 'TAGGING': - CliUx.ux.action.start('◷ Tagging the squid'); + case 'CONFIGURING_INGRESS': + CliUx.ux.action.start('◷ Configuring ingress'); return false; case 'OK': - this.log(`Done! ✔️`); + this.log(`Done! ${SUCCESS_CHECK_MARK}`); return true; default: @@ -123,16 +116,20 @@ Do you want to attach to the running deploy process?`, }, { pause: 3000 }, ); - if (!this.deploy?.squid) return; - const squid = await getSquid({ + return this.deploy; + } + + async streamLogs(organization: Organization, squid: Pick) { + CliUx.ux.action.start(`Streaming logs from the squid`); + + await streamSquidLogs({ organization, - squid: this.deploy.squid, + reference: squid.reference, + onLog: (l) => this.log(l), }); - if (!squid) return; - - return squid; } + printDebug = () => { if (!this.deploy) return; @@ -173,7 +170,7 @@ Do you want to attach to the running deploy process?`, ); if (this.deploy?.squid) { - errors.push(`${chalk.dim('Squid:')} ${this.deploy.squid.name}#${this.deploy.squid.slot}`); + errors.push(`${chalk.dim('Squid:')} ${this.deploy.squid.name}#${this.deploy.squid.hash}`); } } @@ -186,4 +183,15 @@ Do you want to attach to the running deploy process?`, return this.deploy.failed !== 'NO'; } + + logDeployResult(color: typeof ForegroundColor, message: string) { + this.log( + [ + '', + chalk[color](`=================================================`), + message, + chalk[color](`=================================================`), + ].join('\n'), + ); + } } diff --git a/src/help.ts b/src/help.ts index e3bbbd4..042b504 100644 --- a/src/help.ts +++ b/src/help.ts @@ -90,7 +90,7 @@ export default class Help extends OclifHelp { const [description] = (c.summary || c.description || '').split('\n'); return { - name: c.id, + name: c.id.replace(':', ' '), aliases: c.aliases, description: description, }; diff --git a/src/manifest/manifest.ts b/src/manifest/manifest.ts index d6d2aa3..5e277f3 100644 --- a/src/manifest/manifest.ts +++ b/src/manifest/manifest.ts @@ -3,23 +3,14 @@ import path from 'path'; import { Manifest } from '@subsquid/manifest'; import { Expression, Parser } from '@subsquid/manifest-expr'; -import yaml from 'js-yaml'; import { mapValues } from 'lodash'; export function readManifest(path: string) { - return yaml.load(fs.readFileSync(path).toString()) as Partial; + return fs.readFileSync(path).toString(); } -export function saveManifest(path: string, manifest: Partial) { - fs.writeFileSync(path, formatManifest(manifest)); -} - -export function formatManifest(manifest: Partial): string { - return yaml.dump(manifest, { - styles: { - 'tag:yaml.org,2002:null': 'empty', - }, - }); +export function saveManifest(path: string, manifest: string) { + fs.writeFileSync(path, manifest); } export function evalManifestEnv(env: Record, context: Record) { diff --git a/src/manifest/manifest.unit.spec.ts b/src/manifest/manifest.unit.spec.ts deleted file mode 100644 index 8e986c6..0000000 --- a/src/manifest/manifest.unit.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { formatManifest } from './manifest'; - -describe('Manifest', () => { - describe('formatManifest', () => { - it('should replace null as empty string', () => { - const formatted = formatManifest({ - name: 'test', - version: 1, - build: null as any, - }); - - expect(formatted).toEqual(['name: test', 'version: 1', 'build: ', ''].join('\n')); - }); - }); -}); diff --git a/src/ui/components/VersionLogsTab.ts b/src/ui/components/VersionLogsTab.ts index 1cb9d21..7983392 100644 --- a/src/ui/components/VersionLogsTab.ts +++ b/src/ui/components/VersionLogsTab.ts @@ -1,7 +1,7 @@ import { addMinutes } from 'date-fns'; -import blessed, { Element, List, Log } from 'reblessed'; +import blessed, { Element } from 'reblessed'; -import { streamSquidLogs, squidHistoryLogs } from '../../api'; +import { squidHistoryLogs, streamSquidLogs } from '../../api'; import { pretty } from '../../logs'; import { mainColor, scrollBarTheme } from '../theme'; @@ -39,13 +39,14 @@ export class VersionLogTab implements VersionTab { try { const { logs } = await squidHistoryLogs({ organization: squid.organization, - squid: squid, + reference: squid.reference, query: { limit: 100, from: addMinutes(new Date(), -30), }, abortController, }); + pretty(logs.reverse()).forEach((line) => { logsBox.add(line); }); @@ -60,7 +61,7 @@ export class VersionLogTab implements VersionTab { streamSquidLogs({ organization: squid.organization, - squid, + reference: squid.reference, onLog: (line) => { logsBox.add(line); }, diff --git a/src/ui/components/VersionSummaryTab.ts b/src/ui/components/VersionSummaryTab.ts index 26231d7..62e8445 100644 --- a/src/ui/components/VersionSummaryTab.ts +++ b/src/ui/components/VersionSummaryTab.ts @@ -27,7 +27,10 @@ export class VersionSummaryTab implements VersionTab { } lines.push(`${chalkMainColor(`API`)} ${chalkMainColor(squid.api?.status)}`); - lines.push(`${squid.api?.url}`); + for (const url of squid.api?.urls || []) { + lines.push(`${url.url}`); + } + lines.push(''); const table = new Table({ diff --git a/src/utils.ts b/src/utils.ts index 783989d..ed3ca16 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,5 @@ -import { Command } from '@oclif/core'; import { ConfigNotFound, getConfig } from '@subsquid/commands'; +import chalk from 'chalk'; export async function getSquidCommands() { try { @@ -23,19 +23,21 @@ export async function doUntil(fn: () => Promise, { pause }: { pause: nu } } -export function parseSquidName(squidName: string) { - if (squidName.includes('#')) { - const [name, slot] = squidName.split('#'); - return { name, slot }; - } else if (squidName.includes('#')) { - const [name, tag] = squidName.split('@'); +export const SQUID_HASH_SYMBOL = ':'; +export const SQUID_TAG_SYMBOL = '@'; + +export function parseSquidReference(reference: string) { + if (reference.includes(SQUID_HASH_SYMBOL)) { + const [name, hash] = reference.split(SQUID_HASH_SYMBOL); + return { name, hash }; + } else if (reference.includes(SQUID_TAG_SYMBOL)) { + const [name, tag] = reference.split(SQUID_TAG_SYMBOL); return { name, tag }; - } else { - throw new Error(`Invalid squid name: "${squidName}"`); } + + throw new Error(`Invalid squid reference: "${reference}"`); } -export function formatSquidName( - opts: { name: string; tag: string; slot?: undefined } | { name: string; slot: string; tag?: undefined }, -) { - return 'tag' in opts ? `${opts.name}@${opts.tag}` : `${opts.name}#${opts.slot}`; + +export function formatSquidName({ reference }: { reference: string }) { + return chalk.bold(reference); } diff --git a/yarn.lock b/yarn.lock index 3731a28..0ef8690 100644 --- a/yarn.lock +++ b/yarn.lock @@ -516,7 +516,14 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.10.0": + version: 4.11.0 + resolution: "@eslint-community/regexpp@npm:4.11.0" + checksum: 10c0/0f6328869b2741e2794da4ad80beac55cba7de2d3b44f796a60955b0586212ec75e6b0253291fd4aad2100ad471d1480d8895f2b54f1605439ba4c875e05e523 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: 10c0/c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 @@ -1068,9 +1075,9 @@ __metadata: languageName: node linkType: hard -"@oclif/core@npm:3.26.0, @oclif/core@npm:^3.23.0": - version: 3.26.0 - resolution: "@oclif/core@npm:3.26.0" +"@oclif/core@npm:3.27.0": + version: 3.27.0 + resolution: "@oclif/core@npm:3.27.0" dependencies: "@types/cli-progress": "npm:^3.11.5" ansi-escapes: "npm:^4.3.2" @@ -1080,15 +1087,15 @@ __metadata: clean-stack: "npm:^3.0.1" cli-progress: "npm:^3.12.0" color: "npm:^4.2.3" - debug: "npm:^4.3.4" - ejs: "npm:^3.1.9" + debug: "npm:^4.3.5" + ejs: "npm:^3.1.10" get-package-type: "npm:^0.1.0" globby: "npm:^11.1.0" hyperlinker: "npm:^1.0.0" indent-string: "npm:^4.0.0" is-wsl: "npm:^2.2.0" js-yaml: "npm:^3.14.1" - minimatch: "npm:^9.0.3" + minimatch: "npm:^9.0.4" natural-orderby: "npm:^2.0.3" object-treeify: "npm:^1.1.33" password-prompt: "npm:^1.1.3" @@ -1100,7 +1107,7 @@ __metadata: widest-line: "npm:^3.1.0" wordwrap: "npm:^1.0.0" wrap-ansi: "npm:^7.0.0" - checksum: 10c0/e2a066b85b7cd6996e0bc261f53399f06dcbb888caf0b31ba935068abaa69e9e6497d759e25a105f83a2bee3c23ba10fee51b0575417324a8e174827d95714e3 + checksum: 10c0/4f663ccb3bed74fa5b73a82f3bf722c9be5564f0543cc29bd70e1a76b953bd2fe6ca1d6684561a3bd7bd1fe70eab1855b98f5563b2109d11161c06283c312b93 languageName: node linkType: hard @@ -1243,15 +1250,15 @@ __metadata: languageName: node linkType: hard -"@oclif/plugin-autocomplete@npm:3.0.13": - version: 3.0.13 - resolution: "@oclif/plugin-autocomplete@npm:3.0.13" +"@oclif/plugin-autocomplete@npm:3.2.2": + version: 3.2.2 + resolution: "@oclif/plugin-autocomplete@npm:3.2.2" dependencies: - "@oclif/core": "npm:^3.23.0" - chalk: "npm:^5.3.0" - debug: "npm:^4.3.4" - ejs: "npm:^3.1.9" - checksum: 10c0/121104795e3336ac477ab9eb93769f1e70573836191b05a5ecbc5cdf7b7949c319bb5702f3b362d5ae561d87f6615ed6243b32472d60da39d043a0623094186f + "@oclif/core": "npm:^4" + ansis: "npm:^3.3.1" + debug: "npm:^4.3.6" + ejs: "npm:^3.1.10" + checksum: 10c0/cdd81336791080a12f1fcd41d443335b62912f70190989335fd15b7ec4cb89bea55396b75d9a6e73dc010990ff3e74fb7eb2ad43097fa06ec8746189b207c851 languageName: node linkType: hard @@ -1274,16 +1281,16 @@ __metadata: languageName: node linkType: hard -"@oclif/plugin-warn-if-update-available@npm:^3.1.6": - version: 3.1.6 - resolution: "@oclif/plugin-warn-if-update-available@npm:3.1.6" +"@oclif/plugin-warn-if-update-available@npm:^3.1.13": + version: 3.1.13 + resolution: "@oclif/plugin-warn-if-update-available@npm:3.1.13" dependencies: "@oclif/core": "npm:^4" - ansis: "npm:^3.2.0" + ansis: "npm:^3.3.1" debug: "npm:^4.3.5" http-call: "npm:^5.2.2" lodash: "npm:^4.17.21" - checksum: 10c0/7a7bffc26f94c8860a9955a9f1de08f61d6763943bc4d8d6a4079778ae7e8a1b1480058e8cb415e39658cc0fa2e95f8d9427a54493d8437bf947cfbe3e459498 + checksum: 10c0/4e6bfc6b278f8b6e0f3aa0bd6993b001bd78eb1000bf7ca6a0d9467f8e0cde505b1e7df53747b6357246bf5dc85fb36861cea288ef91f28f91bbd884f2fb7fe5 languageName: node linkType: hard @@ -1398,13 +1405,13 @@ __metadata: version: 0.0.0-use.local resolution: "@subsquid/cli@workspace:." dependencies: - "@oclif/core": "npm:3.26.0" + "@oclif/core": "npm:3.27.0" "@oclif/dev-cli": "npm:^1.26.10" "@oclif/help": "npm:^1.0.15" - "@oclif/plugin-autocomplete": "npm:3.0.13" - "@oclif/plugin-warn-if-update-available": "npm:^3.1.6" + "@oclif/plugin-autocomplete": "npm:3.2.2" + "@oclif/plugin-warn-if-update-available": "npm:^3.1.13" "@subsquid/commands": "npm:^2.3.1" - "@subsquid/manifest": "npm:^1.0.0-beta.11" + "@subsquid/manifest": "npm:^1.0.0-beta.12" "@subsquid/manifest-expr": "npm:^0.0.1" "@types/async-retry": "npm:^1.4.8" "@types/blessed": "npm:^0.1.25" @@ -1414,20 +1421,21 @@ __metadata: "@types/inquirer": "npm:^8.2.10" "@types/jest": "npm:^29.5.12" "@types/js-yaml": "npm:^4.0.9" - "@types/lodash": "npm:^4.17.0" + "@types/lodash": "npm:^4.17.7" "@types/ms": "npm:^0.7.34" - "@types/node": "npm:^20.12.3" - "@types/qs": "npm:^6.9.14" + "@types/node": "npm:^20.16.2" + "@types/qs": "npm:^6.9.15" "@types/split2": "npm:^3.2.1" "@types/targz": "npm:^1.0.4" - "@typescript-eslint/eslint-plugin": "npm:^7.5.0" + "@typescript-eslint/eslint-plugin": "npm:^7.18.0" "@typescript-eslint/eslint-plugin-tslint": "npm:^7.0.2" - "@typescript-eslint/parser": "npm:^7.5.0" + "@typescript-eslint/parser": "npm:^7.18.0" async-retry: "npm:^1.3.3" - axios: "npm:^1.6.8" - axios-retry: "npm:^4.1.0" + axios: "npm:^1.7.5" + axios-retry: "npm:^4.5.0" blessed-contrib: "npm:^4.11.0" chalk: "npm:^4.1.2" + cli-diff: "npm:^1.0.0" cli-select: "npm:^1.1.2" cross-spawn: "npm:^7.0.3" date-fns: "npm:^3.6.0" @@ -1443,8 +1451,8 @@ __metadata: fast-levenshtein: "npm:^3.0.0" figlet: "npm:^1.7.0" form-data: "npm:^4.0.0" - glob: "npm:^10.3.12" - ignore: "npm:^5.3.1" + glob: "npm:^10.4.5" + ignore: "npm:^5.3.2" inquirer: "npm:^8.2.6" jest: "npm:^29.7.0" js-yaml: "npm:^4.1.0" @@ -1454,19 +1462,18 @@ __metadata: open: "npm:^8.1.0" openapi-typescript: "npm:^7.3.0" pkg: "npm:^5.8.1" - prettier: "npm:^3.2.5" + prettier: "npm:^3.3.3" pretty-bytes: "npm:^5.6.0" - qs: "npm:^6.12.0" + qs: "npm:^6.13.0" reblessed: "npm:^0.2.1" - simple-git: "npm:^3.24.0" + simple-git: "npm:^3.25.0" split2: "npm:^4.2.0" targz: "npm:^1.0.1" tree-kill: "npm:^1.2.2" - ts-jest: "npm:^29.1.2" + ts-jest: "npm:^29.2.5" ts-node: "npm:^10.9.2" - type-fest: "npm:^4.24.0" - typescript: "npm:~5.4.3" - unique-names-generator: "npm:^4.7.1" + type-fest: "npm:^4.26.0" + typescript: "npm:~5.5.4" bin: sqd: ./bin/run.js languageName: unknown @@ -1505,15 +1512,15 @@ __metadata: languageName: node linkType: hard -"@subsquid/manifest@npm:^1.0.0-beta.11": - version: 1.0.0-beta.11 - resolution: "@subsquid/manifest@npm:1.0.0-beta.11" +"@subsquid/manifest@npm:^1.0.0-beta.12": + version: 1.0.0-beta.12 + resolution: "@subsquid/manifest@npm:1.0.0-beta.12" dependencies: "@subsquid/manifest-expr": "npm:^0.0.1" joi: "npm:^17.12.0" js-yaml: "npm:^4.1.0" lodash: "npm:^4.17.21" - checksum: 10c0/6ced44b1943c90e46557d56654da2dbedf28d83b0d4b0e2201effc33d9a4501ce433320593640ad92e29d9ef1ce381c7542250afd10d9f85b9b3967a50061748 + checksum: 10c0/ad95eadcc8c0093c7954cdb7a7ed81b67592736e9c30eea6299f883abbc4e95d0c8b249e2c769cfeb3e1175b8d2f03a8b96d76d489bb82a87526280416d7973a languageName: node linkType: hard @@ -1638,11 +1645,11 @@ __metadata: linkType: hard "@types/cli-progress@npm:^3.11.5": - version: 3.11.5 - resolution: "@types/cli-progress@npm:3.11.5" + version: 3.11.6 + resolution: "@types/cli-progress@npm:3.11.6" dependencies: "@types/node": "npm:*" - checksum: 10c0/bf00f543ee677f61b12e390876df59354943d6c13d96640171528e9b7827f4edb7701cdd4675d6256d13ef9ee542731bd5cae585e1b43502553f69fc210dcb92 + checksum: 10c0/d9a2d60b8fc6ccef73368fa20a23d5b16506808a81ec65f7e8eedf58d236ebaf2ab46578936c000c8e39dde825cb48a3cf9195c8b410177efd5388bcf9d07370 languageName: node linkType: hard @@ -1754,10 +1761,10 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.17.0": - version: 4.17.0 - resolution: "@types/lodash@npm:4.17.0" - checksum: 10c0/4c5b41c9a6c41e2c05d08499e96f7940bcf194dcfa84356235b630da920c2a5e05f193618cea76006719bec61c76617dff02defa9d29934f9f6a76a49291bd8f +"@types/lodash@npm:^4.17.7": + version: 4.17.7 + resolution: "@types/lodash@npm:4.17.7" + checksum: 10c0/40c965b5ffdcf7ff5c9105307ee08b782da228c01b5c0529122c554c64f6b7168fc8f11dc79aa7bae4e67e17efafaba685dc3a47e294dbf52a65ed2b67100561 languageName: node linkType: hard @@ -1782,19 +1789,19 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.12.3": - version: 20.12.3 - resolution: "@types/node@npm:20.12.3" +"@types/node@npm:^20.16.2": + version: 20.16.2 + resolution: "@types/node@npm:20.16.2" dependencies: - undici-types: "npm:~5.26.4" - checksum: 10c0/45c8485a0e55276b42c26ba1df6c480e4e1a3a3abbf4ea0ff6b4e2823c4f77e32b7e166d4263d464f207cfea5bd4de8879b8df2c7132a727b0346a30191d6bea + undici-types: "npm:~6.19.2" + checksum: 10c0/74fac185dbd2c6b301cde75747c1cd6c9ca1ad7266147ea107a798837f40b8a05991177ebd7925fc7450d51334096259d186afad6e0d22864b7c97f8afef6ba7 languageName: node linkType: hard -"@types/qs@npm:^6.9.14": - version: 6.9.14 - resolution: "@types/qs@npm:6.9.14" - checksum: 10c0/11ad1eb7f6d7c216002789959d88acc7c43f72854fa4335f01de0df41b4c4024668dace8a37ba12270314345ede0ec6b07f93053a45e7bd4cd7318a3dcf0b6b8 +"@types/qs@npm:^6.9.15": + version: 6.9.15 + resolution: "@types/qs@npm:6.9.15" + checksum: 10c0/49c5ff75ca3adb18a1939310042d273c9fc55920861bd8e5100c8a923b3cda90d759e1a95e18334092da1c8f7b820084687770c83a1ccef04fb2c6908117c823 languageName: node linkType: hard @@ -1894,46 +1901,44 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.5.0" +"@typescript-eslint/eslint-plugin@npm:^7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0" dependencies: - "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:7.5.0" - "@typescript-eslint/type-utils": "npm:7.5.0" - "@typescript-eslint/utils": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" - debug: "npm:^4.3.4" + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:7.18.0" + "@typescript-eslint/type-utils": "npm:7.18.0" + "@typescript-eslint/utils": "npm:7.18.0" + "@typescript-eslint/visitor-keys": "npm:7.18.0" graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.4" + ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: "@typescript-eslint/parser": ^7.0.0 eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/932a7b5a09c0138ef5a0bf00f8e6039fa209d4047092ffc187de048543c21f7ce24dc14f25f4c87b6f3bbb62335fc952e259e271fde88baf793217bde6460cfa + checksum: 10c0/2b37948fa1b0dab77138909dabef242a4d49ab93e4019d4ef930626f0a7d96b03e696cd027fa0087881c20e73be7be77c942606b4a76fa599e6b37f6985304c3 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/parser@npm:7.5.0" +"@typescript-eslint/parser@npm:^7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/parser@npm:7.18.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.5.0" - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/typescript-estree": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" + "@typescript-eslint/scope-manager": "npm:7.18.0" + "@typescript-eslint/types": "npm:7.18.0" + "@typescript-eslint/typescript-estree": "npm:7.18.0" + "@typescript-eslint/visitor-keys": "npm:7.18.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/65521202ff024e79594272fbb7e4731ecf9d2fdd2f58fc81450bfd2bca94ce9c17b0eadd7338c01701f5cf16d38b6c025ed3fc322380b1e4b5424b7484098cda + checksum: 10c0/370e73fca4278091bc1b657f85e7d74cd52b24257ea20c927a8e17546107ce04fbf313fec99aed0cc2a145ddbae1d3b12e9cc2c1320117636dc1281bcfd08059 languageName: node linkType: hard @@ -1947,30 +1952,30 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/scope-manager@npm:7.5.0" +"@typescript-eslint/scope-manager@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/scope-manager@npm:7.18.0" dependencies: - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" - checksum: 10c0/a017b151a6b39ef591f8e2e65598e005e1b4b2d5494e4b91bddb5856b3a4d57dd8a58d2bc7a140e627eb574f93a2c8fe55f1307aa264c928ffd31d9e190bc5dd + "@typescript-eslint/types": "npm:7.18.0" + "@typescript-eslint/visitor-keys": "npm:7.18.0" + checksum: 10c0/038cd58c2271de146b3a594afe2c99290034033326d57ff1f902976022c8b0138ffd3cb893ae439ae41003b5e4bcc00cabf6b244ce40e8668f9412cc96d97b8e languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/type-utils@npm:7.5.0" +"@typescript-eslint/type-utils@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/type-utils@npm:7.18.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.5.0" - "@typescript-eslint/utils": "npm:7.5.0" + "@typescript-eslint/typescript-estree": "npm:7.18.0" + "@typescript-eslint/utils": "npm:7.18.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/12915d4d1872638f5281e222a0d191676c478f250699c84864862e95a59e708222acefbf7ffdafc0872a007261219a3a2b1e667ff45eeafea7c4bcc5b955262c + checksum: 10c0/ad92a38007be620f3f7036f10e234abdc2fdc518787b5a7227e55fd12896dacf56e8b34578723fbf9bea8128df2510ba8eb6739439a3879eda9519476d5783fd languageName: node linkType: hard @@ -1981,10 +1986,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/types@npm:7.5.0" - checksum: 10c0/f3394f71f422dbd89f63b230f20e9769c12e47a287ff30ca03a80714e57ea21279b6f12a8ab14bafb00b59926f20a88894b2d1e72679f7ff298bae112679d4b3 +"@typescript-eslint/types@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/types@npm:7.18.0" + checksum: 10c0/eb7371ac55ca77db8e59ba0310b41a74523f17e06f485a0ef819491bc3dd8909bb930120ff7d30aaf54e888167e0005aa1337011f3663dc90fb19203ce478054 languageName: node linkType: hard @@ -2007,22 +2012,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.5.0" +"@typescript-eslint/typescript-estree@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.18.0" dependencies: - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/visitor-keys": "npm:7.5.0" + "@typescript-eslint/types": "npm:7.18.0" + "@typescript-eslint/visitor-keys": "npm:7.18.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" - minimatch: "npm:9.0.3" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/ea3a270c725d6be273188b86110e0393052cd64d1c54a56eb5ea405e6d3fbbe84fb3b1ce1b8496a4078ac1eefd37aedcf12be91876764f6de31d5aa5131c7bcd + checksum: 10c0/0c7f109a2e460ec8a1524339479cf78ff17814d23c83aa5112c77fb345e87b3642616291908dcddea1e671da63686403dfb712e4a4435104f92abdfddf9aba81 languageName: node linkType: hard @@ -2043,20 +2048,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/utils@npm:7.5.0" +"@typescript-eslint/utils@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/utils@npm:7.18.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@types/json-schema": "npm:^7.0.12" - "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:7.5.0" - "@typescript-eslint/types": "npm:7.5.0" - "@typescript-eslint/typescript-estree": "npm:7.5.0" - semver: "npm:^7.5.4" + "@typescript-eslint/scope-manager": "npm:7.18.0" + "@typescript-eslint/types": "npm:7.18.0" + "@typescript-eslint/typescript-estree": "npm:7.18.0" peerDependencies: eslint: ^8.56.0 - checksum: 10c0/c815ed6909769648953d6963c069038f7cac0c979051b25718feb30e0d3337b9647b75b8de00ac03fe960f0cc8dc4e8a81d4aac4719090a99785e0068712bd24 + checksum: 10c0/a25a6d50eb45c514469a01ff01f215115a4725fb18401055a847ddf20d1b681409c4027f349033a95c4ff7138d28c3b0a70253dfe8262eb732df4b87c547bd1e languageName: node linkType: hard @@ -2070,13 +2072,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.5.0": - version: 7.5.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.5.0" +"@typescript-eslint/visitor-keys@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.18.0" dependencies: - "@typescript-eslint/types": "npm:7.5.0" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10c0/eecf02b8dd54e83738a143aca87b902af4b357028a90fd34ed7a2f40a3ae2f6a188b9ba53903f23c80e868f1fffbb039e9ddb63525438d659707cc7bfb269317 + "@typescript-eslint/types": "npm:7.18.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 10c0/538b645f8ff1d9debf264865c69a317074eaff0255e63d7407046176b0f6a6beba34a6c51d511f12444bae12a98c69891eb6f403c9f54c6c2e2849d1c1cb73c0 languageName: node linkType: hard @@ -2274,13 +2276,20 @@ __metadata: languageName: node linkType: hard -"ansis@npm:^3.1.1, ansis@npm:^3.2.0": +"ansis@npm:^3.1.1": version: 3.2.0 resolution: "ansis@npm:3.2.0" checksum: 10c0/b61c16554e707f30685ab153ffafc02b59bb9e86567a04b2e2ad521ade771c9ae3cd67f3e486a1cd2e3c89ad898653266bc38d76ea7af4ac67762baa3c87befa languageName: node linkType: hard +"ansis@npm:^3.3.1": + version: 3.3.2 + resolution: "ansis@npm:3.3.2" + checksum: 10c0/7b5bd3d28e5fa12dbd2268e984b292540f863bb113fbaa78be93e512417df014e547279ecec264b39948364e13f245424a0bc911802d68def185545d2290d11c + languageName: node + linkType: hard + "anymatch@npm:^3.0.3": version: 3.1.2 resolution: "anymatch@npm:3.1.2" @@ -2461,25 +2470,25 @@ __metadata: languageName: node linkType: hard -"axios-retry@npm:^4.1.0": - version: 4.1.0 - resolution: "axios-retry@npm:4.1.0" +"axios-retry@npm:^4.5.0": + version: 4.5.0 + resolution: "axios-retry@npm:4.5.0" dependencies: is-retry-allowed: "npm:^2.2.0" peerDependencies: axios: 0.x || 1.x - checksum: 10c0/381ae8b03f2edf444e426a4be3c94e31b0b66c45bac30ce0dcf3aff48d9f2ed9607c826fa32d4a8cf0d40ae0cb9369449bb69837abe478d8821ce3375f34d73a + checksum: 10c0/574e7b1bf24aad99b560042d232a932d51bfaa29b5a6d4612d748ed799a6f11a5afb2582792492c55d95842200cbdfbe3454027a8c1b9a2d3e895d13c3d03c10 languageName: node linkType: hard -"axios@npm:^1.6.8": - version: 1.6.8 - resolution: "axios@npm:1.6.8" +"axios@npm:^1.7.5": + version: 1.7.5 + resolution: "axios@npm:1.7.5" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 + checksum: 10c0/1d5daeb28b3d1bb2a7b9f0743433c4bfbeaddc15461e50ebde487eec6c009af2515749d5261096dd430c90cd891bd310bcba5ec3967bae2033c4a307f58a6ad3 languageName: node linkType: hard @@ -2665,7 +2674,7 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:0.x": +"bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" dependencies: @@ -2867,13 +2876,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^5.3.0": - version: 5.3.0 - resolution: "chalk@npm:5.3.0" - checksum: 10c0/8297d436b2c0f95801103ff2ef67268d362021b8210daf8ddbe349695333eb3610a71122172ff3b0272f1ef2cf7cc2c41fdaa4715f52e49ffe04c56340feed09 - languageName: node - linkType: hard - "char-regex@npm:^1.0.2": version: 1.0.2 resolution: "char-regex@npm:1.0.2" @@ -2948,6 +2950,16 @@ __metadata: languageName: node linkType: hard +"cli-diff@npm:^1.0.0": + version: 1.0.0 + resolution: "cli-diff@npm:1.0.0" + dependencies: + chalk: "npm:^2.4.1" + diff: "npm:^3.5.0" + checksum: 10c0/8dcb8c10d11f3c7479cb39b014e0a5080d7b4b5cd9befe3359b305d4c2dfadf14d46cbc458e21fddf2fb68a1cc19a9e86b01ba8f9ac498476c6391872f98b13c + languageName: node + linkType: hard + "cli-progress@npm:^3.12.0": version: 3.12.0 resolution: "cli-progress@npm:3.12.0" @@ -3268,6 +3280,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.3.6": + version: 4.3.6 + resolution: "debug@npm:4.3.6" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/3293416bff072389c101697d4611c402a6bacd1900ac20c0492f61a9cdd6b3b29750fc7f5e299f8058469ef60ff8fb79b86395a30374fbd2490113c1c7112285 + languageName: node + linkType: hard + "decompress-response@npm:^6.0.0": version: 6.0.0 resolution: "decompress-response@npm:6.0.0" @@ -3405,6 +3429,13 @@ __metadata: languageName: node linkType: hard +"diff@npm:^3.5.0": + version: 3.5.0 + resolution: "diff@npm:3.5.0" + checksum: 10c0/fc62d5ba9f6d1b8b5833380969037007913d4886997838c247c54ec6934f09ae5a07e17ae28b1f016018149d81df8ad89306f52eac1afa899e0bed49015a64d1 + languageName: node + linkType: hard + "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -3484,17 +3515,6 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^3.1.9": - version: 3.1.9 - resolution: "ejs@npm:3.1.9" - dependencies: - jake: "npm:^10.8.5" - bin: - ejs: bin/cli.js - checksum: 10c0/f0e249c79128810f5f6d5cbf347fc906d86bb9384263db0b2a9004aea649f2bc2d112736de5716c509c80afb4721c47281bd5b57c757d3b63f1bf5ac5f885893 - languageName: node - linkType: hard - "electron-to-chromium@npm:^1.4.202": version: 1.4.242 resolution: "electron-to-chromium@npm:1.4.242" @@ -4569,7 +4589,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.12": +"glob@npm:^10.2.2": version: 10.3.12 resolution: "glob@npm:10.3.12" dependencies: @@ -4599,6 +4619,22 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.4.5": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + "glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -4935,13 +4971,20 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.4, ignore@npm:^5.3.1": +"ignore@npm:^5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 10c0/703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd languageName: node linkType: hard +"ignore@npm:^5.3.2": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 + languageName: node + linkType: hard + "import-fresh@npm:^3.2.1": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" @@ -5489,6 +5532,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + "jake@npm:^10.8.5": version: 10.8.5 resolution: "jake@npm:10.8.5" @@ -6179,7 +6235,7 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:4.x": +"lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" checksum: 10c0/c8713e51eccc650422716a14cece1809cfe34bc5ab5e242b7f8b4e2241c2483697b971a604252807689b9dd69bfe3a98852e19a5b89d506b000b4187a1285df8 @@ -6235,7 +6291,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:1.x, make-error@npm:^1.1.1": +"make-error@npm:^1.1.1, make-error@npm:^1.3.6": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f @@ -6402,7 +6458,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.4": version: 9.0.4 resolution: "minimatch@npm:9.0.4" dependencies: @@ -6492,6 +6548,13 @@ __metadata: languageName: node linkType: hard +"minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": version: 2.1.2 resolution: "minizlib@npm:2.1.2" @@ -6986,6 +7049,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -7103,6 +7173,16 @@ __metadata: languageName: node linkType: hard +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -7255,12 +7335,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.2.5": - version: 3.2.5 - resolution: "prettier@npm:3.2.5" +"prettier@npm:^3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" bin: prettier: bin/prettier.cjs - checksum: 10c0/ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6 + checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 languageName: node linkType: hard @@ -7385,12 +7465,12 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.12.0": - version: 6.12.0 - resolution: "qs@npm:6.12.0" +"qs@npm:^6.13.0": + version: 6.13.0 + resolution: "qs@npm:6.13.0" dependencies: side-channel: "npm:^1.0.6" - checksum: 10c0/e165a77ac5f3ca60c15c5f3d51b321ddec7aa438804436b29d160117bc6fb7bf7dab94abd0c7d7c0785890d3a75ae41e1d6346e158aaf1540c6fe53a31f11675 + checksum: 10c0/62372cdeec24dc83a9fb240b7533c0fdcf0c5f7e0b83343edd7310f0ab4c8205a5e7c56406531f2e47e1b4878a3821d652be4192c841de5b032ca83619d8f860 languageName: node linkType: hard @@ -7801,6 +7881,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.0, semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf + languageName: node + linkType: hard + "set-function-length@npm:^1.2.0": version: 1.2.1 resolution: "set-function-length@npm:1.2.1" @@ -7927,14 +8016,14 @@ __metadata: languageName: node linkType: hard -"simple-git@npm:^3.24.0": - version: 3.24.0 - resolution: "simple-git@npm:3.24.0" +"simple-git@npm:^3.25.0": + version: 3.25.0 + resolution: "simple-git@npm:3.25.0" dependencies: "@kwsites/file-exists": "npm:^1.1.1" "@kwsites/promise-deferred": "npm:^1.1.1" - debug: "npm:^4.3.4" - checksum: 10c0/4329e5be1a7af1ebb476354ed6edf6d2828dc221e15d22ce3e5e8028f537d5e9ac059d813911516f78e22dfa2ee4db4c8cf30bf912bd284e530b733bd6b5c3a0 + debug: "npm:^4.3.5" + checksum: 10c0/2087dddac041eac6330cbb7fafea21f3e45786ea54e50ae07a49ba6a7134298e12727e5e4b6580310b679c7cb4f2a83804c04e7eab247eeabcd48d33b7885e16 languageName: node linkType: hard @@ -8549,20 +8638,31 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:^29.1.2": - version: 29.1.2 - resolution: "ts-jest@npm:29.1.2" +"ts-api-utils@npm:^1.3.0": + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" + peerDependencies: + typescript: ">=4.2.0" + checksum: 10c0/f54a0ba9ed56ce66baea90a3fa087a484002e807f28a8ccb2d070c75e76bde64bd0f6dce98b3802834156306050871b67eec325cb4e918015a360a3f0868c77c + languageName: node + linkType: hard + +"ts-jest@npm:^29.2.5": + version: 29.2.5 + resolution: "ts-jest@npm:29.2.5" dependencies: - bs-logger: "npm:0.x" - fast-json-stable-stringify: "npm:2.x" + bs-logger: "npm:^0.2.6" + ejs: "npm:^3.1.10" + fast-json-stable-stringify: "npm:^2.1.0" jest-util: "npm:^29.0.0" json5: "npm:^2.2.3" - lodash.memoize: "npm:4.x" - make-error: "npm:1.x" - semver: "npm:^7.5.3" - yargs-parser: "npm:^21.0.1" + lodash.memoize: "npm:^4.1.2" + make-error: "npm:^1.3.6" + semver: "npm:^7.6.3" + yargs-parser: "npm:^21.1.1" peerDependencies: "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/transform": ^29.0.0 "@jest/types": ^29.0.0 babel-jest: ^29.0.0 jest: ^29.0.0 @@ -8570,6 +8670,8 @@ __metadata: peerDependenciesMeta: "@babel/core": optional: true + "@jest/transform": + optional: true "@jest/types": optional: true babel-jest: @@ -8578,7 +8680,7 @@ __metadata: optional: true bin: ts-jest: cli.js - checksum: 10c0/c2f51f0241f89d127d41392decbcb83b5dfd5e57ab9d50220aa7b7e2f9b3f3b07ccdbba33311284df1c41941879e4ddfad44b15a9d0da4b74bd1b98702b729df + checksum: 10c0/acb62d168faec073e64b20873b583974ba8acecdb94681164eb346cef82ade8fb481c5b979363e01a97ce4dd1e793baf64d9efd90720bc941ad7fc1c3d6f3f68 languageName: node linkType: hard @@ -8706,10 +8808,10 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.24.0": - version: 4.24.0 - resolution: "type-fest@npm:4.24.0" - checksum: 10c0/9770471a397733b17b5a9ce48ee5a4d6c042c84a4858ff4e15abd126f351c61b5fea8b7b5e55bfa34840098a920b915d5ff878db1b3c007a2512a6a9c7f21579 +"type-fest@npm:^4.26.0": + version: 4.26.0 + resolution: "type-fest@npm:4.26.0" + checksum: 10c0/3819b65fedd4655ed90703dad9e14248fb61f0a232dce8385e59771bdeaeca08195fe0683d892d62fcd84c0f3bb18bd4b0c3c2ba29023187d267868e75c53076 languageName: node linkType: hard @@ -8776,23 +8878,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:~5.4.3": - version: 5.4.3 - resolution: "typescript@npm:5.4.3" +"typescript@npm:~5.5.4": + version: 5.5.4 + resolution: "typescript@npm:5.5.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/22443a8760c3668e256c0b34b6b45c359ef6cecc10c42558806177a7d500ab1a7d7aac1f976d712e26989ddf6731d2fbdd3212b7c73290a45127c1c43ba2005a + checksum: 10c0/422be60f89e661eab29ac488c974b6cc0a660fb2228003b297c3d10c32c90f3bcffc1009b43876a082515a3c376b1eefcce823d6e78982e6878408b9a923199c languageName: node linkType: hard -"typescript@patch:typescript@npm%3A~5.4.3#optional!builtin": - version: 5.4.3 - resolution: "typescript@patch:typescript@npm%3A5.4.3#optional!builtin::version=5.4.3&hash=5adc0c" +"typescript@patch:typescript@npm%3A~5.5.4#optional!builtin": + version: 5.5.4 + resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin::version=5.5.4&hash=5adc0c" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/6e51f8b7e6ec55b897b9e56b67e864fe8f44e30f4a14357aad5dc0f7432db2f01efc0522df0b6c36d361c51f2dc3dcac5c832efd96a404cfabf884e915d38828 + checksum: 10c0/10dd9881baba22763de859e8050d6cb6e2db854197495c6f1929b08d1eb2b2b00d0b5d9b0bcee8472f1c3f4a7ef6a5d7ebe0cfd703f853aa5ae465b8404bc1ba languageName: node linkType: hard @@ -8808,10 +8910,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.26.4": - version: 5.26.5 - resolution: "undici-types@npm:5.26.5" - checksum: 10c0/bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501 +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 languageName: node linkType: hard @@ -8824,13 +8926,6 @@ __metadata: languageName: node linkType: hard -"unique-names-generator@npm:^4.7.1": - version: 4.7.1 - resolution: "unique-names-generator@npm:4.7.1" - checksum: 10c0/db07b9a0fee6eac4a21cf567c9744ee97895aa744d51ec913557205173a65c1a7a4d12470295796acb7247e6646e7975c340bb634c7adf41e5d950fa5cf94375 - languageName: node - linkType: hard - "unique-slug@npm:^4.0.0": version: 4.0.0 resolution: "unique-slug@npm:4.0.0" @@ -9164,7 +9259,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.0, yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": +"yargs-parser@npm:^21.0.0, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 From 7ce8f1184765f23aaa0acaeb9d90025d710c0a40 Mon Sep 17 00:00:00 2001 From: belopash Date: Fri, 6 Sep 2024 02:44:01 +0500 Subject: [PATCH 04/15] feat: implement new command interfaces --- src/api/squids.ts | 4 +- src/command.ts | 39 +++-- src/commands/deploy.ts | 318 ++++++++++++++++++++++-------------- src/commands/logs.ts | 62 +++++-- src/commands/ls.ts | 31 ++-- src/commands/restart.ts | 70 ++++++-- src/commands/rm.ts | 75 +++++++-- src/commands/tag.ts | 74 --------- src/commands/tags/add.ts | 118 +++++++++++++ src/commands/tags/remove.ts | 110 +++++++++++++ src/deploy-command.ts | 2 +- src/flags/fullname.ts | 20 +++ src/flags/index.ts | 5 + src/flags/name.ts | 13 ++ src/flags/org.ts | 13 ++ src/flags/ref.ts | 13 ++ src/flags/tag.ts | 13 ++ src/ui/components/types.ts | 4 +- src/utils.ts | 35 ++-- 19 files changed, 735 insertions(+), 284 deletions(-) delete mode 100644 src/commands/tag.ts create mode 100644 src/commands/tags/add.ts create mode 100644 src/commands/tags/remove.ts create mode 100644 src/flags/fullname.ts create mode 100644 src/flags/index.ts create mode 100644 src/flags/name.ts create mode 100644 src/flags/org.ts create mode 100644 src/flags/ref.ts create mode 100644 src/flags/tag.ts diff --git a/src/api/squids.ts b/src/api/squids.ts index 315d316..c149d3e 100644 --- a/src/api/squids.ts +++ b/src/api/squids.ts @@ -220,8 +220,8 @@ export async function tagSquid({ organization, reference, data, -}: SquidRequest & { data: { tag: string } }): Promise { - const { body } = await api>({ +}: SquidRequest & { data: { tag: string } }): Promise { + const { body } = await api>({ method: 'post', path: `/orgs/${organization.code}/squids/${reference}/tag`, data, diff --git a/src/command.ts b/src/command.ts index 33e2841..b5f4a9f 100644 --- a/src/command.ts +++ b/src/command.ts @@ -1,11 +1,12 @@ import { Args, Command } from '@oclif/core'; +import { FailedFlagValidationError } from '@oclif/core/lib/parser/errors'; import chalk from 'chalk'; import inquirer from 'inquirer'; import { isNil, uniqBy } from 'lodash'; import { ApiError, getOrganization, getSquid, listOrganizations, listUserSquids, SquidRequest } from './api'; import { getTTY } from './tty'; -import { parseSquidReference, SQUID_HASH_SYMBOL, SQUID_TAG_SYMBOL } from './utils'; +import { parseSquidFullname } from './utils'; export const SUCCESS_CHECK_MARK = chalk.green('✓'); @@ -22,6 +23,23 @@ export abstract class CliCommand extends Command { this.log(chalk.dim(message)); } + // Haven't find a way to do it with native settings + validateSquidNameFlags(flags: { fullname?: any; name?: any }) { + if (flags.fullname || flags.name) return; + + throw new FailedFlagValidationError({ + failed: [ + { + name: 'squid name', + validationFn: 'validateSquidName', + reason: 'One of the following must be provided: --fullname, --name', + status: 'failed', + }, + ], + parse: {}, + }); + } + async catch(error: any) { if (error instanceof ApiError) { const { request, body } = error; @@ -111,24 +129,11 @@ export abstract class CliCommand extends Command { return await this.getOrganizationPrompt(organizations, using); } - async promptSquidOrganization({ - code, - reference, - using, - }: { - code?: string | null; - reference: string; - using?: string; - }) { + async promptSquidOrganization({ code, name, using }: { code?: string | null; name: string; using?: string }) { if (code) { return await getOrganization({ organization: { code } }); } - const name = - reference.includes(SQUID_TAG_SYMBOL) || reference.includes(SQUID_HASH_SYMBOL) - ? parseSquidReference(reference).name - : reference; - const squids = await listUserSquids({ name }); let organizations = squids.map((s) => s.organization).filter((o) => !isNil(o)); @@ -180,7 +185,7 @@ export abstract class CliCommand extends Command { } export const SquidReferenceArg = Args.string({ - description: ` or `, + // description: ` or `, required: true, parse: async (input) => { input = input.toLowerCase(); @@ -190,3 +195,5 @@ export const SquidReferenceArg = Args.string({ return input; }, }); + +export * as SqdFlags from './flags'; diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 69f77e2..31ff1b9 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -9,14 +9,15 @@ import diff from 'cli-diff'; import { globSync } from 'glob'; import ignore from 'ignore'; import inquirer from 'inquirer'; +import { defaults, get, isNil, keys, pick, pickBy } from 'lodash'; import prettyBytes from 'pretty-bytes'; import targz from 'targz'; -import { deploySquid, OrganizationRequest, uploadFile } from '../api'; -import { SUCCESS_CHECK_MARK } from '../command'; +import { deploySquid, OrganizationRequest, Squid, uploadFile } from '../api'; +import { SqdFlags, SUCCESS_CHECK_MARK } from '../command'; import { DeployCommand } from '../deploy-command'; import { loadManifestFile } from '../manifest'; -import { formatSquidName, parseSquidReference, SQUID_HASH_SYMBOL, SQUID_TAG_SYMBOL } from '../utils'; +import { formatSquidFullname, ParsedSquidFullname, parseSquidFullname } from '../utils'; const compressAsync = promisify(targz.compress); @@ -76,20 +77,45 @@ export default class Deploy extends DeployCommand { ]; static args = { - squid_name_or_reference: Args.string({ + // squid_name_or_reference: Args.string({ + // description: [ + // `Reference to squid for the update.`, + // `If argument not specified, the squid name will be retrieved from the manifest or prompted and a new squid will be created.`, + // ``, + // `Alternatively, you can overwrite the name of the squid from the manifest by explicitly providing a new name instead of a reference.`, + // ``, + // `See Examples section for more information`, + // ].join('\n'), + // required: false, + // }), + source: Args.string({ description: [ - `Reference to squid for the update.`, - `If argument not specified, the squid name will be retrieved from the manifest or prompted and a new squid will be created.`, - ``, - `Alternatively, you can overwrite the name of the squid from the manifest by explicitly providing a new name instead of a reference.`, - ``, - `See Examples section for more information`, + `Squid source. Could be:`, + ` - a relative or absolute path to a local folder (e.g. ".")`, + ` - a URL to a .tar.gz archive`, + ` - a github URL to a git repo with a branch or commit tag`, ].join('\n'), - required: false, + required: true, + default: '.', }), }; static flags = { + org: SqdFlags.org({ + required: false, + }), + name: SqdFlags.name({ + required: false, + }), + tag: SqdFlags.tag({ + required: false, + }), + ref: SqdFlags.ref({ + required: false, + }), + fullname: SqdFlags.fullname({ + required: false, + }), manifest: Flags.string({ char: 'm', description: 'Relative local path to a squid manifest file in squid working directory', @@ -97,70 +123,67 @@ export default class Deploy extends DeployCommand { default: 'squid.yaml', helpValue: '', }), - dir: Flags.string({ - char: 'd', - description: SQUID_WORKDIR_DESC.join('\n'), + // dir: Flags.string({ + // char: 'd', + // description: SQUID_WORKDIR_DESC.join('\n'), + // required: false, + // default: '.', + // helpValue: '', + // }), + // tag: Flags.string({ + // char: 't', + // description: [ + // 'Assign the tag to the squid deployment. ', + // 'The previous deployment API URL assigned with the same tag will be transitioned to the new deployment', + // 'Tag must contain only alphanumeric characters, dashes, and underscores', + // ].join('\n'), + // required: false, + // helpValue: '', + // }), + force: Flags.boolean({ required: false, - default: '.', - helpValue: '', - }), - tag: Flags.string({ - char: 't', - description: [ - 'Assign the tag to the squid deployment. ', - 'The previous deployment API URL assigned with the same tag will be transitioned to the new deployment', - 'Tag must contain only alphanumeric characters, dashes, and underscores', - ].join('\n'), - required: false, - helpValue: '', + default: false, }), 'hard-reset': Flags.boolean({ - char: 'r', description: 'Do a hard reset before deploying. Drops and re-creates all the squid resources including the database. Will cause a short API downtime', required: false, + default: false, }), 'no-stream-logs': Flags.boolean({ description: 'Do not attach and stream squid logs after the deploy', required: false, default: false, }), - org: Flags.string({ - char: 'o', - description: 'Organization code', - helpValue: '', + 'apply-tag': Flags.boolean({ required: false, + default: false, }), }; async run(): Promise { const { - args: { squid_name_or_reference }, - flags: { dir, manifest: manifestPath, 'hard-reset': hardReset, 'no-stream-logs': disableStreamLogs, org, tag }, + args: { source }, + flags: { + manifest: manifestPath, + 'hard-reset': hardReset, + 'no-stream-logs': noStreamLogs, + 'apply-tag': applyTag, + force, + fullname, + ...flags + }, } = await this.parse(Deploy); - const isUrl = dir.startsWith('http://') || dir.startsWith('https://'); + const isUrl = source.startsWith('http://') || source.startsWith('https://'); if (isUrl) { - // this.log(`🦑 Releasing the squid from remote`); - // - // squid = await deployDemoSquid({ - // orgCode, - // name: manifest.name, - // tag, - // data: { - // hardReset, - // artifactUrl: source, - // manifestPath, - // }, - // }); + this.log(`🦑 Releasing the squid from remote`); return this.error('Not implemented yet'); } - const organization = await this.promptOrganization(org); - this.log(`🦑 Releasing the squid from local folder`); - const res = resolveManifest(dir, manifestPath); + const res = resolveManifest(source, manifestPath); if ('error' in res) return this.showError(res.error, 'MANIFEST_VALIDATION_FAILED'); const { buildDir, squidDir, manifest } = res; @@ -169,50 +192,50 @@ export default class Deploy extends DeployCommand { this.log(chalk.dim(`Build directory: ${buildDir}`)); this.log(chalk.dim(`Manifest: ${manifestPath}`)); - let reference = squid_name_or_reference?.trim(); - if (!reference) { - reference = manifest.name; - } + const overrides = fullname ? fullname : pick(flags, 'name', 'org', 'ref', 'tag'); + + const override = await this.promptOverrideConflict(manifest, overrides); + if (!override) return; - const isUpdate = reference.includes(SQUID_HASH_SYMBOL) || reference.includes(SQUID_TAG_SYMBOL); - const overrideName = isUpdate ? parseSquidReference(reference).name : reference; + // eslint-disable-next-line prefer-const + let { name, org, ref, tag } = defaults(overrides, manifest); - await this.checkNameMismatch({ fileName: path.basename(manifestPath), manifest, overrideName }); + const organization = await this.promptOrganization(org); - const finalName = await this.getFinalSquidName(manifest, overrideName); + // name = await this.promptSquidName(name); - if (tag) { - const oldSquid = await this.findSquid({ + let target: Squid | null = null; + if (ref || tag) { + target = await this.findSquid({ organization, - reference: `${finalName}${tag.padStart(1, SQUID_TAG_SYMBOL)}`, + reference: formatSquidFullname(ref ? { name, ref } : { name, tag: tag! }), }); - if (oldSquid) { - const { confirm } = await inquirer.prompt([ - { - name: 'confirm', - type: 'confirm', - message: [ - chalk.reset( - `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidName(oldSquid)}.`, - ), - chalk.reset(`The tag URL will be assigned to the newly created deployment.`), - chalk.bold(`Are you sure?`), - ].join('\n'), - }, - ]); - if (!confirm) return; - } } - const target = reference && isUpdate ? await this.findOrThrowSquid({ organization, reference }) : null; + /** + * Squid exists we should check running deploys + */ if (target) { - /** - * Squid exists we should check running deploys - */ - const attached = await this.attachToParallelDeploy(target); + const attached = await this.promptAttachToDeploy(target); if (attached) return; } + /** + * Squid exists we should ask for update + */ + if (target && !force) { + const update = await this.promptUpdateSquid(target); + if (!update) return; + } + + /** + * Squid exists we should check if tag belongs to another squid + */ + if (target && ref && tag && !applyTag) { + const apply = await this.promptApplyTag(target, tag); + if (!apply) return; + } + const archiveName = `${manifest.name}.tar.gz`; const artifactPath = await this.pack({ buildDir, squidDir, archiveName }); const artifactUrl = await this.upload({ organization, artifactPath }); @@ -224,7 +247,7 @@ export default class Deploy extends DeployCommand { manifestPath, options: { hardReset, - overrideName: finalName !== manifest.name ? finalName : undefined, + overrideName: name, updateByHash: target?.hash, tag, }, @@ -234,72 +257,119 @@ export default class Deploy extends DeployCommand { const deployment = await this.pollDeploy({ organization, deploy }); if (!deployment || !deployment.squid) return; - if (isUpdate) { + if (target) { this.logDeployResult( UPDATE_COLOR, - `The squid ${formatSquidName(deployment.squid)} has been successfully updated`, + `The squid ${formatSquidFullname({ + org: deployment.organization.code, + name: deployment.squid.name, + ref: deployment.squid.hash, + })} has been successfully updated`, ); } else { this.logDeployResult( CREATE_COLOR, - `A new squid ${formatSquidName(deployment.squid)}${tag ? ` with tag ${chalk.bold(tag)}` : ''} was successfully created`, + `A new squid ${formatSquidFullname({ + org: deployment.organization.code, + name: deployment.squid.name, + ref: deployment.squid.hash, + })} has been successfully created`, ); } - if (!disableStreamLogs) { + if (!noStreamLogs) { await this.streamLogs(organization, deployment.squid); } } - private async checkNameMismatch({ - fileName, - overrideName, - manifest, - }: { - fileName: string; - manifest: Manifest; - overrideName?: string; - }) { - if (!manifest.name) return; - else if (!overrideName) return; - - if (manifest.name !== overrideName) { - this.log( - [ - chalk.bold('Name conflict detected!'), - - `A manifest squid name ${chalk.bold(manifest.name)} does not match with specified in the argument: ${chalk.bold(overrideName)}.`, - `If it is intended and you'd like to override the name, just skip this message and confirm, the manifest name will be overridden automatically in the Cloud during the deploy.`, - ``, - `Patch:`, - diff( - { name: fileName, content: `name: ${manifest.name}\n` }, - { name: fileName, content: `name: ${overrideName}\n` }, + private async promptUpdateSquid(target: Squid) { + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: [ + chalk.reset( + `A squid "${formatSquidFullname({ + org: target.organization.code, + name: target.name, + ref: target.hash, + })}" will be updated. ${chalk.bold('Are you sure?')}`, ), ].join('\n'), - ); + }, + ]); - const { confirm } = await inquirer.prompt([ - { - name: 'confirm', - type: 'confirm', - message: 'Are you sure?', - }, - ]); - if (!confirm) return; - } + return !!confirm; + } + + private async promptApplyTag(target: Squid, tag: string) { + if (!!target.tags.find((t) => t.name === tag)) return true; + + const oldSquid = await this.findSquid({ + organization: target.organization, + reference: formatSquidFullname({ name: target.name, tag }), + }); + if (!oldSquid) return true; + + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: [ + chalk.reset( + `A squid tag "${tag}" has already been assigned to ${formatSquidFullname({ name: oldSquid.name, ref: oldSquid.hash })}.`, + ), + chalk.reset(`The tag will be assigned to the newly created squid. ${chalk.bold('Are you sure?')}`), + ].join('\n'), + }, + ]); + + return !!confirm; + } + + private async promptOverrideConflict(manifest: Manifest, override: Record) { + const conflictKeys = keys(override).filter((k) => { + const m = get(manifest, k); + const o = get(override, k); + return !isNil(m) && m !== o; + }); + + if (!conflictKeys.length) return true; + + this.log( + [ + chalk.bold('Conflict detected!'), + + `A manifest values do not match with specified ones.`, + `If it is intended and you'd like to override them, just skip this message and confirm, the manifest name will be overridden automatically in the Cloud during the deploy.`, + ``, + diff( + { content: conflictKeys.map((k) => `${k}: ${get(manifest, k)}`).join('\n') + '\n' }, + { content: conflictKeys.map((k) => `${k}: ${get(override, k)}`).join('\n') + '\n' }, + ), + ].join('\n'), + ); + + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: chalk.reset(`Manifest values will be overridden. ${chalk.bold('Are you sure?')}`), + }, + ]); + + return !!confirm; } - private async getFinalSquidName(manifest: Manifest, overrideName?: string) { - if (overrideName) return overrideName; - else if (manifest.name) return manifest.name; + private async promptSquidName(name?: string) { + if (name) return name; const { input } = await inquirer.prompt([ { name: 'input', type: 'input', message: [ - chalk.reset(`The squid name is not defined either in the manifest or via CLI argument.`), + chalk.reset(`The squid name is not defined either in the manifest or via CLI command.`), chalk.reset(`Please enter the name of the squid:`), ].join('\n'), }, diff --git a/src/commands/logs.ts b/src/commands/logs.ts index 70e217a..37d0744 100644 --- a/src/commands/logs.ts +++ b/src/commands/logs.ts @@ -1,9 +1,11 @@ import { Flags, ux as CliUx } from '@oclif/core'; +import { isNil, omitBy } from 'lodash'; import ms from 'ms'; import { debugLog, squidHistoryLogs, SquidRequest, streamSquidLogs } from '../api'; -import { CliCommand, SquidReferenceArg } from '../command'; +import { CliCommand, SqdFlags, SquidReferenceArg } from '../command'; import { pretty } from '../logs'; +import { formatSquidFullname } from '../utils'; type LogResult = { hasLogs: boolean; @@ -21,11 +23,48 @@ function parseDate(str: string): Date { export default class Logs extends CliCommand { static description = 'Fetch logs from a squid deployed to the Cloud'; - static args = { - squid_reference: SquidReferenceArg, - }; static flags = { + org: SqdFlags.org({ + required: false, + relationships: [ + { + type: 'all', + flags: ['name'], + }, + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + name: SqdFlags.name({ + required: false, + relationships: [ + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + ref: SqdFlags.ref({ + required: false, + dependsOn: ['name'], + }), + tag: SqdFlags.tag({ + required: false, + dependsOn: ['name'], + exclusive: ['ref'], + }), + fullname: SqdFlags.fullname({ + required: false, + }), container: Flags.string({ char: 'c', summary: `Container name`, @@ -63,20 +102,19 @@ export default class Logs extends CliCommand { default: false, exclusive: ['fromDate', 'pageSize'], }), - org: Flags.string({ - char: 'o', - description: 'Organization', - required: false, - }), }; async run(): Promise { const { - args: { squid_reference: reference }, - flags: { follow, pageSize, container, level, since, org, search }, + flags: { follow, pageSize, container, level, since, search, fullname, ...flags }, } = await this.parse(Logs); - const organization = await this.promptSquidOrganization({ code: org, reference }); + this.validateSquidNameFlags({ fullname, ...flags }); + + const { org, name, tag, ref } = fullname ? fullname : omitBy(flags, isNil); + const reference = formatSquidFullname({ name, ref, tag }); + + const organization = await this.promptSquidOrganization({ code: org, name }); const squid = await this.findOrThrowSquid({ organization, reference }); if (!squid) return; diff --git a/src/commands/ls.ts b/src/commands/ls.ts index 5df1dcc..e491975 100644 --- a/src/commands/ls.ts +++ b/src/commands/ls.ts @@ -2,15 +2,25 @@ import { ux as CliUx, Flags } from '@oclif/core'; import chalk from 'chalk'; import { listSquids } from '../api'; -import { CliCommand } from '../command'; +import { CliCommand, SqdFlags } from '../command'; export default class Ls extends CliCommand { static description = 'List squids deployed to the Cloud'; static flags = { - name: Flags.string({ - char: 'n', - description: 'Filter by squid name', + org: SqdFlags.org({ + required: false, + relationships: [ + { + type: 'all', + flags: ['name'], + }, + ], + }), + name: SqdFlags.name({ + required: false, + }), + fullname: SqdFlags.fullname({ required: false, }), truncate: Flags.boolean({ @@ -19,21 +29,18 @@ export default class Ls extends CliCommand { required: false, default: false, }), - org: Flags.string({ - char: 'o', - description: 'Organization code', - required: false, - }), }; async run(): Promise { const { - flags: { org, truncate, name }, + flags: { truncate, fullname, ...flags }, } = await this.parse(Ls); const noTruncate = !truncate; + const { org, name } = fullname ? fullname : (flags as any); + const organization = name - ? await this.promptSquidOrganization({ code: org, reference: name }) + ? await this.promptSquidOrganization({ code: org, name }) : await this.promptOrganization(org); const squids = await listSquids({ organization, name }); @@ -43,7 +50,7 @@ export default class Ls extends CliCommand { { name: { header: 'Squid', - get: (s) => `${s.name}${chalk.dim(`:${s.hash}`)}`, + get: (s) => `${s.name}${chalk.dim(`@${s.hash}`)}`, }, tags: { header: 'Tags', diff --git a/src/commands/restart.ts b/src/commands/restart.ts index 769e48d..ca8ad5c 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -1,38 +1,82 @@ import { Flags } from '@oclif/core'; import { restartSquid } from '../api'; -import { SquidReferenceArg } from '../command'; +import { SqdFlags, SquidReferenceArg } from '../command'; import { DeployCommand } from '../deploy-command'; +import { formatSquidFullname } from '../utils'; import { UPDATE_COLOR } from './deploy'; export default class Restart extends DeployCommand { static description = 'Restart a squid deployed to the Cloud'; - static args = { - squid_reference: SquidReferenceArg, - }; static flags = { - org: Flags.string({ - char: 'o', - description: 'Organization', + org: SqdFlags.org({ + required: false, + relationships: [ + { + type: 'all', + flags: ['name'], + }, + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + name: SqdFlags.name({ + required: false, + relationships: [ + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + ref: SqdFlags.ref({ + required: false, + dependsOn: ['name'], + }), + tag: SqdFlags.tag({ + required: false, + dependsOn: ['name'], + exclusive: ['ref'], + }), + fullname: SqdFlags.fullname({ required: false, }), }; async run(): Promise { const { - flags: { org }, - args: { squid_reference: reference }, + flags: { fullname, ...flags }, } = await this.parse(Restart); - const organization = await this.promptSquidOrganization({ code: org, reference }); + this.validateSquidNameFlags({ fullname, ...flags }); + + const { org, name, tag, ref } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, ref, tag }); + const organization = await this.promptSquidOrganization({ code: org, name }); await this.findOrThrowSquid({ organization, reference }); - const deploy = await restartSquid({ organization, reference }); - await this.pollDeploy({ organization, deploy }); + const deployment = await restartSquid({ organization, reference }); + await this.pollDeploy({ organization, deploy: deployment }); + if (!deployment || !deployment.squid) return; - this.logDeployResult(UPDATE_COLOR, `The squid ${reference} has been successfully restarted`); + this.logDeployResult( + UPDATE_COLOR, + `The squid ${formatSquidFullname({ + org: deployment.organization.code, + name: deployment.squid.name, + ref: deployment.squid.hash, + })} has been successfully restarted`, + ); } } diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 3dab302..0b1b8e5 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -2,9 +2,9 @@ import { Flags } from '@oclif/core'; import inquirer from 'inquirer'; import { deleteSquid } from '../api'; -import { SquidReferenceArg } from '../command'; +import { SqdFlags, SquidReferenceArg } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidName } from '../utils'; +import { formatSquidFullname } from '../utils'; import { DELETE_COLOR } from './deploy'; @@ -16,25 +16,64 @@ export default class Rm extends DeployCommand { }; static flags = { + org: SqdFlags.org({ + required: false, + relationships: [ + { + type: 'all', + flags: ['name'], + }, + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + name: SqdFlags.name({ + required: false, + relationships: [ + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + ref: SqdFlags.ref({ + required: false, + dependsOn: ['name'], + }), + tag: SqdFlags.tag({ + required: false, + dependsOn: ['name'], + exclusive: ['ref'], + }), + fullname: SqdFlags.fullname({ + required: false, + }), force: Flags.boolean({ char: 'f', description: 'Does not prompt before removing a squid or its version', required: false, }), - org: Flags.string({ - char: 'o', - description: 'Organization', - required: false, - }), }; async run(): Promise { const { - args: { squid_reference: reference }, - flags: { force, org }, + flags: { force, fullname, ...flags }, } = await this.parse(Rm); - const organization = await this.promptSquidOrganization({ code: org, reference }); + this.validateSquidNameFlags({ fullname, ...flags }); + + const { org, name, tag, ref } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, ref, tag }); + + const organization = await this.promptSquidOrganization({ code: org, name }); const squid = await this.findOrThrowSquid({ organization, reference }); if (!force) { @@ -42,15 +81,23 @@ export default class Rm extends DeployCommand { { name: 'confirm', type: 'confirm', - message: `Your squid ${formatSquidName(squid)} will be completely removed. This action can not be undone. Are you sure?`, + message: `Your squid ${formatSquidFullname({ org, name, ref: squid.hash })} will be completely removed. This action can not be undone. Are you sure?`, }, ]); if (!confirm) return; } - const deploy = await deleteSquid({ organization, reference }); - await this.pollDeploy({ organization, deploy }); + const deployment = await deleteSquid({ organization, reference }); + await this.pollDeploy({ organization, deploy: deployment }); + if (!deployment || !deployment.squid) return; - this.logDeployResult(DELETE_COLOR, `A squid deployment ${reference} was successfully deleted`); + this.logDeployResult( + DELETE_COLOR, + `A squid deployment ${formatSquidFullname({ + org: deployment.organization.code, + name: deployment.squid.name, + ref: deployment.squid.hash, + })} was successfully deleted`, + ); } } diff --git a/src/commands/tag.ts b/src/commands/tag.ts deleted file mode 100644 index 1486f72..0000000 --- a/src/commands/tag.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Args, Flags } from '@oclif/core'; -import chalk from 'chalk'; -import inquirer from 'inquirer'; - -import { tagSquid } from '../api'; -import { SquidReferenceArg } from '../command'; -import { DeployCommand } from '../deploy-command'; -import { formatSquidName } from '../utils'; - -import { UPDATE_COLOR } from './deploy'; - -export default class Tag extends DeployCommand { - static description = 'Set a tag for squid'; - - static args = { - squid_reference: SquidReferenceArg, - - tag: Args.string({ - description: `New tag to assign`, - required: true, - }), - }; - - static flags = { - org: Flags.string({ - char: 'o', - description: 'Organization', - required: false, - }), - }; - - async run(): Promise { - const { - args: { squid_reference: reference, tag }, - flags: { org }, - } = await this.parse(Tag); - - const organization = await this.promptSquidOrganization({ code: org, reference }); - const squid = await this.findOrThrowSquid({ organization, reference }); - - if (squid.tags.find((t) => t.name === tag)) { - return this.log(`Tag ${tag} is already assigned to the squid ${formatSquidName(squid)}`); - } - - const oldSquid = await this.findSquid({ organization, reference: `${squid.name}@${tag}` }); - if (oldSquid) { - const { confirm } = await inquirer.prompt([ - { - name: 'confirm', - type: 'confirm', - message: [ - chalk.reset( - `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidName(oldSquid)}.`, - ), - chalk.reset(`The tag URL will be assigned to the newly created deployment.`), - chalk.bold(`Are you sure?`), - ].join('\n'), - }, - ]); - if (!confirm) return; - } - - const deploy = await tagSquid({ - organization, - reference, - data: { - tag, - }, - }); - await this.pollDeploy({ organization, deploy }); - - this.logDeployResult(UPDATE_COLOR, `The squid ${squid.name}#${squid.hash} has been successfully updated`); - } -} diff --git a/src/commands/tags/add.ts b/src/commands/tags/add.ts new file mode 100644 index 0000000..094f62b --- /dev/null +++ b/src/commands/tags/add.ts @@ -0,0 +1,118 @@ +import { Args, Flags } from '@oclif/core'; +import chalk from 'chalk'; +import inquirer from 'inquirer'; + +import { tagSquid } from '../../api'; +import { SqdFlags } from '../../command'; +import { DeployCommand } from '../../deploy-command'; +import { formatSquidFullname } from '../../utils'; +import { UPDATE_COLOR } from '../deploy'; + +export default class Add extends DeployCommand { + static description = 'Add a tag to a squid'; + + static args = { + tag: Args.string({ + description: `New tag to assign`, + required: true, + }), + }; + + static flags = { + org: SqdFlags.org({ + required: false, + relationships: [ + { + type: 'all', + flags: ['name'], + }, + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + name: SqdFlags.name({ + required: false, + relationships: [ + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + ref: SqdFlags.ref({ + required: false, + dependsOn: ['name'], + }), + tag: SqdFlags.tag({ + required: false, + dependsOn: ['name'], + exclusive: ['ref'], + }), + fullname: SqdFlags.fullname({ + required: false, + }), + }; + + async run(): Promise { + const { + args: { tag: newTag }, + flags: { fullname, ...flags }, + } = await this.parse(Add); + + this.validateSquidNameFlags({ fullname, ...flags }); + + const { org, name, tag, ref } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, ref, tag }); + + const organization = await this.promptSquidOrganization({ code: org, name }); + const squid = await this.findOrThrowSquid({ organization, reference }); + + if (squid.tags.find((t) => t.name === tag)) { + return this.log(`Tag "${tag}" is already assigned to the squid ${formatSquidFullname({ org, name, tag, ref })}`); + } + + const oldSquid = await this.findSquid({ organization, reference: formatSquidFullname({ name, tag: newTag }) }); + if (oldSquid) { + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: [ + chalk.reset( + `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidFullname({ org, name, ref: oldSquid.hash })}.`, + ), + chalk.reset(`The tag URL will be assigned to the newly created deployment. ${chalk.bold(`Are you sure?`)}`), + ].join('\n'), + }, + ]); + if (!confirm) return; + } + + const deployment = await tagSquid({ + organization, + reference, + data: { + tag: newTag, + }, + }); + await this.pollDeploy({ organization, deploy: deployment }); + if (!deployment || !deployment.squid) return; + + this.logDeployResult( + UPDATE_COLOR, + `The squid ${formatSquidFullname({ + org: deployment.organization.code, + name: deployment.squid.name, + ref: deployment.squid.hash, + })} has been successfully updated`, + ); + } +} diff --git a/src/commands/tags/remove.ts b/src/commands/tags/remove.ts new file mode 100644 index 0000000..b6bcc00 --- /dev/null +++ b/src/commands/tags/remove.ts @@ -0,0 +1,110 @@ +import { Args, Flags } from '@oclif/core'; +import chalk from 'chalk'; +import inquirer from 'inquirer'; + +import { tagSquid } from '../../api'; +import { SqdFlags } from '../../command'; +import { DeployCommand } from '../../deploy-command'; +import { formatSquidFullname } from '../../utils'; +import { UPDATE_COLOR } from '../deploy'; + +export default class Remove extends DeployCommand { + static description = 'Remove a tag from a squid'; + + static args = {}; + + static flags = { + org: SqdFlags.org({ + required: false, + relationships: [ + { + type: 'all', + flags: ['name'], + }, + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + name: SqdFlags.name({ + required: false, + relationships: [ + { + type: 'some', + flags: [ + { name: 'ref', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['ref'] }, + ], + }, + ], + }), + ref: SqdFlags.ref({ + required: false, + dependsOn: ['name'], + }), + tag: SqdFlags.tag({ + required: false, + dependsOn: ['name'], + exclusive: ['ref'], + }), + fullname: SqdFlags.fullname({ + required: false, + }), + }; + + async run(): Promise { + const { + flags: { fullname, ...flags }, + } = await this.parse(Remove); + + this.validateSquidNameFlags({ fullname, ...flags }); + + const { org, name, tag, ref } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, ref, tag }); + + const organization = await this.promptSquidOrganization({ code: org, name }); + const squid = await this.findOrThrowSquid({ organization, reference }); + + throw new Error('API is not implemented yet'); + + // const oldSquid = await this.findSquid({ organization, reference: formatSquidFullname({ name, tag: newTag }) }); + // if (oldSquid) { + // const { confirm } = await inquirer.prompt([ + // { + // name: 'confirm', + // type: 'confirm', + // message: [ + // chalk.reset( + // `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidFullname({ org, name, ref: oldSquid.hash })}.`, + // ), + // chalk.reset(`The tag URL will be assigned to the newly created deployment. ${chalk.bold(`Are you sure?`)}`), + // ].join('\n'), + // }, + // ]); + // if (!confirm) return; + // } + + // const deployment = await tagSquid({ + // organization, + // reference, + // data: { + // tag: newTag, + // }, + // }); + // await this.pollDeploy({ organization, deploy: deployment }); + // if (!deployment || !deployment.squid) return; + + // this.logDeployResult( + // UPDATE_COLOR, + // `The squid ${formatSquidFullname({ + // org: deployment.organization.code, + // name: deployment.squid.name, + // ref: deployment.squid.hash, + // })} has been successfully updated`, + // ); + } +} diff --git a/src/deploy-command.ts b/src/deploy-command.ts index b57df64..4f4f8ed 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -10,7 +10,7 @@ export abstract class DeployCommand extends CliCommand { deploy: Deployment | undefined; logsPrinted = 0; - async attachToParallelDeploy(squid: Squid) { + async promptAttachToDeploy(squid: Squid) { if (!squid.lastDeploy) return false; if (squid.status !== 'DEPLOYING') return false; diff --git a/src/flags/fullname.ts b/src/flags/fullname.ts new file mode 100644 index 0000000..578cd16 --- /dev/null +++ b/src/flags/fullname.ts @@ -0,0 +1,20 @@ +import { Flags } from '@oclif/core'; + +import { ParsedSquidFullname, parseSquidFullname, SQUID_FULLNAME_REGEXP } from '../utils'; + +export const fullname = Flags.custom({ + helpGroup: 'COMMON', + name: 'fullname', + description: `Full name of a squid`, + helpValue: '[/](@|:)', + required: false, + exclusive: ['org', 'name', 'ref', 'tag'], + parse: async (input) => { + input = input.toLowerCase(); + if (!SQUID_FULLNAME_REGEXP.test(input)) { + throw new Error(`Expected a squid full name but received: ${input}`); + } + + return parseSquidFullname(input); + }, +}); diff --git a/src/flags/index.ts b/src/flags/index.ts new file mode 100644 index 0000000..ffa4778 --- /dev/null +++ b/src/flags/index.ts @@ -0,0 +1,5 @@ +export { fullname } from './fullname'; +export { name } from './name'; +export { org } from './org'; +export { ref } from './ref'; +export { tag } from './tag'; diff --git a/src/flags/name.ts b/src/flags/name.ts new file mode 100644 index 0000000..7fa4c4c --- /dev/null +++ b/src/flags/name.ts @@ -0,0 +1,13 @@ +import { Flags } from '@oclif/core'; + +export const name = Flags.custom({ + helpGroup: 'COMMON', + char: 'n', + name: 'name', + description: 'Squid name', + helpValue: '', + required: false, + parse: async (input) => { + return input.toLowerCase(); + }, +}); diff --git a/src/flags/org.ts b/src/flags/org.ts new file mode 100644 index 0000000..a30c81b --- /dev/null +++ b/src/flags/org.ts @@ -0,0 +1,13 @@ +import { Flags } from '@oclif/core'; + +export const org = Flags.custom({ + helpGroup: 'COMMON', + char: 'o', + name: 'org', + description: 'Organization code', + helpValue: '', + required: false, + parse: async (input) => { + return input.toLowerCase(); + }, +}); diff --git a/src/flags/ref.ts b/src/flags/ref.ts new file mode 100644 index 0000000..20b6ff2 --- /dev/null +++ b/src/flags/ref.ts @@ -0,0 +1,13 @@ +import { Flags } from '@oclif/core'; + +export const ref = Flags.custom({ + helpGroup: 'COMMON', + char: 'r', + name: 'ref', + description: 'Squid ref', + helpValue: '', + parse: async (input) => { + return input.toLowerCase(); + }, + required: false, +}); diff --git a/src/flags/tag.ts b/src/flags/tag.ts new file mode 100644 index 0000000..05de0be --- /dev/null +++ b/src/flags/tag.ts @@ -0,0 +1,13 @@ +import { Flags } from '@oclif/core'; + +export const tag = Flags.custom({ + helpGroup: 'COMMON', + char: 't', + name: 'tag', + description: 'Squid tag', + helpValue: '', + required: false, + parse: async (input) => { + return input.toLowerCase(); + }, +}); diff --git a/src/ui/components/types.ts b/src/ui/components/types.ts index 1616e1c..2b46b55 100644 --- a/src/ui/components/types.ts +++ b/src/ui/components/types.ts @@ -1,5 +1,5 @@ import { Squid as ApiSquid } from '../../api'; -import { formatSquidName } from '../../utils'; +import { formatSquidFullname } from '../../utils'; export interface Squid extends ApiSquid {} export class Squid { @@ -8,7 +8,7 @@ export class Squid { constructor(squid: ApiSquid) { Object.assign(this, squid); - this.displayName = formatSquidName(this); + this.displayName = formatSquidFullname({ name: this.name, ref: this.hash }); if (this.tags.length) { this.displayName += ` (${this.tags.map((a) => a.name).join(', ')})`; diff --git a/src/utils.ts b/src/utils.ts index ed3ca16..fd07e18 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -23,21 +23,28 @@ export async function doUntil(fn: () => Promise, { pause }: { pause: nu } } -export const SQUID_HASH_SYMBOL = ':'; -export const SQUID_TAG_SYMBOL = '@'; - -export function parseSquidReference(reference: string) { - if (reference.includes(SQUID_HASH_SYMBOL)) { - const [name, hash] = reference.split(SQUID_HASH_SYMBOL); - return { name, hash }; - } else if (reference.includes(SQUID_TAG_SYMBOL)) { - const [name, tag] = reference.split(SQUID_TAG_SYMBOL); - return { name, tag }; - } +export type ParsedSquidFullname = { org?: string; name: string } & ( + | { ref: string; tag?: never } + | { ref?: never; tag: string } +); + +export function formatSquidFullname({ org, name, ref, tag }: ParsedSquidFullname) { + let res = org ? `${org}/` : ''; + res += name; + res += ref ? `@${ref}` : `:${tag}`; - throw new Error(`Invalid squid reference: "${reference}"`); + return res; } -export function formatSquidName({ reference }: { reference: string }) { - return chalk.bold(reference); +export const SQUID_FULLNAME_REGEXP = /^(([a-z0-9\-]+)\/)?([a-z0-9\-]+)([:@])([a-z0-9\-]+)$/; + +export function parseSquidFullname(fullname: string): ParsedSquidFullname { + const parsed = SQUID_FULLNAME_REGEXP.exec(fullname); + if (!parsed) { + throw new Error(`Invalid squid full name: "${fullname}"`); + } + + const [, , org, name, type, tagOrRef] = parsed; + + return { org, name, ...(type === ':' ? { tag: tagOrRef } : { ref: tagOrRef }) }; } From 30751a00168445aa856e42ddf274d08876d5d584 Mon Sep 17 00:00:00 2001 From: belopash Date: Mon, 9 Sep 2024 02:11:03 +0500 Subject: [PATCH 05/15] feat: update api and manifest --- package.json | 4 +- src/api/schema.d.ts | 77 ++++++++++++++++++++++++++------ src/api/squids.ts | 26 ++++++++--- src/command.ts | 2 +- src/commands/deploy.ts | 32 ++++++++------ src/commands/logs.ts | 20 +++------ src/commands/ls.ts | 5 ++- src/commands/restart.ts | 24 ++++------ src/commands/rm.ts | 23 ++++------ src/commands/tags/add.ts | 41 +++++++---------- src/commands/tags/remove.ts | 83 +++++++++++++++-------------------- src/deploy-command.ts | 6 +-- src/flags/fullname.ts | 9 ++-- src/flags/index.ts | 2 +- src/flags/{ref.ts => slot.ts} | 10 ++--- src/ui/components/types.ts | 2 +- src/utils.ts | 12 ++--- yarn.lock | 20 ++++----- 18 files changed, 213 insertions(+), 185 deletions(-) rename src/flags/{ref.ts => slot.ts} (54%) diff --git a/package.json b/package.json index 2310f0f..65f2ec9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.3", + "version": "3.0.0-beta.4", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { @@ -78,7 +78,7 @@ "@oclif/plugin-autocomplete": "3.2.2", "@oclif/plugin-warn-if-update-available": "^3.1.13", "@subsquid/commands": "^2.3.1", - "@subsquid/manifest": "^1.0.0-beta.12", + "@subsquid/manifest": "^2.0.0-beta.2", "@subsquid/manifest-expr": "^0.0.1", "@types/fast-levenshtein": "^0.0.4", "@types/lodash": "^4.17.7", diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts index b6fd877..0e60677 100644 --- a/src/api/schema.d.ts +++ b/src/api/schema.d.ts @@ -192,7 +192,7 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/orgs/{org}/squids/{reference}/tag": { + "/v1/orgs/{org}/squids/{reference}/tags/{tag}": { parameters: { query?: never; header?: never; @@ -200,10 +200,11 @@ export interface paths { cookie?: never; }; get?: never; - put?: never; - /** Assign tag to a squid */ - post: operations["SquidController_setTag"]; - delete?: never; + /** Add tag to a squid */ + put: operations["SquidController_addTag"]; + post?: never; + /** Remove tag from a squid */ + delete: operations["SquidController_removeTag"]; options?: never; head?: never; patch?: never; @@ -682,7 +683,7 @@ export interface components { /** @example my-squid */ name: string; /** @example abc12 */ - hash: string; + slot: string; /** @example my-squid:abc12 */ reference: string; }; @@ -836,7 +837,7 @@ export interface components { /** @example my-squid:4fush9 */ reference: string; /** @example 4fush9 */ - hash: string; + slot: string; description?: string | null; tags: components["schemas"]["SquidTagResponse"][]; manifest: components["schemas"]["SquidManifestResponse"]; @@ -1331,9 +1332,9 @@ export interface operations { manifestPath?: string; /** @default {} */ options?: { - updateByHash?: string; + overrideSlot?: string; hardReset?: boolean; - overrideName: string; + overrideName?: string; tag?: string; }; }; @@ -1578,23 +1579,71 @@ export interface operations { }; }; }; - SquidController_setTag: { + SquidController_addTag: { parameters: { query?: never; header?: never; path: { org: string; reference: string; + tag: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": { - tag: string; + requestBody?: never; + responses: { + /** @description Successful response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example null */ + error?: string; + payload?: components["schemas"]["DeploymentResponse"]; + }; + }; + }; + /** @description Bad user input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + invalidFields: { + message: string; + path: string[]; + type: string; + }[]; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UnauthorizedResponse"]; }; }; }; + }; + SquidController_removeTag: { + parameters: { + query?: never; + header?: never; + path: { + org: string; + reference: string; + tag: string; + }; + cookie?: never; + }; + requestBody?: never; responses: { /** @description Successful response */ 201: { diff --git a/src/api/squids.ts b/src/api/squids.ts index c149d3e..9df15b5 100644 --- a/src/api/squids.ts +++ b/src/api/squids.ts @@ -173,7 +173,7 @@ export async function deploySquid({ artifactUrl: string; manifestPath: string; options: { - updateByHash?: string; + overrideSlot?: string; overrideName?: string; tag?: string; hardReset?: boolean; @@ -216,15 +216,27 @@ export async function deleteSquid({ organization, reference }: SquidRequest): Pr return body.payload; } -export async function tagSquid({ +export async function addSquidTag({ organization, reference, - data, -}: SquidRequest & { data: { tag: string } }): Promise { + tag, +}: SquidRequest & { tag: string }): Promise { const { body } = await api>({ - method: 'post', - path: `/orgs/${organization.code}/squids/${reference}/tag`, - data, + method: 'PUT', + path: `/orgs/${organization.code}/squids/${reference}/tags/${tag}`, + }); + + return body.payload; +} + +export async function removeSquidTag({ + organization, + reference, + tag, +}: SquidRequest & { tag: string }): Promise { + const { body } = await api>({ + method: 'DELETE', + path: `/orgs/${organization.code}/squids/${reference}/tags/${tag}`, }); return body.payload; diff --git a/src/command.ts b/src/command.ts index b5f4a9f..52f135e 100644 --- a/src/command.ts +++ b/src/command.ts @@ -95,7 +95,7 @@ export abstract class CliCommand extends Command { async findSquid({ organization, reference }: SquidRequest) { try { - return getSquid({ organization, reference }); + return await getSquid({ organization, reference }); } catch (e) { if (e instanceof ApiError && e.request.status === 404) { return null; diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 31ff1b9..b7eda51 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -110,7 +110,7 @@ export default class Deploy extends DeployCommand { tag: SqdFlags.tag({ required: false, }), - ref: SqdFlags.ref({ + slot: SqdFlags.slot({ required: false, }), fullname: SqdFlags.fullname({ @@ -192,23 +192,29 @@ export default class Deploy extends DeployCommand { this.log(chalk.dim(`Build directory: ${buildDir}`)); this.log(chalk.dim(`Manifest: ${manifestPath}`)); - const overrides = fullname ? fullname : pick(flags, 'name', 'org', 'ref', 'tag'); + const overrides = fullname ? fullname : flags; + + // some hack to add slot name in case if version is used + { + manifest.slot = manifest.slotName(); + delete manifest['version']; + } const override = await this.promptOverrideConflict(manifest, overrides); if (!override) return; // eslint-disable-next-line prefer-const - let { name, org, ref, tag } = defaults(overrides, manifest); + let { name, slot, org, tag } = defaults(overrides, manifest); const organization = await this.promptOrganization(org); - // name = await this.promptSquidName(name); + name = await this.promptSquidName(name); let target: Squid | null = null; - if (ref || tag) { + if (slot || tag) { target = await this.findSquid({ organization, - reference: formatSquidFullname(ref ? { name, ref } : { name, tag: tag! }), + reference: formatSquidFullname(slot ? { name, slot } : { name, tag: tag! }), }); } @@ -231,7 +237,7 @@ export default class Deploy extends DeployCommand { /** * Squid exists we should check if tag belongs to another squid */ - if (target && ref && tag && !applyTag) { + if (target && slot && tag && !applyTag) { const apply = await this.promptApplyTag(target, tag); if (!apply) return; } @@ -248,7 +254,7 @@ export default class Deploy extends DeployCommand { options: { hardReset, overrideName: name, - updateByHash: target?.hash, + overrideSlot: slot, tag, }, }, @@ -263,7 +269,7 @@ export default class Deploy extends DeployCommand { `The squid ${formatSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, - ref: deployment.squid.hash, + slot: deployment.squid.slot, })} has been successfully updated`, ); } else { @@ -272,7 +278,7 @@ export default class Deploy extends DeployCommand { `A new squid ${formatSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, - ref: deployment.squid.hash, + slot: deployment.squid.slot, })} has been successfully created`, ); } @@ -292,7 +298,7 @@ export default class Deploy extends DeployCommand { `A squid "${formatSquidFullname({ org: target.organization.code, name: target.name, - ref: target.hash, + slot: target.slot, })}" will be updated. ${chalk.bold('Are you sure?')}`, ), ].join('\n'), @@ -317,7 +323,7 @@ export default class Deploy extends DeployCommand { type: 'confirm', message: [ chalk.reset( - `A squid tag "${tag}" has already been assigned to ${formatSquidFullname({ name: oldSquid.name, ref: oldSquid.hash })}.`, + `A squid tag "${tag}" has already been assigned to ${formatSquidFullname({ name: oldSquid.name, slot: oldSquid.slot })}.`, ), chalk.reset(`The tag will be assigned to the newly created squid. ${chalk.bold('Are you sure?')}`), ].join('\n'), @@ -375,7 +381,7 @@ export default class Deploy extends DeployCommand { }, ]); - return input.name; + return input.name as string; } private async pack({ buildDir, squidDir, archiveName }: { buildDir: string; squidDir: string; archiveName: string }) { diff --git a/src/commands/logs.ts b/src/commands/logs.ts index 37d0744..73058de 100644 --- a/src/commands/logs.ts +++ b/src/commands/logs.ts @@ -32,13 +32,6 @@ export default class Logs extends CliCommand { type: 'all', flags: ['name'], }, - { - type: 'some', - flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, - ], - }, ], }), name: SqdFlags.name({ @@ -47,20 +40,20 @@ export default class Logs extends CliCommand { { type: 'some', flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, ], }, ], }), - ref: SqdFlags.ref({ + slot: SqdFlags.slot({ required: false, dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, dependsOn: ['name'], - exclusive: ['ref'], + exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -91,7 +84,6 @@ export default class Logs extends CliCommand { default: '1d', }), search: Flags.string({ - char: 's', summary: 'Filter by content', required: false, }), @@ -111,8 +103,8 @@ export default class Logs extends CliCommand { this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, ref } = fullname ? fullname : omitBy(flags, isNil); - const reference = formatSquidFullname({ name, ref, tag }); + const { org, name, tag, slot } = fullname ? fullname : omitBy(flags, isNil); + const reference = formatSquidFullname({ name, slot, tag }); const organization = await this.promptSquidOrganization({ code: org, name }); const squid = await this.findOrThrowSquid({ organization, reference }); diff --git a/src/commands/ls.ts b/src/commands/ls.ts index e491975..c465167 100644 --- a/src/commands/ls.ts +++ b/src/commands/ls.ts @@ -1,5 +1,6 @@ import { ux as CliUx, Flags } from '@oclif/core'; import chalk from 'chalk'; +import { isNil, omitBy } from 'lodash'; import { listSquids } from '../api'; import { CliCommand, SqdFlags } from '../command'; @@ -37,7 +38,7 @@ export default class Ls extends CliCommand { } = await this.parse(Ls); const noTruncate = !truncate; - const { org, name } = fullname ? fullname : (flags as any); + const { org, name } = fullname ? fullname : omitBy(flags, isNil); const organization = name ? await this.promptSquidOrganization({ code: org, name }) @@ -50,7 +51,7 @@ export default class Ls extends CliCommand { { name: { header: 'Squid', - get: (s) => `${s.name}${chalk.dim(`@${s.hash}`)}`, + get: (s) => `${s.name}${chalk.dim(`@${s.slot}`)}`, }, tags: { header: 'Tags', diff --git a/src/commands/restart.ts b/src/commands/restart.ts index ca8ad5c..a8f950b 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -1,7 +1,8 @@ import { Flags } from '@oclif/core'; +import { isNil, omitBy } from 'lodash'; import { restartSquid } from '../api'; -import { SqdFlags, SquidReferenceArg } from '../command'; +import { SqdFlags } from '../command'; import { DeployCommand } from '../deploy-command'; import { formatSquidFullname } from '../utils'; @@ -18,13 +19,6 @@ export default class Restart extends DeployCommand { type: 'all', flags: ['name'], }, - { - type: 'some', - flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, - ], - }, ], }), name: SqdFlags.name({ @@ -33,20 +27,20 @@ export default class Restart extends DeployCommand { { type: 'some', flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, ], }, ], }), - ref: SqdFlags.ref({ + slot: SqdFlags.slot({ required: false, dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, dependsOn: ['name'], - exclusive: ['ref'], + exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -60,8 +54,8 @@ export default class Restart extends DeployCommand { this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, ref } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, ref, tag }); + const { org, name, tag, slot } = fullname ? fullname : omitBy(flags, isNil); + const reference = formatSquidFullname({ name, slot, tag }); const organization = await this.promptSquidOrganization({ code: org, name }); await this.findOrThrowSquid({ organization, reference }); @@ -75,7 +69,7 @@ export default class Restart extends DeployCommand { `The squid ${formatSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, - ref: deployment.squid.hash, + slot: deployment.squid.slot, })} has been successfully restarted`, ); } diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 0b1b8e5..1a81f6d 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -23,13 +23,6 @@ export default class Rm extends DeployCommand { type: 'all', flags: ['name'], }, - { - type: 'some', - flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, - ], - }, ], }), name: SqdFlags.name({ @@ -38,20 +31,20 @@ export default class Rm extends DeployCommand { { type: 'some', flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, ], }, ], }), - ref: SqdFlags.ref({ + slot: SqdFlags.slot({ required: false, dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, dependsOn: ['name'], - exclusive: ['ref'], + exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -70,8 +63,8 @@ export default class Rm extends DeployCommand { this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, ref } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, ref, tag }); + const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, slot, tag }); const organization = await this.promptSquidOrganization({ code: org, name }); const squid = await this.findOrThrowSquid({ organization, reference }); @@ -81,7 +74,7 @@ export default class Rm extends DeployCommand { { name: 'confirm', type: 'confirm', - message: `Your squid ${formatSquidFullname({ org, name, ref: squid.hash })} will be completely removed. This action can not be undone. Are you sure?`, + message: `Your squid ${formatSquidFullname({ org, name, slot: squid.slot })} will be completely removed. This action can not be undone. Are you sure?`, }, ]); if (!confirm) return; @@ -96,7 +89,7 @@ export default class Rm extends DeployCommand { `A squid deployment ${formatSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, - ref: deployment.squid.hash, + slot: deployment.squid.slot, })} was successfully deleted`, ); } diff --git a/src/commands/tags/add.ts b/src/commands/tags/add.ts index 094f62b..f6cf5c4 100644 --- a/src/commands/tags/add.ts +++ b/src/commands/tags/add.ts @@ -2,7 +2,7 @@ import { Args, Flags } from '@oclif/core'; import chalk from 'chalk'; import inquirer from 'inquirer'; -import { tagSquid } from '../../api'; +import { addSquidTag } from '../../api'; import { SqdFlags } from '../../command'; import { DeployCommand } from '../../deploy-command'; import { formatSquidFullname } from '../../utils'; @@ -26,13 +26,6 @@ export default class Add extends DeployCommand { type: 'all', flags: ['name'], }, - { - type: 'some', - flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, - ], - }, ], }), name: SqdFlags.name({ @@ -41,20 +34,20 @@ export default class Add extends DeployCommand { { type: 'some', flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, ], }, ], }), - ref: SqdFlags.ref({ + slot: SqdFlags.slot({ required: false, dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, dependsOn: ['name'], - exclusive: ['ref'], + exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -63,23 +56,25 @@ export default class Add extends DeployCommand { async run(): Promise { const { - args: { tag: newTag }, + args: { tag: tagName }, flags: { fullname, ...flags }, } = await this.parse(Add); this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, ref } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, ref, tag }); + const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, slot, tag }); const organization = await this.promptSquidOrganization({ code: org, name }); const squid = await this.findOrThrowSquid({ organization, reference }); - if (squid.tags.find((t) => t.name === tag)) { - return this.log(`Tag "${tag}" is already assigned to the squid ${formatSquidFullname({ org, name, tag, ref })}`); + if (squid.tags.find((t) => t.name === tagName)) { + return this.log( + `Tag "${tagName}" is already assigned to the squid ${formatSquidFullname({ org, name, tag, slot })}`, + ); } - const oldSquid = await this.findSquid({ organization, reference: formatSquidFullname({ name, tag: newTag }) }); + const oldSquid = await this.findSquid({ organization, reference: formatSquidFullname({ name, tag: tagName }) }); if (oldSquid) { const { confirm } = await inquirer.prompt([ { @@ -87,7 +82,7 @@ export default class Add extends DeployCommand { type: 'confirm', message: [ chalk.reset( - `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidFullname({ org, name, ref: oldSquid.hash })}.`, + `A squid tag "${tagName}" has already been assigned to the previous squid deployment ${formatSquidFullname({ org, name, slot: oldSquid.slot })}.`, ), chalk.reset(`The tag URL will be assigned to the newly created deployment. ${chalk.bold(`Are you sure?`)}`), ].join('\n'), @@ -96,12 +91,10 @@ export default class Add extends DeployCommand { if (!confirm) return; } - const deployment = await tagSquid({ + const deployment = await addSquidTag({ organization, reference, - data: { - tag: newTag, - }, + tag: tagName, }); await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; @@ -111,7 +104,7 @@ export default class Add extends DeployCommand { `The squid ${formatSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, - ref: deployment.squid.hash, + slot: deployment.squid.slot, })} has been successfully updated`, ); } diff --git a/src/commands/tags/remove.ts b/src/commands/tags/remove.ts index b6bcc00..230ca6d 100644 --- a/src/commands/tags/remove.ts +++ b/src/commands/tags/remove.ts @@ -1,8 +1,6 @@ -import { Args, Flags } from '@oclif/core'; -import chalk from 'chalk'; -import inquirer from 'inquirer'; +import { Args } from '@oclif/core'; -import { tagSquid } from '../../api'; +import { removeSquidTag } from '../../api'; import { SqdFlags } from '../../command'; import { DeployCommand } from '../../deploy-command'; import { formatSquidFullname } from '../../utils'; @@ -11,7 +9,12 @@ import { UPDATE_COLOR } from '../deploy'; export default class Remove extends DeployCommand { static description = 'Remove a tag from a squid'; - static args = {}; + static args = { + tag: Args.string({ + description: `New tag to assign`, + required: true, + }), + }; static flags = { org: SqdFlags.org({ @@ -24,8 +27,8 @@ export default class Remove extends DeployCommand { { type: 'some', flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, ], }, ], @@ -36,20 +39,20 @@ export default class Remove extends DeployCommand { { type: 'some', flags: [ - { name: 'ref', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['ref'] }, + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, ], }, ], }), - ref: SqdFlags.ref({ + slot: SqdFlags.slot({ required: false, dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, dependsOn: ['name'], - exclusive: ['ref'], + exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -58,53 +61,37 @@ export default class Remove extends DeployCommand { async run(): Promise { const { + args: { tag: tagName }, flags: { fullname, ...flags }, } = await this.parse(Remove); this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, ref } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, ref, tag }); + const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const reference = formatSquidFullname({ name, slot, tag }); const organization = await this.promptSquidOrganization({ code: org, name }); const squid = await this.findOrThrowSquid({ organization, reference }); - throw new Error('API is not implemented yet'); - - // const oldSquid = await this.findSquid({ organization, reference: formatSquidFullname({ name, tag: newTag }) }); - // if (oldSquid) { - // const { confirm } = await inquirer.prompt([ - // { - // name: 'confirm', - // type: 'confirm', - // message: [ - // chalk.reset( - // `A squid tag "${tag}" has already been assigned to the previous squid deployment ${formatSquidFullname({ org, name, ref: oldSquid.hash })}.`, - // ), - // chalk.reset(`The tag URL will be assigned to the newly created deployment. ${chalk.bold(`Are you sure?`)}`), - // ].join('\n'), - // }, - // ]); - // if (!confirm) return; - // } + if (!squid.tags.some((t) => t.name === tagName)) { + return this.log(`Tag "${tagName}" is not assigned to the squid ${formatSquidFullname({ org, name, tag, slot })}`); + } - // const deployment = await tagSquid({ - // organization, - // reference, - // data: { - // tag: newTag, - // }, - // }); - // await this.pollDeploy({ organization, deploy: deployment }); - // if (!deployment || !deployment.squid) return; + const deployment = await removeSquidTag({ + organization, + reference, + tag: tagName, + }); + await this.pollDeploy({ organization, deploy: deployment }); + if (!deployment || !deployment.squid) return; - // this.logDeployResult( - // UPDATE_COLOR, - // `The squid ${formatSquidFullname({ - // org: deployment.organization.code, - // name: deployment.squid.name, - // ref: deployment.squid.hash, - // })} has been successfully updated`, - // ); + this.logDeployResult( + UPDATE_COLOR, + `The squid ${formatSquidFullname({ + org: deployment.organization.code, + name: deployment.squid.name, + slot: deployment.squid.slot, + })} has been successfully updated`, + ); } } diff --git a/src/deploy-command.ts b/src/deploy-command.ts index 4f4f8ed..f3ccf59 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -4,7 +4,7 @@ import inquirer from 'inquirer'; import { Deployment, DeployRequest, getDeploy, Organization, Squid, streamSquidLogs } from './api'; import { CliCommand, SUCCESS_CHECK_MARK } from './command'; -import { doUntil } from './utils'; +import { doUntil, formatSquidFullname } from './utils'; export abstract class DeployCommand extends CliCommand { deploy: Deployment | undefined; @@ -21,7 +21,7 @@ export abstract class DeployCommand extends CliCommand { { name: 'confirm', type: 'confirm', - message: `Squid "${squid.name}#${squid.hash}" is being deploying. + message: `Squid "${formatSquidFullname(squid)}" is being deploying. You can not run deploys on the same squid in parallel. Do you want to attach to the running deploy process?`, }, @@ -170,7 +170,7 @@ Do you want to attach to the running deploy process?`, ); if (this.deploy?.squid) { - errors.push(`${chalk.dim('Squid:')} ${this.deploy.squid.name}#${this.deploy.squid.hash}`); + errors.push(`${chalk.dim('Squid:')} ${formatSquidFullname(this.deploy.squid)}`); } } diff --git a/src/flags/fullname.ts b/src/flags/fullname.ts index 578cd16..a64721f 100644 --- a/src/flags/fullname.ts +++ b/src/flags/fullname.ts @@ -5,14 +5,15 @@ import { ParsedSquidFullname, parseSquidFullname, SQUID_FULLNAME_REGEXP } from ' export const fullname = Flags.custom({ helpGroup: 'COMMON', name: 'fullname', - description: `Full name of a squid`, - helpValue: '[/](@|:)', + aliases: ['ref'], + description: `Reference of a squid`, + helpValue: '[/](@|:)', required: false, - exclusive: ['org', 'name', 'ref', 'tag'], + exclusive: ['org', 'name', 'slot', 'tag'], parse: async (input) => { input = input.toLowerCase(); if (!SQUID_FULLNAME_REGEXP.test(input)) { - throw new Error(`Expected a squid full name but received: ${input}`); + throw new Error(`Expected a squid reference name but received: ${input}`); } return parseSquidFullname(input); diff --git a/src/flags/index.ts b/src/flags/index.ts index ffa4778..d5815f4 100644 --- a/src/flags/index.ts +++ b/src/flags/index.ts @@ -1,5 +1,5 @@ export { fullname } from './fullname'; export { name } from './name'; export { org } from './org'; -export { ref } from './ref'; +export { slot } from './slot'; export { tag } from './tag'; diff --git a/src/flags/ref.ts b/src/flags/slot.ts similarity index 54% rename from src/flags/ref.ts rename to src/flags/slot.ts index 20b6ff2..a193ba3 100644 --- a/src/flags/ref.ts +++ b/src/flags/slot.ts @@ -1,11 +1,11 @@ import { Flags } from '@oclif/core'; -export const ref = Flags.custom({ +export const slot = Flags.custom({ helpGroup: 'COMMON', - char: 'r', - name: 'ref', - description: 'Squid ref', - helpValue: '', + char: 's', + name: 'slot', + description: 'Squid slot', + helpValue: '', parse: async (input) => { return input.toLowerCase(); }, diff --git a/src/ui/components/types.ts b/src/ui/components/types.ts index 2b46b55..c862f2f 100644 --- a/src/ui/components/types.ts +++ b/src/ui/components/types.ts @@ -8,7 +8,7 @@ export class Squid { constructor(squid: ApiSquid) { Object.assign(this, squid); - this.displayName = formatSquidFullname({ name: this.name, ref: this.hash }); + this.displayName = formatSquidFullname({ name: this.name, slot: this.slot }); if (this.tags.length) { this.displayName += ` (${this.tags.map((a) => a.name).join(', ')})`; diff --git a/src/utils.ts b/src/utils.ts index fd07e18..3018395 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -24,14 +24,14 @@ export async function doUntil(fn: () => Promise, { pause }: { pause: nu } export type ParsedSquidFullname = { org?: string; name: string } & ( - | { ref: string; tag?: never } - | { ref?: never; tag: string } + | { slot: string; tag?: never } + | { slot?: never; tag: string } ); -export function formatSquidFullname({ org, name, ref, tag }: ParsedSquidFullname) { +export function formatSquidFullname({ org, name, slot, tag }: ParsedSquidFullname) { let res = org ? `${org}/` : ''; res += name; - res += ref ? `@${ref}` : `:${tag}`; + res += slot ? `@${slot}` : `:${tag}`; return res; } @@ -44,7 +44,7 @@ export function parseSquidFullname(fullname: string): ParsedSquidFullname { throw new Error(`Invalid squid full name: "${fullname}"`); } - const [, , org, name, type, tagOrRef] = parsed; + const [, , org, name, type, tagOrSlot] = parsed; - return { org, name, ...(type === ':' ? { tag: tagOrRef } : { ref: tagOrRef }) }; + return { org, name, ...(type === ':' ? { tag: tagOrSlot } : { slot: tagOrSlot }) }; } diff --git a/yarn.lock b/yarn.lock index 0ef8690..9bd21b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1411,7 +1411,7 @@ __metadata: "@oclif/plugin-autocomplete": "npm:3.2.2" "@oclif/plugin-warn-if-update-available": "npm:^3.1.13" "@subsquid/commands": "npm:^2.3.1" - "@subsquid/manifest": "npm:^1.0.0-beta.12" + "@subsquid/manifest": "npm:^2.0.0-beta.2" "@subsquid/manifest-expr": "npm:^0.0.1" "@types/async-retry": "npm:^1.4.8" "@types/blessed": "npm:^0.1.25" @@ -1512,15 +1512,15 @@ __metadata: languageName: node linkType: hard -"@subsquid/manifest@npm:^1.0.0-beta.12": - version: 1.0.0-beta.12 - resolution: "@subsquid/manifest@npm:1.0.0-beta.12" +"@subsquid/manifest@npm:^2.0.0-beta.2": + version: 2.0.0-beta.2 + resolution: "@subsquid/manifest@npm:2.0.0-beta.2" dependencies: "@subsquid/manifest-expr": "npm:^0.0.1" - joi: "npm:^17.12.0" + joi: "npm:17.13.3" js-yaml: "npm:^4.1.0" lodash: "npm:^4.17.21" - checksum: 10c0/ad95eadcc8c0093c7954cdb7a7ed81b67592736e9c30eea6299f883abbc4e95d0c8b249e2c769cfeb3e1175b8d2f03a8b96d76d489bb82a87526280416d7973a + checksum: 10c0/32059ac92737aa1728fdfd50f6e3c300e662b7d05f13c33dd59538aa84a9beb5ae4d830513754f6a0a87b8f2f41968b14890144be93ccf0455b15b2bc59b539b languageName: node linkType: hard @@ -5998,16 +5998,16 @@ __metadata: languageName: node linkType: hard -"joi@npm:^17.12.0": - version: 17.12.1 - resolution: "joi@npm:17.12.1" +"joi@npm:17.13.3": + version: 17.13.3 + resolution: "joi@npm:17.13.3" dependencies: "@hapi/hoek": "npm:^9.3.0" "@hapi/topo": "npm:^5.1.0" "@sideway/address": "npm:^4.1.5" "@sideway/formula": "npm:^3.0.1" "@sideway/pinpoint": "npm:^2.0.0" - checksum: 10c0/552ec235a4fb068290f85c8248e0afc6a8fa91a33d7fd7552fa1f1d8682b5d2d0f0c29901b6843d7936f1e15e8bf0a537126ccb01fa72cf0eb626ff1a0a77a73 + checksum: 10c0/9262aef1da3f1bec5b03caf50c46368899fe03b8ff26cbe3d53af4584dd1049079fc97230bbf1500b6149db7cc765b9ee45f0deb24bb6fc3fa06229d7148c17f languageName: node linkType: hard From 03114b699341b87f6b2f9bda9c91eef52ebfa5b1 Mon Sep 17 00:00:00 2001 From: Eugene Formanenko Date: Mon, 9 Sep 2024 15:57:31 +0400 Subject: [PATCH 06/15] feat: print full ref as bold --- src/command.ts | 1 - src/commands/deploy.ts | 53 ++++++++++++++++++++++--------------- src/commands/restart.ts | 4 +-- src/commands/rm.ts | 6 ++--- src/commands/tags/add.ts | 8 +++--- src/commands/tags/remove.ts | 6 ++--- src/utils.ts | 4 +++ 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/command.ts b/src/command.ts index 52f135e..8bcf16a 100644 --- a/src/command.ts +++ b/src/command.ts @@ -6,7 +6,6 @@ import { isNil, uniqBy } from 'lodash'; import { ApiError, getOrganization, getSquid, listOrganizations, listUserSquids, SquidRequest } from './api'; import { getTTY } from './tty'; -import { parseSquidFullname } from './utils'; export const SUCCESS_CHECK_MARK = chalk.green('✓'); diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index b7eda51..91c56cf 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -17,7 +17,7 @@ import { deploySquid, OrganizationRequest, Squid, uploadFile } from '../api'; import { SqdFlags, SUCCESS_CHECK_MARK } from '../command'; import { DeployCommand } from '../deploy-command'; import { loadManifestFile } from '../manifest'; -import { formatSquidFullname, ParsedSquidFullname, parseSquidFullname } from '../utils'; +import { formatSquidFullname, ParsedSquidFullname, parseSquidFullname, printSquidFullname } from '../utils'; const compressAsync = promisify(targz.compress); @@ -188,10 +188,6 @@ export default class Deploy extends DeployCommand { const { buildDir, squidDir, manifest } = res; - this.log(chalk.dim(`Squid directory: ${squidDir}`)); - this.log(chalk.dim(`Build directory: ${buildDir}`)); - this.log(chalk.dim(`Manifest: ${manifestPath}`)); - const overrides = fullname ? fullname : flags; // some hack to add slot name in case if version is used @@ -210,6 +206,20 @@ export default class Deploy extends DeployCommand { name = await this.promptSquidName(name); + this.log(chalk.dim(`Squid directory: ${squidDir}`)); + this.log(chalk.dim(`Build directory: ${buildDir}`)); + this.log(chalk.dim(`Manifest: ${manifestPath}`)); + this.log(chalk.cyan(`-----------------------------`)); + this.log(chalk.cyan(`Organization: ${organization.code}`)); + this.log(chalk.cyan(`Squid name: ${name}`)); + if (slot) { + this.log(chalk.cyan(`Squid slot: ${slot}`)); + } + if (tag) { + this.log(chalk.cyan(`Squid tag: ${tag}`)); + } + this.log(chalk.cyan(`-----------------------------`)); + let target: Squid | null = null; if (slot || tag) { target = await this.findSquid({ @@ -266,7 +276,7 @@ export default class Deploy extends DeployCommand { if (target) { this.logDeployResult( UPDATE_COLOR, - `The squid ${formatSquidFullname({ + `The squid ${printSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, slot: deployment.squid.slot, @@ -275,7 +285,7 @@ export default class Deploy extends DeployCommand { } else { this.logDeployResult( CREATE_COLOR, - `A new squid ${formatSquidFullname({ + `A new squid ${printSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, slot: deployment.squid.slot, @@ -289,19 +299,18 @@ export default class Deploy extends DeployCommand { } private async promptUpdateSquid(target: Squid) { + this.log( + `A squid "${printSquidFullname({ + org: target.organization.code, + name: target.name, + slot: target.slot, + })}" will be updated.`, + ); const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', - message: [ - chalk.reset( - `A squid "${formatSquidFullname({ - org: target.organization.code, - name: target.name, - slot: target.slot, - })}" will be updated. ${chalk.bold('Are you sure?')}`, - ), - ].join('\n'), + message: 'Are you sure you wish to proceed?', }, ]); @@ -317,16 +326,16 @@ export default class Deploy extends DeployCommand { }); if (!oldSquid) return true; + this.log( + `A squid tag "${tag}" has already been assigned to ${printSquidFullname({ name: oldSquid.name, slot: oldSquid.slot })}.`, + ); + this.log(`The tag will be assigned to the newly created squid.`); + const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', - message: [ - chalk.reset( - `A squid tag "${tag}" has already been assigned to ${formatSquidFullname({ name: oldSquid.name, slot: oldSquid.slot })}.`, - ), - chalk.reset(`The tag will be assigned to the newly created squid. ${chalk.bold('Are you sure?')}`), - ].join('\n'), + message: 'Are you sure you wish to proceed?', }, ]); diff --git a/src/commands/restart.ts b/src/commands/restart.ts index a8f950b..d954853 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -4,7 +4,7 @@ import { isNil, omitBy } from 'lodash'; import { restartSquid } from '../api'; import { SqdFlags } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidFullname } from '../utils'; +import { formatSquidFullname, printSquidFullname } from '../utils'; import { UPDATE_COLOR } from './deploy'; @@ -66,7 +66,7 @@ export default class Restart extends DeployCommand { this.logDeployResult( UPDATE_COLOR, - `The squid ${formatSquidFullname({ + `The squid ${printSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, slot: deployment.squid.slot, diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 1a81f6d..245cba9 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -4,7 +4,7 @@ import inquirer from 'inquirer'; import { deleteSquid } from '../api'; import { SqdFlags, SquidReferenceArg } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidFullname } from '../utils'; +import { formatSquidFullname, printSquidFullname } from '../utils'; import { DELETE_COLOR } from './deploy'; @@ -74,7 +74,7 @@ export default class Rm extends DeployCommand { { name: 'confirm', type: 'confirm', - message: `Your squid ${formatSquidFullname({ org, name, slot: squid.slot })} will be completely removed. This action can not be undone. Are you sure?`, + message: `Your squid ${printSquidFullname({ org, name, slot: squid.slot })} will be completely removed. This action can not be undone. Are you sure?`, }, ]); if (!confirm) return; @@ -86,7 +86,7 @@ export default class Rm extends DeployCommand { this.logDeployResult( DELETE_COLOR, - `A squid deployment ${formatSquidFullname({ + `A squid deployment ${printSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, slot: deployment.squid.slot, diff --git a/src/commands/tags/add.ts b/src/commands/tags/add.ts index f6cf5c4..4e50d42 100644 --- a/src/commands/tags/add.ts +++ b/src/commands/tags/add.ts @@ -5,7 +5,7 @@ import inquirer from 'inquirer'; import { addSquidTag } from '../../api'; import { SqdFlags } from '../../command'; import { DeployCommand } from '../../deploy-command'; -import { formatSquidFullname } from '../../utils'; +import { formatSquidFullname, printSquidFullname } from '../../utils'; import { UPDATE_COLOR } from '../deploy'; export default class Add extends DeployCommand { @@ -70,7 +70,7 @@ export default class Add extends DeployCommand { if (squid.tags.find((t) => t.name === tagName)) { return this.log( - `Tag "${tagName}" is already assigned to the squid ${formatSquidFullname({ org, name, tag, slot })}`, + `Tag "${tagName}" is already assigned to the squid ${printSquidFullname({ org, name, tag, slot })}`, ); } @@ -82,7 +82,7 @@ export default class Add extends DeployCommand { type: 'confirm', message: [ chalk.reset( - `A squid tag "${tagName}" has already been assigned to the previous squid deployment ${formatSquidFullname({ org, name, slot: oldSquid.slot })}.`, + `A squid tag "${tagName}" has already been assigned to the previous squid deployment ${printSquidFullname({ org, name, slot: oldSquid.slot })}.`, ), chalk.reset(`The tag URL will be assigned to the newly created deployment. ${chalk.bold(`Are you sure?`)}`), ].join('\n'), @@ -101,7 +101,7 @@ export default class Add extends DeployCommand { this.logDeployResult( UPDATE_COLOR, - `The squid ${formatSquidFullname({ + `The squid ${printSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, slot: deployment.squid.slot, diff --git a/src/commands/tags/remove.ts b/src/commands/tags/remove.ts index 230ca6d..a267985 100644 --- a/src/commands/tags/remove.ts +++ b/src/commands/tags/remove.ts @@ -3,7 +3,7 @@ import { Args } from '@oclif/core'; import { removeSquidTag } from '../../api'; import { SqdFlags } from '../../command'; import { DeployCommand } from '../../deploy-command'; -import { formatSquidFullname } from '../../utils'; +import { formatSquidFullname, printSquidFullname } from '../../utils'; import { UPDATE_COLOR } from '../deploy'; export default class Remove extends DeployCommand { @@ -74,7 +74,7 @@ export default class Remove extends DeployCommand { const squid = await this.findOrThrowSquid({ organization, reference }); if (!squid.tags.some((t) => t.name === tagName)) { - return this.log(`Tag "${tagName}" is not assigned to the squid ${formatSquidFullname({ org, name, tag, slot })}`); + return this.log(`Tag "${tagName}" is not assigned to the squid ${printSquidFullname({ org, name, tag, slot })}`); } const deployment = await removeSquidTag({ @@ -87,7 +87,7 @@ export default class Remove extends DeployCommand { this.logDeployResult( UPDATE_COLOR, - `The squid ${formatSquidFullname({ + `The squid ${printSquidFullname({ org: deployment.organization.code, name: deployment.squid.name, slot: deployment.squid.slot, diff --git a/src/utils.ts b/src/utils.ts index 3018395..daf2805 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -36,6 +36,10 @@ export function formatSquidFullname({ org, name, slot, tag }: ParsedSquidFullnam return res; } +export function printSquidFullname(args: ParsedSquidFullname) { + return chalk.bold(formatSquidFullname(args)); +} + export const SQUID_FULLNAME_REGEXP = /^(([a-z0-9\-]+)\/)?([a-z0-9\-]+)([:@])([a-z0-9\-]+)$/; export function parseSquidFullname(fullname: string): ParsedSquidFullname { From 255ef5f17d577efad493cd1e0f5339f417a8108c Mon Sep 17 00:00:00 2001 From: belopash Date: Tue, 10 Sep 2024 19:28:15 +0500 Subject: [PATCH 07/15] feat: fix --add-tag flag and improve ux --- package.json | 2 +- src/api/schema.d.ts | 3 +- src/api/squids.ts | 37 +++--- src/api/types.ts | 10 +- src/command.ts | 97 ++++++++------ src/commands/deploy.ts | 196 +++++++++++++--------------- src/commands/explorer.ts | 4 +- src/commands/logs.ts | 41 ++---- src/commands/ls.ts | 40 +++--- src/commands/restart.ts | 40 +----- src/commands/rm.ts | 46 ++----- src/commands/secrets/ls.ts | 4 +- src/commands/secrets/rm.ts | 4 +- src/commands/secrets/set.ts | 4 +- src/commands/tags/add.ts | 47 +++---- src/commands/tags/remove.ts | 22 +--- src/deploy-command.ts | 46 ++++++- src/flags/fullname.ts | 8 +- src/flags/name.ts | 11 +- src/flags/org.ts | 2 +- src/flags/slot.ts | 4 +- src/flags/tag.ts | 4 +- src/ui/components/VersionLogsTab.ts | 4 +- src/ui/components/types.ts | 4 +- src/utils.ts | 32 +++-- 25 files changed, 341 insertions(+), 371 deletions(-) diff --git a/package.json b/package.json index 65f2ec9..11b8f1b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.4", + "version": "3.0.0-beta.5", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts index 0e60677..2890d75 100644 --- a/src/api/schema.d.ts +++ b/src/api/schema.d.ts @@ -2981,7 +2981,8 @@ export enum DeploymentResponseStatus { UNPACKING = "UNPACKING", IMAGE_BUILDING = "IMAGE_BUILDING", RESETTING = "RESETTING", - CONFIGURING_INGRESS = "CONFIGURING_INGRESS", + ADDING_INGRESS = "ADDING_INGRESS", + REMOVING_INGRESS = "REMOVING_INGRESS", SQUID_SYNCING = "SQUID_SYNCING", SQUID_DELETING = "SQUID_DELETING", ADDONS_SYNCING = "ADDONS_SYNCING", diff --git a/src/api/squids.ts b/src/api/squids.ts index 9df15b5..25f7d79 100644 --- a/src/api/squids.ts +++ b/src/api/squids.ts @@ -1,6 +1,7 @@ import split2 from 'split2'; import { pretty } from '../logs'; +import { formatSquidReference } from '../utils'; import { api, debugLog } from './api'; import { @@ -24,10 +25,10 @@ export async function listSquids({ organization, name }: OrganizationRequest & { return body.payload.sort((a, b) => a.name.localeCompare(b.name)); } -export async function getSquid({ organization, reference }: SquidRequest): Promise { +export async function getSquid({ organization, squid }: SquidRequest): Promise { const { body } = await api>({ method: 'get', - path: `/orgs/${organization.code}/squids/${reference}`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}`, }); return body.payload; @@ -35,7 +36,7 @@ export async function getSquid({ organization, reference }: SquidRequest): Promi export async function squidHistoryLogs({ organization, - reference, + squid, query, abortController, }: SquidRequest & { @@ -52,7 +53,7 @@ export async function squidHistoryLogs({ }): Promise { const { body } = await api>({ method: 'get', - path: `/orgs/${organization.code}/squids/${reference}/logs/history`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/logs/history`, query: { ...query, from: query.from.toISOString(), @@ -68,7 +69,7 @@ export async function squidHistoryLogs({ export async function squidLogsFollow({ organization, - reference, + squid, query, abortController, }: SquidRequest & { @@ -77,7 +78,7 @@ export async function squidLogsFollow({ }) { const { body } = await api({ method: 'get', - path: `/orgs/${organization.code}/squids/${reference}/logs/follow`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/logs/follow`, query, responseType: 'stream', abortController: abortController, @@ -88,7 +89,7 @@ export async function squidLogsFollow({ export async function streamSquidLogs({ organization, - reference, + squid, abortController, query = {}, onLog, @@ -106,7 +107,7 @@ export async function streamSquidLogs({ try { stream = await squidLogsFollow({ organization, - reference, + squid, query, abortController, }); @@ -198,32 +199,28 @@ export async function getUploadUrl({ organization }: OrganizationRequest): Promi return body.payload; } -export async function restartSquid({ organization, reference }: SquidRequest): Promise { +export async function restartSquid({ organization, squid }: SquidRequest): Promise { const { body } = await api>({ method: 'post', - path: `/orgs/${organization.code}/squids/${reference}/restart`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/restart`, }); return body.payload; } -export async function deleteSquid({ organization, reference }: SquidRequest): Promise { +export async function deleteSquid({ organization, squid }: SquidRequest): Promise { const { body } = await api>({ method: 'delete', - path: `/orgs/${organization.code}/squids/${reference}`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}`, }); return body.payload; } -export async function addSquidTag({ - organization, - reference, - tag, -}: SquidRequest & { tag: string }): Promise { +export async function addSquidTag({ organization, squid, tag }: SquidRequest & { tag: string }): Promise { const { body } = await api>({ method: 'PUT', - path: `/orgs/${organization.code}/squids/${reference}/tags/${tag}`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/tags/${tag}`, }); return body.payload; @@ -231,12 +228,12 @@ export async function addSquidTag({ export async function removeSquidTag({ organization, - reference, + squid, tag, }: SquidRequest & { tag: string }): Promise { const { body } = await api>({ method: 'DELETE', - path: `/orgs/${organization.code}/squids/${reference}/tags/${tag}`, + path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/tags/${tag}`, }); return body.payload; diff --git a/src/api/types.ts b/src/api/types.ts index 2a09afc..d28e17d 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -51,6 +51,14 @@ export type LogsResponse = { export type OrganizationRequest = { organization: PickDeep }; -export type SquidRequest = OrganizationRequest & { reference: string }; +export type SquidRequest = OrganizationRequest & { + squid: + | ({ name: string } & ( + | { tag?: never; slot: string } + | { tag: string; slot?: never } + | { tag: string; slot: string } + )) + | string; +}; export type DeployRequest = OrganizationRequest & { deploy: PickDeep }; diff --git a/src/command.ts b/src/command.ts index 8bcf16a..c19b69b 100644 --- a/src/command.ts +++ b/src/command.ts @@ -1,4 +1,4 @@ -import { Args, Command } from '@oclif/core'; +import { Command, Flags } from '@oclif/core'; import { FailedFlagValidationError } from '@oclif/core/lib/parser/errors'; import chalk from 'chalk'; import inquirer from 'inquirer'; @@ -6,10 +6,19 @@ import { isNil, uniqBy } from 'lodash'; import { ApiError, getOrganization, getSquid, listOrganizations, listUserSquids, SquidRequest } from './api'; import { getTTY } from './tty'; +import { formatSquidReference, printSquid } from './utils'; export const SUCCESS_CHECK_MARK = chalk.green('✓'); export abstract class CliCommand extends Command { + static baseFlags = { + interactive: Flags.boolean({ + required: false, + default: true, + allowNo: true, + }), + }; + logSuccess(message: string) { this.log(SUCCESS_CHECK_MARK + message); } @@ -92,9 +101,9 @@ export abstract class CliCommand extends Command { throw error; } - async findSquid({ organization, reference }: SquidRequest) { + async findSquid(req: SquidRequest) { try { - return await getSquid({ organization, reference }); + return await getSquid(req); } catch (e) { if (e instanceof ApiError && e.request.status === 404) { return null; @@ -104,31 +113,41 @@ export abstract class CliCommand extends Command { } } - async findOrThrowSquid({ organization, reference }: SquidRequest) { - const squid = await this.findSquid({ organization, reference }); - if (!squid) { - throw new Error(`The squid "${reference}" is not found`); + async findOrThrowSquid({ organization, squid }: SquidRequest) { + const res = await this.findSquid({ organization, squid }); + if (!res) { + throw new Error( + `The squid ${formatSquidReference(typeof squid === 'string' ? squid : squid, { colored: true })} is not found`, + ); } - return squid; + return res; } - async promptOrganization(code: string | null | undefined, using?: string) { + async promptOrganization( + code: string | null | undefined, + { using, interactive }: { using?: string; interactive?: boolean } = {}, + ) { if (code) { return await getOrganization({ organization: { code } }); } const organizations = await listOrganizations(); - if (organizations.length === 0) { - return this.error(`You have no organizations. Please create organization first.`); - } else if (organizations.length === 1) { - return organizations[0]; - } - return await this.getOrganizationPrompt(organizations, using); + return await this.getOrganizationPrompt(organizations, { using, interactive }); } - async promptSquidOrganization({ code, name, using }: { code?: string | null; name: string; using?: string }) { + async promptSquidOrganization( + code: string, + name: string, + { + using, + interactive, + }: { + using?: string; + interactive?: boolean; + } = {}, + ) { if (code) { return await getOrganization({ organization: { code } }); } @@ -139,25 +158,37 @@ export abstract class CliCommand extends Command { organizations = uniqBy(organizations, (o) => o.code); if (organizations.length === 0) { - return this.error(`Squid "${name}" was not found.`); - } else if (organizations.length === 1) { - return organizations[0]; + return this.error(`You have no organizations with squid "${name}".`); } - return await this.getOrganizationPrompt(organizations, using); + return await this.getOrganizationPrompt(organizations, { using, interactive }); } private async getOrganizationPrompt( organizations: T[], - using: string = 'using "-o" flag', + { + using = 'using "--org" flag', + interactive, + }: { + using?: string; + interactive?: boolean; + }, ): Promise { + if (organizations.length === 0) { + return this.error(`You have no organizations. Please create organization first.`); + } else if (organizations.length === 1) { + return organizations[0]; + } + const { stdin, stdout } = getTTY(); - if (!stdin || !stdout) { - this.log(chalk.dim(`You have ${organizations.length} organizations:`)); - for (const organization of organizations) { - this.log(`${chalk.dim(' - ')}${chalk.dim(organization.code)}`); - } - return this.error(`Please specify one of them explicitly ${using}`); + if (!stdin || !stdout || !interactive) { + return this.error( + [ + `You have ${organizations.length} organizations:`, + ...organizations.map((o) => `${chalk.dim(' - ')}${chalk.dim(o.code)}`), + `Please specify one of them explicitly ${using}`, + ].join('\n'), + ); } const prompt = inquirer.createPromptModule({ input: stdin, output: stdout }); @@ -183,16 +214,4 @@ export abstract class CliCommand extends Command { } } -export const SquidReferenceArg = Args.string({ - // description: ` or `, - required: true, - parse: async (input) => { - input = input.toLowerCase(); - if (!/^[a-z0-9\-]+[:@][a-z0-9\-]+$/.test(input)) { - throw new Error(`Expected a squid reference but received: ${input}`); - } - return input; - }, -}); - export * as SqdFlags from './flags'; diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 91c56cf..a852e2d 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -9,7 +9,7 @@ import diff from 'cli-diff'; import { globSync } from 'glob'; import ignore from 'ignore'; import inquirer from 'inquirer'; -import { defaults, get, isNil, keys, pick, pickBy } from 'lodash'; +import { defaults, get, isNil, keys } from 'lodash'; import prettyBytes from 'pretty-bytes'; import targz from 'targz'; @@ -17,7 +17,7 @@ import { deploySquid, OrganizationRequest, Squid, uploadFile } from '../api'; import { SqdFlags, SUCCESS_CHECK_MARK } from '../command'; import { DeployCommand } from '../deploy-command'; import { loadManifestFile } from '../manifest'; -import { formatSquidFullname, ParsedSquidFullname, parseSquidFullname, printSquidFullname } from '../utils'; +import { printSquid } from '../utils'; const compressAsync = promisify(targz.compress); @@ -60,22 +60,24 @@ function example(command: string, description: string) { export default class Deploy extends DeployCommand { static description = 'Deploy new or update an existing squid in the Cloud'; static examples = [ - example('sqd deploy', 'Create a new squid with name provided in the manifest file'), + example('sqd deploy ./', 'Create a new squid with name provided in the manifest file'), example( - 'sqd deploy my-squid-override', + 'sqd deploy ./ -n my-squid-override', 'Create a new squid deployment and override it\'s name to "my-squid-override"', ), - example('sqd deploy my-squid#asmzf5', 'Update the "my-squid" squid with hash "asmzf5"'), + example('sqd deploy ./ -n my-squid -s asmzf5', 'Update the "my-squid" squid with slot "asmzf5"'), example( - 'sqd deploy -d ./path-to-the-squid -m squid.prod.yaml', + 'sqd deploy ./path-to-the-squid -m squid.prod.yaml', 'Use a manifest file located in ./path-to-the-squid/squid.prod.yaml', ), example( - 'sqd deploy -d /Users/dev/path-to-the-squid -m /Users/dev/path-to-the-squid/squid.prod.yaml', + 'sqd deploy /Users/dev/path-to-the-squid -m /Users/dev/path-to-the-squid/squid.prod.yaml', 'Full paths are also fine', ), ]; + static help = 'If squid flags are not specified, the they will be retrieved from the manifest or prompted.'; + static args = { // squid_name_or_reference: Args.string({ // description: [ @@ -88,7 +90,7 @@ export default class Deploy extends DeployCommand { // ].join('\n'), // required: false, // }), - source: Args.string({ + source: Args.directory({ description: [ `Squid source. Could be:`, ` - a relative or absolute path to a local folder (e.g. ".")`, @@ -106,58 +108,48 @@ export default class Deploy extends DeployCommand { }), name: SqdFlags.name({ required: false, + relationships: [], }), tag: SqdFlags.tag({ required: false, + dependsOn: [], }), slot: SqdFlags.slot({ required: false, + dependsOn: [], }), fullname: SqdFlags.fullname({ required: false, }), - manifest: Flags.string({ + manifest: Flags.file({ char: 'm', description: 'Relative local path to a squid manifest file in squid working directory', required: false, default: 'squid.yaml', helpValue: '', }), - // dir: Flags.string({ - // char: 'd', - // description: SQUID_WORKDIR_DESC.join('\n'), - // required: false, - // default: '.', - // helpValue: '', - // }), - // tag: Flags.string({ - // char: 't', - // description: [ - // 'Assign the tag to the squid deployment. ', - // 'The previous deployment API URL assigned with the same tag will be transitioned to the new deployment', - // 'Tag must contain only alphanumeric characters, dashes, and underscores', - // ].join('\n'), - // required: false, - // helpValue: '', - // }), force: Flags.boolean({ required: false, default: false, }), + override: Flags.boolean({ + required: false, + default: false, + }), 'hard-reset': Flags.boolean({ description: 'Do a hard reset before deploying. Drops and re-creates all the squid resources including the database. Will cause a short API downtime', required: false, default: false, }), - 'no-stream-logs': Flags.boolean({ - description: 'Do not attach and stream squid logs after the deploy', + 'stream-logs': Flags.boolean({ + description: 'Attach and stream squid logs after the deploy', required: false, - default: false, + default: true, + allowNo: true, }), - 'apply-tag': Flags.boolean({ + 'add-tag': Flags.string({ required: false, - default: false, }), }; @@ -165,12 +157,14 @@ export default class Deploy extends DeployCommand { const { args: { source }, flags: { + interactive, manifest: manifestPath, 'hard-reset': hardReset, - 'no-stream-logs': noStreamLogs, - 'apply-tag': applyTag, + 'stream-logs': streamLogs, + 'add-tag': addTag, force, fullname, + override, ...flags }, } = await this.parse(Deploy); @@ -190,21 +184,23 @@ export default class Deploy extends DeployCommand { const overrides = fullname ? fullname : flags; - // some hack to add slot name in case if version is used + // some hack to normalize slot name in case if version is used { manifest.slot = manifest.slotName(); delete manifest['version']; } - const override = await this.promptOverrideConflict(manifest, overrides); - if (!override) return; + if (!override) { + const confirm = await this.promptOverrideConflict(manifest, overrides, { interactive }); + if (!confirm) return; + } // eslint-disable-next-line prefer-const let { name, slot, org, tag } = defaults(overrides, manifest); - const organization = await this.promptOrganization(org); + const organization = await this.promptOrganization(org, { interactive }); - name = await this.promptSquidName(name); + name = await this.promptSquidName(name, { interactive }); this.log(chalk.dim(`Squid directory: ${squidDir}`)); this.log(chalk.dim(`Build directory: ${buildDir}`)); @@ -214,8 +210,7 @@ export default class Deploy extends DeployCommand { this.log(chalk.cyan(`Squid name: ${name}`)); if (slot) { this.log(chalk.cyan(`Squid slot: ${slot}`)); - } - if (tag) { + } else if (tag) { this.log(chalk.cyan(`Squid tag: ${tag}`)); } this.log(chalk.cyan(`-----------------------------`)); @@ -224,7 +219,7 @@ export default class Deploy extends DeployCommand { if (slot || tag) { target = await this.findSquid({ organization, - reference: formatSquidFullname(slot ? { name, slot } : { name, tag: tag! }), + squid: { name, slot, tag: tag! }, }); } @@ -247,9 +242,10 @@ export default class Deploy extends DeployCommand { /** * Squid exists we should check if tag belongs to another squid */ - if (target && slot && tag && !applyTag) { - const apply = await this.promptApplyTag(target, tag); - if (!apply) return; + const hasTag = !!target?.tags.find((t) => t.name === addTag) || tag === addTag; + if (addTag && !force && !hasTag) { + const add = await this.promptAddTag({ organization, name, tag: addTag }); + if (!add) return; } const archiveName = `${manifest.name}.tar.gz`; @@ -274,75 +270,48 @@ export default class Deploy extends DeployCommand { if (!deployment || !deployment.squid) return; if (target) { - this.logDeployResult( - UPDATE_COLOR, - `The squid ${printSquidFullname({ - org: deployment.organization.code, - name: deployment.squid.name, - slot: deployment.squid.slot, - })} has been successfully updated`, - ); + this.logDeployResult(UPDATE_COLOR, `The squid ${printSquid(target)} has been successfully updated`); } else { this.logDeployResult( CREATE_COLOR, - `A new squid ${printSquidFullname({ - org: deployment.organization.code, - name: deployment.squid.name, - slot: deployment.squid.slot, - })} has been successfully created`, + `A new squid ${printSquid({ ...deployment.squid, organization: deployment.organization })} has been successfully created`, ); } - if (!noStreamLogs) { - await this.streamLogs(organization, deployment.squid); + if (streamLogs) { + await this.streamLogs({ organization: deployment.organization, squid: deployment.squid }); } } - private async promptUpdateSquid(target: Squid) { - this.log( - `A squid "${printSquidFullname({ - org: target.organization.code, - name: target.name, - slot: target.slot, - })}" will be updated.`, - ); - const { confirm } = await inquirer.prompt([ - { - name: 'confirm', - type: 'confirm', - message: 'Are you sure you wish to proceed?', - }, - ]); - - return !!confirm; - } - - private async promptApplyTag(target: Squid, tag: string) { - if (!!target.tags.find((t) => t.name === tag)) return true; + private async promptUpdateSquid( + target: Squid, + { using = 'using "--force" flag', interactive }: { using?: string; interactive?: boolean } = {}, + ) { + const warning = `A squid ${printSquid(target)} already exists.`; - const oldSquid = await this.findSquid({ - organization: target.organization, - reference: formatSquidFullname({ name: target.name, tag }), - }); - if (!oldSquid) return true; + if (!interactive) { + this.error([warning, `Please do it explicitly ${using}`].join('\n')); + } - this.log( - `A squid tag "${tag}" has already been assigned to ${printSquidFullname({ name: oldSquid.name, slot: oldSquid.slot })}.`, - ); - this.log(`The tag will be assigned to the newly created squid.`); + this.warn(warning); const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', - message: 'Are you sure you wish to proceed?', + message: 'Are you sure?', + prefix: `A squid ${printSquid(target)} will be updated.`, }, ]); return !!confirm; } - private async promptOverrideConflict(manifest: Manifest, override: Record) { + private async promptOverrideConflict( + manifest: Manifest, + override: Record, + { using = 'using "--override" flag', interactive }: { using?: string; interactive?: boolean } = {}, + ) { const conflictKeys = keys(override).filter((k) => { const m = get(manifest, k); const o = get(override, k); @@ -351,18 +320,24 @@ export default class Deploy extends DeployCommand { if (!conflictKeys.length) return true; + const warning = [ + 'Conflict detected!', + `A manifest values do not match with specified ones.`, + ``, + diff( + { content: conflictKeys.map((k) => `${k}: ${get(manifest, k)}`).join('\n') + '\n' }, + { content: conflictKeys.map((k) => `${k}: ${get(override, k)}`).join('\n') + '\n' }, + ), + ``, + ].join('\n'); + + if (!interactive) { + this.error([warning, `Please do it explicitly ${using}`].join('\n')); + } + + this.warn(warning); this.log( - [ - chalk.bold('Conflict detected!'), - - `A manifest values do not match with specified ones.`, - `If it is intended and you'd like to override them, just skip this message and confirm, the manifest name will be overridden automatically in the Cloud during the deploy.`, - ``, - diff( - { content: conflictKeys.map((k) => `${k}: ${get(manifest, k)}`).join('\n') + '\n' }, - { content: conflictKeys.map((k) => `${k}: ${get(override, k)}`).join('\n') + '\n' }, - ), - ].join('\n'), + `If it is intended and you'd like to override them, just skip this message and confirm, the manifest name will be overridden automatically in the Cloud during the deploy.`, ); const { confirm } = await inquirer.prompt([ @@ -376,17 +351,24 @@ export default class Deploy extends DeployCommand { return !!confirm; } - private async promptSquidName(name?: string) { + private async promptSquidName( + name?: string | null | undefined, + { using = 'using "--name" flag', interactive }: { using?: string; interactive?: boolean } = {}, + ) { if (name) return name; + const warning = `The squid name is not defined either in the manifest or via CLI command.`; + + if (!interactive) { + this.error([warning, `Please specify it explicitly ${using}`].join('\n')); + } + + this.warn(warning); const { input } = await inquirer.prompt([ { name: 'input', type: 'input', - message: [ - chalk.reset(`The squid name is not defined either in the manifest or via CLI command.`), - chalk.reset(`Please enter the name of the squid:`), - ].join('\n'), + message: `Please enter the name of the squid:`, }, ]); diff --git a/src/commands/explorer.ts b/src/commands/explorer.ts index 01669f9..3dd7623 100644 --- a/src/commands/explorer.ts +++ b/src/commands/explorer.ts @@ -18,10 +18,10 @@ export default class Explorer extends CliCommand { async run(): Promise { const { - flags: { org }, + flags: { org, interactive }, } = await this.parse(Explorer); - const organization = await this.promptOrganization(org); + const organization = await this.promptOrganization(org, { interactive }); const screen = blessed.screen({ smartCSR: true, fastCSR: true, diff --git a/src/commands/logs.ts b/src/commands/logs.ts index 73058de..dd70cd0 100644 --- a/src/commands/logs.ts +++ b/src/commands/logs.ts @@ -3,9 +3,9 @@ import { isNil, omitBy } from 'lodash'; import ms from 'ms'; import { debugLog, squidHistoryLogs, SquidRequest, streamSquidLogs } from '../api'; -import { CliCommand, SqdFlags, SquidReferenceArg } from '../command'; +import { CliCommand, SqdFlags } from '../command'; import { pretty } from '../logs'; -import { formatSquidFullname } from '../utils'; +import { formatSquidReference } from '../utils'; type LogResult = { hasLogs: boolean; @@ -27,33 +27,15 @@ export default class Logs extends CliCommand { static flags = { org: SqdFlags.org({ required: false, - relationships: [ - { - type: 'all', - flags: ['name'], - }, - ], }), name: SqdFlags.name({ required: false, - relationships: [ - { - type: 'some', - flags: [ - { name: 'slot', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['slot'] }, - ], - }, - ], }), slot: SqdFlags.slot({ required: false, - dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, - dependsOn: ['name'], - exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -98,16 +80,15 @@ export default class Logs extends CliCommand { async run(): Promise { const { - flags: { follow, pageSize, container, level, since, search, fullname, ...flags }, + flags: { follow, pageSize, container, level, since, search, fullname, interactive, ...flags }, } = await this.parse(Logs); this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : omitBy(flags, isNil); - const reference = formatSquidFullname({ name, slot, tag }); + const { org, name, tag, slot } = fullname ? fullname : (flags as any); - const organization = await this.promptSquidOrganization({ code: org, name }); - const squid = await this.findOrThrowSquid({ organization, reference }); + const organization = await this.promptSquidOrganization(org, name, { interactive }); + const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); if (!squid) return; const fromDate = parseDate(since); @@ -115,7 +96,7 @@ export default class Logs extends CliCommand { if (follow) { await this.fetchLogs({ organization, - reference, + squid, reverse: true, query: { limit: 30, @@ -127,7 +108,7 @@ export default class Logs extends CliCommand { }); await streamSquidLogs({ organization, - reference, + squid, onLog: (l) => this.log(l), query: { container, level, search }, }); @@ -138,7 +119,7 @@ export default class Logs extends CliCommand { do { const { hasLogs, nextPage }: LogResult = await this.fetchLogs({ organization, - reference, + squid, query: { limit: pageSize, from: fromDate, @@ -164,7 +145,7 @@ export default class Logs extends CliCommand { async fetchLogs({ organization, - reference, + squid, query, reverse, }: SquidRequest & { @@ -180,7 +161,7 @@ export default class Logs extends CliCommand { }; }): Promise { // eslint-disable-next-line prefer-const - let { logs, nextPage } = await squidHistoryLogs({ organization, reference, query }); + let { logs, nextPage } = await squidHistoryLogs({ organization, squid, query }); if (reverse) { logs = logs.reverse(); diff --git a/src/commands/ls.ts b/src/commands/ls.ts index c465167..7c0869b 100644 --- a/src/commands/ls.ts +++ b/src/commands/ls.ts @@ -1,9 +1,8 @@ import { ux as CliUx, Flags } from '@oclif/core'; -import chalk from 'chalk'; -import { isNil, omitBy } from 'lodash'; import { listSquids } from '../api'; import { CliCommand, SqdFlags } from '../command'; +import { printSquid } from '../utils'; export default class Ls extends CliCommand { static description = 'List squids deployed to the Cloud'; @@ -11,47 +10,52 @@ export default class Ls extends CliCommand { static flags = { org: SqdFlags.org({ required: false, - relationships: [ - { - type: 'all', - flags: ['name'], - }, - ], }), name: SqdFlags.name({ required: false, + relationships: [], + }), + tag: SqdFlags.tag({ + required: false, + dependsOn: [], + }), + slot: SqdFlags.slot({ + required: false, + dependsOn: [], }), fullname: SqdFlags.fullname({ required: false, }), truncate: Flags.boolean({ - char: 't', description: 'Truncate data in columns: false by default', required: false, default: false, + allowNo: true, }), }; async run(): Promise { const { - flags: { truncate, fullname, ...flags }, + flags: { truncate, fullname, interactive, ...flags }, } = await this.parse(Ls); - const noTruncate = !truncate; - const { org, name } = fullname ? fullname : omitBy(flags, isNil); + const { org, name, slot, tag } = fullname ? fullname : (flags as any); const organization = name - ? await this.promptSquidOrganization({ code: org, name }) - : await this.promptOrganization(org); + ? await this.promptSquidOrganization(org, name, { interactive }) + : await this.promptOrganization(org, { interactive }); - const squids = await listSquids({ organization, name }); - if (squids) { + let squids = await listSquids({ organization, name }); + if (tag || slot) { + squids = squids.filter((s) => s.slot === slot || s.tags.some((t) => t.name === tag)); + } + if (squids.length) { CliUx.ux.table( squids, { name: { header: 'Squid', - get: (s) => `${s.name}${chalk.dim(`@${s.slot}`)}`, + get: (s) => `${printSquid(s)}`, }, tags: { header: 'Tags', @@ -70,7 +74,7 @@ export default class Ls extends CliCommand { get: (s) => (s.deployedAt ? new Date(s.deployedAt).toUTCString() : `-`), }, }, - { 'no-truncate': noTruncate }, + { 'no-truncate': !truncate }, ); } } diff --git a/src/commands/restart.ts b/src/commands/restart.ts index d954853..3415ad5 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -4,7 +4,7 @@ import { isNil, omitBy } from 'lodash'; import { restartSquid } from '../api'; import { SqdFlags } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidFullname, printSquidFullname } from '../utils'; +import { formatSquidReference as formatSquidReference, printSquid } from '../utils'; import { UPDATE_COLOR } from './deploy'; @@ -14,33 +14,15 @@ export default class Restart extends DeployCommand { static flags = { org: SqdFlags.org({ required: false, - relationships: [ - { - type: 'all', - flags: ['name'], - }, - ], }), name: SqdFlags.name({ required: false, - relationships: [ - { - type: 'some', - flags: [ - { name: 'slot', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['slot'] }, - ], - }, - ], }), slot: SqdFlags.slot({ required: false, - dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, - dependsOn: ['name'], - exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -49,28 +31,20 @@ export default class Restart extends DeployCommand { async run(): Promise { const { - flags: { fullname, ...flags }, + flags: { fullname, interactive, ...flags }, } = await this.parse(Restart); this.validateSquidNameFlags({ fullname, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : omitBy(flags, isNil); - const reference = formatSquidFullname({ name, slot, tag }); + const { org, name, tag, slot } = fullname ? fullname : (flags as any); - const organization = await this.promptSquidOrganization({ code: org, name }); - await this.findOrThrowSquid({ organization, reference }); + const organization = await this.promptSquidOrganization(org, name, { interactive }); + const squid = await this.findOrThrowSquid({ organization, squid: { name, tag, slot } }); - const deployment = await restartSquid({ organization, reference }); + const deployment = await restartSquid({ organization, squid }); await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; - this.logDeployResult( - UPDATE_COLOR, - `The squid ${printSquidFullname({ - org: deployment.organization.code, - name: deployment.squid.name, - slot: deployment.squid.slot, - })} has been successfully restarted`, - ); + this.logDeployResult(UPDATE_COLOR, `The squid ${printSquid(squid)} has been successfully restarted`); } } diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 245cba9..8a45e8a 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -2,49 +2,27 @@ import { Flags } from '@oclif/core'; import inquirer from 'inquirer'; import { deleteSquid } from '../api'; -import { SqdFlags, SquidReferenceArg } from '../command'; +import { SqdFlags } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidFullname, printSquidFullname } from '../utils'; +import { formatSquidReference, printSquid } from '../utils'; import { DELETE_COLOR } from './deploy'; export default class Rm extends DeployCommand { static description = 'Remove a squid deployed to the Cloud'; - static args = { - squid_reference: SquidReferenceArg, - }; - static flags = { org: SqdFlags.org({ required: false, - relationships: [ - { - type: 'all', - flags: ['name'], - }, - ], }), name: SqdFlags.name({ required: false, - relationships: [ - { - type: 'some', - flags: [ - { name: 'slot', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['slot'] }, - ], - }, - ], }), slot: SqdFlags.slot({ required: false, - dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, - dependsOn: ['name'], - exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -58,39 +36,31 @@ export default class Rm extends DeployCommand { async run(): Promise { const { - flags: { force, fullname, ...flags }, + flags: { interactive, force, fullname, ...flags }, } = await this.parse(Rm); this.validateSquidNameFlags({ fullname, ...flags }); const { org, name, tag, slot } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, slot, tag }); - const organization = await this.promptSquidOrganization({ code: org, name }); - const squid = await this.findOrThrowSquid({ organization, reference }); + const organization = await this.promptSquidOrganization(org, name, { interactive }); + const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); if (!force) { const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', - message: `Your squid ${printSquidFullname({ org, name, slot: squid.slot })} will be completely removed. This action can not be undone. Are you sure?`, + message: `Your squid ${printSquid(squid)} will be completely removed. This action can not be undone. Are you sure?`, }, ]); if (!confirm) return; } - const deployment = await deleteSquid({ organization, reference }); + const deployment = await deleteSquid({ organization, squid }); await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; - this.logDeployResult( - DELETE_COLOR, - `A squid deployment ${printSquidFullname({ - org: deployment.organization.code, - name: deployment.squid.name, - slot: deployment.squid.slot, - })} was successfully deleted`, - ); + this.logDeployResult(DELETE_COLOR, `A squid deployment ${printSquid(squid)} was successfully deleted`); } } diff --git a/src/commands/secrets/ls.ts b/src/commands/secrets/ls.ts index 397b753..e81794d 100644 --- a/src/commands/secrets/ls.ts +++ b/src/commands/secrets/ls.ts @@ -16,11 +16,11 @@ export default class Ls extends CliCommand { async run(): Promise { const { - flags: { org }, + flags: { org, interactive }, args: {}, } = await this.parse(Ls); - const organization = await this.promptOrganization(org); + const organization = await this.promptOrganization(org, { interactive }); const response = await listSecrets({ organization }); if (!Object.keys(response.secrets).length) { diff --git a/src/commands/secrets/rm.ts b/src/commands/secrets/rm.ts index 582a376..0fad46c 100644 --- a/src/commands/secrets/rm.ts +++ b/src/commands/secrets/rm.ts @@ -22,11 +22,11 @@ export default class Rm extends CliCommand { async run(): Promise { const { - flags: { org }, + flags: { org, interactive }, args: { name }, } = await this.parse(Rm); - const organization = await this.promptOrganization(org); + const organization = await this.promptOrganization(org, { interactive }); await removeSecret({ organization, name }); this.log(`Secret '${name}' removed`); diff --git a/src/commands/secrets/set.ts b/src/commands/secrets/set.ts index 05f2395..704c3b1 100644 --- a/src/commands/secrets/set.ts +++ b/src/commands/secrets/set.ts @@ -33,11 +33,11 @@ export default class Set extends CliCommand { async run(): Promise { const { - flags: { org }, + flags: { org, interactive }, args: { name, value }, } = await this.parse(Set); - const organization = await this.promptOrganization(org); + const organization = await this.promptOrganization(org, { interactive }); let secretValue = value; if (!secretValue) { diff --git a/src/commands/tags/add.ts b/src/commands/tags/add.ts index 4e50d42..8431997 100644 --- a/src/commands/tags/add.ts +++ b/src/commands/tags/add.ts @@ -5,7 +5,7 @@ import inquirer from 'inquirer'; import { addSquidTag } from '../../api'; import { SqdFlags } from '../../command'; import { DeployCommand } from '../../deploy-command'; -import { formatSquidFullname, printSquidFullname } from '../../utils'; +import { formatSquidReference, printSquid } from '../../utils'; import { UPDATE_COLOR } from '../deploy'; export default class Add extends DeployCommand { @@ -52,60 +52,49 @@ export default class Add extends DeployCommand { fullname: SqdFlags.fullname({ required: false, }), + force: Flags.boolean({ + required: false, + default: false, + }), }; async run(): Promise { const { args: { tag: tagName }, - flags: { fullname, ...flags }, + flags: { fullname, interactive, force, ...flags }, } = await this.parse(Add); this.validateSquidNameFlags({ fullname, ...flags }); const { org, name, tag, slot } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, slot, tag }); - const organization = await this.promptSquidOrganization({ code: org, name }); - const squid = await this.findOrThrowSquid({ organization, reference }); + const organization = await this.promptSquidOrganization(org, name, { interactive }); + const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); if (squid.tags.find((t) => t.name === tagName)) { - return this.log( - `Tag "${tagName}" is already assigned to the squid ${printSquidFullname({ org, name, tag, slot })}`, - ); + return this.log(`Tag "${tagName}" is already assigned to the squid ${printSquid(squid)}`); } - const oldSquid = await this.findSquid({ organization, reference: formatSquidFullname({ name, tag: tagName }) }); - if (oldSquid) { - const { confirm } = await inquirer.prompt([ + if (!force) { + const confirm = await this.promptAddTag( { - name: 'confirm', - type: 'confirm', - message: [ - chalk.reset( - `A squid tag "${tagName}" has already been assigned to the previous squid deployment ${printSquidFullname({ org, name, slot: oldSquid.slot })}.`, - ), - chalk.reset(`The tag URL will be assigned to the newly created deployment. ${chalk.bold(`Are you sure?`)}`), - ].join('\n'), + organization, + name, + tag: tagName, }, - ]); + { interactive }, + ); if (!confirm) return; } const deployment = await addSquidTag({ organization, - reference, + squid, tag: tagName, }); await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; - this.logDeployResult( - UPDATE_COLOR, - `The squid ${printSquidFullname({ - org: deployment.organization.code, - name: deployment.squid.name, - slot: deployment.squid.slot, - })} has been successfully updated`, - ); + this.logDeployResult(UPDATE_COLOR, `The squid ${printSquid(squid)} has been successfully updated`); } } diff --git a/src/commands/tags/remove.ts b/src/commands/tags/remove.ts index a267985..3fb36a3 100644 --- a/src/commands/tags/remove.ts +++ b/src/commands/tags/remove.ts @@ -3,7 +3,7 @@ import { Args } from '@oclif/core'; import { removeSquidTag } from '../../api'; import { SqdFlags } from '../../command'; import { DeployCommand } from '../../deploy-command'; -import { formatSquidFullname, printSquidFullname } from '../../utils'; +import { formatSquidReference, printSquid } from '../../utils'; import { UPDATE_COLOR } from '../deploy'; export default class Remove extends DeployCommand { @@ -62,36 +62,28 @@ export default class Remove extends DeployCommand { async run(): Promise { const { args: { tag: tagName }, - flags: { fullname, ...flags }, + flags: { fullname, interactive, ...flags }, } = await this.parse(Remove); this.validateSquidNameFlags({ fullname, ...flags }); const { org, name, tag, slot } = fullname ? fullname : (flags as any); - const reference = formatSquidFullname({ name, slot, tag }); - const organization = await this.promptSquidOrganization({ code: org, name }); - const squid = await this.findOrThrowSquid({ organization, reference }); + const organization = await this.promptSquidOrganization(org, name, { interactive }); + const squid = await this.findOrThrowSquid({ organization, squid: { name, tag, slot } }); if (!squid.tags.some((t) => t.name === tagName)) { - return this.log(`Tag "${tagName}" is not assigned to the squid ${printSquidFullname({ org, name, tag, slot })}`); + return this.log(`Tag "${tagName}" is not assigned to the squid ${printSquid(squid)}`); } const deployment = await removeSquidTag({ organization, - reference, + squid, tag: tagName, }); await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; - this.logDeployResult( - UPDATE_COLOR, - `The squid ${printSquidFullname({ - org: deployment.organization.code, - name: deployment.squid.name, - slot: deployment.squid.slot, - })} has been successfully updated`, - ); + this.logDeployResult(UPDATE_COLOR, `The squid ${printSquid(squid)} has been successfully updated`); } } diff --git a/src/deploy-command.ts b/src/deploy-command.ts index f3ccf59..2179a6c 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -2,9 +2,9 @@ import { ux as CliUx } from '@oclif/core'; import chalk, { ForegroundColor } from 'chalk'; import inquirer from 'inquirer'; -import { Deployment, DeployRequest, getDeploy, Organization, Squid, streamSquidLogs } from './api'; +import { Deployment, DeployRequest, getDeploy, Organization, Squid, SquidRequest, streamSquidLogs } from './api'; import { CliCommand, SUCCESS_CHECK_MARK } from './command'; -import { doUntil, formatSquidFullname } from './utils'; +import { doUntil, formatSquidReference, printSquid } from './utils'; export abstract class DeployCommand extends CliCommand { deploy: Deployment | undefined; @@ -21,7 +21,7 @@ export abstract class DeployCommand extends CliCommand { { name: 'confirm', type: 'confirm', - message: `Squid "${formatSquidFullname(squid)}" is being deploying. + message: `Squid "${formatSquidReference(squid)}" is being deploying. You can not run deploys on the same squid in parallel. Do you want to attach to the running deploy process?`, }, @@ -40,6 +40,36 @@ Do you want to attach to the running deploy process?`, } } + async promptAddTag( + { organization, name, tag }: { organization: Pick; name: string; tag: string }, + { using = 'using "--force" flag', interactive }: { using?: string; interactive?: boolean } = {}, + ) { + const oldSquid = await this.findSquid({ + organization, + squid: { name, tag }, + }); + if (!oldSquid) return true; + + const warning = `A tag "${tag}" has already been assigned to ${printSquid(oldSquid)}.`; + + if (!interactive) { + this.error([warning, `Please do it explicitly ${using}`].join('\n')); + } + + this.warn(warning); + + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: 'Are you sure?', + prefix: `The tag will be assigned to the newly created squid.`, + }, + ]); + + return !!confirm; + } + async pollDeploy({ deploy, organization, @@ -98,7 +128,8 @@ Do you want to attach to the running deploy process?`, CliUx.ux.action.start('◷ Syncing the squid addons'); return false; - case 'CONFIGURING_INGRESS': + case 'ADDING_INGRESS': + case 'REMOVING_INGRESS': CliUx.ux.action.start('◷ Configuring ingress'); return false; @@ -120,12 +151,12 @@ Do you want to attach to the running deploy process?`, return this.deploy; } - async streamLogs(organization: Organization, squid: Pick) { + async streamLogs({ organization, squid }: SquidRequest) { CliUx.ux.action.start(`Streaming logs from the squid`); await streamSquidLogs({ organization, - reference: squid.reference, + squid, onLog: (l) => this.log(l), }); } @@ -170,7 +201,7 @@ Do you want to attach to the running deploy process?`, ); if (this.deploy?.squid) { - errors.push(`${chalk.dim('Squid:')} ${formatSquidFullname(this.deploy.squid)}`); + errors.push(`${chalk.dim('Squid:')} ${formatSquidReference(this.deploy.squid)}`); } } @@ -191,6 +222,7 @@ Do you want to attach to the running deploy process?`, chalk[color](`=================================================`), message, chalk[color](`=================================================`), + '', ].join('\n'), ); } diff --git a/src/flags/fullname.ts b/src/flags/fullname.ts index a64721f..094a7f4 100644 --- a/src/flags/fullname.ts +++ b/src/flags/fullname.ts @@ -1,9 +1,9 @@ import { Flags } from '@oclif/core'; -import { ParsedSquidFullname, parseSquidFullname, SQUID_FULLNAME_REGEXP } from '../utils'; +import { ParsedSquidReference, parseSquidReference, SQUID_FULLNAME_REGEXP } from '../utils'; -export const fullname = Flags.custom({ - helpGroup: 'COMMON', +export const fullname = Flags.custom({ + helpGroup: 'SQUID', name: 'fullname', aliases: ['ref'], description: `Reference of a squid`, @@ -16,6 +16,6 @@ export const fullname = Flags.custom({ throw new Error(`Expected a squid reference name but received: ${input}`); } - return parseSquidFullname(input); + return parseSquidReference(input); }, }); diff --git a/src/flags/name.ts b/src/flags/name.ts index 7fa4c4c..fee828b 100644 --- a/src/flags/name.ts +++ b/src/flags/name.ts @@ -1,7 +1,7 @@ import { Flags } from '@oclif/core'; export const name = Flags.custom({ - helpGroup: 'COMMON', + helpGroup: 'SQUID', char: 'n', name: 'name', description: 'Squid name', @@ -10,4 +10,13 @@ export const name = Flags.custom({ parse: async (input) => { return input.toLowerCase(); }, + relationships: [ + { + type: 'some', + flags: [ + { name: 'slot', when: async (flags) => !flags['tag'] }, + { name: 'tag', when: async (flags) => !flags['slot'] }, + ], + }, + ], }); diff --git a/src/flags/org.ts b/src/flags/org.ts index a30c81b..53bcfd2 100644 --- a/src/flags/org.ts +++ b/src/flags/org.ts @@ -1,7 +1,7 @@ import { Flags } from '@oclif/core'; export const org = Flags.custom({ - helpGroup: 'COMMON', + helpGroup: 'ORG', char: 'o', name: 'org', description: 'Organization code', diff --git a/src/flags/slot.ts b/src/flags/slot.ts index a193ba3..1d45e5f 100644 --- a/src/flags/slot.ts +++ b/src/flags/slot.ts @@ -1,7 +1,7 @@ import { Flags } from '@oclif/core'; export const slot = Flags.custom({ - helpGroup: 'COMMON', + helpGroup: 'SQUID', char: 's', name: 'slot', description: 'Squid slot', @@ -10,4 +10,6 @@ export const slot = Flags.custom({ return input.toLowerCase(); }, required: false, + dependsOn: ['name'], + exclusive: ['tag'], }); diff --git a/src/flags/tag.ts b/src/flags/tag.ts index 05de0be..0285ecc 100644 --- a/src/flags/tag.ts +++ b/src/flags/tag.ts @@ -1,7 +1,7 @@ import { Flags } from '@oclif/core'; export const tag = Flags.custom({ - helpGroup: 'COMMON', + helpGroup: 'SQUID', char: 't', name: 'tag', description: 'Squid tag', @@ -10,4 +10,6 @@ export const tag = Flags.custom({ parse: async (input) => { return input.toLowerCase(); }, + dependsOn: ['name'], + exclusive: ['slot'], }); diff --git a/src/ui/components/VersionLogsTab.ts b/src/ui/components/VersionLogsTab.ts index 7983392..627710d 100644 --- a/src/ui/components/VersionLogsTab.ts +++ b/src/ui/components/VersionLogsTab.ts @@ -39,7 +39,7 @@ export class VersionLogTab implements VersionTab { try { const { logs } = await squidHistoryLogs({ organization: squid.organization, - reference: squid.reference, + squid, query: { limit: 100, from: addMinutes(new Date(), -30), @@ -61,7 +61,7 @@ export class VersionLogTab implements VersionTab { streamSquidLogs({ organization: squid.organization, - reference: squid.reference, + squid, onLog: (line) => { logsBox.add(line); }, diff --git a/src/ui/components/types.ts b/src/ui/components/types.ts index c862f2f..b5e529c 100644 --- a/src/ui/components/types.ts +++ b/src/ui/components/types.ts @@ -1,5 +1,5 @@ import { Squid as ApiSquid } from '../../api'; -import { formatSquidFullname } from '../../utils'; +import { formatSquidReference } from '../../utils'; export interface Squid extends ApiSquid {} export class Squid { @@ -8,7 +8,7 @@ export class Squid { constructor(squid: ApiSquid) { Object.assign(this, squid); - this.displayName = formatSquidFullname({ name: this.name, slot: this.slot }); + this.displayName = formatSquidReference({ name: this.name, slot: this.slot }); if (this.tags.length) { this.displayName += ` (${this.tags.map((a) => a.name).join(', ')})`; diff --git a/src/utils.ts b/src/utils.ts index daf2805..975e09e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,8 @@ import { ConfigNotFound, getConfig } from '@subsquid/commands'; import chalk from 'chalk'; +import { PickDeep } from 'type-fest'; + +import { Squid } from './api'; export async function getSquidCommands() { try { @@ -23,32 +26,37 @@ export async function doUntil(fn: () => Promise, { pause }: { pause: nu } } -export type ParsedSquidFullname = { org?: string; name: string } & ( +export type ParsedSquidReference = { org?: string; name: string } & ( | { slot: string; tag?: never } | { slot?: never; tag: string } + | { slot: string; tag: string } ); -export function formatSquidFullname({ org, name, slot, tag }: ParsedSquidFullname) { - let res = org ? `${org}/` : ''; - res += name; - res += slot ? `@${slot}` : `:${tag}`; +export function formatSquidReference( + reference: ParsedSquidReference | string, + { colored }: { colored?: boolean } = {}, +) { + const { org, name, slot, tag } = typeof reference === 'string' ? parseSquidReference(reference) : reference; - return res; -} + const prefix = org ? `${org}/` : ``; + const suffix = slot ? `@${slot}` : `:${tag}`; -export function printSquidFullname(args: ParsedSquidFullname) { - return chalk.bold(formatSquidFullname(args)); + return colored ? chalk`{bold {green ${prefix}}{green ${name}}{blue ${suffix}}}` : `${prefix}${name}${suffix}`; } export const SQUID_FULLNAME_REGEXP = /^(([a-z0-9\-]+)\/)?([a-z0-9\-]+)([:@])([a-z0-9\-]+)$/; -export function parseSquidFullname(fullname: string): ParsedSquidFullname { - const parsed = SQUID_FULLNAME_REGEXP.exec(fullname); +export function parseSquidReference(reference: string): ParsedSquidReference { + const parsed = SQUID_FULLNAME_REGEXP.exec(reference); if (!parsed) { - throw new Error(`Invalid squid full name: "${fullname}"`); + throw new Error(`Invalid squid full name: "${reference}"`); } const [, , org, name, type, tagOrSlot] = parsed; return { org, name, ...(type === ':' ? { tag: tagOrSlot } : { slot: tagOrSlot }) }; } + +export function printSquid(squid: PickDeep) { + return formatSquidReference({ org: squid.organization.code, name: squid.name, slot: squid.slot }, { colored: true }); +} From 6c3a817881390422d5c3043c8830e1147d2ee7fc Mon Sep 17 00:00:00 2001 From: belopash Date: Tue, 10 Sep 2024 20:04:59 +0500 Subject: [PATCH 08/15] fix: pass interactive flag to all prompts --- package.json | 2 +- src/commands/deploy.ts | 6 +++--- src/deploy-command.ts | 15 +++++++++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 11b8f1b..c36867e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.5", + "version": "3.0.0-beta.6", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index a852e2d..bd0b33a 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -227,7 +227,7 @@ export default class Deploy extends DeployCommand { * Squid exists we should check running deploys */ if (target) { - const attached = await this.promptAttachToDeploy(target); + const attached = await this.promptAttachToDeploy(target, { interactive }); if (attached) return; } @@ -235,7 +235,7 @@ export default class Deploy extends DeployCommand { * Squid exists we should ask for update */ if (target && !force) { - const update = await this.promptUpdateSquid(target); + const update = await this.promptUpdateSquid(target, { interactive }); if (!update) return; } @@ -244,7 +244,7 @@ export default class Deploy extends DeployCommand { */ const hasTag = !!target?.tags.find((t) => t.name === addTag) || tag === addTag; if (addTag && !force && !hasTag) { - const add = await this.promptAddTag({ organization, name, tag: addTag }); + const add = await this.promptAddTag({ organization, name, tag: addTag }, { interactive }); if (!add) return; } diff --git a/src/deploy-command.ts b/src/deploy-command.ts index 2179a6c..15a1163 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -10,10 +10,19 @@ export abstract class DeployCommand extends CliCommand { deploy: Deployment | undefined; logsPrinted = 0; - async promptAttachToDeploy(squid: Squid) { + async promptAttachToDeploy(squid: Squid, { interactive }: { interactive?: boolean } = {}) { if (!squid.lastDeploy) return false; if (squid.status !== 'DEPLOYING') return false; + const warning = `Squid "${formatSquidReference(squid)}" is being deploying. +You can not run deploys on the same squid in parallel`; + + if (!interactive) { + this.error(warning); + } + + this.warn(warning); + switch (squid.lastDeploy.type) { // we should react only for running deploy case 'DEPLOY': @@ -21,9 +30,7 @@ export abstract class DeployCommand extends CliCommand { { name: 'confirm', type: 'confirm', - message: `Squid "${formatSquidReference(squid)}" is being deploying. -You can not run deploys on the same squid in parallel. -Do you want to attach to the running deploy process?`, + message: `Do you want to attach to the running deploy process?`, }, ]); if (!confirm) return false; From b3ab7d7f0337abf5a41c65e92a21b796471d3ba6 Mon Sep 17 00:00:00 2001 From: belopash Date: Wed, 11 Sep 2024 16:02:15 +0500 Subject: [PATCH 09/15] feat: split --force to separate flags. Add missing descriptions --- package.json | 2 +- src/command.ts | 1 + src/commands/deploy.ts | 75 +++++++++++++++++-------------------- src/commands/restart.ts | 3 ++ src/commands/rm.ts | 5 ++- src/commands/tags/add.ts | 28 ++++---------- src/commands/tags/remove.ts | 28 ++------------ src/deploy-command.ts | 2 +- src/flags/fullname.ts | 4 +- src/flags/name.ts | 2 +- src/flags/org.ts | 2 +- src/flags/slot.ts | 2 +- src/flags/tag.ts | 2 +- 13 files changed, 61 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index c36867e..0252cd5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.6", + "version": "3.0.0-beta.7", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { diff --git a/src/command.ts b/src/command.ts index c19b69b..5893fa2 100644 --- a/src/command.ts +++ b/src/command.ts @@ -13,6 +13,7 @@ export const SUCCESS_CHECK_MARK = chalk.green('✓'); export abstract class CliCommand extends Command { static baseFlags = { interactive: Flags.boolean({ + description: 'Enable or disable interactive mode', required: false, default: true, allowNo: true, diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index bd0b33a..af16a30 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -9,7 +9,7 @@ import diff from 'cli-diff'; import { globSync } from 'glob'; import ignore from 'ignore'; import inquirer from 'inquirer'; -import { defaults, get, isNil, keys } from 'lodash'; +import { defaults, get, isNil, keys, pick } from 'lodash'; import prettyBytes from 'pretty-bytes'; import targz from 'targz'; @@ -60,12 +60,12 @@ function example(command: string, description: string) { export default class Deploy extends DeployCommand { static description = 'Deploy new or update an existing squid in the Cloud'; static examples = [ - example('sqd deploy ./', 'Create a new squid with name provided in the manifest file'), + example('sqd deploy .', 'Create a new squid with name provided in the manifest file'), example( - 'sqd deploy ./ -n my-squid-override', + 'sqd deploy . -n my-squid-override', 'Create a new squid deployment and override it\'s name to "my-squid-override"', ), - example('sqd deploy ./ -n my-squid -s asmzf5', 'Update the "my-squid" squid with slot "asmzf5"'), + example('sqd deploy . -n my-squid -s asmzf5', 'Update the "my-squid" squid with slot "asmzf5"'), example( 'sqd deploy ./path-to-the-squid -m squid.prod.yaml', 'Use a manifest file located in ./path-to-the-squid/squid.prod.yaml', @@ -79,17 +79,6 @@ export default class Deploy extends DeployCommand { static help = 'If squid flags are not specified, the they will be retrieved from the manifest or prompted.'; static args = { - // squid_name_or_reference: Args.string({ - // description: [ - // `Reference to squid for the update.`, - // `If argument not specified, the squid name will be retrieved from the manifest or prompted and a new squid will be created.`, - // ``, - // `Alternatively, you can overwrite the name of the squid from the manifest by explicitly providing a new name instead of a reference.`, - // ``, - // `See Examples section for more information`, - // ].join('\n'), - // required: false, - // }), source: Args.directory({ description: [ `Squid source. Could be:`, @@ -123,33 +112,41 @@ export default class Deploy extends DeployCommand { }), manifest: Flags.file({ char: 'm', - description: 'Relative local path to a squid manifest file in squid working directory', + description: 'Specify the relative local path to a squid manifest file in the squid working directory', required: false, default: 'squid.yaml', helpValue: '', }), - force: Flags.boolean({ - required: false, - default: false, - }), - override: Flags.boolean({ - required: false, - default: false, - }), 'hard-reset': Flags.boolean({ description: - 'Do a hard reset before deploying. Drops and re-creates all the squid resources including the database. Will cause a short API downtime', + 'Perform a hard reset before deploying. This will drop and re-create all squid resources, including the database, causing a short API downtime', required: false, default: false, }), 'stream-logs': Flags.boolean({ - description: 'Attach and stream squid logs after the deploy', + description: 'Attach and stream squid logs after the deployment', required: false, default: true, allowNo: true, }), 'add-tag': Flags.string({ + description: 'Add a tag to the deployed squid', + required: false, + }), + 'allow-update': Flags.boolean({ + description: 'Allow updating an existing squid', required: false, + default: false, + }), + 'allow-tag-reassign': Flags.boolean({ + description: 'Allow reassigning an existing tag', + required: false, + default: false, + }), + 'allow-manifest-override': Flags.boolean({ + description: 'Allow overriding the manifest during deployment', + required: false, + default: false, }), }; @@ -162,9 +159,7 @@ export default class Deploy extends DeployCommand { 'hard-reset': hardReset, 'stream-logs': streamLogs, 'add-tag': addTag, - force, fullname, - override, ...flags }, } = await this.parse(Deploy); @@ -182,7 +177,7 @@ export default class Deploy extends DeployCommand { const { buildDir, squidDir, manifest } = res; - const overrides = fullname ? fullname : flags; + const overrides = fullname ? fullname : pick(flags, 'slot', 'name', 'tag', 'org'); // some hack to normalize slot name in case if version is used { @@ -190,7 +185,7 @@ export default class Deploy extends DeployCommand { delete manifest['version']; } - if (!override) { + if (!flags['allow-manifest-override']) { const confirm = await this.promptOverrideConflict(manifest, overrides, { interactive }); if (!confirm) return; } @@ -223,18 +218,10 @@ export default class Deploy extends DeployCommand { }); } - /** - * Squid exists we should check running deploys - */ - if (target) { - const attached = await this.promptAttachToDeploy(target, { interactive }); - if (attached) return; - } - /** * Squid exists we should ask for update */ - if (target && !force) { + if (target && !flags['allow-update']) { const update = await this.promptUpdateSquid(target, { interactive }); if (!update) return; } @@ -243,11 +230,19 @@ export default class Deploy extends DeployCommand { * Squid exists we should check if tag belongs to another squid */ const hasTag = !!target?.tags.find((t) => t.name === addTag) || tag === addTag; - if (addTag && !force && !hasTag) { + if (addTag && !flags['allow-tag-reassign'] && !hasTag) { const add = await this.promptAddTag({ organization, name, tag: addTag }, { interactive }); if (!add) return; } + /** + * Squid exists we should check running deploys + */ + if (target) { + const attached = await this.promptAttachToDeploy(target, { interactive }); + if (attached) return; + } + const archiveName = `${manifest.name}.tar.gz`; const artifactPath = await this.pack({ buildDir, squidDir, archiveName }); const artifactUrl = await this.upload({ organization, artifactPath }); diff --git a/src/commands/restart.ts b/src/commands/restart.ts index 3415ad5..dd150be 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -41,6 +41,9 @@ export default class Restart extends DeployCommand { const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, tag, slot } }); + const attached = await this.promptAttachToDeploy(squid, { interactive }); + if (attached) return; + const deployment = await restartSquid({ organization, squid }); await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 8a45e8a..d32dda7 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -46,7 +46,10 @@ export default class Rm extends DeployCommand { const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); - if (!force) { + const attached = await this.promptAttachToDeploy(squid, { interactive }); + if (attached) return; + + if (!force && interactive) { const { confirm } = await inquirer.prompt([ { name: 'confirm', diff --git a/src/commands/tags/add.ts b/src/commands/tags/add.ts index 8431997..d22b27d 100644 --- a/src/commands/tags/add.ts +++ b/src/commands/tags/add.ts @@ -21,38 +21,21 @@ export default class Add extends DeployCommand { static flags = { org: SqdFlags.org({ required: false, - relationships: [ - { - type: 'all', - flags: ['name'], - }, - ], }), name: SqdFlags.name({ required: false, - relationships: [ - { - type: 'some', - flags: [ - { name: 'slot', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['slot'] }, - ], - }, - ], }), slot: SqdFlags.slot({ required: false, - dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, - dependsOn: ['name'], - exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, }), - force: Flags.boolean({ + 'allow-tag-reassign': Flags.boolean({ + description: 'Allow reassigning an existing tag', required: false, default: false, }), @@ -61,7 +44,7 @@ export default class Add extends DeployCommand { async run(): Promise { const { args: { tag: tagName }, - flags: { fullname, interactive, force, ...flags }, + flags: { fullname, interactive, ...flags }, } = await this.parse(Add); this.validateSquidNameFlags({ fullname, ...flags }); @@ -75,7 +58,7 @@ export default class Add extends DeployCommand { return this.log(`Tag "${tagName}" is already assigned to the squid ${printSquid(squid)}`); } - if (!force) { + if (!flags['allow-tag-reassign']) { const confirm = await this.promptAddTag( { organization, @@ -87,6 +70,9 @@ export default class Add extends DeployCommand { if (!confirm) return; } + const attached = await this.promptAttachToDeploy(squid, { interactive }); + if (attached) return; + const deployment = await addSquidTag({ organization, squid, diff --git a/src/commands/tags/remove.ts b/src/commands/tags/remove.ts index 3fb36a3..59b0c86 100644 --- a/src/commands/tags/remove.ts +++ b/src/commands/tags/remove.ts @@ -19,40 +19,15 @@ export default class Remove extends DeployCommand { static flags = { org: SqdFlags.org({ required: false, - relationships: [ - { - type: 'all', - flags: ['name'], - }, - { - type: 'some', - flags: [ - { name: 'slot', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['slot'] }, - ], - }, - ], }), name: SqdFlags.name({ required: false, - relationships: [ - { - type: 'some', - flags: [ - { name: 'slot', when: async (flags) => !flags['tag'] }, - { name: 'tag', when: async (flags) => !flags['slot'] }, - ], - }, - ], }), slot: SqdFlags.slot({ required: false, - dependsOn: ['name'], }), tag: SqdFlags.tag({ required: false, - dependsOn: ['name'], - exclusive: ['slot'], }), fullname: SqdFlags.fullname({ required: false, @@ -76,6 +51,9 @@ export default class Remove extends DeployCommand { return this.log(`Tag "${tagName}" is not assigned to the squid ${printSquid(squid)}`); } + const attached = await this.promptAttachToDeploy(squid, { interactive }); + if (attached) return; + const deployment = await removeSquidTag({ organization, squid, diff --git a/src/deploy-command.ts b/src/deploy-command.ts index 15a1163..a2792dc 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -14,7 +14,7 @@ export abstract class DeployCommand extends CliCommand { if (!squid.lastDeploy) return false; if (squid.status !== 'DEPLOYING') return false; - const warning = `Squid "${formatSquidReference(squid)}" is being deploying. + const warning = `Squid ${printSquid(squid)} is being deploying. You can not run deploys on the same squid in parallel`; if (!interactive) { diff --git a/src/flags/fullname.ts b/src/flags/fullname.ts index 094a7f4..c20ca00 100644 --- a/src/flags/fullname.ts +++ b/src/flags/fullname.ts @@ -6,14 +6,14 @@ export const fullname = Flags.custom({ helpGroup: 'SQUID', name: 'fullname', aliases: ['ref'], - description: `Reference of a squid`, + description: `Fully qualified reference of the squid. It can include the organization, name, slot, or tag`, helpValue: '[/](@|:)', required: false, exclusive: ['org', 'name', 'slot', 'tag'], parse: async (input) => { input = input.toLowerCase(); if (!SQUID_FULLNAME_REGEXP.test(input)) { - throw new Error(`Expected a squid reference name but received: ${input}`); + throw new Error(`Expected full name of the squid but received: ${input}`); } return parseSquidReference(input); diff --git a/src/flags/name.ts b/src/flags/name.ts index fee828b..778c671 100644 --- a/src/flags/name.ts +++ b/src/flags/name.ts @@ -4,7 +4,7 @@ export const name = Flags.custom({ helpGroup: 'SQUID', char: 'n', name: 'name', - description: 'Squid name', + description: 'Name of the squid', helpValue: '', required: false, parse: async (input) => { diff --git a/src/flags/org.ts b/src/flags/org.ts index 53bcfd2..2b22fae 100644 --- a/src/flags/org.ts +++ b/src/flags/org.ts @@ -4,7 +4,7 @@ export const org = Flags.custom({ helpGroup: 'ORG', char: 'o', name: 'org', - description: 'Organization code', + description: 'Code of the organization', helpValue: '', required: false, parse: async (input) => { diff --git a/src/flags/slot.ts b/src/flags/slot.ts index 1d45e5f..9840c22 100644 --- a/src/flags/slot.ts +++ b/src/flags/slot.ts @@ -4,7 +4,7 @@ export const slot = Flags.custom({ helpGroup: 'SQUID', char: 's', name: 'slot', - description: 'Squid slot', + description: 'Slot of the squid', helpValue: '', parse: async (input) => { return input.toLowerCase(); diff --git a/src/flags/tag.ts b/src/flags/tag.ts index 0285ecc..af62342 100644 --- a/src/flags/tag.ts +++ b/src/flags/tag.ts @@ -4,7 +4,7 @@ export const tag = Flags.custom({ helpGroup: 'SQUID', char: 't', name: 'tag', - description: 'Squid tag', + description: 'Tag of the squid', helpValue: '', required: false, parse: async (input) => { From 005f8d63cd1ae6a680c37c7e4f23749d54b64a3a Mon Sep 17 00:00:00 2001 From: belopash Date: Wed, 11 Sep 2024 23:50:30 +0500 Subject: [PATCH 10/15] fix: improve log messages --- package.json | 2 +- src/commands/deploy.ts | 12 ++++++++++-- src/deploy-command.ts | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0252cd5..10ecb52 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.7", + "version": "3.0.0-beta.8", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index af16a30..3b84831 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -280,7 +280,15 @@ export default class Deploy extends DeployCommand { private async promptUpdateSquid( target: Squid, - { using = 'using "--force" flag', interactive }: { using?: string; interactive?: boolean } = {}, + { + using = 'using "--force" flag', + interactive, + hardReset, + }: { + using?: string; + interactive?: boolean; + hardReset?: boolean; + } = {}, ) { const warning = `A squid ${printSquid(target)} already exists.`; @@ -295,7 +303,7 @@ export default class Deploy extends DeployCommand { name: 'confirm', type: 'confirm', message: 'Are you sure?', - prefix: `A squid ${printSquid(target)} will be updated.`, + prefix: `A squid ${printSquid(target)} will be ${hardReset ? `recreated` : `updated`}.`, }, ]); diff --git a/src/deploy-command.ts b/src/deploy-command.ts index a2792dc..72dffd2 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -57,7 +57,7 @@ You can not run deploys on the same squid in parallel`; }); if (!oldSquid) return true; - const warning = `A tag "${tag}" has already been assigned to ${printSquid(oldSquid)}.`; + const warning = `The tag "${tag}" has already been assigned to ${printSquid(oldSquid)}.`; if (!interactive) { this.error([warning, `Please do it explicitly ${using}`].join('\n')); @@ -70,7 +70,7 @@ You can not run deploys on the same squid in parallel`; name: 'confirm', type: 'confirm', message: 'Are you sure?', - prefix: `The tag will be assigned to the newly created squid.`, + prefix: `The tag will be reassigned.`, }, ]); From f6e22dca9d69e806efc26562399235941ae4fee1 Mon Sep 17 00:00:00 2001 From: belopash Date: Thu, 12 Sep 2024 00:31:12 +0500 Subject: [PATCH 11/15] fix: add tag to deploy request --- package.json | 2 +- src/commands/deploy.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 10ecb52..1d23040 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.8", + "version": "3.0.0-beta.9", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 3b84831..e0b121f 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -256,7 +256,7 @@ export default class Deploy extends DeployCommand { hardReset, overrideName: name, overrideSlot: slot, - tag, + tag: addTag, }, }, }); From 4dc71dce14a48badf25dd7bf4b0e43f4fad68ec0 Mon Sep 17 00:00:00 2001 From: belopash Date: Fri, 13 Sep 2024 16:21:40 +0500 Subject: [PATCH 12/15] feat: rename fullname to reference, better flags validation --- package.json | 3 ++- src/command.ts | 6 +++--- src/commands/deploy.ts | 16 ++++++++-------- src/commands/logs.ts | 8 ++++---- src/commands/ls.ts | 6 +++--- src/commands/restart.ts | 8 ++++---- src/commands/rm.ts | 8 ++++---- src/commands/tags/add.ts | 8 ++++---- src/commands/tags/remove.ts | 8 ++++---- src/deploy-command.ts | 2 +- src/flags/fullname.ts | 16 +++++++--------- src/flags/index.ts | 2 +- src/flags/name.ts | 3 ++- src/flags/slot.ts | 3 ++- src/flags/tag.ts | 3 ++- src/utils.ts | 24 +++++++++++++++++++++--- yarn.lock | 3 ++- 17 files changed, 74 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 1d23040..a6457a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.9", + "version": "3.0.0-beta.10", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { @@ -99,6 +99,7 @@ "glob": "^10.4.5", "ignore": "^5.3.2", "inquirer": "^8.2.6", + "joi": "^17.13.3", "js-yaml": "^4.1.0", "lodash": "^4.17.21", "ms": "^2.1.3", diff --git a/src/command.ts b/src/command.ts index 5893fa2..af9b3bb 100644 --- a/src/command.ts +++ b/src/command.ts @@ -33,15 +33,15 @@ export abstract class CliCommand extends Command { } // Haven't find a way to do it with native settings - validateSquidNameFlags(flags: { fullname?: any; name?: any }) { - if (flags.fullname || flags.name) return; + validateSquidNameFlags(flags: { reference?: any; name?: any }) { + if (flags.reference || flags.name) return; throw new FailedFlagValidationError({ failed: [ { name: 'squid name', validationFn: 'validateSquidName', - reason: 'One of the following must be provided: --fullname, --name', + reason: 'One of the following must be provided: --reference, --name', status: 'failed', }, ], diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index e0b121f..2993ffb 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -107,7 +107,7 @@ export default class Deploy extends DeployCommand { required: false, dependsOn: [], }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), manifest: Flags.file({ @@ -159,7 +159,7 @@ export default class Deploy extends DeployCommand { 'hard-reset': hardReset, 'stream-logs': streamLogs, 'add-tag': addTag, - fullname, + reference, ...flags }, } = await this.parse(Deploy); @@ -177,7 +177,7 @@ export default class Deploy extends DeployCommand { const { buildDir, squidDir, manifest } = res; - const overrides = fullname ? fullname : pick(flags, 'slot', 'name', 'tag', 'org'); + const overrides = reference ? reference : pick(flags, 'slot', 'name', 'tag', 'org'); // some hack to normalize slot name in case if version is used { @@ -222,7 +222,7 @@ export default class Deploy extends DeployCommand { * Squid exists we should ask for update */ if (target && !flags['allow-update']) { - const update = await this.promptUpdateSquid(target, { interactive }); + const update = await this.promptUpdateSquid(target, { interactive, hardReset }); if (!update) return; } @@ -255,7 +255,7 @@ export default class Deploy extends DeployCommand { options: { hardReset, overrideName: name, - overrideSlot: slot, + overrideSlot: target?.slot || slot, tag: addTag, }, }, @@ -281,7 +281,7 @@ export default class Deploy extends DeployCommand { private async promptUpdateSquid( target: Squid, { - using = 'using "--force" flag', + using = 'using "--allow-update" flag', interactive, hardReset, }: { @@ -313,7 +313,7 @@ export default class Deploy extends DeployCommand { private async promptOverrideConflict( manifest: Manifest, override: Record, - { using = 'using "--override" flag', interactive }: { using?: string; interactive?: boolean } = {}, + { using = 'using "--allow--manifest-override" flag', interactive }: { using?: string; interactive?: boolean } = {}, ) { const conflictKeys = keys(override).filter((k) => { const m = get(manifest, k); @@ -375,7 +375,7 @@ export default class Deploy extends DeployCommand { }, ]); - return input.name as string; + return input as string; } private async pack({ buildDir, squidDir, archiveName }: { buildDir: string; squidDir: string; archiveName: string }) { diff --git a/src/commands/logs.ts b/src/commands/logs.ts index dd70cd0..dd36438 100644 --- a/src/commands/logs.ts +++ b/src/commands/logs.ts @@ -37,7 +37,7 @@ export default class Logs extends CliCommand { tag: SqdFlags.tag({ required: false, }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), container: Flags.string({ @@ -80,12 +80,12 @@ export default class Logs extends CliCommand { async run(): Promise { const { - flags: { follow, pageSize, container, level, since, search, fullname, interactive, ...flags }, + flags: { follow, pageSize, container, level, since, search, reference, interactive, ...flags }, } = await this.parse(Logs); - this.validateSquidNameFlags({ fullname, ...flags }); + this.validateSquidNameFlags({ reference, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const { org, name, tag, slot } = reference ? reference : (flags as any); const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); diff --git a/src/commands/ls.ts b/src/commands/ls.ts index 7c0869b..7d080a4 100644 --- a/src/commands/ls.ts +++ b/src/commands/ls.ts @@ -23,7 +23,7 @@ export default class Ls extends CliCommand { required: false, dependsOn: [], }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), truncate: Flags.boolean({ @@ -36,10 +36,10 @@ export default class Ls extends CliCommand { async run(): Promise { const { - flags: { truncate, fullname, interactive, ...flags }, + flags: { truncate, reference, interactive, ...flags }, } = await this.parse(Ls); - const { org, name, slot, tag } = fullname ? fullname : (flags as any); + const { org, name, slot, tag } = reference ? reference : (flags as any); const organization = name ? await this.promptSquidOrganization(org, name, { interactive }) diff --git a/src/commands/restart.ts b/src/commands/restart.ts index dd150be..da25567 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -24,19 +24,19 @@ export default class Restart extends DeployCommand { tag: SqdFlags.tag({ required: false, }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), }; async run(): Promise { const { - flags: { fullname, interactive, ...flags }, + flags: { reference, interactive, ...flags }, } = await this.parse(Restart); - this.validateSquidNameFlags({ fullname, ...flags }); + this.validateSquidNameFlags({ reference, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const { org, name, tag, slot } = reference ? reference : (flags as any); const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, tag, slot } }); diff --git a/src/commands/rm.ts b/src/commands/rm.ts index d32dda7..3ef77a6 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -24,7 +24,7 @@ export default class Rm extends DeployCommand { tag: SqdFlags.tag({ required: false, }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), force: Flags.boolean({ @@ -36,12 +36,12 @@ export default class Rm extends DeployCommand { async run(): Promise { const { - flags: { interactive, force, fullname, ...flags }, + flags: { interactive, force, reference, ...flags }, } = await this.parse(Rm); - this.validateSquidNameFlags({ fullname, ...flags }); + this.validateSquidNameFlags({ reference, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const { org, name, tag, slot } = reference ? reference : (flags as any); const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); diff --git a/src/commands/tags/add.ts b/src/commands/tags/add.ts index d22b27d..a1136e7 100644 --- a/src/commands/tags/add.ts +++ b/src/commands/tags/add.ts @@ -31,7 +31,7 @@ export default class Add extends DeployCommand { tag: SqdFlags.tag({ required: false, }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), 'allow-tag-reassign': Flags.boolean({ @@ -44,12 +44,12 @@ export default class Add extends DeployCommand { async run(): Promise { const { args: { tag: tagName }, - flags: { fullname, interactive, ...flags }, + flags: { reference, interactive, ...flags }, } = await this.parse(Add); - this.validateSquidNameFlags({ fullname, ...flags }); + this.validateSquidNameFlags({ reference, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const { org, name, tag, slot } = reference ? reference : (flags as any); const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); diff --git a/src/commands/tags/remove.ts b/src/commands/tags/remove.ts index 59b0c86..16f5dac 100644 --- a/src/commands/tags/remove.ts +++ b/src/commands/tags/remove.ts @@ -29,7 +29,7 @@ export default class Remove extends DeployCommand { tag: SqdFlags.tag({ required: false, }), - fullname: SqdFlags.fullname({ + reference: SqdFlags.reference({ required: false, }), }; @@ -37,12 +37,12 @@ export default class Remove extends DeployCommand { async run(): Promise { const { args: { tag: tagName }, - flags: { fullname, interactive, ...flags }, + flags: { reference, interactive, ...flags }, } = await this.parse(Remove); - this.validateSquidNameFlags({ fullname, ...flags }); + this.validateSquidNameFlags({ reference, ...flags }); - const { org, name, tag, slot } = fullname ? fullname : (flags as any); + const { org, name, tag, slot } = reference ? reference : (flags as any); const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, tag, slot } }); diff --git a/src/deploy-command.ts b/src/deploy-command.ts index 72dffd2..f54bb22 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -49,7 +49,7 @@ You can not run deploys on the same squid in parallel`; async promptAddTag( { organization, name, tag }: { organization: Pick; name: string; tag: string }, - { using = 'using "--force" flag', interactive }: { using?: string; interactive?: boolean } = {}, + { using = 'using "--allow-tag-reassign" flag', interactive }: { using?: string; interactive?: boolean } = {}, ) { const oldSquid = await this.findSquid({ organization, diff --git a/src/flags/fullname.ts b/src/flags/fullname.ts index c20ca00..442d35b 100644 --- a/src/flags/fullname.ts +++ b/src/flags/fullname.ts @@ -1,21 +1,19 @@ import { Flags } from '@oclif/core'; +import Joi from 'joi'; -import { ParsedSquidReference, parseSquidReference, SQUID_FULLNAME_REGEXP } from '../utils'; +import { JoiSquidReference, ParsedSquidReference, parseSquidReference, SQUID_FULLNAME_REGEXP } from '../utils'; -export const fullname = Flags.custom({ +export const reference = Flags.custom({ + char: 'r', helpGroup: 'SQUID', - name: 'fullname', + name: 'reference', aliases: ['ref'], description: `Fully qualified reference of the squid. It can include the organization, name, slot, or tag`, helpValue: '[/](@|:)', required: false, exclusive: ['org', 'name', 'slot', 'tag'], parse: async (input) => { - input = input.toLowerCase(); - if (!SQUID_FULLNAME_REGEXP.test(input)) { - throw new Error(`Expected full name of the squid but received: ${input}`); - } - - return parseSquidReference(input); + const res = parseSquidReference(input); + return await JoiSquidReference.validateAsync(res); }, }); diff --git a/src/flags/index.ts b/src/flags/index.ts index d5815f4..962407a 100644 --- a/src/flags/index.ts +++ b/src/flags/index.ts @@ -1,4 +1,4 @@ -export { fullname } from './fullname'; +export { reference } from './fullname'; export { name } from './name'; export { org } from './org'; export { slot } from './slot'; diff --git a/src/flags/name.ts b/src/flags/name.ts index 778c671..1af810a 100644 --- a/src/flags/name.ts +++ b/src/flags/name.ts @@ -1,4 +1,5 @@ import { Flags } from '@oclif/core'; +import { JoiSquidName } from '@subsquid/manifest'; export const name = Flags.custom({ helpGroup: 'SQUID', @@ -8,7 +9,7 @@ export const name = Flags.custom({ helpValue: '', required: false, parse: async (input) => { - return input.toLowerCase(); + return await JoiSquidName.validateAsync(input); }, relationships: [ { diff --git a/src/flags/slot.ts b/src/flags/slot.ts index 9840c22..34da42c 100644 --- a/src/flags/slot.ts +++ b/src/flags/slot.ts @@ -1,4 +1,5 @@ import { Flags } from '@oclif/core'; +import { JoiSquidSlot } from '@subsquid/manifest'; export const slot = Flags.custom({ helpGroup: 'SQUID', @@ -7,7 +8,7 @@ export const slot = Flags.custom({ description: 'Slot of the squid', helpValue: '', parse: async (input) => { - return input.toLowerCase(); + return await JoiSquidSlot.validateAsync(input); }, required: false, dependsOn: ['name'], diff --git a/src/flags/tag.ts b/src/flags/tag.ts index af62342..8e4fe77 100644 --- a/src/flags/tag.ts +++ b/src/flags/tag.ts @@ -1,4 +1,5 @@ import { Flags } from '@oclif/core'; +import { JoiSquidTag } from '@subsquid/manifest'; export const tag = Flags.custom({ helpGroup: 'SQUID', @@ -8,7 +9,7 @@ export const tag = Flags.custom({ helpValue: '', required: false, parse: async (input) => { - return input.toLowerCase(); + return await JoiSquidTag.validateAsync(input); }, dependsOn: ['name'], exclusive: ['slot'], diff --git a/src/utils.ts b/src/utils.ts index 975e09e..62cd2be 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,18 @@ import { ConfigNotFound, getConfig } from '@subsquid/commands'; +import { + JoiSquidName, + JoiSquidSlot, + JoiSquidTag, + SQUID_NAME_PATTERN, + SQUID_SLOT_PATTERN, + SQUID_TAG_PATTERN, +} from '@subsquid/manifest'; import chalk from 'chalk'; +import Joi from 'joi'; import { PickDeep } from 'type-fest'; import { Squid } from './api'; +import { org } from './flags'; export async function getSquidCommands() { try { @@ -44,17 +54,25 @@ export function formatSquidReference( return colored ? chalk`{bold {green ${prefix}}{green ${name}}{blue ${suffix}}}` : `${prefix}${name}${suffix}`; } -export const SQUID_FULLNAME_REGEXP = /^(([a-z0-9\-]+)\/)?([a-z0-9\-]+)([:@])([a-z0-9\-]+)$/; +export const SQUID_FULLNAME_REGEXP = /^((.+)\/)?(.+)([@:])(.+)$/; + +export const JoiSquidReference = Joi.object({ + org: JoiSquidName, + name: JoiSquidName.required(), + slot: JoiSquidSlot, + tag: JoiSquidTag, +}).xor('slot', 'tag'); export function parseSquidReference(reference: string): ParsedSquidReference { const parsed = SQUID_FULLNAME_REGEXP.exec(reference); if (!parsed) { - throw new Error(`Invalid squid full name: "${reference}"`); + throw new Error(`The squid reference "${reference}" is invalid.`); } const [, , org, name, type, tagOrSlot] = parsed; - return { org, name, ...(type === ':' ? { tag: tagOrSlot } : { slot: tagOrSlot }) }; + // the last case should never happen, used only for flag validation + return { org, name, ...(type === ':' ? { tag: tagOrSlot } : type === '@' ? { slot: tagOrSlot } : ({} as any)) }; } export function printSquid(squid: PickDeep) { diff --git a/yarn.lock b/yarn.lock index 9bd21b1..c3d7f0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1455,6 +1455,7 @@ __metadata: ignore: "npm:^5.3.2" inquirer: "npm:^8.2.6" jest: "npm:^29.7.0" + joi: "npm:^17.13.3" js-yaml: "npm:^4.1.0" lodash: "npm:^4.17.21" ms: "npm:^2.1.3" @@ -5998,7 +5999,7 @@ __metadata: languageName: node linkType: hard -"joi@npm:17.13.3": +"joi@npm:17.13.3, joi@npm:^17.13.3": version: 17.13.3 resolution: "joi@npm:17.13.3" dependencies: From 7441774469e4a8575cdb4dd6e548b2f3b0f958bc Mon Sep 17 00:00:00 2001 From: belopash Date: Mon, 16 Sep 2024 19:34:03 +0500 Subject: [PATCH 13/15] feat: rename rm --> remove, ls -> list --- src/api/types.ts | 8 +------- src/command.ts | 4 ++-- src/commands/deploy.ts | 4 ++-- src/commands/docs.ts | 2 +- src/commands/explorer.ts | 2 ++ src/commands/gateways/{ls.ts => list.ts} | 2 ++ src/commands/{ls.ts => list.ts} | 6 ++++-- src/commands/prod.ts | 6 ++++-- src/commands/{rm.ts => remove.ts} | 16 ++++++++++------ src/commands/secrets/{ls.ts => list.ts} | 2 ++ src/commands/secrets/{rm.ts => remove.ts} | 2 ++ src/deploy-command.ts | 2 +- src/manifest/manifest.ts | 2 +- src/utils.ts | 6 ++++-- 14 files changed, 38 insertions(+), 26 deletions(-) rename src/commands/gateways/{ls.ts => list.ts} (98%) rename src/commands/{ls.ts => list.ts} (94%) rename src/commands/{rm.ts => remove.ts} (75%) rename src/commands/secrets/{ls.ts => list.ts} (96%) rename src/commands/secrets/{rm.ts => remove.ts} (95%) diff --git a/src/api/types.ts b/src/api/types.ts index d28e17d..7d95206 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -52,13 +52,7 @@ export type LogsResponse = { export type OrganizationRequest = { organization: PickDeep }; export type SquidRequest = OrganizationRequest & { - squid: - | ({ name: string } & ( - | { tag?: never; slot: string } - | { tag: string; slot?: never } - | { tag: string; slot: string } - )) - | string; + squid: ({ name: string } & { tag?: string; slot?: string }) | string; }; export type DeployRequest = OrganizationRequest & { deploy: PickDeep }; diff --git a/src/command.ts b/src/command.ts index af9b3bb..740a748 100644 --- a/src/command.ts +++ b/src/command.ts @@ -13,7 +13,7 @@ export const SUCCESS_CHECK_MARK = chalk.green('✓'); export abstract class CliCommand extends Command { static baseFlags = { interactive: Flags.boolean({ - description: 'Enable or disable interactive mode', + description: 'Disable interactive mode', required: false, default: true, allowNo: true, @@ -139,7 +139,7 @@ export abstract class CliCommand extends Command { } async promptSquidOrganization( - code: string, + code: string | null | undefined, name: string, { using, diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 2993ffb..c7637df 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -290,7 +290,7 @@ export default class Deploy extends DeployCommand { hardReset?: boolean; } = {}, ) { - const warning = `A squid ${printSquid(target)} already exists.`; + const warning = `The squid ${printSquid(target)} already exists.`; if (!interactive) { this.error([warning, `Please do it explicitly ${using}`].join('\n')); @@ -303,7 +303,7 @@ export default class Deploy extends DeployCommand { name: 'confirm', type: 'confirm', message: 'Are you sure?', - prefix: `A squid ${printSquid(target)} will be ${hardReset ? `recreated` : `updated`}.`, + prefix: `The squid ${printSquid(target)} will be updated.`, }, ]); diff --git a/src/commands/docs.ts b/src/commands/docs.ts index 1322b3e..e8fb714 100644 --- a/src/commands/docs.ts +++ b/src/commands/docs.ts @@ -7,6 +7,6 @@ export default class Docs extends Command { async run(): Promise { await this.parse(Docs); - void open('https://docs.subsquid.io'); + void open('https://docs.sqd.dev/'); } } diff --git a/src/commands/explorer.ts b/src/commands/explorer.ts index 3dd7623..9701be6 100644 --- a/src/commands/explorer.ts +++ b/src/commands/explorer.ts @@ -6,6 +6,8 @@ import { Loader } from '../ui/components/Loader'; import { VersionManager } from '../ui/components/VersionManager'; export default class Explorer extends CliCommand { + static hidden = true; + static description = 'Open a visual explorer for the Cloud deployments'; // static hidden = true; static flags = { diff --git a/src/commands/gateways/ls.ts b/src/commands/gateways/list.ts similarity index 98% rename from src/commands/gateways/ls.ts rename to src/commands/gateways/list.ts index f1cd978..503797f 100644 --- a/src/commands/gateways/ls.ts +++ b/src/commands/gateways/list.ts @@ -7,6 +7,8 @@ import { Gateway, getEvmGateways, getSubstrateGateways } from '../../api/gateway import { CliCommand } from '../../command'; export default class Ls extends CliCommand { + static aliases = ['gateways ls']; + static description = 'List available gateways'; static flags = { diff --git a/src/commands/ls.ts b/src/commands/list.ts similarity index 94% rename from src/commands/ls.ts rename to src/commands/list.ts index 7d080a4..fae721e 100644 --- a/src/commands/ls.ts +++ b/src/commands/list.ts @@ -4,7 +4,9 @@ import { listSquids } from '../api'; import { CliCommand, SqdFlags } from '../command'; import { printSquid } from '../utils'; -export default class Ls extends CliCommand { +export default class List extends CliCommand { + static aliases = ['ls']; + static description = 'List squids deployed to the Cloud'; static flags = { @@ -37,7 +39,7 @@ export default class Ls extends CliCommand { async run(): Promise { const { flags: { truncate, reference, interactive, ...flags }, - } = await this.parse(Ls); + } = await this.parse(List); const { org, name, slot, tag } = reference ? reference : (flags as any); diff --git a/src/commands/prod.ts b/src/commands/prod.ts index 8db2c44..d11d1dc 100644 --- a/src/commands/prod.ts +++ b/src/commands/prod.ts @@ -2,6 +2,8 @@ import { Command } from '@oclif/core'; import chalk from 'chalk'; export default class Prod extends Command { + static hidden = true; + static description = 'Assign the canonical production API alias for a squid deployed to the Cloud'; async run(): Promise { @@ -13,8 +15,8 @@ export default class Prod extends Command { chalk.yellow('*******************************************************'), chalk.yellow('* *'), chalk.yellow('* WARNING! This command has been deprecated *'), - chalk.yellow('* Please check the migration guide *'), - chalk.yellow('* https://docs.subsquid.io/deploy-squid/migration/ *'), + chalk.yellow('* Please check the release notes *'), + chalk.yellow('* https://docs.sqd.dev/deployments-two-release-notes/ *'), chalk.yellow('* *'), chalk.yellow('*******************************************************'), ].join('\n'), diff --git a/src/commands/rm.ts b/src/commands/remove.ts similarity index 75% rename from src/commands/rm.ts rename to src/commands/remove.ts index 3ef77a6..0f64427 100644 --- a/src/commands/rm.ts +++ b/src/commands/remove.ts @@ -1,16 +1,19 @@ import { Flags } from '@oclif/core'; +import chalk from 'chalk'; import inquirer from 'inquirer'; import { deleteSquid } from '../api'; import { SqdFlags } from '../command'; import { DeployCommand } from '../deploy-command'; -import { formatSquidReference, printSquid } from '../utils'; +import { ParsedSquidReference, printSquid } from '../utils'; import { DELETE_COLOR } from './deploy'; -export default class Rm extends DeployCommand { +export default class Remove extends DeployCommand { static description = 'Remove a squid deployed to the Cloud'; + static aliases = ['rm']; + static flags = { org: SqdFlags.org({ required: false, @@ -37,11 +40,11 @@ export default class Rm extends DeployCommand { async run(): Promise { const { flags: { interactive, force, reference, ...flags }, - } = await this.parse(Rm); + } = await this.parse(Remove); this.validateSquidNameFlags({ reference, ...flags }); - const { org, name, tag, slot } = reference ? reference : (flags as any); + const { org, name, tag, slot } = reference || (flags as ParsedSquidReference); const organization = await this.promptSquidOrganization(org, name, { interactive }); const squid = await this.findOrThrowSquid({ organization, squid: { name, slot, tag } }); @@ -54,7 +57,8 @@ export default class Rm extends DeployCommand { { name: 'confirm', type: 'confirm', - message: `Your squid ${printSquid(squid)} will be completely removed. This action can not be undone. Are you sure?`, + message: `Are you sure?`, + prefix: `The squid ${printSquid(squid)} will be completely removed. This action can not be undone.`, }, ]); if (!confirm) return; @@ -64,6 +68,6 @@ export default class Rm extends DeployCommand { await this.pollDeploy({ organization, deploy: deployment }); if (!deployment || !deployment.squid) return; - this.logDeployResult(DELETE_COLOR, `A squid deployment ${printSquid(squid)} was successfully deleted`); + this.logDeployResult(DELETE_COLOR, `The squid ${printSquid(squid)} was successfully deleted`); } } diff --git a/src/commands/secrets/ls.ts b/src/commands/secrets/list.ts similarity index 96% rename from src/commands/secrets/ls.ts rename to src/commands/secrets/list.ts index e81794d..4d8c7c3 100644 --- a/src/commands/secrets/ls.ts +++ b/src/commands/secrets/list.ts @@ -4,6 +4,8 @@ import { listSecrets } from '../../api'; import { CliCommand } from '../../command'; export default class Ls extends CliCommand { + static aliases = ['secrets ls']; + static description = 'List organization secrets in the Cloud'; static flags = { diff --git a/src/commands/secrets/rm.ts b/src/commands/secrets/remove.ts similarity index 95% rename from src/commands/secrets/rm.ts rename to src/commands/secrets/remove.ts index 0fad46c..fab4764 100644 --- a/src/commands/secrets/rm.ts +++ b/src/commands/secrets/remove.ts @@ -4,6 +4,8 @@ import { removeSecret } from '../../api'; import { CliCommand } from '../../command'; export default class Rm extends CliCommand { + static aliases = ['secrets rm']; + static description = 'Delete an organization secret in the Cloud'; static args = { name: Args.string({ diff --git a/src/deploy-command.ts b/src/deploy-command.ts index f54bb22..ca53413 100644 --- a/src/deploy-command.ts +++ b/src/deploy-command.ts @@ -128,7 +128,7 @@ You can not run deploys on the same squid in parallel`; return false; case 'DEPLOYING': case 'SQUID_SYNCING': - CliUx.ux.action.start('◷ Deploying the squid'); + CliUx.ux.action.start('◷ Syncing the squid'); return false; case 'ADDONS_SYNCING': diff --git a/src/manifest/manifest.ts b/src/manifest/manifest.ts index 5e277f3..fd2ca37 100644 --- a/src/manifest/manifest.ts +++ b/src/manifest/manifest.ts @@ -31,7 +31,7 @@ export function loadManifestFile(localPath: string, manifestPath: string): { squ if (!fs.statSync(squidDir).isDirectory()) { throw new Error( [ - `The squid directory is not a directory`, + `The provided path is not a directory`, ``, `Squid directory ${squidDir}`, ``, diff --git a/src/utils.ts b/src/utils.ts index 62cd2be..b4e47db 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -39,14 +39,16 @@ export async function doUntil(fn: () => Promise, { pause }: { pause: nu export type ParsedSquidReference = { org?: string; name: string } & ( | { slot: string; tag?: never } | { slot?: never; tag: string } - | { slot: string; tag: string } ); export function formatSquidReference( - reference: ParsedSquidReference | string, + reference: { org?: string; name: string; slot?: string; tag?: string } | string, { colored }: { colored?: boolean } = {}, ) { const { org, name, slot, tag } = typeof reference === 'string' ? parseSquidReference(reference) : reference; + if (!tag && !slot) { + throw new Error('At least one of slot or tag has to be defined'); + } const prefix = org ? `${org}/` : ``; const suffix = slot ? `@${slot}` : `:${tag}`; From f538c74b02c432506145a47d82d30738838e7076 Mon Sep 17 00:00:00 2001 From: belopash Date: Mon, 16 Sep 2024 19:34:25 +0500 Subject: [PATCH 14/15] feat: do not allow to delete squid with tags --- src/commands/remove.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/commands/remove.ts b/src/commands/remove.ts index 0f64427..4de9b14 100644 --- a/src/commands/remove.ts +++ b/src/commands/remove.ts @@ -52,6 +52,20 @@ export default class Remove extends DeployCommand { const attached = await this.promptAttachToDeploy(squid, { interactive }); if (attached) return; + const hasOtherTags = !tag || !!squid.tags.some((t) => t.name !== tag); + if (hasOtherTags) { + const warning = [ + `The squid ${printSquid(squid)} has one or more tags assigned to it:`, + ...squid.tags.map((t) => chalk.dim(` - ${t.name}`)), + ]; + + if (!interactive && !force) { + this.error([...warning, 'Please do it explicitly using --force flag'].join('\n')); + } else { + this.warn(warning.join('\n')); + } + } + if (!force && interactive) { const { confirm } = await inquirer.prompt([ { From f48ec30604b4624d8847f36b73641cf868ee304c Mon Sep 17 00:00:00 2001 From: belopash Date: Mon, 16 Sep 2024 20:27:23 +0500 Subject: [PATCH 15/15] feat: prompt on hard-reset --- package.json | 4 +-- src/commands/deploy.ts | 65 ++++++++++++++++++++++++++---------------- yarn.lock | 10 +++---- 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index a6457a2..194bb36 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.0.0-beta.10", + "version": "3.0.0-beta.11", "license": "GPL-3.0-or-later", "repository": "git@github.com:subsquid/squid-cli.git", "publishConfig": { @@ -78,7 +78,7 @@ "@oclif/plugin-autocomplete": "3.2.2", "@oclif/plugin-warn-if-update-available": "^3.1.13", "@subsquid/commands": "^2.3.1", - "@subsquid/manifest": "^2.0.0-beta.2", + "@subsquid/manifest": "^2.0.0-beta.3", "@subsquid/manifest-expr": "^0.0.1", "@types/fast-levenshtein": "^0.0.4", "@types/lodash": "^4.17.7", diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index c7637df..afc6286 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -17,7 +17,7 @@ import { deploySquid, OrganizationRequest, Squid, uploadFile } from '../api'; import { SqdFlags, SUCCESS_CHECK_MARK } from '../command'; import { DeployCommand } from '../deploy-command'; import { loadManifestFile } from '../manifest'; -import { printSquid } from '../utils'; +import { formatSquidReference, ParsedSquidReference, printSquid } from '../utils'; const compressAsync = promisify(targz.compress); @@ -170,6 +170,18 @@ export default class Deploy extends DeployCommand { return this.error('Not implemented yet'); } + if (interactive && hardReset) { + const { confirm } = await inquirer.prompt([ + { + name: 'confirm', + type: 'confirm', + message: `Are you sure?`, + prefix: `Your squid will be reset, which may potentially result in data loss.`, + }, + ]); + if (!confirm) return; + } + this.log(`🦑 Releasing the squid from local folder`); const res = resolveManifest(source, manifestPath); @@ -177,7 +189,7 @@ export default class Deploy extends DeployCommand { const { buildDir, squidDir, manifest } = res; - const overrides = reference ? reference : pick(flags, 'slot', 'name', 'tag', 'org'); + const overrides = reference || (pick(flags, 'slot', 'name', 'tag', 'org') as Partial); // some hack to normalize slot name in case if version is used { @@ -218,11 +230,19 @@ export default class Deploy extends DeployCommand { }); } + /** + * Squid exists we should check running deploys + */ + if (target) { + const attached = await this.promptAttachToDeploy(target, { interactive }); + if (attached) return; + } + /** * Squid exists we should ask for update */ if (target && !flags['allow-update']) { - const update = await this.promptUpdateSquid(target, { interactive, hardReset }); + const update = await this.promptUpdateSquid(target, { interactive }); if (!update) return; } @@ -235,15 +255,7 @@ export default class Deploy extends DeployCommand { if (!add) return; } - /** - * Squid exists we should check running deploys - */ - if (target) { - const attached = await this.promptAttachToDeploy(target, { interactive }); - if (attached) return; - } - - const archiveName = `${manifest.name}.tar.gz`; + const archiveName = `${formatSquidReference({ name, slot, tag })}.tar.gz`; const artifactPath = await this.pack({ buildDir, squidDir, archiveName }); const artifactUrl = await this.upload({ organization, artifactPath }); @@ -279,31 +291,32 @@ export default class Deploy extends DeployCommand { } private async promptUpdateSquid( - target: Squid, + squid: Squid, { using = 'using "--allow-update" flag', interactive, - hardReset, }: { using?: string; interactive?: boolean; - hardReset?: boolean; } = {}, ) { - const warning = `The squid ${printSquid(target)} already exists.`; + const warning = [ + `The squid ${printSquid(squid)} already exists${squid.tags.length > 0 ? ` and has one or more tags assigned to it:` : ``}`, + ...squid.tags.map((t) => chalk.dim(` - ${t.name}`)), + ]; - if (!interactive) { - this.error([warning, `Please do it explicitly ${using}`].join('\n')); + if (interactive) { + this.warn(warning.join('\n')); + } else { + this.error([...warning, `Please do it explicitly ${using}`].join('\n')); } - this.warn(warning); - const { confirm } = await inquirer.prompt([ { name: 'confirm', type: 'confirm', message: 'Are you sure?', - prefix: `The squid ${printSquid(target)} will be updated.`, + prefix: `The squid ${printSquid(squid)} will be updated.`, }, ]); @@ -334,11 +347,12 @@ export default class Deploy extends DeployCommand { ``, ].join('\n'); - if (!interactive) { + if (interactive) { + this.warn(warning); + } else { this.error([warning, `Please do it explicitly ${using}`].join('\n')); } - this.warn(warning); this.log( `If it is intended and you'd like to override them, just skip this message and confirm, the manifest name will be overridden automatically in the Cloud during the deploy.`, ); @@ -362,11 +376,12 @@ export default class Deploy extends DeployCommand { const warning = `The squid name is not defined either in the manifest or via CLI command.`; - if (!interactive) { + if (interactive) { + this.warn(warning); + } else { this.error([warning, `Please specify it explicitly ${using}`].join('\n')); } - this.warn(warning); const { input } = await inquirer.prompt([ { name: 'input', diff --git a/yarn.lock b/yarn.lock index c3d7f0b..55da827 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1411,7 +1411,7 @@ __metadata: "@oclif/plugin-autocomplete": "npm:3.2.2" "@oclif/plugin-warn-if-update-available": "npm:^3.1.13" "@subsquid/commands": "npm:^2.3.1" - "@subsquid/manifest": "npm:^2.0.0-beta.2" + "@subsquid/manifest": "npm:^2.0.0-beta.3" "@subsquid/manifest-expr": "npm:^0.0.1" "@types/async-retry": "npm:^1.4.8" "@types/blessed": "npm:^0.1.25" @@ -1513,15 +1513,15 @@ __metadata: languageName: node linkType: hard -"@subsquid/manifest@npm:^2.0.0-beta.2": - version: 2.0.0-beta.2 - resolution: "@subsquid/manifest@npm:2.0.0-beta.2" +"@subsquid/manifest@npm:^2.0.0-beta.3": + version: 2.0.0-beta.3 + resolution: "@subsquid/manifest@npm:2.0.0-beta.3" dependencies: "@subsquid/manifest-expr": "npm:^0.0.1" joi: "npm:17.13.3" js-yaml: "npm:^4.1.0" lodash: "npm:^4.17.21" - checksum: 10c0/32059ac92737aa1728fdfd50f6e3c300e662b7d05f13c33dd59538aa84a9beb5ae4d830513754f6a0a87b8f2f41968b14890144be93ccf0455b15b2bc59b539b + checksum: 10c0/7265c405631db86b2ac553f2c95070dd1f0e612ac71211b6cf70fed7d4150bc7bc979c6605662fd66364c25a40905a60f29477f415add31fee4cc4fa16220112 languageName: node linkType: hard