@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.
Files changed (157) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +78 -0
  3. package/dist/api/exchange-context.d.ts +34 -0
  4. package/dist/api/exchange-context.d.ts.map +1 -0
  5. package/dist/api/exchange-context.js +2 -0
  6. package/dist/api/exchange-context.js.map +1 -0
  7. package/dist/api/headers.d.ts +10 -0
  8. package/dist/api/headers.d.ts.map +1 -0
  9. package/dist/api/headers.js +69 -0
  10. package/dist/api/headers.js.map +1 -0
  11. package/dist/api/index.d.ts +5 -0
  12. package/dist/api/index.d.ts.map +1 -0
  13. package/dist/api/index.js +4 -0
  14. package/dist/api/index.js.map +1 -0
  15. package/dist/api/request.d.ts +11 -0
  16. package/dist/api/request.d.ts.map +1 -0
  17. package/dist/api/request.js +49 -0
  18. package/dist/api/request.js.map +1 -0
  19. package/dist/api/response.d.ts +11 -0
  20. package/dist/api/response.d.ts.map +1 -0
  21. package/dist/api/response.js +19 -0
  22. package/dist/api/response.js.map +1 -0
  23. package/dist/blockwise/block1-assembler.d.ts +26 -0
  24. package/dist/blockwise/block1-assembler.d.ts.map +1 -0
  25. package/dist/blockwise/block1-assembler.js +94 -0
  26. package/dist/blockwise/block1-assembler.js.map +1 -0
  27. package/dist/blockwise/block2-chunker.d.ts +23 -0
  28. package/dist/blockwise/block2-chunker.d.ts.map +1 -0
  29. package/dist/blockwise/block2-chunker.js +99 -0
  30. package/dist/blockwise/block2-chunker.js.map +1 -0
  31. package/dist/blockwise/index.d.ts +8 -0
  32. package/dist/blockwise/index.d.ts.map +1 -0
  33. package/dist/blockwise/index.js +5 -0
  34. package/dist/blockwise/index.js.map +1 -0
  35. package/dist/blockwise/middleware.d.ts +7 -0
  36. package/dist/blockwise/middleware.d.ts.map +1 -0
  37. package/dist/blockwise/middleware.js +120 -0
  38. package/dist/blockwise/middleware.js.map +1 -0
  39. package/dist/blockwise/option.d.ts +12 -0
  40. package/dist/blockwise/option.d.ts.map +1 -0
  41. package/dist/blockwise/option.js +55 -0
  42. package/dist/blockwise/option.js.map +1 -0
  43. package/dist/index.d.ts +10 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +6 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/message/index.d.ts +21 -0
  48. package/dist/message/index.d.ts.map +1 -0
  49. package/dist/message/index.js +79 -0
  50. package/dist/message/index.js.map +1 -0
  51. package/dist/observability.d.ts +44 -0
  52. package/dist/observability.d.ts.map +1 -0
  53. package/dist/observability.js +71 -0
  54. package/dist/observability.js.map +1 -0
  55. package/dist/observe-notification.d.ts +21 -0
  56. package/dist/observe-notification.d.ts.map +1 -0
  57. package/dist/observe-notification.js +87 -0
  58. package/dist/observe-notification.js.map +1 -0
  59. package/dist/observe.d.ts +10 -0
  60. package/dist/observe.d.ts.map +1 -0
  61. package/dist/observe.js +3 -0
  62. package/dist/observe.js.map +1 -0
  63. package/dist/option-parser/index.d.ts +30 -0
  64. package/dist/option-parser/index.d.ts.map +1 -0
  65. package/dist/option-parser/index.js +125 -0
  66. package/dist/option-parser/index.js.map +1 -0
  67. package/dist/router/app.d.ts +8 -0
  68. package/dist/router/app.d.ts.map +1 -0
  69. package/dist/router/app.js +25 -0
  70. package/dist/router/app.js.map +1 -0
  71. package/dist/router/content-format.d.ts +7 -0
  72. package/dist/router/content-format.d.ts.map +1 -0
  73. package/dist/router/content-format.js +23 -0
  74. package/dist/router/content-format.js.map +1 -0
  75. package/dist/router/index.d.ts +9 -0
  76. package/dist/router/index.d.ts.map +1 -0
  77. package/dist/router/index.js +5 -0
  78. package/dist/router/index.js.map +1 -0
  79. package/dist/router/radix.d.ts +16 -0
  80. package/dist/router/radix.d.ts.map +1 -0
  81. package/dist/router/radix.js +69 -0
  82. package/dist/router/radix.js.map +1 -0
  83. package/dist/router/router.d.ts +38 -0
  84. package/dist/router/router.d.ts.map +1 -0
  85. package/dist/router/router.js +111 -0
  86. package/dist/router/router.js.map +1 -0
  87. package/dist/router.d.ts +2 -0
  88. package/dist/router.d.ts.map +1 -0
  89. package/dist/router.js +2 -0
  90. package/dist/router.js.map +1 -0
  91. package/dist/security.d.ts +3 -0
  92. package/dist/security.d.ts.map +1 -0
  93. package/dist/security.js +2 -0
  94. package/dist/security.js.map +1 -0
  95. package/dist/store/index.d.ts +26 -0
  96. package/dist/store/index.d.ts.map +1 -0
  97. package/dist/store/index.js +68 -0
  98. package/dist/store/index.js.map +1 -0
  99. package/dist/store/sqlite-store.d.ts +10 -0
  100. package/dist/store/sqlite-store.d.ts.map +1 -0
  101. package/dist/store/sqlite-store.js +75 -0
  102. package/dist/store/sqlite-store.js.map +1 -0
  103. package/dist/store.d.ts +5 -0
  104. package/dist/store.d.ts.map +1 -0
  105. package/dist/store.js +3 -0
  106. package/dist/store.js.map +1 -0
  107. package/dist/transport/dtls.d.ts +38 -0
  108. package/dist/transport/dtls.d.ts.map +1 -0
  109. package/dist/transport/dtls.js +151 -0
  110. package/dist/transport/dtls.js.map +1 -0
  111. package/dist/transport/events.d.ts +34 -0
  112. package/dist/transport/events.d.ts.map +1 -0
  113. package/dist/transport/events.js +2 -0
  114. package/dist/transport/events.js.map +1 -0
  115. package/dist/transport/index.d.ts +10 -0
  116. package/dist/transport/index.d.ts.map +1 -0
  117. package/dist/transport/index.js +5 -0
  118. package/dist/transport/index.js.map +1 -0
  119. package/dist/transport/tcp-connection.d.ts +18 -0
  120. package/dist/transport/tcp-connection.d.ts.map +1 -0
  121. package/dist/transport/tcp-connection.js +72 -0
  122. package/dist/transport/tcp-connection.js.map +1 -0
  123. package/dist/transport/tcp-frame.d.ts +17 -0
  124. package/dist/transport/tcp-frame.d.ts.map +1 -0
  125. package/dist/transport/tcp-frame.js +112 -0
  126. package/dist/transport/tcp-frame.js.map +1 -0
  127. package/dist/transport/tcp-stream.d.ts +21 -0
  128. package/dist/transport/tcp-stream.d.ts.map +1 -0
  129. package/dist/transport/tcp-stream.js +52 -0
  130. package/dist/transport/tcp-stream.js.map +1 -0
  131. package/dist/transport/udp.d.ts +97 -0
  132. package/dist/transport/udp.d.ts.map +1 -0
  133. package/dist/transport/udp.js +994 -0
  134. package/dist/transport/udp.js.map +1 -0
  135. package/dist/transport.d.ts +3 -0
  136. package/dist/transport.d.ts.map +1 -0
  137. package/dist/transport.js +2 -0
  138. package/dist/transport.js.map +1 -0
  139. package/docs/api-reference.md +536 -0
  140. package/docs/blockwise.md +117 -0
  141. package/docs/observability.md +206 -0
  142. package/docs/observe.md +203 -0
  143. package/docs/releasing.md +106 -0
  144. package/docs/router.md +170 -0
  145. package/docs/store.md +212 -0
  146. package/docs/tcp-transport.md +89 -0
  147. package/docs/udp-transport.md +81 -0
  148. package/examples/slice-1.ts +12 -0
  149. package/examples/slice-2.ts +96 -0
  150. package/examples/slice-3-psk.ts +70 -0
  151. package/examples/slice-3-x509.ts +85 -0
  152. package/examples/slice-4.ts +45 -0
  153. package/examples/slice-5-firmware.ts +207 -0
  154. package/examples/slice-6-temperature.ts +163 -0
  155. package/examples/slice-7-file-store.ts +92 -0
  156. package/examples/slice-7-otel.ts +123 -0
  157. package/package.json +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blockwise/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAChG,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { BlockOptionError, encodeBlockOption, decodeBlockOption, blockSize } from './option.js';
2
+ export { Block1Assembler } from './block1-assembler.js';
3
+ export { Block2Chunker } from './block2-chunker.js';
4
+ export { blockwiseMiddleware } from './middleware.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blockwise/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Middleware } from '../router/router.js';
2
+ export interface BlockwiseMiddlewareOptions {
3
+ maxBytes?: number;
4
+ idleTimeoutMs?: number;
5
+ }
6
+ export declare function blockwiseMiddleware(options?: BlockwiseMiddlewareOptions): Middleware;
7
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/blockwise/middleware.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,UAAU,CAyGpF"}
@@ -0,0 +1,120 @@
1
+ import { OptionNumber } from '../option-parser/index.js';
2
+ import { decodeBlockOption, encodeBlockOption } from './option.js';
3
+ import { Block1Assembler } from './block1-assembler.js';
4
+ import { Block2Chunker } from './block2-chunker.js';
5
+ // RFC 7959 / RFC 7252 CoAP response codes (cls<<5 | detail)
6
+ const CODE_REQUEST_INCOMPLETE = 0x88; // 4.08
7
+ const CODE_TOO_LARGE = 0x8d; // 4.13
8
+ const ETAG_OPTION = 4;
9
+ function makeResponse(statusCode, body, opts) {
10
+ return {
11
+ statusCode,
12
+ status: '',
13
+ body: body ?? null,
14
+ headers: {
15
+ get: (_name) => null,
16
+ has: (_name) => false,
17
+ set: (_name, _value) => { },
18
+ toOptions: () => opts ?? [],
19
+ },
20
+ };
21
+ }
22
+ export function blockwiseMiddleware(options) {
23
+ const assemblers = new Map();
24
+ const chunkers = new Map();
25
+ return async (req, ctx, next) => {
26
+ const tokenKey = Buffer.from(ctx.token).toString('hex');
27
+ const block1Opt = ctx.options.find(o => o.number === OptionNumber.Block1);
28
+ const block2Opt = ctx.options.find(o => o.number === OptionNumber.Block2);
29
+ // Block1 upload path
30
+ if (block1Opt) {
31
+ const block = decodeBlockOption(block1Opt.value);
32
+ let assembler = assemblers.get(tokenKey);
33
+ if (!assembler) {
34
+ assembler = new Block1Assembler({
35
+ maxBytes: options?.maxBytes,
36
+ idleTimeoutMs: options?.idleTimeoutMs,
37
+ });
38
+ assemblers.set(tokenKey, assembler);
39
+ assembler.once('block-transfer-aborted', () => assemblers.delete(tokenKey));
40
+ assembler.once('block-transfer-complete', () => assemblers.delete(tokenKey));
41
+ }
42
+ let chunkPayload;
43
+ if (req.body) {
44
+ const reader = req.body.getReader();
45
+ const chunks = [];
46
+ while (true) {
47
+ const { done, value } = await reader.read();
48
+ if (done)
49
+ break;
50
+ if (value)
51
+ chunks.push(value);
52
+ }
53
+ const total = chunks.reduce((n, c) => n + c.length, 0);
54
+ chunkPayload = new Uint8Array(total);
55
+ let pos = 0;
56
+ for (const chunk of chunks) {
57
+ chunkPayload.set(chunk, pos);
58
+ pos += chunk.length;
59
+ }
60
+ }
61
+ else {
62
+ chunkPayload = new Uint8Array(0);
63
+ }
64
+ const result = assembler.addChunk(block.num, block.szx, block.m, chunkPayload);
65
+ if (result === 'continue') {
66
+ await ctx.continue();
67
+ return;
68
+ }
69
+ if (result === 'out-of-order') {
70
+ assembler.abort('out-of-order');
71
+ await ctx.respond(makeResponse(CODE_REQUEST_INCOMPLETE));
72
+ return;
73
+ }
74
+ if (result === 'too-large') {
75
+ await ctx.respond(makeResponse(CODE_TOO_LARGE));
76
+ return;
77
+ }
78
+ // 'complete': attach assembled body and forward to handler
79
+ req.body = assembler.body;
80
+ await next();
81
+ return;
82
+ }
83
+ // Block2 download path
84
+ if (block2Opt) {
85
+ const block = decodeBlockOption(block2Opt.value);
86
+ let capturedResponse;
87
+ const originalRespond = ctx.respond.bind(ctx);
88
+ ctx.respond = async (res) => { capturedResponse = res; };
89
+ await next();
90
+ ctx.respond = originalRespond;
91
+ if (!capturedResponse)
92
+ return;
93
+ let chunker = chunkers.get(tokenKey);
94
+ if (!chunker) {
95
+ const responseBody = capturedResponse.body;
96
+ if (!responseBody) {
97
+ await originalRespond(capturedResponse);
98
+ return;
99
+ }
100
+ const reqBlockSize = Math.min(1 << (block.szx + 4), 1024);
101
+ chunker = new Block2Chunker(Buffer.from(responseBody), { blockSize: reqBlockSize });
102
+ chunkers.set(tokenKey, chunker);
103
+ chunker.once('block-transfer-complete', () => chunkers.delete(tokenKey));
104
+ chunker.once('block-transfer-aborted', () => chunkers.delete(tokenKey));
105
+ }
106
+ const { payload, m, etag } = await chunker.getBlock(block.num);
107
+ const existingOpts = capturedResponse.headers.toOptions();
108
+ const responseOpts = [
109
+ ...existingOpts,
110
+ { number: ETAG_OPTION, value: etag },
111
+ { number: OptionNumber.Block2, value: encodeBlockOption({ num: block.num, szx: block.szx, m }) },
112
+ ];
113
+ await originalRespond(makeResponse(capturedResponse.statusCode, payload, responseOpts));
114
+ return;
115
+ }
116
+ // Plain request — pass through unchanged
117
+ await next();
118
+ };
119
+ }
120
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/blockwise/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAUpD,4DAA4D;AAC5D,MAAM,uBAAuB,GAAG,IAAI,CAAC,CAAC,OAAO;AAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,CAAU,OAAO;AAC7C,MAAM,WAAW,GAAG,CAAC,CAAC;AAOtB,SAAS,YAAY,CAAC,UAAkB,EAAE,IAAiB,EAAE,IAAmB;IAC9E,OAAO;QACL,UAAU;QACV,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,IAAI,IAAI,IAAI;QAClB,OAAO,EAAE;YACP,GAAG,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI;YAC5B,GAAG,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK;YAC7B,GAAG,EAAE,CAAC,KAAa,EAAE,MAAc,EAAE,EAAE,GAAE,CAAC;YAC1C,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE;SAC5B;KACqB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAoC;IACtE,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IAElD,OAAO,KAAK,EAAE,GAAY,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;QAE1E,qBAAqB;QACrB,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAEjD,IAAI,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,GAAG,IAAI,eAAe,CAAC;oBAC9B,QAAQ,EAAE,OAAO,EAAE,QAAQ;oBAC3B,aAAa,EAAE,OAAO,EAAE,aAAa;iBACtC,CAAC,CAAC;gBACH,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;gBACpC,SAAS,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC5E,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/E,CAAC;YAED,IAAI,YAAwB,CAAC;YAC7B,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAiB,EAAE,CAAC;gBAChC,OAAO,IAAI,EAAE,CAAC;oBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;oBAC5C,IAAI,IAAI;wBAAE,MAAM;oBAChB,IAAI,KAAK;wBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChC,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBACvD,YAAY,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;gBACrC,IAAI,GAAG,GAAG,CAAC,CAAC;gBACZ,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;oBAAC,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC;gBAAC,CAAC;YACpF,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YAE/E,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;gBAC9B,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;gBAChC,MAAM,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC,CAAC;gBACzD,OAAO;YACT,CAAC;YACD,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC3B,MAAM,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,2DAA2D;YAC1D,GAAuD,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;YAC/E,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,uBAAuB;QACvB,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAEjD,IAAI,gBAAsC,CAAC;YAC3C,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9C,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,GAAa,EAAE,EAAE,GAAG,gBAAgB,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAEnE,MAAM,IAAI,EAAE,CAAC;YAEb,GAAG,CAAC,OAAO,GAAG,eAAe,CAAC;YAE9B,IAAI,CAAC,gBAAgB;gBAAE,OAAO;YAE9B,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC;gBAC3C,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,MAAM,eAAe,CAAC,gBAAgB,CAAC,CAAC;oBACxC,OAAO;gBACT,CAAC;gBACD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC1D,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAW,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;gBAC9F,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACzE,OAAO,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC1E,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAE/D,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC1D,MAAM,YAAY,GAAiB;gBACjC,GAAG,YAAY;gBACf,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE;gBACpC,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;aACjG,CAAC;YACF,MAAM,eAAe,CAAC,YAAY,CAAC,gBAAgB,CAAC,UAAU,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QAED,yCAAyC;QACzC,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface BlockOption {
2
+ num: number;
3
+ szx: number;
4
+ m: boolean;
5
+ }
6
+ export declare class BlockOptionError extends Error {
7
+ constructor(message: string);
8
+ }
9
+ export declare function blockSize(szx: number): number;
10
+ export declare function encodeBlockOption(opt: BlockOption): Uint8Array;
11
+ export declare function decodeBlockOption(value: Uint8Array): BlockOption;
12
+ //# sourceMappingURL=option.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option.d.ts","sourceRoot":"","sources":["../../src/blockwise/option.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,OAAO,CAAC;CACZ;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,UAAU,CAqB9D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAwBhE"}
@@ -0,0 +1,55 @@
1
+ // RFC 7959 §2.2 — Block option encoding/decoding
2
+ export class BlockOptionError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = 'BlockOptionError';
6
+ }
7
+ }
8
+ export function blockSize(szx) {
9
+ return 2 ** (szx + 4);
10
+ }
11
+ export function encodeBlockOption(opt) {
12
+ const { num, szx, m } = opt;
13
+ const mBit = m ? 1 : 0;
14
+ // Lower 4 bits of first byte: M(1) | SZX(3)
15
+ const lsb = (mBit << 3) | (szx & 0x07);
16
+ if (num < 16) {
17
+ // 1 byte: NUM(4) | M(1) | SZX(3)
18
+ return new Uint8Array([(num << 4) | lsb]);
19
+ }
20
+ else if (num < 4096) {
21
+ // 2 bytes: 4 high bits of NUM in first byte, 8 low bits in second
22
+ return new Uint8Array([((num >> 4) & 0xff), ((num & 0x0f) << 4) | lsb]);
23
+ }
24
+ else {
25
+ // 3 bytes: 12 high bits split across first two bytes, 8 low bits in third
26
+ return new Uint8Array([
27
+ (num >> 12) & 0xff,
28
+ (num >> 4) & 0xff,
29
+ ((num & 0x0f) << 4) | lsb,
30
+ ]);
31
+ }
32
+ }
33
+ export function decodeBlockOption(value) {
34
+ if (value.length === 0 || value.length > 3) {
35
+ throw new BlockOptionError(`Block option value must be 1–3 bytes, got ${value.length}`);
36
+ }
37
+ const lastByte = value[value.length - 1];
38
+ const szx = lastByte & 0x07;
39
+ if (szx === 7) {
40
+ throw new BlockOptionError('SZX value 7 is reserved');
41
+ }
42
+ const m = ((lastByte >> 3) & 0x01) === 1;
43
+ let num;
44
+ if (value.length === 1) {
45
+ num = (lastByte >> 4) & 0x0f;
46
+ }
47
+ else if (value.length === 2) {
48
+ num = (value[0] << 4) | ((lastByte >> 4) & 0x0f);
49
+ }
50
+ else {
51
+ num = (value[0] << 12) | (value[1] << 4) | ((lastByte >> 4) & 0x0f);
52
+ }
53
+ return { num, szx, m };
54
+ }
55
+ //# sourceMappingURL=option.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option.js","sourceRoot":"","sources":["../../src/blockwise/option.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export { encodeOptions, decodeOptions, uintToBytes, bytesToUint, stringToBytes, bytesToString, OptionNumber, } from './option-parser/index.js';
2
+ export type { CoapOption, EncodeOptionsOpts, DecodeOptionsResult } from './option-parser/index.js';
3
+ export { encodeMessage, decodeMessage, codeToString, stringToCode, CoapDecodeError, } from './message/index.js';
4
+ export type { CoapMessage, CoapMessageType, CoapCode } from './message/index.js';
5
+ export { Request, Response, Headers } from './api/index.js';
6
+ export type { ExchangeContext, Peer } from './api/index.js';
7
+ export { createServer } from './transport/index.js';
8
+ export type { Server, ServerOptions, ListenAddress, Logger, ServerEventMap, SecurityOptions, PskSecurityOptions, X509SecurityOptions, DtlsHandshakeEvent } from './transport/index.js';
9
+ export type { Observable, Observer, Unsubscribe } from './observe.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEnG,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEjF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5D,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAEvL,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // @sirena-lwm2m/coap — RFC 7252 CoAP stack
2
+ export { encodeOptions, decodeOptions, uintToBytes, bytesToUint, stringToBytes, bytesToString, OptionNumber, } from './option-parser/index.js';
3
+ export { encodeMessage, decodeMessage, codeToString, stringToCode, CoapDecodeError, } from './message/index.js';
4
+ export { Request, Response, Headers } from './api/index.js';
5
+ export { createServer } from './transport/index.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { CoapOption } from '../option-parser/index.js';
2
+ export type { CoapOption };
3
+ export type CoapMessageType = 'CON' | 'NON' | 'ACK' | 'RST';
4
+ export type CoapCode = number;
5
+ export interface CoapMessage {
6
+ version: number;
7
+ type: CoapMessageType;
8
+ token: Uint8Array;
9
+ code: CoapCode;
10
+ messageId: number;
11
+ options: CoapOption[];
12
+ payload: Uint8Array;
13
+ }
14
+ export declare class CoapDecodeError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ export declare function codeToString(code: CoapCode): string;
18
+ export declare function stringToCode(s: string): CoapCode;
19
+ export declare function encodeMessage(msg: CoapMessage): Uint8Array;
20
+ export declare function decodeMessage(buf: Uint8Array): CoapMessage;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/message/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAInD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAKhD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,UAAU,CA6B1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW,CAyC1D"}
@@ -0,0 +1,79 @@
1
+ import { encodeOptions, decodeOptions } from '../option-parser/index.js';
2
+ export class CoapDecodeError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = 'CoapDecodeError';
6
+ }
7
+ }
8
+ const TYPE_MAP = ['CON', 'NON', 'ACK', 'RST'];
9
+ export function codeToString(code) {
10
+ const cls = (code >> 5) & 0x07;
11
+ const detail = code & 0x1f;
12
+ return `${cls}.${detail.toString().padStart(2, '0')}`;
13
+ }
14
+ export function stringToCode(s) {
15
+ const [clsStr, detailStr] = s.split('.');
16
+ const cls = parseInt(clsStr, 10);
17
+ const detail = parseInt(detailStr, 10);
18
+ return ((cls & 0x07) << 5) | (detail & 0x1f);
19
+ }
20
+ export function encodeMessage(msg) {
21
+ const tkl = msg.token.length;
22
+ const typeVal = TYPE_MAP.indexOf(msg.type);
23
+ // byte 0: Ver=1 (bits 7-6), T (bits 5-4), TKL (bits 3-0)
24
+ const byte0 = (1 << 6) | ((typeVal & 0x03) << 4) | (tkl & 0x0f);
25
+ const byte1 = msg.code & 0xff;
26
+ const byte2 = (msg.messageId >> 8) & 0xff;
27
+ const byte3 = msg.messageId & 0xff;
28
+ const header = new Uint8Array([byte0, byte1, byte2, byte3]);
29
+ const encodedOptions = encodeOptions(msg.options);
30
+ const hasPayload = msg.payload.length > 0;
31
+ const totalLen = 4 + tkl + encodedOptions.length + (hasPayload ? 1 + msg.payload.length : 0);
32
+ const result = new Uint8Array(totalLen);
33
+ let pos = 0;
34
+ result.set(header, pos);
35
+ pos += 4;
36
+ result.set(msg.token, pos);
37
+ pos += tkl;
38
+ result.set(encodedOptions, pos);
39
+ pos += encodedOptions.length;
40
+ if (hasPayload) {
41
+ result[pos++] = 0xff;
42
+ result.set(msg.payload, pos);
43
+ }
44
+ return result;
45
+ }
46
+ export function decodeMessage(buf) {
47
+ if (buf.length < 4) {
48
+ throw new CoapDecodeError(`Buffer too short: ${buf.length} bytes (minimum 4)`);
49
+ }
50
+ const byte0 = buf[0];
51
+ const ver = (byte0 >> 6) & 0x03;
52
+ if (ver !== 1) {
53
+ throw new CoapDecodeError(`Invalid CoAP version: ${ver} (expected 1)`);
54
+ }
55
+ const typeVal = (byte0 >> 4) & 0x03;
56
+ const tkl = byte0 & 0x0f;
57
+ if (tkl > 8) {
58
+ throw new CoapDecodeError(`Invalid TKL: ${tkl} (max 8)`);
59
+ }
60
+ const code = buf[1];
61
+ const messageId = (buf[2] << 8) | buf[3];
62
+ if (buf.length < 4 + tkl) {
63
+ throw new CoapDecodeError(`Buffer too short for token: need ${4 + tkl}, got ${buf.length}`);
64
+ }
65
+ const token = buf.slice(4, 4 + tkl);
66
+ const optionsStart = 4 + tkl;
67
+ const { options, payloadOffset } = decodeOptions(buf, optionsStart);
68
+ const payload = payloadOffset < buf.length ? buf.slice(payloadOffset) : new Uint8Array(0);
69
+ return {
70
+ version: 1,
71
+ type: TYPE_MAP[typeVal],
72
+ token,
73
+ code,
74
+ messageId,
75
+ options,
76
+ payload,
77
+ };
78
+ }
79
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/message/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface Counter {
2
+ add(value: number, attributes?: Record<string, string | number | boolean>): void;
3
+ }
4
+ export interface UpDownCounter {
5
+ add(value: number, attributes?: Record<string, string | number | boolean>): void;
6
+ }
7
+ export interface Histogram {
8
+ record(value: number, attributes?: Record<string, string | number | boolean>): void;
9
+ }
10
+ export interface CoapMetrics {
11
+ /** Incremented on every incoming request (CON or NON). */
12
+ requestRate: Counter;
13
+ /** Tracks the number of currently-active exchanges (in-flight handlers). */
14
+ activeExchanges: UpDownCounter;
15
+ /** Tracks the number of active Observe registrations. */
16
+ observeRegistrations: UpDownCounter;
17
+ /** Incremented when a block-wise transfer completes successfully. */
18
+ blockTransferComplete: Counter;
19
+ /** Incremented when a block-wise transfer is aborted. */
20
+ blockTransferAborted: Counter;
21
+ /** Incremented on every dedup-store hit (CON retransmission replayed). */
22
+ dedupHits: Counter;
23
+ /** Incremented on every transport-level error (decode failure, socket error). */
24
+ transportErrors: Counter;
25
+ }
26
+ export declare function createNoopMetrics(): CoapMetrics;
27
+ interface OtelMeter {
28
+ createCounter(name: string, options?: {
29
+ description?: string;
30
+ unit?: string;
31
+ }): Counter;
32
+ createUpDownCounter(name: string, options?: {
33
+ description?: string;
34
+ unit?: string;
35
+ }): UpDownCounter;
36
+ createHistogram(name: string, options?: {
37
+ description?: string;
38
+ unit?: string;
39
+ }): Histogram;
40
+ }
41
+ export declare function bindOtel(meter: OtelMeter): CoapMetrics;
42
+ export declare function tryBindOtel(meterName: string): Promise<CoapMetrics>;
43
+ export {};
44
+ //# sourceMappingURL=observability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;CACrF;AAED,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,WAAW,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,eAAe,EAAE,aAAa,CAAC;IAC/B,yDAAyD;IACzD,oBAAoB,EAAE,aAAa,CAAC;IACpC,qEAAqE;IACrE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,yDAAyD;IACzD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,eAAe,EAAE,OAAO,CAAC;CAC1B;AAOD,wBAAgB,iBAAiB,IAAI,WAAW,CAU/C;AAID,UAAU,SAAS;IACjB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IACxF,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;IACpG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CAC7F;AAID,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CA+BtD;AAID,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAezE"}
@@ -0,0 +1,71 @@
1
+ // Lazy OTel metrics — zero cost when @opentelemetry/api is absent.
2
+ //
3
+ // Callers that want real metrics must either:
4
+ // a) call bindOtel(meter) with a Meter they obtained from their OTel SDK, or
5
+ // b) call tryBindOtel(meterName) to auto-detect and bind, falling back to no-ops.
6
+ //
7
+ // Import of @opentelemetry/api never happens at module-load time.
8
+ // ── No-op implementations ─────────────────────────────────────────────────────
9
+ const NOOP_COUNTER = { add: () => { } };
10
+ const NOOP_UPDOWN = { add: () => { } };
11
+ export function createNoopMetrics() {
12
+ return {
13
+ requestRate: NOOP_COUNTER,
14
+ activeExchanges: NOOP_UPDOWN,
15
+ observeRegistrations: NOOP_UPDOWN,
16
+ blockTransferComplete: NOOP_COUNTER,
17
+ blockTransferAborted: NOOP_COUNTER,
18
+ dedupHits: NOOP_COUNTER,
19
+ transportErrors: NOOP_COUNTER,
20
+ };
21
+ }
22
+ // ── bindOtel — synchronous, caller supplies the Meter ────────────────────────
23
+ export function bindOtel(meter) {
24
+ return {
25
+ requestRate: meter.createCounter('coap.requests', {
26
+ description: 'Number of incoming CoAP requests',
27
+ unit: '{request}',
28
+ }),
29
+ activeExchanges: meter.createUpDownCounter('coap.exchanges.active', {
30
+ description: 'Number of currently in-flight CoAP exchanges',
31
+ unit: '{exchange}',
32
+ }),
33
+ observeRegistrations: meter.createUpDownCounter('coap.observe.registrations', {
34
+ description: 'Number of active Observe registrations',
35
+ unit: '{registration}',
36
+ }),
37
+ blockTransferComplete: meter.createCounter('coap.block.complete', {
38
+ description: 'Number of successfully completed block-wise transfers',
39
+ unit: '{transfer}',
40
+ }),
41
+ blockTransferAborted: meter.createCounter('coap.block.aborted', {
42
+ description: 'Number of aborted block-wise transfers',
43
+ unit: '{transfer}',
44
+ }),
45
+ dedupHits: meter.createCounter('coap.dedup.hits', {
46
+ description: 'Number of CON retransmissions that were served from the dedup store',
47
+ unit: '{hit}',
48
+ }),
49
+ transportErrors: meter.createCounter('coap.transport.errors', {
50
+ description: 'Number of transport-level errors (decode failures, socket errors)',
51
+ unit: '{error}',
52
+ }),
53
+ };
54
+ }
55
+ // ── tryBindOtel — lazy import, falls back to no-ops ──────────────────────────
56
+ export async function tryBindOtel(meterName) {
57
+ try {
58
+ // Dynamic import kept as a string expression so the TypeScript compiler does
59
+ // not chase the type declaration of the optional peer dep.
60
+ const specifier = '@opentelemetry/api';
61
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
62
+ const api = await (new Function('s', 'return import(s)')(specifier));
63
+ const meter = api.metrics.getMeter(meterName);
64
+ return bindOtel(meter);
65
+ }
66
+ catch {
67
+ // @opentelemetry/api not installed — return zero-cost no-ops.
68
+ return createNoopMetrics();
69
+ }
70
+ }
71
+ //# sourceMappingURL=observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.js","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,8CAA8C;AAC9C,+EAA+E;AAC/E,oFAAoF;AACpF,EAAE;AACF,kEAAkE;AA+BlE,iFAAiF;AAEjF,MAAM,YAAY,GAAY,EAAE,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAChD,MAAM,WAAW,GAAkB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAErD,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,WAAW,EAAW,YAAY;QAClC,eAAe,EAAO,WAAW;QACjC,oBAAoB,EAAE,WAAW;QACjC,qBAAqB,EAAE,YAAY;QACnC,oBAAoB,EAAG,YAAY;QACnC,SAAS,EAAa,YAAY;QAClC,eAAe,EAAO,YAAY;KACnC,CAAC;AACJ,CAAC;AAUD,gFAAgF;AAEhF,MAAM,UAAU,QAAQ,CAAC,KAAgB;IACvC,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,eAAe,EAAE;YAChD,WAAW,EAAE,kCAAkC;YAC/C,IAAI,EAAE,WAAW;SAClB,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,mBAAmB,CAAC,uBAAuB,EAAE;YAClE,WAAW,EAAE,8CAA8C;YAC3D,IAAI,EAAE,YAAY;SACnB,CAAC;QACF,oBAAoB,EAAE,KAAK,CAAC,mBAAmB,CAAC,4BAA4B,EAAE;YAC5E,WAAW,EAAE,wCAAwC;YACrD,IAAI,EAAE,gBAAgB;SACvB,CAAC;QACF,qBAAqB,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,EAAE;YAChE,WAAW,EAAE,uDAAuD;YACpE,IAAI,EAAE,YAAY;SACnB,CAAC;QACF,oBAAoB,EAAE,KAAK,CAAC,aAAa,CAAC,oBAAoB,EAAE;YAC9D,WAAW,EAAE,wCAAwC;YACrD,IAAI,EAAE,YAAY;SACnB,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,EAAE;YAChD,WAAW,EAAE,qEAAqE;YAClF,IAAI,EAAE,OAAO;SACd,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,uBAAuB,EAAE;YAC5D,WAAW,EAAE,mEAAmE;YAChF,IAAI,EAAE,SAAS;SAChB,CAAC;KACH,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB;IACjD,IAAI,CAAC;QACH,6EAA6E;QAC7E,2DAA2D;QAC3D,MAAM,SAAS,GAAG,oBAAoB,CAAC;QACvC,8DAA8D;QAC9D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,SAAS,CAAC,CAElE,CAAC;QACF,MAAM,KAAK,GAAc,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACzD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Observable } from './observe.js';
2
+ export declare const MAX_OBSERVE_SEQ = 16777215;
3
+ export interface NotificationLoopOptions {
4
+ initialSeq?: number;
5
+ }
6
+ export declare class NotificationLoop {
7
+ private seq;
8
+ constructor(opts?: NotificationLoopOptions);
9
+ nextSeq(): number;
10
+ }
11
+ export interface ActiveObserveOptions {
12
+ notifyEveryValue?: boolean;
13
+ }
14
+ export interface NotificationSender {
15
+ (seq: number, payload: Uint8Array): void;
16
+ }
17
+ export declare function startNotificationLoop(observable: Observable<unknown>, encodeValue: (value: unknown) => Uint8Array, send: NotificationSender, onCancel: () => void, opts?: ActiveObserveOptions): {
18
+ ackReceived(): void;
19
+ cancel(): void;
20
+ };
21
+ //# sourceMappingURL=observe-notification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe-notification.d.ts","sourceRoot":"","sources":["../src/observe-notification.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,cAAc,CAAC;AAE5D,eAAO,MAAM,eAAe,WAAW,CAAC;AAExC,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAGD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAAS;gBAER,IAAI,GAAE,uBAA4B;IAK9C,OAAO,IAAI,MAAM;CAKlB;AAED,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1C;AAcD,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,EAC/B,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,UAAU,EAC3C,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,MAAM,IAAI,EACpB,IAAI,GAAE,oBAAyB,GAC9B;IAAE,WAAW,IAAI,IAAI,CAAC;IAAC,MAAM,IAAI,IAAI,CAAA;CAAE,CAuEzC"}
@@ -0,0 +1,87 @@
1
+ // RFC 7641 §4: Observe notification delivery with sequence-number management and conflation
2
+ export const MAX_OBSERVE_SEQ = 0xffffff; // 2^24 - 1
3
+ // Exported for unit-testability of the sequence-number logic
4
+ export class NotificationLoop {
5
+ seq;
6
+ constructor(opts = {}) {
7
+ // initialSeq is the *next* value to return; caller advances from there
8
+ this.seq = opts.initialSeq ?? 0;
9
+ }
10
+ nextSeq() {
11
+ const current = this.seq;
12
+ this.seq = current >= MAX_OBSERVE_SEQ ? 0 : current + 1;
13
+ return current;
14
+ }
15
+ }
16
+ // Drives the notification loop for one (remote, token) registration.
17
+ // Returns a handle with two methods:
18
+ // - ackReceived(): call when the remote ACKs the last CON notification
19
+ // - cancel(): tear down and unsubscribe
20
+ export function startNotificationLoop(observable, encodeValue, send, onCancel, opts = {}) {
21
+ const notifyEveryValue = opts.notifyEveryValue ?? false;
22
+ const state = {
23
+ seq: 1, // 0 was used in the initial ACK
24
+ pendingAck: false,
25
+ queued: null,
26
+ unsub: null,
27
+ cancelled: false,
28
+ };
29
+ function nextSeq() {
30
+ const s = state.seq;
31
+ state.seq = s >= MAX_OBSERVE_SEQ ? 0 : s + 1;
32
+ return s;
33
+ }
34
+ function sendNext(payload) {
35
+ state.pendingAck = true;
36
+ state.queued = null;
37
+ send(nextSeq(), payload);
38
+ }
39
+ function teardown() {
40
+ if (state.cancelled)
41
+ return;
42
+ state.cancelled = true;
43
+ if (state.unsub) {
44
+ state.unsub();
45
+ state.unsub = null;
46
+ }
47
+ onCancel();
48
+ }
49
+ state.unsub = observable.subscribe({
50
+ next(value) {
51
+ if (state.cancelled)
52
+ return;
53
+ const payload = encodeValue(value);
54
+ if (notifyEveryValue) {
55
+ sendNext(payload);
56
+ return;
57
+ }
58
+ if (state.pendingAck) {
59
+ // Conflation: replace queued value with latest
60
+ state.queued = payload;
61
+ return;
62
+ }
63
+ sendNext(payload);
64
+ },
65
+ complete() {
66
+ teardown();
67
+ },
68
+ error(_err) {
69
+ teardown();
70
+ },
71
+ });
72
+ return {
73
+ ackReceived() {
74
+ if (state.cancelled || !state.pendingAck)
75
+ return;
76
+ state.pendingAck = false;
77
+ if (state.queued !== null) {
78
+ const payload = state.queued;
79
+ sendNext(payload);
80
+ }
81
+ },
82
+ cancel() {
83
+ teardown();
84
+ },
85
+ };
86
+ }
87
+ //# sourceMappingURL=observe-notification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe-notification.js","sourceRoot":"","sources":["../src/observe-notification.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export type Unsubscribe = () => void;
2
+ export interface Observer<T> {
3
+ next(value: T): void;
4
+ error?(err: unknown): void;
5
+ complete?(): void;
6
+ }
7
+ export interface Observable<T> {
8
+ subscribe(observer: Observer<T>): Unsubscribe;
9
+ }
10
+ //# sourceMappingURL=observe.d.ts.map