@tak-ps/node-cot 5.3.1 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/types.ts CHANGED
@@ -1,177 +1,178 @@
1
- export interface EventAttributes {
2
- version: string,
3
- uid: string;
4
- type: string;
5
- how: string;
6
- [k: string]: string;
7
- }
8
-
9
- export interface GenericAttributes {
10
- _attributes: {
11
- [k: string]: string;
12
- }
13
- }
14
-
15
- export interface Track {
16
- _attributes: TrackAttributes;
17
- }
18
-
19
- export interface Chat {
20
- _attributes: {
21
- parent?: string;
22
- groupOwner?: string;
23
- messageId?: string;
24
- chatroom: string;
25
- id: string;
26
- senderCallsign: string;
27
- [k: string]: string | undefined;
28
- }
29
-
30
- chatgrp: GenericAttributes
31
- }
32
-
33
- export interface TrackAttributes {
34
- speed?: string,
35
- course?: string,
36
- slope?: string;
37
- eCourse?: string;
38
- eSpeed?: string;
39
- eSlope?: string
40
- [k: string]: string | undefined
41
- }
42
-
43
- export interface TakVersion {
44
- _attributes: {
45
- device?: string;
46
- platform?: string;
47
- os?: string;
48
- version?: string;
49
- [k: string]: string | undefined
50
- }
51
- }
52
-
53
- export interface FlowTags {
54
- _attributes?: {
55
- [k: string]: string
56
- }
57
- [k: string]: string | undefined | object;
58
- }
59
-
60
- export interface Group {
61
- _attributes?: {
62
- name: string;
63
- role: string;
64
- [k: string]: string;
65
- }
66
- }
67
-
68
- export interface Status {
69
- _attributes: {
70
- battery: string;
71
- [k: string]: string;
72
- }
73
- }
74
-
75
- export interface Uid {
76
- _attributes: {
77
- Droid: string;
78
- [k: string]: string;
79
- }
80
- }
81
-
82
- export interface Contact {
83
- _attributes: {
84
- phone?: string;
85
- callsign: string;
86
- endpoint?: string;
87
- [k: string]: string | undefined;
88
- }
89
- }
90
-
91
- export interface Marti {
92
- _attributes?: {
93
- [k: string]: string | undefined;
94
- }
95
-
96
- dest?: MartiDest | MartiDest[]
97
- }
98
-
99
- export interface MartiDest {
100
- _attributes: {
101
- uid?: string;
102
- mission?: string;
103
- callsign?: string;
104
- }
105
- }
106
-
107
- export interface Remarks {
108
- _attributes?: {
109
- source?: string;
110
- to?: string;
111
- time?: string;
112
- [k: string]: string | undefined;
113
- }
114
- _text?: string;
115
- }
116
-
117
- export interface PrecisionLocation {
118
- _attributes: {
119
- geopointsrc?: string;
120
- altsrc?: string;
121
- [k: string]: string | undefined;
122
- }
123
- }
124
-
125
- export interface UserIcon {
126
- _attributes: {
127
- iconsetpath: string;
128
- [k: string]: string;
129
- }
130
- }
131
-
132
- export interface Detail {
133
- contact?: Contact;
134
- tog?: GenericAttributes;
135
- '__group'?: Group;
136
- '__chat'?: Chat;
137
- '_flow-tags_'?: FlowTags;
138
- uid?: Uid;
139
- status?: Status;
140
- remarks?: Remarks;
141
- precisionlocation?: PrecisionLocation;
142
- strokeColor?: GenericAttributes;
143
- strokeWeight?: GenericAttributes;
144
- strokeStyle?: GenericAttributes;
145
- labels_on?: GenericAttributes;
146
- fillColor?: GenericAttributes;
147
- link?: GenericAttributes | GenericAttributes[];
148
- usericon?: UserIcon;
149
- track?: Track;
150
- takv?: TakVersion;
151
- marti?: Marti;
152
- TakControl?: {
153
- TakServerVersionInfo?: GenericAttributes
154
- };
155
- [k: string]: unknown;
156
- }
157
-
158
- export interface Point {
159
- _attributes: {
160
- lat: string | number;
161
- lon: string | number;
162
- hae: string | number;
163
- ce: string | number;
164
- le: string | number;
165
- [k: string]: string | number
166
- }
167
- }
168
-
169
- export default interface JSONCoT {
170
- event: {
1
+ import { Type } from '@sinclair/typebox';
2
+
3
+ export const EventAttributes = Type.Object({
4
+ version: Type.String(),
5
+ uid: Type.String(),
6
+ type: Type.String(),
7
+ how: Type.String(),
8
+
9
+ time: Type.String(),
10
+ stale: Type.String(),
11
+ start: Type.String(),
12
+ });
13
+
14
+ export const TogAttributes = Type.Object({
15
+ _attributes: Type.Optional(Type.Object({
16
+ enabled: Type.Optional(Type.String())
17
+ }))
18
+ })
19
+
20
+ export const LinkAttributes = Type.Object({
21
+ _attributes: Type.Object({
22
+ point: Type.Optional(Type.String()),
23
+
24
+ uid: Type.Optional(Type.String()),
25
+ type: Type.Optional(Type.String()),
26
+ relation: Type.Optional(Type.String()),
27
+ })
28
+ })
29
+
30
+ export const GenericAttributes = Type.Object({
31
+ _attributes: Type.Optional(Type.Object({
32
+ value: Type.Optional(Type.String())
33
+ }))
34
+ })
35
+
36
+ export const TrackAttributes = Type.Object({
37
+ speed: Type.Optional(Type.String()),
38
+ course: Type.Optional(Type.String()),
39
+ slope: Type.Optional(Type.String()),
40
+ eCourse: Type.Optional(Type.String()),
41
+ eSpeed: Type.Optional(Type.String()),
42
+ eSlope: Type.Optional(Type.String())
43
+ });
44
+
45
+
46
+ export const Track = Type.Object({
47
+ _attributes: TrackAttributes
48
+ })
49
+
50
+ export const Chat = Type.Object({
51
+ _attributes: Type.Object({
52
+ parent: Type.Optional(Type.String()),
53
+ groupOwner: Type.Optional(Type.String()),
54
+ messageId: Type.Optional(Type.String()),
55
+ chatroom: Type.String(),
56
+ id: Type.String(),
57
+ senderCallsign: Type.String()
58
+ }),
59
+ chatgrp: Type.Any()
60
+ })
61
+
62
+ export const TakVersion = Type.Object({
63
+ _attributes: Type.Object({
64
+ device: Type.Optional(Type.String()),
65
+ platform: Type.Optional(Type.String()),
66
+ os: Type.Optional(Type.String()),
67
+ version: Type.Optional(Type.String())
68
+ })
69
+ })
70
+
71
+ export const FlowTags = Type.Any();
72
+
73
+ export const Group = Type.Object({
74
+ _attributes: Type.Optional(Type.Object({
75
+ name: Type.String(),
76
+ role: Type.String()
77
+ }))
78
+ })
79
+
80
+ export const Status = Type.Object({
81
+ _attributes: Type.Object({
82
+ battery: Type.Optional(Type.String()),
83
+ readiness: Type.Optional(Type.String())
84
+ })
85
+ })
86
+
87
+ export const Uid = Type.Object({
88
+ _attributes: Type.Object({
89
+ Droid: Type.String()
90
+ })
91
+ })
92
+
93
+ export const Contact = Type.Object({
94
+ _attributes: Type.Object({
95
+ phone: Type.Optional(Type.String()),
96
+ callsign: Type.String(),
97
+ endpoint: Type.Optional(Type.String())
98
+ })
99
+ })
100
+
101
+ export const MartiDest = Type.Object({
102
+ _attributes: Type.Object({
103
+ uid: Type.Optional(Type.String()),
104
+ mission: Type.Optional(Type.String()),
105
+ callsign: Type.Optional(Type.String())
106
+ })
107
+ })
108
+
109
+ export const Marti = Type.Object({
110
+ _attributes: Type.Optional(Type.Object({})),
111
+ dest: Type.Optional(Type.Union([MartiDest, Type.Array(MartiDest)]))
112
+ });
113
+
114
+ export const Remarks = Type.Object({
115
+ _attributes: Type.Optional(Type.Object({
116
+ source: Type.Optional(Type.String()),
117
+ to: Type.Optional(Type.String()),
118
+ time: Type.Optional(Type.String())
119
+ })),
120
+ _text: Type.Optional(Type.String())
121
+ })
122
+
123
+ export const PrecisionLocation = Type.Object({
124
+ _attributes: Type.Object({
125
+ geopointsrc: Type.Optional(Type.String()),
126
+ altsrc: Type.Optional(Type.String())
127
+ })
128
+ })
129
+
130
+ export const UserIcon = Type.Object({
131
+ _attributes: Type.Object({
132
+ iconsetpath: Type.String()
133
+ })
134
+ })
135
+
136
+ export const Detail = Type.Object({
137
+ contact: Type.Optional(Contact),
138
+ tog: Type.Optional(TogAttributes),
139
+ '__group': Type.Optional(Group),
140
+ '__chat': Type.Optional(Chat),
141
+ '_flow-tags_': Type.Optional(FlowTags),
142
+ uid: Type.Optional(Uid),
143
+ status: Type.Optional(Status),
144
+ remarks: Type.Optional(Remarks),
145
+ precisionlocation: Type.Optional(PrecisionLocation),
146
+ strokeColor: Type.Optional(GenericAttributes),
147
+ archived: Type.Optional(GenericAttributes),
148
+ strokeWeight: Type.Optional(GenericAttributes),
149
+ strokeStyle: Type.Optional(GenericAttributes),
150
+ labels_on: Type.Optional(GenericAttributes),
151
+ fillColor: Type.Optional(GenericAttributes),
152
+ link: Type.Optional(Type.Union([LinkAttributes, Type.Array(LinkAttributes)])),
153
+ usericon: Type.Optional(UserIcon),
154
+ track: Type.Optional(Track),
155
+ takv: Type.Optional(TakVersion),
156
+ marti: Type.Optional(Marti),
157
+ TakControl: Type.Optional(Type.Object({
158
+ TakServerVersionInfo: Type.Optional(GenericAttributes)
159
+ }))
160
+ })
161
+
162
+ export const Point = Type.Object({
163
+ _attributes: Type.Object({
164
+ lat: Type.Union([Type.String(), Type.Number()]),
165
+ lon: Type.Union([Type.String(), Type.Number()]),
166
+ hae: Type.Union([Type.String(), Type.Number()]),
167
+ ce: Type.Union([Type.String(), Type.Number()]),
168
+ le: Type.Union([Type.String(), Type.Number()]),
169
+ })
170
+ })
171
+
172
+ export default Type.Object({
173
+ event: Type.Object({
171
174
  _attributes: EventAttributes,
172
- detail?: Detail,
175
+ detail: Type.Optional(Detail),
173
176
  point: Point,
174
- [k: string]: unknown
175
- },
176
- [k: string]: unknown
177
- }
177
+ }),
178
+ })
package/lib/util.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from 'crypto'
2
- import type {
2
+ import { Static } from '@sinclair/typebox';
3
+ import {
3
4
  EventAttributes,
4
5
  TrackAttributes,
5
6
  Detail,
@@ -26,7 +27,7 @@ export default class Util {
26
27
  time?: Date | string | null,
27
28
  start?: Date | string | null,
28
29
  stale?: Date | string | number | null
29
- ): EventAttributes {
30
+ ): Static<typeof EventAttributes> {
30
31
  if (!type) throw new Error('type param required');
31
32
  if (!how) throw new Error('how param required');
32
33
 
@@ -44,7 +45,7 @@ export default class Util {
44
45
  *
45
46
  * @param [callsign=UNKNOWN] Display Callsign
46
47
  */
47
- static cot_event_detail(callsign = 'UNKNOWN'): Detail {
48
+ static cot_event_detail(callsign = 'UNKNOWN'): Static<typeof Detail> {
48
49
  return {
49
50
  contact: {
50
51
  _attributes: { callsign }
@@ -58,7 +59,7 @@ export default class Util {
58
59
  * @param [course] Speed in degrees from north
59
60
  * @param [speed=0] Speed in m/s
60
61
  */
61
- static cot_track_attr(course: number, speed = 0): TrackAttributes {
62
+ static cot_track_attr(course: number, speed = 0): Static<typeof TrackAttributes> {
62
63
  return {
63
64
  course: String(course || 0),
64
65
  speed: String(speed || 0)
@@ -82,7 +83,7 @@ export default class Util {
82
83
  /**
83
84
  * Generate Null Island CoT point object
84
85
  */
85
- static cot_point(): Point {
86
+ static cot_point(): Static<typeof Point> {
86
87
  return {
87
88
  '_attributes': {
88
89
  'lat': '0.000000',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tak-ps/node-cot",
3
3
  "type": "module",
4
- "version": "5.3.1",
4
+ "version": "5.5.0",
5
5
  "description": "Lightweight JavaScript library for parsing and manipulating TAK messages",
6
6
  "author": "Nick Ingalls <nick@ingalls.ca>",
7
7
  "main": "dist/index.js",
@@ -10,10 +10,11 @@
10
10
  "test": "ts-node-test test/",
11
11
  "lint": "eslint *.ts lib/*.ts",
12
12
  "doc": "typedoc index.ts",
13
- "build": "typescript-json-schema --required --out ./lib/schema.json ./lib/types.ts JSONCoT && tsc --build && cp package.json dist/",
13
+ "build": "tsc --build && cp package.json dist/",
14
14
  "pretest": "npm run lint"
15
15
  },
16
16
  "dependencies": {
17
+ "@sinclair/typebox": "^0.32.20",
17
18
  "@turf/helpers": "^6.5.0",
18
19
  "@turf/point-on-feature": "^6.5.0",
19
20
  "@types/color": "^3.0.3",
@@ -34,8 +35,7 @@
34
35
  "ts-node": "^10.9.1",
35
36
  "ts-node-test": "^0.4.0",
36
37
  "typedoc": "^0.25.0",
37
- "typescript": "^5.0.0",
38
- "typescript-json-schema": "^0.62.0"
38
+ "typescript": "^5.0.0"
39
39
  },
40
40
  "repository": {
41
41
  "type": "git",
package/test/chat.test.ts CHANGED
@@ -25,10 +25,12 @@ test('DirectChat - Basic', (t) => {
25
25
  t.ok(cot.raw.event.detail['_flow-tags_']);
26
26
  delete cot.raw.event.detail['_flow-tags_'];
27
27
 
28
- for (const i of ['time', 'start', 'stale']) {
29
- t.equals(typeof cot.raw.event._attributes[i], 'string');
30
- delete cot.raw.event._attributes[i];
31
- }
28
+ t.equals(typeof cot.raw.event._attributes.time, 'string');
29
+ cot.raw.event._attributes.time = '2024-04-01'
30
+ t.equals(typeof cot.raw.event._attributes.start, 'string');
31
+ cot.raw.event._attributes.start = '2024-04-01'
32
+ t.equals(typeof cot.raw.event._attributes.stale, 'string');
33
+ cot.raw.event._attributes.stale = '2024-04-01'
32
34
 
33
35
  if (!cot.raw.event.detail.__chat) {
34
36
  t.fail('No Detail Section')
@@ -51,6 +53,10 @@ test('DirectChat - Basic', (t) => {
51
53
  version: '2.0',
52
54
  type: 'b-t-f',
53
55
  how: 'h-g-i-g-o',
56
+
57
+ time: '2024-04-01',
58
+ stale: '2024-04-01',
59
+ start: '2024-04-01'
54
60
  },
55
61
  point: {
56
62
  _attributes: { lat: '0.000000', lon: '0.000000', hae: '0.0', ce: '9999999.0', le: '9999999.0' }
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "123",
3
+ "type": "Feature",
4
+ "properties": {
5
+ "type": "a-f-G",
6
+ "how": "m-g",
7
+ "callsign": "BasicTest",
8
+ "center": [ 1.1, 2.2, 0 ],
9
+ "archived": true,
10
+ "time": "2023-08-04T15:17:43.649Z",
11
+ "start": "2023-08-04T15:17:43.649Z",
12
+ "stale": "2023-08-04T15:17:43.649Z"
13
+ },
14
+ "geometry": {
15
+ "type": "Point",
16
+ "coordinates": [1.1, 2.2, 0]
17
+ }
18
+ }