@sirena-lwm2m/coap 0.8.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/LICENSE +17 -0
- package/README.md +78 -0
- package/dist/api/exchange-context.d.ts +34 -0
- package/dist/api/exchange-context.d.ts.map +1 -0
- package/dist/api/exchange-context.js +2 -0
- package/dist/api/exchange-context.js.map +1 -0
- package/dist/api/headers.d.ts +10 -0
- package/dist/api/headers.d.ts.map +1 -0
- package/dist/api/headers.js +69 -0
- package/dist/api/headers.js.map +1 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/request.d.ts +11 -0
- package/dist/api/request.d.ts.map +1 -0
- package/dist/api/request.js +49 -0
- package/dist/api/request.js.map +1 -0
- package/dist/api/response.d.ts +11 -0
- package/dist/api/response.d.ts.map +1 -0
- package/dist/api/response.js +19 -0
- package/dist/api/response.js.map +1 -0
- package/dist/blockwise/block1-assembler.d.ts +26 -0
- package/dist/blockwise/block1-assembler.d.ts.map +1 -0
- package/dist/blockwise/block1-assembler.js +94 -0
- package/dist/blockwise/block1-assembler.js.map +1 -0
- package/dist/blockwise/block2-chunker.d.ts +23 -0
- package/dist/blockwise/block2-chunker.d.ts.map +1 -0
- package/dist/blockwise/block2-chunker.js +99 -0
- package/dist/blockwise/block2-chunker.js.map +1 -0
- package/dist/blockwise/index.d.ts +8 -0
- package/dist/blockwise/index.d.ts.map +1 -0
- package/dist/blockwise/index.js +5 -0
- package/dist/blockwise/index.js.map +1 -0
- package/dist/blockwise/middleware.d.ts +7 -0
- package/dist/blockwise/middleware.d.ts.map +1 -0
- package/dist/blockwise/middleware.js +120 -0
- package/dist/blockwise/middleware.js.map +1 -0
- package/dist/blockwise/option.d.ts +12 -0
- package/dist/blockwise/option.d.ts.map +1 -0
- package/dist/blockwise/option.js +55 -0
- package/dist/blockwise/option.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/message/index.d.ts +21 -0
- package/dist/message/index.d.ts.map +1 -0
- package/dist/message/index.js +79 -0
- package/dist/message/index.js.map +1 -0
- package/dist/observability.d.ts +44 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +71 -0
- package/dist/observability.js.map +1 -0
- package/dist/observe-notification.d.ts +21 -0
- package/dist/observe-notification.d.ts.map +1 -0
- package/dist/observe-notification.js +87 -0
- package/dist/observe-notification.js.map +1 -0
- package/dist/observe.d.ts +10 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +3 -0
- package/dist/observe.js.map +1 -0
- package/dist/option-parser/index.d.ts +30 -0
- package/dist/option-parser/index.d.ts.map +1 -0
- package/dist/option-parser/index.js +125 -0
- package/dist/option-parser/index.js.map +1 -0
- package/dist/router/app.d.ts +8 -0
- package/dist/router/app.d.ts.map +1 -0
- package/dist/router/app.js +25 -0
- package/dist/router/app.js.map +1 -0
- package/dist/router/content-format.d.ts +7 -0
- package/dist/router/content-format.d.ts.map +1 -0
- package/dist/router/content-format.js +23 -0
- package/dist/router/content-format.js.map +1 -0
- package/dist/router/index.d.ts +9 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +5 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/radix.d.ts +16 -0
- package/dist/router/radix.d.ts.map +1 -0
- package/dist/router/radix.js +69 -0
- package/dist/router/radix.js.map +1 -0
- package/dist/router/router.d.ts +38 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +111 -0
- package/dist/router/router.js.map +1 -0
- package/dist/router.d.ts +2 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +2 -0
- package/dist/router.js.map +1 -0
- package/dist/security.d.ts +3 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +2 -0
- package/dist/security.js.map +1 -0
- package/dist/store/index.d.ts +26 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +68 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/sqlite-store.d.ts +10 -0
- package/dist/store/sqlite-store.d.ts.map +1 -0
- package/dist/store/sqlite-store.js +75 -0
- package/dist/store/sqlite-store.js.map +1 -0
- package/dist/store.d.ts +5 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +3 -0
- package/dist/store.js.map +1 -0
- package/dist/transport/dtls.d.ts +38 -0
- package/dist/transport/dtls.d.ts.map +1 -0
- package/dist/transport/dtls.js +151 -0
- package/dist/transport/dtls.js.map +1 -0
- package/dist/transport/events.d.ts +34 -0
- package/dist/transport/events.d.ts.map +1 -0
- package/dist/transport/events.js +2 -0
- package/dist/transport/events.js.map +1 -0
- package/dist/transport/index.d.ts +10 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/tcp-connection.d.ts +18 -0
- package/dist/transport/tcp-connection.d.ts.map +1 -0
- package/dist/transport/tcp-connection.js +72 -0
- package/dist/transport/tcp-connection.js.map +1 -0
- package/dist/transport/tcp-frame.d.ts +17 -0
- package/dist/transport/tcp-frame.d.ts.map +1 -0
- package/dist/transport/tcp-frame.js +112 -0
- package/dist/transport/tcp-frame.js.map +1 -0
- package/dist/transport/tcp-stream.d.ts +21 -0
- package/dist/transport/tcp-stream.d.ts.map +1 -0
- package/dist/transport/tcp-stream.js +52 -0
- package/dist/transport/tcp-stream.js.map +1 -0
- package/dist/transport/udp.d.ts +97 -0
- package/dist/transport/udp.d.ts.map +1 -0
- package/dist/transport/udp.js +994 -0
- package/dist/transport/udp.js.map +1 -0
- package/dist/transport.d.ts +3 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +2 -0
- package/dist/transport.js.map +1 -0
- package/docs/api-reference.md +536 -0
- package/docs/blockwise.md +117 -0
- package/docs/observability.md +206 -0
- package/docs/observe.md +203 -0
- package/docs/releasing.md +106 -0
- package/docs/router.md +170 -0
- package/docs/store.md +212 -0
- package/docs/tcp-transport.md +89 -0
- package/docs/udp-transport.md +81 -0
- package/examples/slice-1.ts +12 -0
- package/examples/slice-2.ts +96 -0
- package/examples/slice-3-psk.ts +70 -0
- package/examples/slice-3-x509.ts +85 -0
- package/examples/slice-4.ts +45 -0
- package/examples/slice-5-firmware.ts +207 -0
- package/examples/slice-6-temperature.ts +163 -0
- package/examples/slice-7-file-store.ts +92 -0
- package/examples/slice-7-otel.ts +123 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2026 Dejan Dimic <dejan.dimic@gmail.com>
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @sirena-lwm2m/coap
|
|
2
|
+
|
|
3
|
+
RFC 7252 CoAP stack for Node.js with RFC 8323 TCP transport support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @sirena-lwm2m/coap
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start — UDP
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createServer, Response, stringToBytes } from '@sirena-lwm2m/coap';
|
|
15
|
+
|
|
16
|
+
const server = createServer({
|
|
17
|
+
listen: [{ host: '0.0.0.0', port: 5683 }],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
server.on('request', async (req, ctx) => {
|
|
21
|
+
await ctx.respond(Response.ok(stringToBytes(req.url)));
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await server.start();
|
|
25
|
+
console.log('Listening on:', server.listenerSummary());
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## TCP transport (RFC 8323)
|
|
29
|
+
|
|
30
|
+
The server supports CoAP over TCP using the `coap+tcp://` URI scheme. Bind one or more TCP listeners alongside UDP by passing URI strings to the `listen` array.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createServer, Response, stringToBytes } from '@sirena-lwm2m/coap';
|
|
34
|
+
|
|
35
|
+
const server = createServer({
|
|
36
|
+
listen: [
|
|
37
|
+
'coap://127.0.0.1:5683', // UDP
|
|
38
|
+
'coap+tcp://127.0.0.1:5684', // TCP (RFC 8323)
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
server.on('request', async (req, ctx) => {
|
|
43
|
+
// ctx.transport is 'udp' or 'tcp'
|
|
44
|
+
console.log(`[${ctx.transport}] ${req.url}`);
|
|
45
|
+
await ctx.respond(Response.ok(stringToBytes(`hello via ${ctx.transport}`)));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await server.start();
|
|
49
|
+
console.log('Listening on:', server.listenerSummary());
|
|
50
|
+
await server.stop();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
See [`examples/slice-2.ts`](./examples/slice-2.ts) for a working dual-transport demo.
|
|
54
|
+
|
|
55
|
+
See [`docs/tcp-transport.md`](./docs/tcp-transport.md) for framing details, connection multiplexing, and configuration.
|
|
56
|
+
|
|
57
|
+
## ExchangeContext
|
|
58
|
+
|
|
59
|
+
Every `'request'` event handler receives a `Request` and an `ExchangeContext`:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
interface ExchangeContext {
|
|
63
|
+
remote: string; // "ip:port" of the sender
|
|
64
|
+
local: string; // "ip:port" of the receiving socket
|
|
65
|
+
transport: 'udp' | 'tcp'; // which transport delivered this request
|
|
66
|
+
token: Uint8Array; // CoAP token bytes
|
|
67
|
+
messageId: number; // CoAP message ID (0 for TCP)
|
|
68
|
+
options: CoapOption[]; // raw parsed options
|
|
69
|
+
peer: Peer; // { mode: 'anonymous' }
|
|
70
|
+
respond(res: Response): Promise<void>;
|
|
71
|
+
cancel(): void;
|
|
72
|
+
abort(code: CoapCode): void;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { X509Certificate } from 'node:crypto';
|
|
2
|
+
import type { CoapCode } from '../message/index.js';
|
|
3
|
+
import type { CoapOption } from '../option-parser/index.js';
|
|
4
|
+
import type { Observable } from '../observe.js';
|
|
5
|
+
import type { Response } from './response.js';
|
|
6
|
+
export type Peer = {
|
|
7
|
+
mode: 'anonymous';
|
|
8
|
+
} | {
|
|
9
|
+
mode: 'psk';
|
|
10
|
+
identity: string;
|
|
11
|
+
} | {
|
|
12
|
+
mode: 'x509';
|
|
13
|
+
certChain: X509Certificate[];
|
|
14
|
+
};
|
|
15
|
+
export interface ObserveOptions {
|
|
16
|
+
notifyEveryValue?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface ExchangeContext {
|
|
19
|
+
remote: string;
|
|
20
|
+
local: string;
|
|
21
|
+
transport: 'udp' | 'tcp';
|
|
22
|
+
token: Uint8Array;
|
|
23
|
+
messageId: number;
|
|
24
|
+
options: CoapOption[];
|
|
25
|
+
peer: Peer;
|
|
26
|
+
params?: Record<string, string>;
|
|
27
|
+
observeSeq: number;
|
|
28
|
+
respond(res: Response): Promise<void>;
|
|
29
|
+
continue(): Promise<void>;
|
|
30
|
+
cancel(): void;
|
|
31
|
+
abort(code: CoapCode): void;
|
|
32
|
+
observe(observable: Observable<unknown>, opts?: ObserveOptions): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=exchange-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exchange-context.d.ts","sourceRoot":"","sources":["../../src/api/exchange-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,MAAM,IAAI,GACZ;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACvE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exchange-context.js","sourceRoot":"","sources":["../../src/api/exchange-context.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CoapOption } from '../option-parser/index.js';
|
|
2
|
+
export declare class Headers {
|
|
3
|
+
private options;
|
|
4
|
+
constructor(options: CoapOption[]);
|
|
5
|
+
get(name: string): string | null;
|
|
6
|
+
has(name: string): boolean;
|
|
7
|
+
set(name: string, value: string): void;
|
|
8
|
+
toOptions(): CoapOption[];
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAuC5D,qBAAa,OAAO;IAClB,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE,UAAU,EAAE;IAIjC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQhC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAM1B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYtC,SAAS,IAAI,UAAU,EAAE;CAG1B"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { OptionNumber, bytesToUint, bytesToString, uintToBytes, stringToBytes } from '../option-parser/index.js';
|
|
2
|
+
const NAME_TO_NUMBER = {
|
|
3
|
+
'Content-Format': OptionNumber.ContentFormat,
|
|
4
|
+
'Max-Age': OptionNumber.MaxAge,
|
|
5
|
+
'Accept': OptionNumber.Accept,
|
|
6
|
+
'ETag': 4,
|
|
7
|
+
};
|
|
8
|
+
const NUMBER_TO_NAME = Object.fromEntries(Object.entries(NAME_TO_NUMBER).map(([k, v]) => [v, k]));
|
|
9
|
+
function optionToString(number, value) {
|
|
10
|
+
switch (number) {
|
|
11
|
+
case OptionNumber.ContentFormat:
|
|
12
|
+
case OptionNumber.Accept:
|
|
13
|
+
return String(bytesToUint(value));
|
|
14
|
+
case OptionNumber.MaxAge:
|
|
15
|
+
return String(bytesToUint(value));
|
|
16
|
+
case 4: // ETag
|
|
17
|
+
return bytesToString(value);
|
|
18
|
+
default:
|
|
19
|
+
return bytesToString(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function stringToOptionValue(number, s) {
|
|
23
|
+
switch (number) {
|
|
24
|
+
case OptionNumber.ContentFormat:
|
|
25
|
+
case OptionNumber.Accept:
|
|
26
|
+
case OptionNumber.MaxAge:
|
|
27
|
+
return uintToBytes(parseInt(s, 10));
|
|
28
|
+
default:
|
|
29
|
+
return stringToBytes(s);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class Headers {
|
|
33
|
+
options;
|
|
34
|
+
constructor(options) {
|
|
35
|
+
this.options = [...options];
|
|
36
|
+
}
|
|
37
|
+
get(name) {
|
|
38
|
+
const num = NAME_TO_NUMBER[name];
|
|
39
|
+
if (num === undefined)
|
|
40
|
+
return null;
|
|
41
|
+
const opt = this.options.find(o => o.number === num);
|
|
42
|
+
if (!opt)
|
|
43
|
+
return null;
|
|
44
|
+
return optionToString(num, opt.value);
|
|
45
|
+
}
|
|
46
|
+
has(name) {
|
|
47
|
+
const num = NAME_TO_NUMBER[name];
|
|
48
|
+
if (num === undefined)
|
|
49
|
+
return false;
|
|
50
|
+
return this.options.some(o => o.number === num);
|
|
51
|
+
}
|
|
52
|
+
set(name, value) {
|
|
53
|
+
const num = NAME_TO_NUMBER[name];
|
|
54
|
+
if (num === undefined)
|
|
55
|
+
return;
|
|
56
|
+
const idx = this.options.findIndex(o => o.number === num);
|
|
57
|
+
const encoded = stringToOptionValue(num, value);
|
|
58
|
+
if (idx >= 0) {
|
|
59
|
+
this.options[idx] = { number: num, value: encoded };
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.options.push({ number: num, value: encoded });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
toOptions() {
|
|
66
|
+
return [...this.options];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/api/headers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CoapMessage, CoapCode } from '../message/index.js';
|
|
2
|
+
import { Headers } from './headers.js';
|
|
3
|
+
export declare class Request {
|
|
4
|
+
readonly method: string;
|
|
5
|
+
readonly methodCode: CoapCode;
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly headers: Headers;
|
|
8
|
+
readonly body: ReadableStream<Uint8Array> | null;
|
|
9
|
+
constructor(msg: CoapMessage);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/api/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGjE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAiCvC,qBAAa,OAAO;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;gBAErC,GAAG,EAAE,WAAW;CAc7B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { codeToString } from '../message/index.js';
|
|
2
|
+
import { OptionNumber, bytesToString, bytesToUint } from '../option-parser/index.js';
|
|
3
|
+
import { Headers } from './headers.js';
|
|
4
|
+
const METHOD_CODE_MAP = {
|
|
5
|
+
0x01: 'GET',
|
|
6
|
+
0x02: 'POST',
|
|
7
|
+
0x03: 'PUT',
|
|
8
|
+
0x04: 'DELETE',
|
|
9
|
+
};
|
|
10
|
+
function assembleUrl(msg) {
|
|
11
|
+
const pathParts = msg.options
|
|
12
|
+
.filter(o => o.number === OptionNumber.UriPath)
|
|
13
|
+
.map(o => bytesToString(o.value));
|
|
14
|
+
const queryParts = msg.options
|
|
15
|
+
.filter(o => o.number === OptionNumber.UriQuery)
|
|
16
|
+
.map(o => bytesToString(o.value));
|
|
17
|
+
const hostOpt = msg.options.find(o => o.number === OptionNumber.UriHost);
|
|
18
|
+
const portOpt = msg.options.find(o => o.number === OptionNumber.UriPort);
|
|
19
|
+
const path = pathParts.length > 0 ? '/' + pathParts.join('/') : '/';
|
|
20
|
+
const query = queryParts.length > 0 ? '?' + queryParts.join('&') : '';
|
|
21
|
+
if (hostOpt) {
|
|
22
|
+
const host = bytesToString(hostOpt.value);
|
|
23
|
+
const port = portOpt ? bytesToUint(portOpt.value) : 5683;
|
|
24
|
+
return `coap://${host}:${port}${path}${query}`;
|
|
25
|
+
}
|
|
26
|
+
return `${path}${query}`;
|
|
27
|
+
}
|
|
28
|
+
export class Request {
|
|
29
|
+
method;
|
|
30
|
+
methodCode;
|
|
31
|
+
url;
|
|
32
|
+
headers;
|
|
33
|
+
body;
|
|
34
|
+
constructor(msg) {
|
|
35
|
+
this.methodCode = msg.code;
|
|
36
|
+
this.method = METHOD_CODE_MAP[msg.code] ?? codeToString(msg.code);
|
|
37
|
+
this.url = assembleUrl(msg);
|
|
38
|
+
this.headers = new Headers(msg.options);
|
|
39
|
+
this.body = msg.payload.length > 0
|
|
40
|
+
? new ReadableStream({
|
|
41
|
+
start(controller) {
|
|
42
|
+
controller.enqueue(msg.payload);
|
|
43
|
+
controller.close();
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
: null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/api/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CoapCode } from '../message/index.js';
|
|
2
|
+
import { Headers } from './headers.js';
|
|
3
|
+
export declare class Response {
|
|
4
|
+
readonly status: string;
|
|
5
|
+
readonly statusCode: CoapCode;
|
|
6
|
+
readonly headers: Headers;
|
|
7
|
+
readonly body: Uint8Array | null;
|
|
8
|
+
constructor(statusCode: CoapCode, body?: Uint8Array, headers?: Headers);
|
|
9
|
+
static ok(body?: Uint8Array, headers?: Headers): Response;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/api/response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,qBAAa,QAAQ;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;gBAErB,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,OAAO;IAOtE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ;CAG1D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { codeToString, stringToCode } from '../message/index.js';
|
|
2
|
+
import { Headers } from './headers.js';
|
|
3
|
+
const OK_CODE = stringToCode('2.05');
|
|
4
|
+
export class Response {
|
|
5
|
+
status;
|
|
6
|
+
statusCode;
|
|
7
|
+
headers;
|
|
8
|
+
body;
|
|
9
|
+
constructor(statusCode, body, headers) {
|
|
10
|
+
this.statusCode = statusCode;
|
|
11
|
+
this.status = codeToString(statusCode);
|
|
12
|
+
this.headers = headers ?? new Headers([]);
|
|
13
|
+
this.body = body ?? null;
|
|
14
|
+
}
|
|
15
|
+
static ok(body, headers) {
|
|
16
|
+
return new Response(OK_CODE, body, headers);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/api/response.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAErC,MAAM,OAAO,QAAQ;IACV,MAAM,CAAS;IACf,UAAU,CAAW;IACrB,OAAO,CAAU;IACjB,IAAI,CAAoB;IAEjC,YAAY,UAAoB,EAAE,IAAiB,EAAE,OAAiB;QACpE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,EAAE,CAAC,IAAiB,EAAE,OAAiB;QAC5C,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
export interface Block1AssemblerOptions {
|
|
3
|
+
maxBytes?: number;
|
|
4
|
+
idleTimeoutMs?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface BlockTransferEvent {
|
|
7
|
+
reason: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class Block1Assembler extends EventEmitter {
|
|
10
|
+
readonly tempPath: string;
|
|
11
|
+
private _body;
|
|
12
|
+
private expectedNum;
|
|
13
|
+
private totalBytes;
|
|
14
|
+
private idleTimer;
|
|
15
|
+
private aborted;
|
|
16
|
+
private readonly maxBytes;
|
|
17
|
+
private readonly idleTimeoutMs;
|
|
18
|
+
constructor(options?: Block1AssemblerOptions);
|
|
19
|
+
addChunk(num: number, _szx: number, m: boolean, payload: Uint8Array): 'continue' | 'complete' | 'out-of-order' | 'too-large';
|
|
20
|
+
get body(): ReadableStream<Uint8Array>;
|
|
21
|
+
abort(reason?: string): void;
|
|
22
|
+
private buildReadableStream;
|
|
23
|
+
private resetIdleTimer;
|
|
24
|
+
private clearIdleTimer;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=block1-assembler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block1-assembler.d.ts","sourceRoot":"","sources":["../../src/blockwise/block1-assembler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;gBAE3B,OAAO,CAAC,EAAE,sBAAsB;IAQ5C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,WAAW;IA0B5H,IAAI,IAAI,IAAI,cAAc,CAAC,UAAU,CAAC,CAKrC;IAED,KAAK,CAAC,MAAM,SAAa,GAAG,IAAI;IAYhC,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,cAAc;CAMvB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
export class Block1Assembler extends EventEmitter {
|
|
6
|
+
tempPath;
|
|
7
|
+
_body;
|
|
8
|
+
expectedNum = 0;
|
|
9
|
+
totalBytes = 0;
|
|
10
|
+
idleTimer;
|
|
11
|
+
aborted = false;
|
|
12
|
+
maxBytes;
|
|
13
|
+
idleTimeoutMs;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
super();
|
|
16
|
+
this.maxBytes = options?.maxBytes ?? 16 * 1024 * 1024;
|
|
17
|
+
this.idleTimeoutMs = options?.idleTimeoutMs ?? 60_000;
|
|
18
|
+
this.tempPath = path.join(os.tmpdir(), `coap-block1-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
|
|
19
|
+
this.resetIdleTimer();
|
|
20
|
+
}
|
|
21
|
+
addChunk(num, _szx, m, payload) {
|
|
22
|
+
if (num !== this.expectedNum) {
|
|
23
|
+
return 'out-of-order';
|
|
24
|
+
}
|
|
25
|
+
if (this.totalBytes + payload.length > this.maxBytes) {
|
|
26
|
+
this.abort('too-large');
|
|
27
|
+
return 'too-large';
|
|
28
|
+
}
|
|
29
|
+
fs.appendFileSync(this.tempPath, payload);
|
|
30
|
+
this.totalBytes += payload.length;
|
|
31
|
+
this.expectedNum++;
|
|
32
|
+
this.resetIdleTimer();
|
|
33
|
+
if (!m) {
|
|
34
|
+
this.clearIdleTimer();
|
|
35
|
+
this._body = this.buildReadableStream();
|
|
36
|
+
this.emit('block-transfer-complete');
|
|
37
|
+
return 'complete';
|
|
38
|
+
}
|
|
39
|
+
return 'continue';
|
|
40
|
+
}
|
|
41
|
+
get body() {
|
|
42
|
+
if (!this._body) {
|
|
43
|
+
throw new Error('body is not available until addChunk returns "complete"');
|
|
44
|
+
}
|
|
45
|
+
return this._body;
|
|
46
|
+
}
|
|
47
|
+
abort(reason = 'explicit') {
|
|
48
|
+
if (this.aborted)
|
|
49
|
+
return;
|
|
50
|
+
this.aborted = true;
|
|
51
|
+
this.clearIdleTimer();
|
|
52
|
+
try {
|
|
53
|
+
fs.unlinkSync(this.tempPath);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// file may not exist yet
|
|
57
|
+
}
|
|
58
|
+
this.emit('block-transfer-aborted', { reason });
|
|
59
|
+
}
|
|
60
|
+
buildReadableStream() {
|
|
61
|
+
const filePath = this.tempPath;
|
|
62
|
+
return new ReadableStream({
|
|
63
|
+
start(controller) {
|
|
64
|
+
const nodeStream = fs.createReadStream(filePath);
|
|
65
|
+
nodeStream.on('data', (chunk) => {
|
|
66
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
67
|
+
});
|
|
68
|
+
nodeStream.on('end', () => {
|
|
69
|
+
controller.close();
|
|
70
|
+
try {
|
|
71
|
+
fs.unlinkSync(filePath);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// already deleted
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
nodeStream.on('error', (err) => {
|
|
78
|
+
controller.error(err);
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
resetIdleTimer() {
|
|
84
|
+
this.clearIdleTimer();
|
|
85
|
+
this.idleTimer = setTimeout(() => this.abort('idle-timeout'), this.idleTimeoutMs);
|
|
86
|
+
}
|
|
87
|
+
clearIdleTimer() {
|
|
88
|
+
if (this.idleTimer !== undefined) {
|
|
89
|
+
clearTimeout(this.idleTimer);
|
|
90
|
+
this.idleTimer = undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=block1-assembler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block1-assembler.js","sourceRoot":"","sources":["../../src/blockwise/block1-assembler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { BlockTransferEvent } from './block1-assembler.js';
|
|
3
|
+
export type { BlockTransferEvent };
|
|
4
|
+
export declare class Block2Chunker extends EventEmitter {
|
|
5
|
+
private readonly blockSize;
|
|
6
|
+
private buffered;
|
|
7
|
+
private etag;
|
|
8
|
+
private readonly source;
|
|
9
|
+
private aborted;
|
|
10
|
+
private completeFired;
|
|
11
|
+
constructor(body: Buffer | ReadableStream<Uint8Array>, options?: {
|
|
12
|
+
blockSize?: number;
|
|
13
|
+
});
|
|
14
|
+
get totalBlocks(): number;
|
|
15
|
+
abort(reason?: string): void;
|
|
16
|
+
getBlock(num: number): Promise<{
|
|
17
|
+
payload: Uint8Array;
|
|
18
|
+
m: boolean;
|
|
19
|
+
etag: Uint8Array;
|
|
20
|
+
}>;
|
|
21
|
+
private bufferSource;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=block2-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block2-chunker.d.ts","sourceRoot":"","sources":["../../src/blockwise/block2-chunker.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AA0BnC,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,IAAI,CAAyB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAS;gBAG5B,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,EACzC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAiBlC,IAAI,WAAW,IAAI,MAAM,CAKxB;IAED,KAAK,CAAC,MAAM,SAAa,GAAG,IAAI;IAM1B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,UAAU,CAAC;QAAC,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC;YA0B7E,YAAY;CAsB3B"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// RFC 7959 §2.5 — Block2 download chunker
|
|
2
|
+
// ReadableStream input is fully buffered on first getBlock call; RFC 7959 requires
|
|
3
|
+
// stable block numbers across retransmissions, so we cannot stream lazily.
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
const MIN_BLOCK_SIZE = 16;
|
|
6
|
+
const MAX_BLOCK_SIZE = 1024;
|
|
7
|
+
function crc32(data) {
|
|
8
|
+
const table = buildCrc32Table();
|
|
9
|
+
let crc = 0xffffffff;
|
|
10
|
+
for (let i = 0; i < data.length; i++) {
|
|
11
|
+
crc = (crc >>> 8) ^ table[(crc ^ data[i]) & 0xff];
|
|
12
|
+
}
|
|
13
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
14
|
+
}
|
|
15
|
+
function buildCrc32Table() {
|
|
16
|
+
const t = new Uint32Array(256);
|
|
17
|
+
for (let i = 0; i < 256; i++) {
|
|
18
|
+
let c = i;
|
|
19
|
+
for (let j = 0; j < 8; j++) {
|
|
20
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
21
|
+
}
|
|
22
|
+
t[i] = c;
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
}
|
|
26
|
+
export class Block2Chunker extends EventEmitter {
|
|
27
|
+
blockSize;
|
|
28
|
+
buffered;
|
|
29
|
+
etag;
|
|
30
|
+
source;
|
|
31
|
+
aborted = false;
|
|
32
|
+
completeFired = false;
|
|
33
|
+
constructor(body, options) {
|
|
34
|
+
super();
|
|
35
|
+
const size = options?.blockSize ?? 512;
|
|
36
|
+
if (size < MIN_BLOCK_SIZE ||
|
|
37
|
+
size > MAX_BLOCK_SIZE ||
|
|
38
|
+
(size & (size - 1)) !== 0) {
|
|
39
|
+
throw new RangeError(`blockSize must be a power of two between ${MIN_BLOCK_SIZE} and ${MAX_BLOCK_SIZE}, got ${size}`);
|
|
40
|
+
}
|
|
41
|
+
this.blockSize = size;
|
|
42
|
+
this.source = body;
|
|
43
|
+
}
|
|
44
|
+
get totalBlocks() {
|
|
45
|
+
if (!this.buffered) {
|
|
46
|
+
throw new Error('totalBlocks is not available until getBlock() has been called');
|
|
47
|
+
}
|
|
48
|
+
return Math.ceil(this.buffered.length / this.blockSize);
|
|
49
|
+
}
|
|
50
|
+
abort(reason = 'explicit') {
|
|
51
|
+
if (this.aborted)
|
|
52
|
+
return;
|
|
53
|
+
this.aborted = true;
|
|
54
|
+
this.emit('block-transfer-aborted', { reason });
|
|
55
|
+
}
|
|
56
|
+
async getBlock(num) {
|
|
57
|
+
if (!this.buffered) {
|
|
58
|
+
this.buffered = await this.bufferSource();
|
|
59
|
+
const crc = crc32(this.buffered);
|
|
60
|
+
this.etag = new Uint8Array(4);
|
|
61
|
+
new DataView(this.etag.buffer).setUint32(0, crc, false);
|
|
62
|
+
}
|
|
63
|
+
const total = Math.ceil(this.buffered.length / this.blockSize);
|
|
64
|
+
if (num >= total) {
|
|
65
|
+
throw new RangeError(`Block NUM ${num} is out of range (totalBlocks=${total})`);
|
|
66
|
+
}
|
|
67
|
+
const start = num * this.blockSize;
|
|
68
|
+
const end = Math.min(start + this.blockSize, this.buffered.length);
|
|
69
|
+
const payload = this.buffered.slice(start, end);
|
|
70
|
+
const m = num < total - 1;
|
|
71
|
+
if (!m && !this.completeFired) {
|
|
72
|
+
this.completeFired = true;
|
|
73
|
+
this.emit('block-transfer-complete');
|
|
74
|
+
}
|
|
75
|
+
return { payload, m, etag: this.etag };
|
|
76
|
+
}
|
|
77
|
+
async bufferSource() {
|
|
78
|
+
if (Buffer.isBuffer(this.source)) {
|
|
79
|
+
return new Uint8Array(this.source);
|
|
80
|
+
}
|
|
81
|
+
const chunks = [];
|
|
82
|
+
const reader = this.source.getReader();
|
|
83
|
+
while (true) {
|
|
84
|
+
const { done, value } = await reader.read();
|
|
85
|
+
if (done)
|
|
86
|
+
break;
|
|
87
|
+
chunks.push(value);
|
|
88
|
+
}
|
|
89
|
+
const total = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
90
|
+
const result = new Uint8Array(total);
|
|
91
|
+
let offset = 0;
|
|
92
|
+
for (const chunk of chunks) {
|
|
93
|
+
result.set(chunk, offset);
|
|
94
|
+
offset += chunk.length;
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=block2-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block2-chunker.js","sourceRoot":"","sources":["../../src/blockwise/block2-chunker.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,mFAAmF;AACnF,2EAA2E;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B,SAAS,KAAK,CAAC,IAAgB;IAC7B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,GAAG,GAAG,UAAU,CAAC;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,CAAC,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;QACD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC5B,SAAS,CAAS;IAC3B,QAAQ,CAAyB;IACjC,IAAI,CAAyB;IACpB,MAAM,CAAsC;IACrD,OAAO,GAAG,KAAK,CAAC;IAChB,aAAa,GAAG,KAAK,CAAC;IAE9B,YACE,IAAyC,EACzC,OAAgC;QAEhC,KAAK,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,OAAO,EAAE,SAAS,IAAI,GAAG,CAAC;QACvC,IACE,IAAI,GAAG,cAAc;YACrB,IAAI,GAAG,cAAc;YACrB,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EACzB,CAAC;YACD,MAAM,IAAI,UAAU,CAClB,4CAA4C,cAAc,QAAQ,cAAc,SAAS,IAAI,EAAE,CAChG,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,IAAI,WAAW;QACb,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,MAAM,GAAG,UAAU;QACvB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAA+B,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,UAAU,CAAC,aAAa,GAAG,iCAAiC,KAAK,GAAG,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC;QAE1B,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACvC,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAK,EAAE,CAAC;IAC1C,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,MAAM,MAAM,GAAI,IAAI,CAAC,MAAqC,CAAC,SAAS,EAAE,CAAC;QACvE,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QACzB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { BlockOption } from './option.js';
|
|
2
|
+
export { BlockOptionError, encodeBlockOption, decodeBlockOption, blockSize } from './option.js';
|
|
3
|
+
export type { Block1AssemblerOptions, BlockTransferEvent } from './block1-assembler.js';
|
|
4
|
+
export { Block1Assembler } from './block1-assembler.js';
|
|
5
|
+
export { Block2Chunker } from './block2-chunker.js';
|
|
6
|
+
export { blockwiseMiddleware } from './middleware.js';
|
|
7
|
+
export type { BlockwiseMiddlewareOptions } from './middleware.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|