@tak-ps/node-tak 12.8.0 → 12.10.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/CHANGELOG.md +8 -0
- package/dist/lib/auth.js +12 -0
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/multipart.d.ts +8 -0
- package/dist/lib/multipart.js +61 -0
- package/dist/lib/multipart.js.map +1 -0
- package/dist/test/default.test.js +5 -5
- package/dist/test/default.test.js.map +1 -1
- package/dist/test/findCoT.test.js +16 -22
- package/dist/test/findCoT.test.js.map +1 -1
- package/dist/test/pipeline.test.js +56 -70
- package/dist/test/pipeline.test.js.map +1 -1
- package/dist/test/queue.test.js +22 -25
- package/dist/test/queue.test.js.map +1 -1
- package/dist/test/uploadPackage.test.d.ts +1 -0
- package/dist/test/uploadPackage.test.js +51 -0
- package/dist/test/uploadPackage.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/auth.ts +13 -0
- package/lib/multipart.ts +99 -0
- package/package.json +1 -3
- package/test/default.test.ts +5 -5
- package/test/findCoT.test.ts +16 -22
- package/test/pipeline.test.ts +56 -71
- package/test/queue.test.ts +22 -25
- package/test/uploadPackage.test.ts +62 -0
package/dist/test/queue.test.js
CHANGED
|
@@ -1,46 +1,43 @@
|
|
|
1
|
-
import test from '
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
2
3
|
import { Queue } from '../lib/utils/queue.js';
|
|
3
|
-
test('Queue - push/pop FIFO order', (
|
|
4
|
+
test('Queue - push/pop FIFO order', () => {
|
|
4
5
|
const q = new Queue(4);
|
|
5
6
|
q.push(1);
|
|
6
7
|
q.push(2);
|
|
7
8
|
q.push(3);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
t.end();
|
|
9
|
+
assert.equal(q.pop(), 1);
|
|
10
|
+
assert.equal(q.pop(), 2);
|
|
11
|
+
assert.equal(q.pop(), 3);
|
|
12
12
|
});
|
|
13
|
-
test('Queue - capacity enforced', (
|
|
13
|
+
test('Queue - capacity enforced', () => {
|
|
14
14
|
const q = new Queue(2);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
t.end();
|
|
15
|
+
assert.equal(q.push(1), true);
|
|
16
|
+
assert.equal(q.push(2), true);
|
|
17
|
+
assert.equal(q.isFull, true);
|
|
18
|
+
assert.equal(q.push(3), false);
|
|
19
|
+
assert.equal(q.length, 2);
|
|
21
20
|
});
|
|
22
|
-
test('Queue - pop from empty', (
|
|
21
|
+
test('Queue - pop from empty', () => {
|
|
23
22
|
const q = new Queue(2);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
t.end();
|
|
23
|
+
assert.equal(q.pop(), undefined);
|
|
24
|
+
assert.equal(q.length, 0);
|
|
27
25
|
});
|
|
28
|
-
test('Queue - ring buffer wraparound', (
|
|
26
|
+
test('Queue - ring buffer wraparound', () => {
|
|
29
27
|
const q = new Queue(3);
|
|
30
28
|
q.push(1);
|
|
31
29
|
q.push(2);
|
|
32
30
|
q.push(3);
|
|
33
31
|
// Pop two — head advances past midpoint
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
assert.equal(q.pop(), 1);
|
|
33
|
+
assert.equal(q.pop(), 2);
|
|
36
34
|
// Push two more — tail wraps around
|
|
37
35
|
q.push(4);
|
|
38
36
|
q.push(5);
|
|
39
37
|
// Remaining items come out in FIFO order
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
t.end();
|
|
38
|
+
assert.equal(q.pop(), 3);
|
|
39
|
+
assert.equal(q.pop(), 4);
|
|
40
|
+
assert.equal(q.pop(), 5);
|
|
41
|
+
assert.equal(q.length, 0);
|
|
45
42
|
});
|
|
46
43
|
//# sourceMappingURL=queue.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.test.js","sourceRoot":"","sources":["../../test/queue.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"queue.test.js","sourceRoot":"","sources":["../../test/queue.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE;IACrC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACnC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE;IAChC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE;IACxC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,wCAAwC;IACxC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,oCAAoC;IACpC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,yCAAyC;IACzC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { Readable } from 'node:stream';
|
|
4
|
+
import { Client } from 'undici';
|
|
5
|
+
import TAKAPI from '../lib/api.js';
|
|
6
|
+
import { APIAuthCertificate } from '../lib/auth.js';
|
|
7
|
+
import stream2buffer from '../lib/stream.js';
|
|
8
|
+
test('Files.uploadPackage serializes multipart for certificate auth', async () => {
|
|
9
|
+
const originalRequest = Client.prototype.request;
|
|
10
|
+
let captured;
|
|
11
|
+
Client.prototype.request = async function (opts) {
|
|
12
|
+
captured = opts;
|
|
13
|
+
return {
|
|
14
|
+
statusCode: 200,
|
|
15
|
+
headers: {
|
|
16
|
+
'content-type': 'text/plain'
|
|
17
|
+
},
|
|
18
|
+
body: Readable.from([Buffer.from('ok')]),
|
|
19
|
+
trailers: {}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
|
|
24
|
+
const res = await api.Files.uploadPackage({
|
|
25
|
+
name: 'mission.zip',
|
|
26
|
+
creatorUid: 'user-1',
|
|
27
|
+
hash: 'hash-123',
|
|
28
|
+
keywords: ['alpha'],
|
|
29
|
+
groups: ['Blue']
|
|
30
|
+
}, Buffer.from('zip-bytes'));
|
|
31
|
+
assert.equal(res, 'ok');
|
|
32
|
+
assert.ok(captured);
|
|
33
|
+
assert.equal(captured.path, '/Marti/sync/missionupload?filename=mission.zip&creatorUid=user-1&hash=hash-123&keyword=missionpackage&keyword=alpha&Groups=Blue');
|
|
34
|
+
const headers = captured.headers;
|
|
35
|
+
assert.equal(typeof headers['Content-Type'], 'string');
|
|
36
|
+
assert.equal(typeof headers['Content-Length'], 'string');
|
|
37
|
+
assert.match(headers['Content-Type'], /^multipart\/form-data; boundary=----node-tak-/);
|
|
38
|
+
assert.equal(Number(headers['Content-Length']) > 0, true);
|
|
39
|
+
assert.ok(captured.body instanceof Readable);
|
|
40
|
+
const body = await stream2buffer(captured.body);
|
|
41
|
+
const multipart = body.toString('utf8');
|
|
42
|
+
assert.match(multipart, /Content-Disposition: form-data; name="assetfile"; filename="mission.zip"/);
|
|
43
|
+
assert.match(multipart, /Content-Type: application\/zip/);
|
|
44
|
+
assert.match(multipart, /zip-bytes/);
|
|
45
|
+
assert.match(multipart, /--$/m);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
Client.prototype.request = originalRequest;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=uploadPackage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploadPackage.test.js","sourceRoot":"","sources":["../../test/uploadPackage.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,MAAM,MAAM,eAAe,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAI7C,IAAI,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;IAC7E,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;IAEjD,IAAI,QAAiC,CAAC;IAEtC,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK,WAAU,IAAiB;QACvD,QAAQ,GAAG,IAAI,CAAC;QAEhB,OAAO;YACH,UAAU,EAAE,GAAG;YACf,OAAO,EAAE;gBACL,cAAc,EAAE,YAAY;aAC/B;YACD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACxC,QAAQ,EAAE,EAAE;SACuB,CAAC;IAC5C,CAAC,CAAC;IAEF,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,yBAAyB,CAAC,EAAE,IAAI,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAElG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;YACtC,IAAI,EAAE,aAAa;YACnB,UAAU,EAAE,QAAQ;YACpB,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,MAAM,EAAE,CAAC,MAAM,CAAC;SACnB,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAE7B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QACpB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,iIAAiI,CAAC,CAAC;QAC/J,MAAM,OAAO,GAAG,QAAQ,CAAC,OAA8B,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAW,EAAE,+CAA+C,CAAC,CAAC;QACjG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAE1D,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,YAAY,QAAQ,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAExC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,0EAA0E,CAAC,CAAC;QACpG,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;YAAS,CAAC;QACP,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,eAAe,CAAC;IAC/C,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../cli.ts","../index.ts","../test/default.test.ts","../test/findCoT.test.ts","../test/pipeline.test.ts","../test/queue.test.ts","../lib/api.ts","../lib/auth.ts","../lib/commands.ts","../lib/fetch.ts","../lib/stream.ts","../lib/api/certificate.ts","../lib/api/client.ts","../lib/api/contacts.ts","../lib/api/credentials.ts","../lib/api/export.ts","../lib/api/files.ts","../lib/api/groups.ts","../lib/api/iconsets.ts","../lib/api/injectors.ts","../lib/api/locate.ts","../lib/api/mission-invite.ts","../lib/api/mission-layer.ts","../lib/api/mission-log.ts","../lib/api/mission.ts","../lib/api/oauth.ts","../lib/api/package.ts","../lib/api/profile.ts","../lib/api/query.ts","../lib/api/repeater.ts","../lib/api/security.ts","../lib/api/subscriptions.ts","../lib/api/types.ts","../lib/api/video.ts","../lib/utils/queue.ts"],"version":"6.0.2"}
|
|
1
|
+
{"root":["../cli.ts","../index.ts","../test/default.test.ts","../test/findCoT.test.ts","../test/pipeline.test.ts","../test/queue.test.ts","../test/uploadPackage.test.ts","../lib/api.ts","../lib/auth.ts","../lib/commands.ts","../lib/fetch.ts","../lib/multipart.ts","../lib/stream.ts","../lib/api/certificate.ts","../lib/api/client.ts","../lib/api/contacts.ts","../lib/api/credentials.ts","../lib/api/export.ts","../lib/api/files.ts","../lib/api/groups.ts","../lib/api/iconsets.ts","../lib/api/injectors.ts","../lib/api/locate.ts","../lib/api/mission-invite.ts","../lib/api/mission-layer.ts","../lib/api/mission-log.ts","../lib/api/mission.ts","../lib/api/oauth.ts","../lib/api/package.ts","../lib/api/profile.ts","../lib/api/query.ts","../lib/api/repeater.ts","../lib/api/security.ts","../lib/api/subscriptions.ts","../lib/api/types.ts","../lib/api/video.ts","../lib/utils/queue.ts"],"version":"6.0.2"}
|
package/lib/auth.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Type } from '@sinclair/typebox';
|
|
|
3
3
|
import { Client } from 'undici';
|
|
4
4
|
import TAKAPI from './api.js';
|
|
5
5
|
import stream2buffer from './stream.js';
|
|
6
|
+
import { encodeMultipartFormData } from './multipart.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Store the TAK Client Certificate for a connection
|
|
@@ -97,6 +98,18 @@ export class APIAuthCertificate extends APIAuth {
|
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
100
|
|
|
101
|
+
if (typeof FormData !== 'undefined' && opts.body instanceof FormData) {
|
|
102
|
+
const multipart = await encodeMultipartFormData(opts.body);
|
|
103
|
+
opts = {
|
|
104
|
+
...opts,
|
|
105
|
+
headers: {
|
|
106
|
+
...(opts.headers || {}),
|
|
107
|
+
...multipart.headers
|
|
108
|
+
},
|
|
109
|
+
body: multipart.body
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
100
113
|
const res = await client.request({
|
|
101
114
|
path: String(url).replace(api.url.origin, ''),
|
|
102
115
|
...opts
|
package/lib/multipart.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
3
|
+
|
|
4
|
+
type MultipartBufferPart = {
|
|
5
|
+
header: Buffer;
|
|
6
|
+
kind: 'buffer';
|
|
7
|
+
body: Buffer;
|
|
8
|
+
trailer: Buffer;
|
|
9
|
+
size: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type MultipartFilePart = {
|
|
13
|
+
header: Buffer;
|
|
14
|
+
kind: 'file';
|
|
15
|
+
body: File;
|
|
16
|
+
trailer: Buffer;
|
|
17
|
+
size: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type MultipartPart = MultipartBufferPart | MultipartFilePart;
|
|
21
|
+
|
|
22
|
+
function escapeQuoted(value: string): string {
|
|
23
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function encodeMultipartFormData(form: FormData): Promise<{
|
|
27
|
+
body: Readable;
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': string;
|
|
30
|
+
'Content-Length': string;
|
|
31
|
+
};
|
|
32
|
+
}> {
|
|
33
|
+
const boundary = `----node-tak-${crypto.randomUUID()}`;
|
|
34
|
+
const closing = Buffer.from(`--${boundary}--\r\n`);
|
|
35
|
+
|
|
36
|
+
const parts: MultipartPart[] = Array.from(form.entries()).map(([name, value]) => {
|
|
37
|
+
if (typeof value === 'string') {
|
|
38
|
+
const header = Buffer.from(
|
|
39
|
+
`--${boundary}\r\n`
|
|
40
|
+
+ `Content-Disposition: form-data; name="${escapeQuoted(name)}"\r\n\r\n`
|
|
41
|
+
);
|
|
42
|
+
const body = Buffer.from(value);
|
|
43
|
+
const trailer = Buffer.from('\r\n');
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
header,
|
|
47
|
+
kind: 'buffer',
|
|
48
|
+
body,
|
|
49
|
+
trailer,
|
|
50
|
+
size: header.length + body.length + trailer.length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const filename = 'name' in value && typeof value.name === 'string'
|
|
55
|
+
? value.name
|
|
56
|
+
: 'blob';
|
|
57
|
+
const type = value.type || 'application/octet-stream';
|
|
58
|
+
const header = Buffer.from(
|
|
59
|
+
`--${boundary}\r\n`
|
|
60
|
+
+ `Content-Disposition: form-data; name="${escapeQuoted(name)}"; filename="${escapeQuoted(filename)}"\r\n`
|
|
61
|
+
+ `Content-Type: ${type}\r\n\r\n`
|
|
62
|
+
);
|
|
63
|
+
const trailer = Buffer.from('\r\n');
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
header,
|
|
67
|
+
kind: 'file',
|
|
68
|
+
body: value,
|
|
69
|
+
trailer,
|
|
70
|
+
size: header.length + value.size + trailer.length,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const contentLength = parts.reduce((sum, part) => sum + part.size, 0) + closing.length;
|
|
75
|
+
|
|
76
|
+
const body = Readable.from((async function*() {
|
|
77
|
+
for (const part of parts) {
|
|
78
|
+
yield part.header;
|
|
79
|
+
|
|
80
|
+
if (part.kind === 'buffer') {
|
|
81
|
+
yield part.body;
|
|
82
|
+
} else {
|
|
83
|
+
yield Buffer.from(await part.body.arrayBuffer());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
yield part.trailer;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
yield closing;
|
|
90
|
+
})());
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
body,
|
|
94
|
+
headers: {
|
|
95
|
+
'Content-Type': `multipart/form-data; boundary=${boundary}`,
|
|
96
|
+
'Content-Length': String(contentLength),
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tak-ps/node-tak",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "12.
|
|
4
|
+
"version": "12.10.0",
|
|
5
5
|
"description": "Lightweight JavaScript library for communicating with TAK Server",
|
|
6
6
|
"author": "Nick Ingalls <nick@ingalls.ca>",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -44,10 +44,8 @@
|
|
|
44
44
|
"@inquirer/prompts": "^8.0.1",
|
|
45
45
|
"@types/node": "^25.0.0",
|
|
46
46
|
"@types/pem": "^1.14.4",
|
|
47
|
-
"@types/tape": "^5.6.0",
|
|
48
47
|
"c8": "^11.0.0",
|
|
49
48
|
"eslint": "^10.0.0",
|
|
50
|
-
"tape": "^5.6.1",
|
|
51
49
|
"tsx": "^4.19.4",
|
|
52
50
|
"typedoc": "^0.28.1",
|
|
53
51
|
"typescript": "^6.0.0",
|
package/test/default.test.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import TAK, { CoT } from '../index.js';
|
|
2
|
-
import test from '
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
3
4
|
|
|
4
|
-
test('Ensure Export', (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
t.end();
|
|
5
|
+
test('Ensure Export', () => {
|
|
6
|
+
assert.ok(TAK);
|
|
7
|
+
assert.ok(CoT);
|
|
8
8
|
});
|
|
9
9
|
|
package/test/findCoT.test.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import TAK from '../index.js';
|
|
2
|
-
import test from '
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
3
4
|
|
|
4
|
-
test('findCoT - Unfinished', (
|
|
5
|
+
test('findCoT - Unfinished', () => {
|
|
5
6
|
const res = TAK.findCoT('<event ><detail>');
|
|
6
|
-
|
|
7
|
-
t.end();
|
|
7
|
+
assert.equal(res, null);
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
test('findCoT - Basic', (
|
|
10
|
+
test('findCoT - Basic', () => {
|
|
11
11
|
const res = TAK.findCoT('<event></event>');
|
|
12
|
-
|
|
12
|
+
assert.deepEqual(res, {
|
|
13
13
|
event: '<event></event>',
|
|
14
14
|
remainder: '',
|
|
15
15
|
});
|
|
16
|
-
t.end();
|
|
17
16
|
});
|
|
18
17
|
|
|
19
|
-
test('findCoT - New Lines', (
|
|
18
|
+
test('findCoT - New Lines', () => {
|
|
20
19
|
const res = TAK.findCoT(`
|
|
21
20
|
<event>
|
|
22
21
|
<detail remarks="
|
|
@@ -24,14 +23,13 @@ I am a multiline
|
|
|
24
23
|
remarks field
|
|
25
24
|
"/>
|
|
26
25
|
</event>`);
|
|
27
|
-
|
|
26
|
+
assert.deepEqual(res, {
|
|
28
27
|
event: '<event>\n <detail remarks="\nI am a multiline\nremarks field\n "/>\n</event>',
|
|
29
28
|
remainder: '',
|
|
30
29
|
});
|
|
31
|
-
t.end();
|
|
32
30
|
});
|
|
33
31
|
|
|
34
|
-
test('findCoT - New Lines - Non-Greedy', (
|
|
32
|
+
test('findCoT - New Lines - Non-Greedy', () => {
|
|
35
33
|
const res = TAK.findCoT(`
|
|
36
34
|
<event>
|
|
37
35
|
<detail remarks="
|
|
@@ -44,48 +42,44 @@ I am a multiline
|
|
|
44
42
|
remarks field
|
|
45
43
|
"/>
|
|
46
44
|
</event>`);
|
|
47
|
-
|
|
45
|
+
assert.deepEqual(res, {
|
|
48
46
|
event: '<event>\n <detail remarks="\nI am a multiline\nremarks field\n "/>\n</event>',
|
|
49
47
|
remainder: '<event>\n <detail remarks="\nI am a multiline\nremarks field\n "/>\n</event>',
|
|
50
48
|
});
|
|
51
|
-
t.end();
|
|
52
49
|
});
|
|
53
50
|
|
|
54
|
-
test('findCoT - bad preceding data', (
|
|
51
|
+
test('findCoT - bad preceding data', () => {
|
|
55
52
|
const res = TAK.findCoT(`
|
|
56
53
|
<fake/>
|
|
57
54
|
<event><detail remarks="I am remarks"/>
|
|
58
55
|
</event>
|
|
59
56
|
`);
|
|
60
|
-
|
|
57
|
+
assert.deepEqual(res, {
|
|
61
58
|
event: '<event><detail remarks="I am remarks"/>\n</event>',
|
|
62
59
|
remainder: '\n',
|
|
63
60
|
});
|
|
64
|
-
t.end();
|
|
65
61
|
});
|
|
66
62
|
|
|
67
|
-
test('findCoT - bad post data', (
|
|
63
|
+
test('findCoT - bad post data', () => {
|
|
68
64
|
const res = TAK.findCoT(`
|
|
69
65
|
<event><detail remarks="I am remarks"/>
|
|
70
66
|
</event>
|
|
71
67
|
<fake/>
|
|
72
68
|
`);
|
|
73
|
-
|
|
69
|
+
assert.deepEqual(res, {
|
|
74
70
|
event: '<event><detail remarks="I am remarks"/>\n</event>',
|
|
75
71
|
remainder: '\n<fake/>\n',
|
|
76
72
|
});
|
|
77
|
-
t.end();
|
|
78
73
|
});
|
|
79
74
|
|
|
80
|
-
test('findCoT - mixed', (
|
|
75
|
+
test('findCoT - mixed', () => {
|
|
81
76
|
const res = TAK.findCoT(`
|
|
82
77
|
<event><detail remarks="I am remarks"/>
|
|
83
78
|
</event>
|
|
84
79
|
<fake/>
|
|
85
80
|
<event><detail remarks="I am remarks"/></event>`);
|
|
86
|
-
|
|
81
|
+
assert.deepEqual(res, {
|
|
87
82
|
event: '<event><detail remarks="I am remarks"/>\n</event>',
|
|
88
83
|
remainder: '\n<fake/>\n<event><detail remarks="I am remarks"/></event>',
|
|
89
84
|
});
|
|
90
|
-
t.end();
|
|
91
85
|
});
|