Skip to content

Commit

Permalink
feat: fix --add-tag flag and improve ux
Browse files Browse the repository at this point in the history
  • Loading branch information
belopash committed Sep 10, 2024
1 parent 03114b6 commit e4dcdcf
Show file tree
Hide file tree
Showing 25 changed files with 341 additions and 371 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": "[email protected]:subsquid/squid-cli.git",
"publishConfig": {
Expand Down
3 changes: 2 additions & 1 deletion src/api/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
37 changes: 17 additions & 20 deletions src/api/squids.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import split2 from 'split2';

import { pretty } from '../logs';
import { formatSquidReference } from '../utils';

import { api, debugLog } from './api';
import {
Expand All @@ -24,18 +25,18 @@ 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<Squid> {
export async function getSquid({ organization, squid }: SquidRequest): Promise<Squid> {
const { body } = await api<HttpResponse<Squid>>({
method: 'get',
path: `/orgs/${organization.code}/squids/${reference}`,
path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}`,
});

return body.payload;
}

export async function squidHistoryLogs({
organization,
reference,
squid,
query,
abortController,
}: SquidRequest & {
Expand All @@ -52,7 +53,7 @@ export async function squidHistoryLogs({
}): Promise<LogsResponse> {
const { body } = await api<HttpResponse<LogsResponse>>({
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(),
Expand All @@ -68,7 +69,7 @@ export async function squidHistoryLogs({

export async function squidLogsFollow({
organization,
reference,
squid,
query,
abortController,
}: SquidRequest & {
Expand All @@ -77,7 +78,7 @@ export async function squidLogsFollow({
}) {
const { body } = await api<NodeJS.ReadableStream>({
method: 'get',
path: `/orgs/${organization.code}/squids/${reference}/logs/follow`,
path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/logs/follow`,
query,
responseType: 'stream',
abortController: abortController,
Expand All @@ -88,7 +89,7 @@ export async function squidLogsFollow({

export async function streamSquidLogs({
organization,
reference,
squid,
abortController,
query = {},
onLog,
Expand All @@ -106,7 +107,7 @@ export async function streamSquidLogs({
try {
stream = await squidLogsFollow({
organization,
reference,
squid,
query,
abortController,
});
Expand Down Expand Up @@ -198,45 +199,41 @@ export async function getUploadUrl({ organization }: OrganizationRequest): Promi
return body.payload;
}

export async function restartSquid({ organization, reference }: SquidRequest): Promise<Deployment> {
export async function restartSquid({ organization, squid }: SquidRequest): Promise<Deployment> {
const { body } = await api<HttpResponse<Deployment>>({
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<Deployment> {
export async function deleteSquid({ organization, squid }: SquidRequest): Promise<Deployment> {
const { body } = await api<HttpResponse<Deployment>>({
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<Deployment> {
export async function addSquidTag({ organization, squid, tag }: SquidRequest & { tag: string }): Promise<Deployment> {
const { body } = await api<HttpResponse<Deployment>>({
method: 'PUT',
path: `/orgs/${organization.code}/squids/${reference}/tags/${tag}`,
path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/tags/${tag}`,
});

return body.payload;
}

export async function removeSquidTag({
organization,
reference,
squid,
tag,
}: SquidRequest & { tag: string }): Promise<Deployment> {
const { body } = await api<HttpResponse<Deployment>>({
method: 'DELETE',
path: `/orgs/${organization.code}/squids/${reference}/tags/${tag}`,
path: `/orgs/${organization.code}/squids/${formatSquidReference(squid)}/tags/${tag}`,
});

return body.payload;
Expand Down
10 changes: 9 additions & 1 deletion src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ export type LogsResponse = {

export type OrganizationRequest = { organization: PickDeep<Organization, 'code'> };

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<Deployment, 'id'> };
97 changes: 58 additions & 39 deletions src/command.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
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';
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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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 } });
}
Expand All @@ -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<T extends { code: string; name: string }>(
organizations: T[],
using: string = 'using "-o" flag',
{
using = 'using "--org" flag',
interactive,
}: {
using?: string;
interactive?: boolean;
},
): Promise<T> {
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 });
Expand All @@ -183,16 +214,4 @@ export abstract class CliCommand extends Command {
}
}

export const SquidReferenceArg = Args.string({
// description: `<name${SQUID_HASH_SYMBOL}hash> or <name${SQUID_TAG_SYMBOL}tag>`,
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';
Loading

0 comments on commit e4dcdcf

Please sign in to comment.