diff --git a/src/commands/apps/liveupdates/set-native-versions.ts b/src/commands/apps/liveupdates/set-native-versions.ts new file mode 100644 index 0000000..a45ff4d --- /dev/null +++ b/src/commands/apps/liveupdates/set-native-versions.ts @@ -0,0 +1,96 @@ +import appBuildsService from '@/services/app-builds.js'; +import authorizationService from '@/services/authorization-service.js'; +import { isInteractive } from '@/utils/environment.js'; +import { defineCommand, defineOptions } from '@robingenz/zli'; +import consola from 'consola'; +import { z } from 'zod'; + +export default defineCommand({ + description: 'Set native version constraints on a web build.', + options: defineOptions( + z.object({ + appId: z + .string({ + message: 'App ID must be a UUID.', + }) + .uuid({ + message: 'App ID must be a UUID.', + }) + .optional() + .describe('The app ID of the build.'), + buildId: z + .string({ + message: 'Build ID must be a UUID.', + }) + .uuid({ + message: 'Build ID must be a UUID.', + }) + .optional() + .describe('The build ID to update.'), + androidEq: z.coerce + .string() + .optional() + .describe('The exact Android version code (`versionCode`) that the build supports.'), + androidMax: z.coerce + .string() + .optional() + .describe('The maximum Android version code (`versionCode`) that the build supports.'), + androidMin: z.coerce + .string() + .optional() + .describe('The minimum Android version code (`versionCode`) that the build supports.'), + iosEq: z + .string() + .optional() + .describe('The exact iOS bundle version (`CFBundleVersion`) that the build supports.'), + iosMax: z + .string() + .optional() + .describe('The maximum iOS bundle version (`CFBundleVersion`) that the build supports.'), + iosMin: z + .string() + .optional() + .describe('The minimum iOS bundle version (`CFBundleVersion`) that the build supports.'), + }), + ), + action: async (options) => { + const { appId, buildId, androidEq, androidMax, androidMin, iosEq, iosMax, iosMin } = options; + + if (!authorizationService.hasAuthorizationToken()) { + consola.error('You must be logged in to run this command. Please run the `login` command first.'); + process.exit(1); + } + + if (!appId) { + if (!isInteractive()) { + consola.error('You must provide an app ID when running in non-interactive environment.'); + process.exit(1); + } + consola.error('You must provide an app ID with the `--app-id` flag.'); + process.exit(1); + } + + if (!buildId) { + if (!isInteractive()) { + consola.error('You must provide a build ID when running in non-interactive environment.'); + process.exit(1); + } + consola.error('You must provide a build ID with the `--build-id` flag.'); + process.exit(1); + } + + consola.start('Setting native version constraints...'); + await appBuildsService.update({ + appId, + appBuildId: buildId, + eqAndroidAppVersionCode: androidEq, + maxAndroidAppVersionCode: androidMax, + minAndroidAppVersionCode: androidMin, + eqIosAppVersionCode: iosEq, + maxIosAppVersionCode: iosMax, + minIosAppVersionCode: iosMin, + }); + + consola.success('Native version constraints set successfully.'); + }, +}); diff --git a/src/index.ts b/src/index.ts index 9481849..57e46f4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,6 +55,9 @@ const config = defineConfig({ 'apps:liveupdates:rollout': await import('@/commands/apps/liveupdates/rollout.js').then((mod) => mod.default), 'apps:liveupdates:upload': await import('@/commands/apps/liveupdates/upload.js').then((mod) => mod.default), 'apps:liveupdates:register': await import('@/commands/apps/liveupdates/register.js').then((mod) => mod.default), + 'apps:liveupdates:setnativeversions': await import('@/commands/apps/liveupdates/set-native-versions.js').then( + (mod) => mod.default, + ), 'apps:liveupdates:generatemanifest': await import('@/commands/apps/liveupdates/generate-manifest.js').then( (mod) => mod.default, ), diff --git a/src/services/app-builds.ts b/src/services/app-builds.ts index 510531c..12701b3 100644 --- a/src/services/app-builds.ts +++ b/src/services/app-builds.ts @@ -1,5 +1,11 @@ import authorizationService from '@/services/authorization-service.js'; -import { AppBuildDto, CreateAppBuildDto, FindAllAppBuildsDto, FindOneAppBuildDto } from '@/types/app-build.js'; +import { + AppBuildDto, + CreateAppBuildDto, + FindAllAppBuildsDto, + FindOneAppBuildDto, + UpdateAppBuildDto, +} from '@/types/app-build.js'; import httpClient, { HttpClient } from '@/utils/http-client.js'; export interface DownloadArtifactDto { @@ -12,6 +18,7 @@ export interface AppBuildsService { create(dto: CreateAppBuildDto): Promise; findAll(dto: FindAllAppBuildsDto): Promise; findOne(dto: FindOneAppBuildDto): Promise; + update(dto: UpdateAppBuildDto): Promise; downloadArtifact(dto: DownloadArtifactDto): Promise; } @@ -64,6 +71,16 @@ class AppBuildsServiceImpl implements AppBuildsService { return response.data; } + async update(dto: UpdateAppBuildDto): Promise { + const { appId, appBuildId, ...bodyData } = dto; + const response = await this.httpClient.patch(`/v1/apps/${appId}/builds/${appBuildId}`, bodyData, { + headers: { + Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`, + }, + }); + return response.data; + } + async downloadArtifact(dto: DownloadArtifactDto): Promise { const { appId, appBuildId, artifactId } = dto; const response = await this.httpClient.get( diff --git a/src/types/app-build.ts b/src/types/app-build.ts index 0798b84..a78f38c 100644 --- a/src/types/app-build.ts +++ b/src/types/app-build.ts @@ -42,6 +42,17 @@ export interface FindOneAppBuildDto { relations?: string; } +export interface UpdateAppBuildDto { + appId: string; + appBuildId: string; + eqAndroidAppVersionCode?: string; + maxAndroidAppVersionCode?: string; + minAndroidAppVersionCode?: string; + eqIosAppVersionCode?: string; + maxIosAppVersionCode?: string; + minIosAppVersionCode?: string; +} + export interface FindAllAppBuildsDto { appId: string; numberAsString?: string;