@tak-ps/node-tak
Version:
Lightweight JavaScript library for communicating with TAK Server
247 lines • 8.72 kB
JavaScript
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) {
// TODO: This is an issue due to: https://issues.tak.gov/browse/TKS-1023
if (this.#isGUID(name))
name = (await this.api.Mission.getGuid(name, {}, opts)).name;
//const url = new URL(`/Marti/api/missions/guid/${this.#encodeName(name)}/layers`, this.api.url);
const url = new URL(`/Marti/api/missions/${this.#encodeName(name)}/layers`, this.api.url);
const 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