UNPKG

@tak-ps/node-tak

Version:

Lightweight JavaScript library for communicating with TAK Server

253 lines 8.78 kB
import { TAKList, TAKItem } from './types.js'; import { Type } from '@sinclair/typebox'; import { GUIDMatch } from './mission.js'; import Err from '@openaddresses/batch-error'; import Commands, { CommandOutputFormat } from '../commands.js'; export var MissionLayerType; (function (MissionLayerType) { MissionLayerType["GROUP"] = "GROUP"; MissionLayerType["UID"] = "UID"; MissionLayerType["CONTENTS"] = "CONTENTS"; MissionLayerType["MAPLAYER"] = "MAPLAYER"; MissionLayerType["ITEM"] = "ITEM"; })(MissionLayerType || (MissionLayerType = {})); export const MissionLayer = Type.Object({ name: Type.String({ minLength: 1 }), type: Type.Enum(MissionLayerType), parentUid: Type.Optional(Type.String()), uid: Type.String(), mission_layers: Type.Optional(Type.Array(Type.Any())), uids: Type.Optional(Type.Array(Type.Object({ data: Type.String({ description: 'The UID of the COT' }), timestamp: Type.String(), creatorUid: Type.String(), keywords: Type.Optional(Type.Array(Type.String())), details: Type.Optional(Type.Object({ type: Type.String(), callsign: Type.String(), color: Type.Optional(Type.String()), location: Type.Object({ lat: Type.Number(), lon: Type.Number() }) })) }))), contents: Type.Optional(Type.Array(Type.Any())), maplayers: Type.Optional(Type.Array(Type.Any())) }); export const DeleteInput = Type.Object({ uid: Type.Array(Type.String()), creatorUid: Type.String(), }); export const RenameInput = Type.Object({ name: Type.String(), creatorUid: Type.String(), }); export const CreateInput = Type.Object({ name: Type.String(), type: Type.Enum(MissionLayerType), uid: Type.Optional(Type.String()), parentUid: Type.Optional(Type.String()), afterUid: Type.Optional(Type.String()), creatorUid: Type.String() }); export const TAKList_MissionLayer = TAKList(MissionLayer); export const TAKItem_MissionLayer = TAKItem(MissionLayer); export default class MissionLayerCommands extends Commands { schema = { list: { description: 'List Injectors', params: Type.Object({}), query: Type.Object({}), formats: [CommandOutputFormat.JSON] } }; async cli() { throw new Error('Unsupported Subcommand'); } #encodeName(name) { return encodeURIComponent(name.trim()); } #isGUID(id) { return GUIDMatch.test(id); } #headers(opts) { if (opts && opts.token) { return { MissionAuthorization: `Bearer ${opts.token}` }; } else { return {}; } } isEmpty(layer) { if (layer.mission_layers && layer.mission_layers.length) return false; if (layer.uids && layer.uids.length) return false; if (layer.contents && layer.contents.length) return false; if (layer.maplayers && layer.maplayers.length) return false; return true; } async listAsPathMap(name, opts) { const layers = (await this.list(name, opts)).data; const pathMap = new Map(); for (const layer of layers) { this.#listAsPathMapRecurse(pathMap, '', layer); } return pathMap; } #listAsPathMapRecurse(pathMap, pathCurrent, layer) { pathCurrent = `${pathCurrent}/${encodeURIComponent(layer.name)}`; pathMap.set(`${pathCurrent}/`, layer); for (const l of (layer.mission_layers || [])) { this.#listAsPathMapRecurse(pathMap, pathCurrent, l); } } async list(name, opts) { let res; if (this.#isGUID(name)) { const url = new URL(`/Marti/api/missions/guid/${this.#encodeName(name)}/layers`, this.api.url); res = await this.api.fetch(url, { method: 'GET', headers: this.#headers(opts), }); } else { const url = new URL(`/Marti/api/missions/${this.#encodeName(name)}/layers`, this.api.url); res = await this.api.fetch(url, { method: 'GET', headers: this.#headers(opts), }); } res.data.map((l) => { if (l.type === MissionLayerType.UID && !l.uids) { l.uids = []; } return l; }); return res; } /** * Stopgap function until the main latestFeats function can accept a path * parameter */ async latestFeats(name, layerUid, // Layer UID opts) { const layer = (await this.get(name, layerUid, opts)).data; const feats = await this.api.Mission.latestFeats(name, opts); const layerUids = new Set((layer.uids || []).map((u) => { return u.data; })); const filtered = feats.filter((f) => { return layerUids.has(f.id); }); return filtered; } async get(name, layerUid, // Layer UID opts) { const layers = await this.list(name, opts); // TODO this will only return top level layers - need to recurse to lower level layers for (const layer of layers.data) { if (layer.uid === layerUid) { return { version: layers.version, type: layers.type, data: layer, nodeId: layers.nodeId }; } } throw new Err(404, null, `Layer ${layerUid} not found - only top level layers will be returned`); } async create(name, query, opts) { if (this.#isGUID(name)) { const url = new URL(`/Marti/api/missions/guid/${this.#encodeName(name)}/layers`, this.api.url); let q; for (q in query) { if (query[q] !== undefined) { url.searchParams.append(q, String(query[q])); } } return await this.api.fetch(url, { method: 'PUT', headers: this.#headers(opts), }); } else { const url = new URL(`/Marti/api/missions/${this.#encodeName(name)}/layers`, this.api.url); let q; for (q in query) { if (query[q] !== undefined) { url.searchParams.append(q, String(query[q])); } } return await this.api.fetch(url, { method: 'PUT', headers: this.#headers(opts), }); } } async rename(name, layer, query, opts) { if (this.#isGUID(name)) { const url = new URL(`/Marti/api/missions/guid/${this.#encodeName(name)}/layers/${layer}/name`, this.api.url); let q; for (q in query) { if (query[q] !== undefined) { url.searchParams.append(q, String(query[q])); } } return await this.api.fetch(url, { method: 'PUT', headers: this.#headers(opts), }); } else { const url = new URL(`/Marti/api/missions/${this.#encodeName(name)}/layers/${layer}/name`, this.api.url); let q; for (q in query) { if (query[q] !== undefined) { url.searchParams.append(q, String(query[q])); } } return await this.api.fetch(url, { method: 'PUT', headers: this.#headers(opts), }); } } async delete(name, query, opts) { if (this.#isGUID(name)) { const url = new URL(`/Marti/api/missions/guid/${this.#encodeName(name)}/layers`, this.api.url); let q; for (q in query) { if (query[q] !== undefined) { url.searchParams.append(q, String(query[q])); } } return await this.api.fetch(url, { method: 'DELETE', headers: this.#headers(opts), }); } else { const url = new URL(`/Marti/api/missions/${this.#encodeName(name)}/layers`, this.api.url); let q; for (q in query) { if (query[q] !== undefined) { url.searchParams.append(q, String(query[q])); } } return await this.api.fetch(url, { method: 'DELETE', headers: this.#headers(opts), }); } } } //# sourceMappingURL=mission-layer.js.map