diff --git a/lib/commands/app/create.ts b/lib/commands/app/create.ts index aed57b6a..ef1ec7f8 100644 --- a/lib/commands/app/create.ts +++ b/lib/commands/app/create.ts @@ -18,19 +18,9 @@ import { flags } from '@oclif/command'; import Command from '../../command'; -import { ExpectedError } from '../../errors'; import * as cf from '../../utils/common-flags'; -import { getBalenaSdk, stripIndent } from '../../utils/lazy'; - -interface FlagsDef { - organization?: string; - type?: string; // application device type - help: void; -} - -interface ArgsDef { - name: string; -} +import { stripIndent } from '../../utils/lazy'; +import { ArgsDef, FlagsDef } from '../../utils/application-create'; export default class AppCreateCmd extends Command { public static description = stripIndent` @@ -90,61 +80,8 @@ export default class AppCreateCmd extends Command { AppCreateCmd, ); - // Ascertain device type - const deviceType = - options.type || - (await (await import('../../utils/patterns')).selectDeviceType()); - - // Ascertain organization - const organization = - options.organization?.toLowerCase() || (await this.getOrganization()); - - // Create application - try { - const application = await getBalenaSdk().models.application.create({ - name: params.name, - deviceType, - organization, - applicationClass: 'app', - }); - - // Output - console.log( - `App created: slug "${application.slug}", device type "${deviceType}"`, - ); - } catch (err) { - if ((err.message || '').toLowerCase().includes('unique')) { - // BalenaRequestError: Request error: "organization" and "app_name" must be unique. - throw new ExpectedError( - `Error: An app or block or fleet with the name "${params.name}" already exists in organization "${organization}".`, - ); - } else if ((err.message || '').toLowerCase().includes('unauthorized')) { - // BalenaRequestError: Request error: Unauthorized - throw new ExpectedError( - `Error: You are not authorized to create apps in organization "${organization}".`, - ); - } - - throw err; - } - } - - async getOrganization() { - const { getOwnOrganizations } = await import('../../utils/sdk'); - const organizations = await getOwnOrganizations(getBalenaSdk(), { - $select: ['name', 'handle'], - }); - - if (organizations.length === 0) { - // User is not a member of any organizations (should not happen). - throw new Error('This account is not a member of any organizations'); - } else if (organizations.length === 1) { - // User is a member of only one organization - use this. - return organizations[0].handle; - } else { - // User is a member of multiple organizations - - const { selectOrganization } = await import('../../utils/patterns'); - return selectOrganization(organizations); - } + await ( + await import('../../utils/application-create') + ).applicationCreateBase('app', options, params); } } diff --git a/lib/commands/block/create.ts b/lib/commands/block/create.ts index 9303d064..d85bfc92 100644 --- a/lib/commands/block/create.ts +++ b/lib/commands/block/create.ts @@ -18,9 +18,8 @@ import { flags } from '@oclif/command'; import Command from '../../command'; -import { ExpectedError } from '../../errors'; import * as cf from '../../utils/common-flags'; -import { getBalenaSdk, stripIndent } from '../../utils/lazy'; +import { stripIndent } from '../../utils/lazy'; interface FlagsDef { organization?: string; @@ -90,61 +89,8 @@ export default class BlockCreateCmd extends Command { BlockCreateCmd, ); - // Ascertain device type - const deviceType = - options.type || - (await (await import('../../utils/patterns')).selectDeviceType()); - - // Ascertain organization - const organization = - options.organization?.toLowerCase() || (await this.getOrganization()); - - // Create application - try { - const application = await getBalenaSdk().models.application.create({ - name: params.name, - deviceType, - organization, - applicationClass: 'block', - }); - - // Output - console.log( - `Block created: slug "${application.slug}", device type "${deviceType}"`, - ); - } catch (err) { - if ((err.message || '').toLowerCase().includes('unique')) { - // BalenaRequestError: Request error: "organization" and "app_name" must be unique. - throw new ExpectedError( - `Error: An app or block or fleet with the name "${params.name}" already exists in organization "${organization}".`, - ); - } else if ((err.message || '').toLowerCase().includes('unauthorized')) { - // BalenaRequestError: Request error: Unauthorized - throw new ExpectedError( - `Error: You are not authorized to create blocks in organization "${organization}".`, - ); - } - - throw err; - } - } - - async getOrganization() { - const { getOwnOrganizations } = await import('../../utils/sdk'); - const organizations = await getOwnOrganizations(getBalenaSdk(), { - $select: ['name', 'handle'], - }); - - if (organizations.length === 0) { - // User is not a member of any organizations (should not happen). - throw new Error('This account is not a member of any organizations'); - } else if (organizations.length === 1) { - // User is a member of only one organization - use this. - return organizations[0].handle; - } else { - // User is a member of multiple organizations - - const { selectOrganization } = await import('../../utils/patterns'); - return selectOrganization(organizations); - } + await ( + await import('../../utils/application-create') + ).applicationCreateBase('block', options, params); } } diff --git a/lib/commands/fleet/create.ts b/lib/commands/fleet/create.ts index f99dd74a..dc3ad1bc 100644 --- a/lib/commands/fleet/create.ts +++ b/lib/commands/fleet/create.ts @@ -18,19 +18,9 @@ import { flags } from '@oclif/command'; import Command from '../../command'; -import { ExpectedError } from '../../errors'; import * as cf from '../../utils/common-flags'; -import { getBalenaSdk, stripIndent } from '../../utils/lazy'; - -interface FlagsDef { - organization?: string; - type?: string; // application device type - help: void; -} - -interface ArgsDef { - name: string; -} +import { stripIndent } from '../../utils/lazy'; +import { ArgsDef, FlagsDef } from '../../utils/application-create'; export default class FleetCreateCmd extends Command { public static description = stripIndent` @@ -90,60 +80,8 @@ export default class FleetCreateCmd extends Command { FleetCreateCmd, ); - // Ascertain device type - const deviceType = - options.type || - (await (await import('../../utils/patterns')).selectDeviceType()); - - // Ascertain organization - const organization = - options.organization?.toLowerCase() || (await this.getOrganization()); - - // Create application - try { - const application = await getBalenaSdk().models.application.create({ - name: params.name, - deviceType, - organization, - }); - - // Output - console.log( - `Fleet created: slug "${application.slug}", device type "${deviceType}"`, - ); - } catch (err) { - if ((err.message || '').toLowerCase().includes('unique')) { - // BalenaRequestError: Request error: "organization" and "app_name" must be unique. - throw new ExpectedError( - `Error: An app or block or fleet with the name "${params.name}" already exists in organization "${organization}".`, - ); - } else if ((err.message || '').toLowerCase().includes('unauthorized')) { - // BalenaRequestError: Request error: Unauthorized - throw new ExpectedError( - `Error: You are not authorized to create fleets in organization "${organization}".`, - ); - } - - throw err; - } - } - - async getOrganization() { - const { getOwnOrganizations } = await import('../../utils/sdk'); - const organizations = await getOwnOrganizations(getBalenaSdk(), { - $select: ['name', 'handle'], - }); - - if (organizations.length === 0) { - // User is not a member of any organizations (should not happen). - throw new Error('This account is not a member of any organizations'); - } else if (organizations.length === 1) { - // User is a member of only one organization - use this. - return organizations[0].handle; - } else { - // User is a member of multiple organizations - - const { selectOrganization } = await import('../../utils/patterns'); - return selectOrganization(organizations); - } + await ( + await import('../../utils/application-create') + ).applicationCreateBase('fleet', options, params); } } diff --git a/lib/utils/application-create.ts b/lib/utils/application-create.ts new file mode 100644 index 00000000..8a7e9a48 --- /dev/null +++ b/lib/utils/application-create.ts @@ -0,0 +1,58 @@ +import { ExpectedError } from '../errors'; +import { getBalenaSdk } from './lazy'; + +export interface FlagsDef { + organization?: string; + type?: string; // application device type + help: void; +} + +export interface ArgsDef { + name: string; +} + +export async function applicationCreateBase( + resource: 'fleet' | 'app' | 'block', + options: FlagsDef, + params: ArgsDef, +) { + // Ascertain device type + const deviceType = + options.type || (await (await import('./patterns')).selectDeviceType()); + + // Ascertain organization + const organization = + options.organization?.toLowerCase() || + (await (await import('./patterns')).getAndSelectOrganization()); + + // Create application + try { + const application = await getBalenaSdk().models.application.create({ + name: params.name, + deviceType, + organization, + }); + + // Output + const { capitalize } = await import('lodash'); + console.log( + `${capitalize(resource)} created: slug "${ + application.slug + }", device type "${deviceType}"`, + ); + } catch (err) { + if ((err.message || '').toLowerCase().includes('unique')) { + // BalenaRequestError: Request error: "organization" and "app_name" must be unique. + throw new ExpectedError( + `Error: An app or block or fleet with the name "${params.name}" already exists in organization "${organization}".`, + ); + } else if ((err.message || '').toLowerCase().includes('unauthorized')) { + // BalenaRequestError: Request error: Unauthorized + throw new ExpectedError( + `Error: You are not authorized to create ${resource}s in organization "${organization}".`, + ); + } + + throw err; + } +} diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index 2d94d92d..07299390 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -228,6 +228,24 @@ export async function selectOrganization( }); } +export async function getAndSelectOrganization() { + const { getOwnOrganizations } = await import('./sdk'); + const organizations = await getOwnOrganizations(getBalenaSdk(), { + $select: ['name', 'handle'], + }); + + if (organizations.length === 0) { + // User is not a member of any organizations (should not happen). + throw new Error('This account is not a member of any organizations'); + } else if (organizations.length === 1) { + // User is a member of only one organization - use this. + return organizations[0].handle; + } else { + // User is a member of multiple organizations - + return selectOrganization(organizations); + } +} + export async function awaitDeviceOsUpdate( uuid: string, targetOsVersion: string,