From 9a237a4731f7cc1cd3e1e1e5d311e21918a90bf5 Mon Sep 17 00:00:00 2001 From: "shaoqian.zhang" Date: Sat, 4 Mar 2023 22:47:14 +0800 Subject: [PATCH 1/2] feat(cli): rebuild backend api --- cli/src/action/storage/s3.ts | 2 +- cli/src/api/debug.ts | 4 +- cli/src/api/v1/application.ts | 8 +- cli/src/api/v1/data-contracts.ts | 25 +++---- cli/src/api/v1/website.ts | 113 ---------------------------- cli/src/api/v1/websitehosting.ts | 124 +++++++++++++++++++++++++++++++ cli/src/util/request.ts | 4 +- 7 files changed, 146 insertions(+), 134 deletions(-) delete mode 100644 cli/src/api/v1/website.ts create mode 100644 cli/src/api/v1/websitehosting.ts diff --git a/cli/src/action/storage/s3.ts b/cli/src/action/storage/s3.ts index a74ff595cc..43b8b7a0ca 100644 --- a/cli/src/action/storage/s3.ts +++ b/cli/src/action/storage/s3.ts @@ -1,5 +1,5 @@ import * as AWS from 'aws-sdk' -require("aws-sdk/lib/maintenance_mode_message").suppress = true; +require('aws-sdk/lib/maintenance_mode_message').suppress = true export function getS3Client(credentials: any) { return new AWS.S3({ diff --git a/cli/src/api/debug.ts b/cli/src/api/debug.ts index e142b0c123..372e528f48 100644 --- a/cli/src/api/debug.ts +++ b/cli/src/api/debug.ts @@ -1,4 +1,4 @@ -import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios' +import axios, { InternalAxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios' import * as urlencode from 'urlencode' export async function invokeFunction( @@ -26,7 +26,7 @@ const request = axios.create({ // request interceptor request.interceptors.request.use( - (config: AxiosRequestConfig) => { + (config: InternalAxiosRequestConfig) => { let _headers: AxiosRequestHeaders | any = { 'Content-Type': 'application/json', } diff --git a/cli/src/api/v1/application.ts b/cli/src/api/v1/application.ts index eecd5afdce..addb455f00 100644 --- a/cli/src/api/v1/application.ts +++ b/cli/src/api/v1/application.ts @@ -7,6 +7,7 @@ import { CreateApplicationDto, CreateDependencyDto, CreateEnvironmentDto, + DeleteDependencyDto, UpdateApplicationDto, UpdateDependencyDto, } from './data-contracts' @@ -229,17 +230,18 @@ export async function dependencyControllerGetDependencies( * @tags Application * @name DependencyControllerRemove * @summary Remove a dependency - * @request DELETE:/v1/apps/{appid}/dependencies/{name} + * @request DELETE:/v1/apps/{appid}/dependencies * @secure */ export async function dependencyControllerRemove( appid: string, - name: string, + data: DeleteDependencyDto, configParams: RequestParams = {}, ): Promise { return request({ - url: `/v1/apps/${appid}/dependencies/${name}`, + url: `/v1/apps/${appid}/dependencies`, method: 'DELETE', + data: data, ...configParams, }) } diff --git a/cli/src/api/v1/data-contracts.ts b/cli/src/api/v1/data-contracts.ts index 1d61eb6f8c..417d1953a2 100644 --- a/cli/src/api/v1/data-contracts.ts +++ b/cli/src/api/v1/data-contracts.ts @@ -39,7 +39,7 @@ export interface CreateApplicationDto { export interface UpdateApplicationDto { name?: string - state?: 'Running' | 'Stopped' | 'Restarting' + state?: 'Running' | 'Stopped' | 'Restarting' | 'Deleted' } export interface CreateEnvironmentDto { @@ -91,9 +91,14 @@ export interface UpdatePolicyRuleDto { value: string } -export type CreateWebsiteDto = object +export interface CreateWebsiteDto { + bucketName: string + state: string +} -export type UpdateWebsiteDto = object +export interface BindCustomDomainDto { + domain: string +} export interface Pat2TokenDto { /** @@ -142,6 +147,10 @@ export interface UpdateDependencyDto { spec: string } +export interface DeleteDependencyDto { + name: string +} + export interface CreateTriggerDto { desc: string cron: string @@ -162,16 +171,6 @@ export type RegionControllerGetRegionsData = any export type DatabaseControllerProxyData = any -export type WebsitesControllerCreateData = any - -export type WebsitesControllerFindAllData = any - -export type WebsitesControllerFindOneData = any - -export type WebsitesControllerUpdateData = any - -export type WebsitesControllerRemoveData = any - export interface AuthControllerCode2TokenParams { code: string } diff --git a/cli/src/api/v1/website.ts b/cli/src/api/v1/website.ts deleted file mode 100644 index 6125cd2283..0000000000 --- a/cli/src/api/v1/website.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { request, RequestParams } from '../../util/request' -import { - CreateWebsiteDto, - UpdateWebsiteDto, - WebsitesControllerCreateData, - WebsitesControllerFindAllData, - WebsitesControllerFindOneData, - WebsitesControllerRemoveData, - WebsitesControllerUpdateData, -} from './data-contracts' - -/** - * No description - * - * @tags Website - * @name WebsitesControllerCreate - * @summary TODO - ⌛️ - * @request POST:/v1/apps/{appid}/websites - * @secure - */ -export async function websitesControllerCreate( - appid: string, - data: CreateWebsiteDto, - configParams: RequestParams = {}, -): Promise { - return request({ - url: `/v1/apps/${appid}/websites`, - method: 'POST', - data: data, - ...configParams, - }) -} -/** - * No description - * - * @tags Website - * @name WebsitesControllerFindAll - * @summary TODO - ⌛️ - * @request GET:/v1/apps/{appid}/websites - * @secure - */ -export async function websitesControllerFindAll( - appid: string, - configParams: RequestParams = {}, -): Promise { - return request({ - url: `/v1/apps/${appid}/websites`, - method: 'GET', - ...configParams, - }) -} -/** - * No description - * - * @tags Website - * @name WebsitesControllerFindOne - * @summary TODO - ⌛️ - * @request GET:/v1/apps/{appid}/websites/{id} - * @secure - */ -export async function websitesControllerFindOne( - id: string, - appid: string, - configParams: RequestParams = {}, -): Promise { - return request({ - url: `/v1/apps/${appid}/websites/${id}`, - method: 'GET', - ...configParams, - }) -} -/** - * No description - * - * @tags Website - * @name WebsitesControllerUpdate - * @summary TODO - ⌛️ - * @request PATCH:/v1/apps/{appid}/websites/{id} - * @secure - */ -export async function websitesControllerUpdate( - id: string, - appid: string, - data: UpdateWebsiteDto, - configParams: RequestParams = {}, -): Promise { - return request({ - url: `/v1/apps/${appid}/websites/${id}`, - method: 'PATCH', - data: data, - ...configParams, - }) -} -/** - * No description - * - * @tags Website - * @name WebsitesControllerRemove - * @summary TODO - ⌛️ - * @request DELETE:/v1/apps/{appid}/websites/{id} - * @secure - */ -export async function websitesControllerRemove( - id: string, - appid: string, - configParams: RequestParams = {}, -): Promise { - return request({ - url: `/v1/apps/${appid}/websites/${id}`, - method: 'DELETE', - ...configParams, - }) -} diff --git a/cli/src/api/v1/websitehosting.ts b/cli/src/api/v1/websitehosting.ts new file mode 100644 index 0000000000..c63e2ddb0b --- /dev/null +++ b/cli/src/api/v1/websitehosting.ts @@ -0,0 +1,124 @@ +import { request, RequestParams } from '../../util/request' +import { BindCustomDomainDto, CreateWebsiteDto } from './data-contracts' + +/** + * No description + * + * @tags WebsiteHosting + * @name WebsiteControllerCreate + * @summary Create a new website + * @request POST:/v1/apps/{appid}/websites + * @secure + */ +export async function websiteControllerCreate( + appid: string, + data: CreateWebsiteDto, + configParams: RequestParams = {}, +): Promise { + return request({ + url: `/v1/apps/${appid}/websites`, + method: 'POST', + data: data, + ...configParams, + }) +} +/** + * No description + * + * @tags WebsiteHosting + * @name WebsiteControllerFindAll + * @summary Get all websites of an app + * @request GET:/v1/apps/{appid}/websites + * @secure + */ +export async function websiteControllerFindAll(appid: string, configParams: RequestParams = {}): Promise { + return request({ + url: `/v1/apps/${appid}/websites`, + method: 'GET', + ...configParams, + }) +} +/** + * No description + * + * @tags WebsiteHosting + * @name WebsiteControllerFindOne + * @summary Get a website hosting of an app + * @request GET:/v1/apps/{appid}/websites/{id} + * @secure + */ +export async function websiteControllerFindOne( + appid: string, + id: string, + configParams: RequestParams = {}, +): Promise { + return request({ + url: `/v1/apps/${appid}/websites/${id}`, + method: 'GET', + ...configParams, + }) +} +/** + * No description + * + * @tags WebsiteHosting + * @name WebsiteControllerBindDomain + * @summary Bind custom domain to website + * @request PATCH:/v1/apps/{appid}/websites/{id} + * @secure + */ +export async function websiteControllerBindDomain( + appid: string, + id: string, + data: BindCustomDomainDto, + configParams: RequestParams = {}, +): Promise { + return request({ + url: `/v1/apps/${appid}/websites/${id}`, + method: 'PATCH', + data: data, + ...configParams, + }) +} +/** + * No description + * + * @tags WebsiteHosting + * @name WebsiteControllerRemove + * @summary Delete a website hosting + * @request DELETE:/v1/apps/{appid}/websites/{id} + * @secure + */ +export async function websiteControllerRemove( + appid: string, + id: string, + configParams: RequestParams = {}, +): Promise { + return request({ + url: `/v1/apps/${appid}/websites/${id}`, + method: 'DELETE', + ...configParams, + }) +} +/** + * No description + * + * @tags WebsiteHosting + * @name WebsiteControllerCheckResolved + * @summary Check if domain is resolved + * @request POST:/v1/apps/{appid}/websites/{id}/resolved + * @secure + */ +export async function websiteControllerCheckResolved( + appid: string, + id: string, + data: BindCustomDomainDto, + configParams: RequestParams = {}, +): Promise { + return request({ + url: `/v1/apps/${appid}/websites/${id}/resolved`, + method: 'POST', + data: data, + ...configParams, + }) +} diff --git a/cli/src/util/request.ts b/cli/src/util/request.ts index 2e875f045d..d8fe400bf0 100644 --- a/cli/src/util/request.ts +++ b/cli/src/util/request.ts @@ -1,5 +1,5 @@ // request.ts -import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios' +import axios, { InternalAxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios' import { existSystemConfig, readSystemConfig, refreshToken } from '../config/system' import { DEFAULT_REMOTE_SERVER } from '../common/constant' @@ -11,7 +11,7 @@ export const request = axios.create({ // request interceptor request.interceptors.request.use( - async (config: AxiosRequestConfig) => { + async (config: InternalAxiosRequestConfig) => { let _headers: AxiosRequestHeaders | any = { 'Content-Type': 'application/json', } From 979edba491ba62882374167fc129eea6788138f1 Mon Sep 17 00:00:00 2001 From: "shaoqian.zhang" Date: Sun, 5 Mar 2023 00:08:28 +0800 Subject: [PATCH 2/2] feat: impl website command --- cli/src/action/website/index.ts | 85 ++++++++++++++++++++++++++++++++ cli/src/command/policy/index.ts | 2 +- cli/src/command/storage/index.ts | 2 +- cli/src/command/website/index.ts | 41 +++++++++++++++ cli/src/main.ts | 9 ++-- cli/src/util/request.ts | 5 +- 6 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 cli/src/action/website/index.ts create mode 100644 cli/src/command/website/index.ts diff --git a/cli/src/action/website/index.ts b/cli/src/action/website/index.ts new file mode 100644 index 0000000000..57eeb08059 --- /dev/null +++ b/cli/src/action/website/index.ts @@ -0,0 +1,85 @@ +import { websiteControllerBindDomain, websiteControllerCreate, websiteControllerFindAll, websiteControllerRemove } from "../../api/v1/websitehosting" +import { readApplicationConfig } from "../../config/application" +import * as Table from 'cli-table3' +import { formatDate } from "../../util/format" +import { BindCustomDomainDto, CreateWebsiteDto } from "../../api/v1/data-contracts" +import { getEmoji } from "../../util/print" + + +export async function list() { + const appConfig = readApplicationConfig() + const websites = await websiteControllerFindAll(appConfig.appid) + const table = new Table({ + head: ['bucketName', 'domain', 'state', 'updatedAt'], + }) + for (let item of websites) { + table.push([item.bucketName, item.domain, item.state, formatDate(item.updatedAt),]) + } + console.log(table.toString()) +} + +export async function create(bucketName: string, options: any) { + const appConfig = readApplicationConfig() + + if (!bucketName.startsWith(appConfig.appid + '-')) { + bucketName = appConfig.appid + '-' + bucketName + } + + const createDto: CreateWebsiteDto = { + bucketName, + state: 'Active', + } + const website = await websiteControllerCreate(appConfig.appid, createDto) + + if (options) { } + + console.log(`${getEmoji('✅')} create website success!`) + console.log(`You can access through this domain: ${website.domain}`) +} + +export async function del(bucketName: string, options: any) { + const appConfig = readApplicationConfig() + const websites = await websiteControllerFindAll(appConfig.appid) + + if (options) { + } + + if (!bucketName.startsWith(appConfig.appid + '-')) { + bucketName = appConfig.appid + '-' + bucketName + } + + const targetId = websites.find((item) => item.bucketName === bucketName)?.id + if (!targetId) { + console.log(`${getEmoji('❌')} website ${bucketName} not found`) + return + } + await websiteControllerRemove(appConfig.appid, targetId) + + console.log(`${getEmoji('✅')} delete website success!`) +} + +export async function custom(bucketName: string, domain: string, options: any) { + const appConfig = readApplicationConfig() + const websites = await websiteControllerFindAll(appConfig.appid) + + if (options) { + } + + if (!bucketName.startsWith(appConfig.appid + '-')) { + bucketName = appConfig.appid + '-' + bucketName + } + + const targetId = websites.find((item) => item.bucketName === bucketName)?.id + if (!targetId) { + console.log(`${getEmoji('❌')} website ${bucketName} not found`) + return + } + + const patchDto: BindCustomDomainDto = { + domain, + } + const website = await websiteControllerBindDomain(appConfig.appid, targetId, patchDto) + + console.log(`${getEmoji('✅')} bind custom success!`) + console.log(`You can access through this domain: ${website.domain}`) +} \ No newline at end of file diff --git a/cli/src/command/policy/index.ts b/cli/src/command/policy/index.ts index 4cd9acfd39..3fa75856ad 100644 --- a/cli/src/command/policy/index.ts +++ b/cli/src/command/policy/index.ts @@ -2,7 +2,7 @@ import { Command, program } from 'commander' import { list, pullOne, pushOne, pullAll, pushAll } from '../../action/policy' import { checkApplication } from '../../common/hook' -export function policyCommand(): Command { +export function command(): Command { const cmd = program.command('policy').hook('preAction', () => { checkApplication() }) diff --git a/cli/src/command/storage/index.ts b/cli/src/command/storage/index.ts index 3031e0d1be..d24b716041 100644 --- a/cli/src/command/storage/index.ts +++ b/cli/src/command/storage/index.ts @@ -2,7 +2,7 @@ import { Command, program } from 'commander' import { create, del, list, pull, push, update } from '../../action/storage' import { checkApplication, checkStorageToken } from '../../common/hook' -export function bucketCommand(): Command { +export function command(): Command { const cmd = program.command('storage').hook('preAction', () => { checkApplication() }) diff --git a/cli/src/command/website/index.ts b/cli/src/command/website/index.ts new file mode 100644 index 0000000000..9f7e12b83f --- /dev/null +++ b/cli/src/command/website/index.ts @@ -0,0 +1,41 @@ +import { Command, program } from 'commander' +import { create, custom, del, list } from '../../action/website' +import { checkApplication } from '../../common/hook' + + +export function command(): Command { + const cmd = program.command('website').hook('preAction', () => { + checkApplication() + }) + + cmd + .command('list') + .description('website list') + .action(() => { + list() + }) + + cmd + .command('create ') + .description('create a website') + .action((bucketName, options) => { + create(bucketName, options) + }) + + + cmd + .command('del ') + .description('del website') + .action((bucketName, options) => { + del(bucketName, options) + }) + + cmd + .command('custom ') + .description('custom website domain') + .action((bucketName, domain, options) => { + custom(bucketName, domain, options) + }) + + return cmd +} \ No newline at end of file diff --git a/cli/src/main.ts b/cli/src/main.ts index 76e95b9853..ce7ff5448c 100644 --- a/cli/src/main.ts +++ b/cli/src/main.ts @@ -4,10 +4,10 @@ import { Command } from 'commander' import { command as applicationCommand } from './command/application/' import { command as functionCommand } from './command/function/' import { command as dependencyCommand } from './command/dependency/' - import { loginCommand, logoutCommand } from './command/auth' -import { bucketCommand } from './command/storage' -import { policyCommand } from './command/policy' +import { command as storageCommand } from './command/storage' +import { command as policyCommand } from './command/policy' +import { command as websiteCommand } from './command/website' const program = new Command() program.option('-v, --version', 'output version').action((options) => { @@ -23,8 +23,9 @@ program.addCommand(loginCommand()) program.addCommand(logoutCommand()) program.addCommand(applicationCommand()) program.addCommand(functionCommand()) -program.addCommand(bucketCommand()) +program.addCommand(storageCommand()) program.addCommand(dependencyCommand()) program.addCommand(policyCommand()) +program.addCommand(websiteCommand()) program.parse(process.argv) diff --git a/cli/src/util/request.ts b/cli/src/util/request.ts index d8fe400bf0..efe79be950 100644 --- a/cli/src/util/request.ts +++ b/cli/src/util/request.ts @@ -71,7 +71,10 @@ request.interceptors.response.use( } else if (statusCode == 403) { console.log('Forbidden resource!') process.exit(1) - } else if (statusCode === 503) { + } else if (statusCode === 500) { + console.log('Internal server error!') + process.exit(1) + }else if (statusCode === 503) { console.log('The server is abnormal, please contact the administrator!') process.exit(1) }