Skip to content

Commit

Permalink
feat: add apps:bundles:update command
Browse files Browse the repository at this point in the history
  • Loading branch information
robingenz committed May 27, 2024
1 parent 9c348a9 commit 9dbad37
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 2 deletions.
7 changes: 6 additions & 1 deletion src/commands/apps/bundles/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export default defineCommand({
},
},
run: async (ctx) => {
// Prompt for missing arguments
let appId = ctx.args.appId;
let bundleId = ctx.args.bundleId;
if (!appId) {
const apps = await appsService.findAll();
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
Expand All @@ -29,18 +31,21 @@ export default defineCommand({
options: apps.map((app) => ({ label: app.name, value: app.id })),
});
}
let bundleId = ctx.args.bundleId;
if (!bundleId) {
bundleId = await prompt('Enter the bundle ID:', {
type: 'text',
});
}

// Confirm deletion
const confirmed = await prompt('Are you sure you want to delete this bundle?', {
type: 'confirm',
});
if (!confirmed) {
return;
}

// Delete bundle
try {
await appBundlesService.delete({
appId,
Expand Down
91 changes: 91 additions & 0 deletions src/commands/apps/bundles/update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { defineCommand } from 'citty';
import consola from 'consola';
import { prompt } from '../../../utils/prompt';
import { AxiosError } from 'axios';
import zip from '../../../utils/zip';
import FormData from 'form-data';
import { createReadStream } from 'node:fs';
import authorizationService from '../../../services/authorization-service';
import appsService from '../../../services/apps';
import appBundlesService from '../../../services/app-bundle';

export default defineCommand({
meta: {
description: 'Update an app bundle.',
},
args: {
androidMax: {
type: 'string',
description: 'The maximum Android version code (`versionCode`) that the bundle supports.',
},
androidMin: {
type: 'string',
description: 'The minimum Android version code (`versionCode`) that the bundle supports.',
},
appId: {
type: 'string',
description: 'ID of the app.',
},
bundleId: {
type: 'string',
description: 'ID of the bundle.',
},
rollout: {
type: 'string',
description: 'The percentage of devices to deploy the bundle to. Must be a number between 0 and 1 (e.g. 0.5).',
},
iosMax: {
type: 'string',
description: 'The maximum iOS bundle version (`CFBundleVersion`) that the bundle supports.',
},
iosMin: {
type: 'string',
description: 'The minimum iOS bundle version (`CFBundleVersion`) that the bundle supports.',
},
},
run: async (ctx) => {
if (!authorizationService.hasAuthorizationToken()) {
consola.error('You must be logged in to run this command.');
return;
}

// Prompt for missing arguments
const { androidMax, androidMin, rollout, iosMax, iosMin } = ctx.args;
let appId = ctx.args.appId;
let bundleId = ctx.args.bundleId;
if (!appId) {
const apps = await appsService.findAll();
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
appId = await prompt('Which app do you want to update the bundle for?', {
type: 'select',
options: apps.map((app) => ({ label: app.name, value: app.id })),
});
}
if (!bundleId) {
bundleId = await prompt('Enter the bundle ID:', {
type: 'text',
});
}

// Update bundle
try {
const rolloutAsNumber = parseFloat(rollout);
await appBundlesService.update({
appId,
bundleId,
maxAndroidAppVersionCode: androidMax,
maxIosAppVersionCode: iosMax,
minAndroidAppVersionCode: androidMin,
minIosAppVersionCode: iosMin,
rolloutPercentage: rolloutAsNumber,
});
consola.success('Bundle updated successfully.');
} catch (error) {
if (error instanceof AxiosError && error.response?.status === 401) {
consola.error('Your token is no longer valid. Please sign in again.');
} else {
consola.error('Failed to delete bundle.');
}
}
},
});
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const main = defineCommand({
'apps:delete': import('./commands/apps/delete').then((mod) => mod.default),
'apps:bundles:create': import('./commands/apps/bundles/create').then((mod) => mod.default),
'apps:bundles:delete': import('./commands/apps/bundles/delete').then((mod) => mod.default),
'apps:bundles:update': import('./commands/apps/bundles/update').then((mod) => mod.default),
'apps:channels:create': import('./commands/apps/channels/create').then((mod) => mod.default),
'apps:channels:delete': import('./commands/apps/channels/delete').then((mod) => mod.default),
'apps:devices:delete': import('./commands/apps/devices/delete').then((mod) => mod.default),
Expand Down
15 changes: 14 additions & 1 deletion src/services/app-bundle.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { AppBundleDto, CreateAppBundleDto, DeleteAppBundleDto } from '../types';
import { AppBundleDto, CreateAppBundleDto, DeleteAppBundleDto, UpadteAppBundleDto } from '../types';
import httpClient, { HttpClient } from '../utils/http-client';
import authorizationService from './authorization-service';

export interface AppBundlesService {
create(dto: CreateAppBundleDto): Promise<AppBundleDto>;
delete(dto: DeleteAppBundleDto): Promise<void>;
update(dto: UpadteAppBundleDto): Promise<AppBundleDto>;
}

class AppBundlesServiceImpl implements AppBundlesService {
Expand All @@ -27,6 +28,18 @@ class AppBundlesServiceImpl implements AppBundlesService {
return response.data;
}

async update(data: UpadteAppBundleDto): Promise<AppBundleDto> {
const response = await this.httpClient.patch<AppBundleDto>(`/apps/${data.appId}/bundles/${data.bundleId}`, data, {
headers: {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}

async delete(data: DeleteAppBundleDto): Promise<void> {
const response = await this.httpClient.delete(`/apps/${data.appId}/bundles/${data.bundleId}`, {
headers: {
Expand Down
10 changes: 10 additions & 0 deletions src/types/app-bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,13 @@ export interface DeleteAppBundleDto {
appId: string;
bundleId: string;
}

export interface UpadteAppBundleDto {
appId: string;
bundleId: string;
maxAndroidAppVersionCode?: string;
maxIosAppVersionCode?: string;
minAndroidAppVersionCode?: string;
minIosAppVersionCode?: string;
rolloutPercentage?: number;
}
18 changes: 18 additions & 0 deletions src/utils/http-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type HttpResponse<T> = SuccessHttpResponse<T> | FailureHttpResponse;
export interface HttpClient {
delete<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
get<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
patch<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
post<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
}

Expand Down Expand Up @@ -56,6 +57,23 @@ class HttpClientImpl implements HttpClient {
}
}

async patch<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>> {
try {
const res = await axios.patch<T>(API_URL + url, data, config);
return {
success: true,
status: res.status,
data: res.data,
};
} catch (e: any) {
return {
success: false,
status: e.response.status,
error: e,
};
}
}

async post<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>> {
try {
const res = await axios.post<T>(API_URL + url, data, config);
Expand Down

0 comments on commit 9dbad37

Please sign in to comment.