UNPKG

@tak-ps/node-tak

Version:

Lightweight JavaScript library for communicating with TAK Server

272 lines (240 loc) 9.15 kB
import { Type, Static } from '@sinclair/typebox'; import { TAKList } from './types.js'; import { GUIDMatch, MissionOptions } from './mission.js'; import Commands, { CommandOutputFormat, type ParsedArgs } from '../commands.js'; export enum MissionSubscriberRole { MISSION_OWNER = 'MISSION_OWNER', MISSION_SUBSCRIBER = 'MISSION_SUBSCRIBER', MISSION_READONLY_SUBSCRIBER = 'MISSION_READONLY_SUBSCRIBER' } export enum MissionInviteType { CLIENT_UID = 'clientUid', CALLSIGN = 'callsign', USERNAME = 'userName', GROUP = 'group', TEAM = 'team' } export const MissionRole = Type.Object({ name: Type.Optional(Type.String()), description: Type.Optional(Type.String()), permissions: Type.Optional(Type.Array(Type.String())) }); export const MissionInvite = Type.Object({ missionName: Type.Optional(Type.String()), invitee: Type.Optional(Type.String()), type: Type.Optional(Type.String()), creatorUid: Type.Optional(Type.String()), createTime: Type.Optional(Type.String()), token: Type.Optional(Type.String()), role: Type.Optional(MissionRole), missionGuid: Type.Optional(Type.String()) }); export const MissionInviteList = TAKList(MissionInvite); /** * @class */ export default class MissionInviteCommands extends Commands { schema = { list: { description: 'List Mission Invites', params: Type.Object({}), query: Type.Object({}), formats: [ CommandOutputFormat.JSON ] }, get: { description: 'Get Mission Invites for a Mission', params: Type.Object({ name: Type.String() }), query: Type.Object({}), formats: [ CommandOutputFormat.JSON ] }, invite: { description: 'Invite a user/group to a mission', params: Type.Object({ name: Type.String(), type: Type.Enum(MissionInviteType), invitee: Type.String() }), query: Type.Object({ creatorUid: Type.String(), role: Type.Optional(Type.Enum(MissionSubscriberRole)) }), formats: [ CommandOutputFormat.JSON ] }, uninvite: { description: 'Uninvite a user/group from a mission', params: Type.Object({ name: Type.String(), type: Type.Enum(MissionInviteType), invitee: Type.String() }), query: Type.Object({ creatorUid: Type.String() }), formats: [ CommandOutputFormat.JSON ] } } async cli(args: ParsedArgs): Promise<object | string> { const clientUid = typeof args.clientUid === 'string' ? args.clientUid : undefined; const token = typeof args.token === 'string' ? args.token : undefined; const creatorUid = typeof args.creatorUid === 'string' ? args.creatorUid : undefined; const role = typeof args.role === 'string' ? (args.role as MissionSubscriberRole) : undefined; if (args._[3] === 'list') { if (!clientUid) throw new Error('Usage: list --clientUid <clientUid>'); const list = await this.list(clientUid, { token }); if (args.format === 'json') { return list; } else { return list.data.map((invite) => { return `${invite.missionName}: ${invite.invitee} (${invite.role?.name || 'Unknown Role'})`; }).join('\n'); } } else if (args._[3] === 'get') { const name = args._[4]; if (!name) throw new Error('Usage: get <name>'); const list = await this.get(name, { token }); if (args.format === 'json') { return list; } else { return list.data.map((invite) => { return JSON.stringify(invite); }).join('\n'); } } else if (args._[3] === 'invite') { const name = args._[4]; const type = args._[5] as MissionInviteType; const invitee = args._[6]; if (!name || !type || !invitee) throw new Error('Usage: invite <name> <type> <invitee>'); if (!creatorUid) throw new Error('Usage: invite requires --creatorUid <uid>'); await this.invite(name, type, invitee, { creatorUid, role }, { token }); return { message: 'OK' }; } else if (args._[3] === 'uninvite') { const name = args._[4]; const type = args._[5] as MissionInviteType; const invitee = args._[6]; if (!name || !type || !invitee) throw new Error('Usage: uninvite <name> <type> <invitee>'); if (!creatorUid) throw new Error('Usage: uninvite requires --creatorUid <uid>'); await this.uninvite(name, type, invitee, { creatorUid }, { token }); return { message: 'OK' }; } else { throw new Error('Unsupported Subcommand'); } } #headers(opts?: Static<typeof MissionOptions>): object { if (opts && opts.token) { return { MissionAuthorization: `Bearer ${opts.token}` } } else { return {}; } } /** * List all Invitations for missions * * {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/getAllMissionInvitations TAK Server Docs}. */ async list( clientUid: string, opts?: Static<typeof MissionOptions> ): Promise<Static<typeof MissionInviteList>> { const url = new URL('/Marti/api/missions/invitations', this.api.url); url.searchParams.append('clientUid', clientUid); const invites = await this.api.fetch(url, { method: 'GET', headers: this.#headers(opts) }); return invites; } /** * Get Mission Invitations * * {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/getMissionInvitations TAK Server Docs}. */ async get( missionName: string, opts?: Static<typeof MissionOptions> ): Promise<Static<typeof MissionInviteList>> { let url; if (GUIDMatch.test(missionName)) { url = new URL(`/Marti/api/missions/guid/${encodeURIComponent(missionName)}/invitations`, this.api.url); } else { url = new URL(`/Marti/api/missions/${encodeURIComponent(missionName)}/invitations`, this.api.url); } return await this.api.fetch(url, { method: 'GET', headers: this.#headers(opts) }); } /** * Invite a user/group to a mission * * {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/inviteToMission TAK Server Docs}. */ async invite( missionName: string, type: MissionInviteType, invitee: string, query: { creatorUid: string; role?: MissionSubscriberRole; }, opts?: Static<typeof MissionOptions> ): Promise<void> { let url; if (GUIDMatch.test(missionName)) { url = new URL(`/Marti/api/missions/guid/${encodeURIComponent(missionName)}/invite/${encodeURIComponent(type)}/${encodeURIComponent(invitee)}`, this.api.url); } else { url = new URL(`/Marti/api/missions/${encodeURIComponent(missionName)}/invite/${encodeURIComponent(type)}/${encodeURIComponent(invitee)}`, this.api.url); } for (const q in query) url.searchParams.append(q, String(query[q as keyof typeof query])); await this.api.fetch(url, { method: 'PUT', headers: this.#headers(opts) }); } /** * Uninvite a user/group from a mission * * {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/uninviteFromMission TAK Server Docs}. */ async uninvite( missionName: string, type: MissionInviteType, invitee: string, query: { creatorUid: string; }, opts?: Static<typeof MissionOptions> ): Promise<void> { let url; if (GUIDMatch.test(missionName)) { url = new URL(`/Marti/api/missions/guid/${encodeURIComponent(missionName)}/invite/${encodeURIComponent(type)}/${encodeURIComponent(invitee)}`, this.api.url); } else { url = new URL(`/Marti/api/missions/${encodeURIComponent(missionName)}/invite/${encodeURIComponent(type)}/${encodeURIComponent(invitee)}`, this.api.url); } for (const q in query) url.searchParams.append(q, String(query[q as keyof typeof query])); await this.api.fetch(url, { method: 'DELETE', headers: this.#headers(opts) }); } }