@private.me/xbind 3.0.2 → 3.0.4

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 (222) hide show
  1. package/README.md +2366 -204
  2. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
  3. package/dist-standalone/_deps/shared/cjs/errors.js +1 -729
  4. package/dist-standalone/_deps/shared/cjs/index.js +1 -463
  5. package/dist-standalone/_deps/shared/cjs/types.js +1 -315
  6. package/dist-standalone/_deps/shared/errors.js +1 -244
  7. package/dist-standalone/_deps/shared/index.js +1 -72
  8. package/dist-standalone/_deps/shared/types.js +1 -86
  9. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  10. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  20. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  21. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  28. package/dist-standalone/_deps/xchange/errors.js +1 -1
  29. package/dist-standalone/_deps/xchange/index.js +1 -1
  30. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  31. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  32. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  33. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  34. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  40. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  41. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  42. package/dist-standalone/_deps/xregistry/index.js +1 -1
  43. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  44. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  45. package/dist-standalone/_deps/xregistry/types.js +1 -1
  46. package/dist-standalone/agent-call.d.ts +2 -2
  47. package/dist-standalone/agent-call.js +1 -659
  48. package/dist-standalone/agent-sdk.js +1 -328
  49. package/dist-standalone/agent.d.ts +2 -0
  50. package/dist-standalone/agent.js +1 -1800
  51. package/dist-standalone/approval.js +1 -193
  52. package/dist-standalone/async-iterators.d.ts +3 -3
  53. package/dist-standalone/async-iterators.js +1 -382
  54. package/dist-standalone/auth.js +1 -219
  55. package/dist-standalone/auto-accept.js +1 -229
  56. package/dist-standalone/backup-config.js +1 -201
  57. package/dist-standalone/backup.js +1 -326
  58. package/dist-standalone/batch-operations.js +1 -388
  59. package/dist-standalone/cancellation.js +1 -477
  60. package/dist-standalone/checkpoint.js +1 -186
  61. package/dist-standalone/circuit-breaker.js +1 -468
  62. package/dist-standalone/cjs/agent-call.js +1 -701
  63. package/dist-standalone/cjs/agent-sdk.js +1 -332
  64. package/dist-standalone/cjs/agent.js +1 -1837
  65. package/dist-standalone/cjs/approval.js +1 -199
  66. package/dist-standalone/cjs/async-iterators.js +1 -392
  67. package/dist-standalone/cjs/auth.js +1 -225
  68. package/dist-standalone/cjs/auto-accept.js +1 -233
  69. package/dist-standalone/cjs/backup-config.js +1 -207
  70. package/dist-standalone/cjs/backup.js +1 -330
  71. package/dist-standalone/cjs/batch-operations.js +1 -397
  72. package/dist-standalone/cjs/cancellation.js +1 -490
  73. package/dist-standalone/cjs/checkpoint.js +1 -193
  74. package/dist-standalone/cjs/circuit-breaker.js +1 -476
  75. package/dist-standalone/cjs/cli/init.js +1 -492
  76. package/dist-standalone/cjs/config-validation.js +1 -522
  77. package/dist-standalone/cjs/connect.js +1 -312
  78. package/dist-standalone/cjs/connection-pool.js +1 -506
  79. package/dist-standalone/cjs/correlation-id.js +1 -339
  80. package/dist-standalone/cjs/crypto-utils.js +1 -176
  81. package/dist-standalone/cjs/debug-mode.js +1 -534
  82. package/dist-standalone/cjs/did-document.js +1 -101
  83. package/dist-standalone/cjs/did-privateme.js +1 -130
  84. package/dist-standalone/cjs/did-web.js +1 -201
  85. package/dist-standalone/cjs/discovery.js +1 -462
  86. package/dist-standalone/cjs/dual-mode.js +1 -251
  87. package/dist-standalone/cjs/email-templates.js +1 -313
  88. package/dist-standalone/cjs/email-transport.js +1 -239
  89. package/dist-standalone/cjs/envelope.js +1 -538
  90. package/dist-standalone/cjs/errors.js +1 -913
  91. package/dist-standalone/cjs/event-emitter.js +1 -461
  92. package/dist-standalone/cjs/gateway-state.js +1 -55
  93. package/dist-standalone/cjs/gateway-transport.js +1 -120
  94. package/dist-standalone/cjs/graceful-degradation.js +1 -403
  95. package/dist-standalone/cjs/guardrails.js +1 -223
  96. package/dist-standalone/cjs/health-check.js +1 -336
  97. package/dist-standalone/cjs/http-compat.js +1 -272
  98. package/dist-standalone/cjs/http-status-map.js +1 -571
  99. package/dist-standalone/cjs/identity.js +1 -645
  100. package/dist-standalone/cjs/index.js +1 -406
  101. package/dist-standalone/cjs/invitation.js +1 -421
  102. package/dist-standalone/cjs/invite.js +1 -328
  103. package/dist-standalone/cjs/key-agreement.js +1 -335
  104. package/dist-standalone/cjs/lazy-init.js +1 -300
  105. package/dist-standalone/cjs/logger.js +1 -291
  106. package/dist-standalone/cjs/loopback-transport.js +1 -0
  107. package/dist-standalone/cjs/mdns-discovery.js +1 -202
  108. package/dist-standalone/cjs/nonce-store.js +1 -80
  109. package/dist-standalone/cjs/pairing-manager.js +1 -223
  110. package/dist-standalone/cjs/plugin-system.js +1 -264
  111. package/dist-standalone/cjs/plugins/logging.js +1 -168
  112. package/dist-standalone/cjs/plugins/metrics.js +1 -181
  113. package/dist-standalone/cjs/plugins/validation.js +1 -302
  114. package/dist-standalone/cjs/policy.js +1 -320
  115. package/dist-standalone/cjs/progress-callbacks.js +1 -583
  116. package/dist-standalone/cjs/redis-nonce-store.js +1 -76
  117. package/dist-standalone/cjs/registry-middleware.js +1 -50
  118. package/dist-standalone/cjs/retry-strategies.js +1 -544
  119. package/dist-standalone/cjs/retry-transport.js +1 -102
  120. package/dist-standalone/cjs/runtime/browser.js +1 -533
  121. package/dist-standalone/cjs/runtime/edge.js +1 -526
  122. package/dist-standalone/cjs/runtime/react-native.js +1 -394
  123. package/dist-standalone/cjs/security-policy.js +1 -245
  124. package/dist-standalone/cjs/serialization.js +1 -1040
  125. package/dist-standalone/cjs/split-channel.js +1 -225
  126. package/dist-standalone/cjs/subscription-proof.js +1 -230
  127. package/dist-standalone/cjs/succession.js +1 -148
  128. package/dist-standalone/cjs/timeouts.js +1 -412
  129. package/dist-standalone/cjs/trace-context.js +1 -424
  130. package/dist-standalone/cjs/trace-spans.js +1 -495
  131. package/dist-standalone/cjs/transport.js +1 -63
  132. package/dist-standalone/cjs/trust-registry.js +1 -991
  133. package/dist-standalone/cjs/types/error-response.js +1 -56
  134. package/dist-standalone/cjs/vault-auth.js +1 -178
  135. package/dist-standalone/cjs/vault-store-loader.js +1 -194
  136. package/dist-standalone/cjs/verify.js +1 -25
  137. package/dist-standalone/cjs/version-info.js +1 -543
  138. package/dist-standalone/cjs/xfetch.js +1 -340
  139. package/dist-standalone/cli/init.js +1 -455
  140. package/dist-standalone/cli/setup.js +1 -514
  141. package/dist-standalone/cli/types.js +1 -27
  142. package/dist-standalone/cli/xbind.js +1 -148
  143. package/dist-standalone/config-validation.js +1 -513
  144. package/dist-standalone/connect.js +1 -274
  145. package/dist-standalone/connection-pool.js +1 -500
  146. package/dist-standalone/correlation-id.js +1 -326
  147. package/dist-standalone/crypto-utils.d.ts +2 -7
  148. package/dist-standalone/crypto-utils.js +1 -157
  149. package/dist-standalone/debug-mode.js +1 -510
  150. package/dist-standalone/did-document.js +1 -96
  151. package/dist-standalone/did-privateme.js +1 -121
  152. package/dist-standalone/did-web.js +1 -196
  153. package/dist-standalone/discovery.js +1 -458
  154. package/dist-standalone/dual-mode.js +1 -247
  155. package/dist-standalone/email-templates.js +1 -309
  156. package/dist-standalone/email-transport.d.ts +2 -2
  157. package/dist-standalone/email-transport.js +1 -232
  158. package/dist-standalone/envelope.js +1 -525
  159. package/dist-standalone/errors.d.ts +13 -3
  160. package/dist-standalone/errors.js +1 -896
  161. package/dist-standalone/event-emitter.js +1 -456
  162. package/dist-standalone/gateway-state.d.ts +1 -1
  163. package/dist-standalone/gateway-state.js +1 -51
  164. package/dist-standalone/gateway-transport.js +1 -116
  165. package/dist-standalone/graceful-degradation.js +1 -396
  166. package/dist-standalone/guardrails.js +1 -216
  167. package/dist-standalone/health-check.d.ts +5 -1
  168. package/dist-standalone/health-check.js +1 -332
  169. package/dist-standalone/http-compat.d.ts +1 -1
  170. package/dist-standalone/http-compat.js +1 -267
  171. package/dist-standalone/http-status-map.js +1 -561
  172. package/dist-standalone/identity.js +1 -619
  173. package/dist-standalone/index.d.ts +15 -4
  174. package/dist-standalone/index.js +1 -78
  175. package/dist-standalone/invitation.js +1 -415
  176. package/dist-standalone/invite.js +1 -324
  177. package/dist-standalone/key-agreement.js +1 -325
  178. package/dist-standalone/lazy-init.d.ts +11 -6
  179. package/dist-standalone/lazy-init.js +1 -295
  180. package/dist-standalone/logger.js +1 -285
  181. package/dist-standalone/loopback-transport.d.ts +87 -0
  182. package/dist-standalone/loopback-transport.js +1 -0
  183. package/dist-standalone/mdns-discovery.js +1 -195
  184. package/dist-standalone/nonce-store.js +1 -76
  185. package/dist-standalone/pairing-manager.js +1 -219
  186. package/dist-standalone/plugin-system.js +1 -257
  187. package/dist-standalone/plugins/logging.js +1 -163
  188. package/dist-standalone/plugins/metrics.d.ts +4 -4
  189. package/dist-standalone/plugins/metrics.js +1 -176
  190. package/dist-standalone/plugins/validation.js +1 -297
  191. package/dist-standalone/policy.js +1 -315
  192. package/dist-standalone/progress-callbacks.js +1 -576
  193. package/dist-standalone/redis-nonce-store.js +1 -72
  194. package/dist-standalone/registry-middleware.js +1 -47
  195. package/dist-standalone/retry-strategies.js +1 -534
  196. package/dist-standalone/retry-transport.js +1 -98
  197. package/dist-standalone/runtime/browser.js +1 -516
  198. package/dist-standalone/runtime/edge.js +1 -511
  199. package/dist-standalone/runtime/react-native.d.ts +1 -1
  200. package/dist-standalone/runtime/react-native.js +1 -383
  201. package/dist-standalone/security-policy.js +1 -239
  202. package/dist-standalone/serialization.js +1 -1031
  203. package/dist-standalone/split-channel.d.ts +1 -1
  204. package/dist-standalone/split-channel.js +1 -219
  205. package/dist-standalone/subscription-proof.js +1 -224
  206. package/dist-standalone/succession.js +1 -142
  207. package/dist-standalone/timeouts.js +1 -398
  208. package/dist-standalone/trace-context.js +1 -414
  209. package/dist-standalone/trace-spans.js +1 -488
  210. package/dist-standalone/transport.d.ts +1 -1
  211. package/dist-standalone/transport.js +1 -59
  212. package/dist-standalone/trust-registry.d.ts +3 -3
  213. package/dist-standalone/trust-registry.js +1 -950
  214. package/dist-standalone/types/error-response.js +1 -52
  215. package/dist-standalone/vault-auth.js +1 -174
  216. package/dist-standalone/vault-store-loader.d.ts +9 -0
  217. package/dist-standalone/vault-store-loader.js +1 -187
  218. package/dist-standalone/verify.js +1 -16
  219. package/dist-standalone/version-info.js +1 -530
  220. package/dist-standalone/xfetch.js +1 -335
  221. package/package.json +1 -1
  222. package/share1.dat +0 -0
@@ -1,1031 +1 @@
1
- /**
2
- * Alternative Serialization Formats (API-14)
3
- *
4
- * Pluggable serialization system supporting JSON, MessagePack, and CBOR.
5
- * Provides format negotiation, backward compatibility, and performance benchmarks.
6
- *
7
- * @module serialization
8
- */
9
- import { ok, err } from"./_deps/shared/index.js";
10
- /* ── JSON Serializer ── */
11
- class JSONSerializer {
12
- format = 'json';
13
- contentType = 'application/json';
14
- serialize(value, options) {
15
- try {
16
- const json = options?.pretty
17
- ? JSON.stringify(value, null, 2)
18
- : JSON.stringify(value);
19
- return ok(new TextEncoder().encode(json));
20
- }
21
- catch (error) {
22
- return err({
23
- code: 'SERIALIZATION_FAILED',
24
- reason: error instanceof Error ? error.message : String(error),
25
- format: 'json',
26
- });
27
- }
28
- }
29
- deserialize(data) {
30
- try {
31
- const text = new TextDecoder().decode(data);
32
- return ok(JSON.parse(text));
33
- }
34
- catch (error) {
35
- return err({
36
- code: 'DESERIALIZATION_FAILED',
37
- reason: error instanceof Error ? error.message : String(error),
38
- });
39
- }
40
- }
41
- detect(data) {
42
- if (data.length === 0)
43
- return false;
44
- // JSON starts with { [ " or whitespace + one of those
45
- const first = data[0];
46
- if (first === undefined)
47
- return false;
48
- if (first === 0x7B || first === 0x5B || first === 0x22)
49
- return true; // { [ "
50
- if (first === 0x20 || first === 0x09 || first === 0x0A || first === 0x0D) {
51
- // Whitespace - scan for first non-whitespace
52
- for (let i = 1; i < Math.min(data.length, 10); i++) {
53
- const byte = data[i];
54
- if (byte === undefined)
55
- return false;
56
- if (byte === 0x7B || byte === 0x5B || byte === 0x22)
57
- return true;
58
- if (byte !== 0x20 && byte !== 0x09 && byte !== 0x0A && byte !== 0x0D)
59
- return false;
60
- }
61
- }
62
- return false;
63
- }
64
- }
65
- /* ── MessagePack Serializer ── */
66
- class MessagePackSerializer {
67
- format = 'msgpack';
68
- contentType = 'application/msgpack';
69
- serialize(value, _options) {
70
- try {
71
- return ok(this.encode(value));
72
- }
73
- catch (error) {
74
- return err({
75
- code: 'SERIALIZATION_FAILED',
76
- reason: error instanceof Error ? error.message : String(error),
77
- format: 'msgpack',
78
- });
79
- }
80
- }
81
- deserialize(data) {
82
- try {
83
- return ok(this.decode(data));
84
- }
85
- catch (error) {
86
- return err({
87
- code: 'DESERIALIZATION_FAILED',
88
- reason: error instanceof Error ? error.message : String(error),
89
- });
90
- }
91
- }
92
- detect(data) {
93
- if (data.length === 0)
94
- return false;
95
- const first = data[0];
96
- if (first === undefined)
97
- return false;
98
- // MessagePack format markers
99
- // fixmap: 0x80-0x8F, fixarray: 0x90-0x9F, fixstr: 0xA0-0xBF
100
- // nil: 0xC0, false: 0xC2, true: 0xC3
101
- // bin8/16/32: 0xC4-0xC6, ext8/16/32: 0xC7-0xC9
102
- // float32/64: 0xCA-0xCB, uint8/16/32/64: 0xCC-0xCF
103
- // int8/16/32/64: 0xD0-0xD3, fixext1/2/4/8/16: 0xD4-0xD8
104
- // str8/16/32: 0xD9-0xDB, array16/32: 0xDC-0xDD, map16/32: 0xDE-0xDF
105
- // Reject invalid patterns that would cause decode errors
106
- if (first >= 0xE0 && first <= 0xFF) {
107
- // Negative fixint: valid only for single-byte integers
108
- // But we need more data to validate structure
109
- if (data.length < 2)
110
- return false;
111
- }
112
- // Try to validate structure
113
- try {
114
- const state = { offset: 0 };
115
- this.decodeValue(data, state);
116
- return true; // Successfully decoded
117
- }
118
- catch {
119
- return false; // Decode failed
120
- }
121
- }
122
- // Minimal MessagePack encoder (subset implementation)
123
- encode(value) {
124
- const chunks = [];
125
- this.encodeValue(value, chunks);
126
- // Concatenate chunks
127
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
128
- const result = new Uint8Array(totalLength);
129
- let offset = 0;
130
- for (const chunk of chunks) {
131
- result.set(chunk, offset);
132
- offset += chunk.length;
133
- }
134
- return result;
135
- }
136
- encodeValue(value, chunks) {
137
- if (value === null || value === undefined) {
138
- chunks.push(new Uint8Array([0xC0])); // nil
139
- }
140
- else if (typeof value === 'boolean') {
141
- chunks.push(new Uint8Array([value ? 0xC3 : 0xC2])); // true/false
142
- }
143
- else if (typeof value === 'number') {
144
- this.encodeNumber(value, chunks);
145
- }
146
- else if (typeof value === 'string') {
147
- this.encodeString(value, chunks);
148
- }
149
- else if (value instanceof Uint8Array) {
150
- this.encodeBinary(value, chunks);
151
- }
152
- else if (Array.isArray(value)) {
153
- this.encodeArray(value, chunks);
154
- }
155
- else if (typeof value === 'object') {
156
- this.encodeObject(value, chunks);
157
- }
158
- else {
159
- throw new Error(`Unsupported type: ${typeof value}`);
160
- }
161
- }
162
- encodeNumber(value, chunks) {
163
- if (Number.isInteger(value)) {
164
- if (value >= 0 && value <= 127) {
165
- chunks.push(new Uint8Array([value])); // positive fixint
166
- }
167
- else if (value >= -32 && value < 0) {
168
- chunks.push(new Uint8Array([0xE0 | (value & 0x1F)])); // negative fixint
169
- }
170
- else if (value >= 0 && value <= 0xFF) {
171
- chunks.push(new Uint8Array([0xCC, value])); // uint8
172
- }
173
- else if (value >= 0 && value <= 0xFFFF) {
174
- chunks.push(new Uint8Array([0xCD, value >> 8, value & 0xFF])); // uint16
175
- }
176
- else if (value >= 0 && value <= 0xFFFFFFFF) {
177
- const bytes = new Uint8Array(5);
178
- bytes[0] = 0xCE;
179
- new DataView(bytes.buffer).setUint32(1, value, false);
180
- chunks.push(bytes);
181
- }
182
- else {
183
- // Use float64 for large integers or negative integers
184
- const bytes = new Uint8Array(9);
185
- bytes[0] = 0xCB;
186
- new DataView(bytes.buffer).setFloat64(1, value, false);
187
- chunks.push(bytes);
188
- }
189
- }
190
- else {
191
- // Float
192
- const bytes = new Uint8Array(9);
193
- bytes[0] = 0xCB; // float64
194
- new DataView(bytes.buffer).setFloat64(1, value, false);
195
- chunks.push(bytes);
196
- }
197
- }
198
- encodeString(value, chunks) {
199
- const utf8 = new TextEncoder().encode(value);
200
- const len = utf8.length;
201
- if (len <= 31) {
202
- chunks.push(new Uint8Array([0xA0 | len])); // fixstr
203
- }
204
- else if (len <= 0xFF) {
205
- chunks.push(new Uint8Array([0xD9, len])); // str8
206
- }
207
- else if (len <= 0xFFFF) {
208
- chunks.push(new Uint8Array([0xDA, len >> 8, len & 0xFF])); // str16
209
- }
210
- else {
211
- const header = new Uint8Array(5);
212
- header[0] = 0xDB;
213
- new DataView(header.buffer).setUint32(1, len, false);
214
- chunks.push(header);
215
- }
216
- chunks.push(utf8);
217
- }
218
- encodeBinary(value, chunks) {
219
- const len = value.length;
220
- if (len <= 0xFF) {
221
- chunks.push(new Uint8Array([0xC4, len])); // bin8
222
- }
223
- else if (len <= 0xFFFF) {
224
- chunks.push(new Uint8Array([0xC5, len >> 8, len & 0xFF])); // bin16
225
- }
226
- else {
227
- const header = new Uint8Array(5);
228
- header[0] = 0xC6;
229
- new DataView(header.buffer).setUint32(1, len, false);
230
- chunks.push(header);
231
- }
232
- chunks.push(value);
233
- }
234
- encodeArray(value, chunks) {
235
- const len = value.length;
236
- if (len <= 15) {
237
- chunks.push(new Uint8Array([0x90 | len])); // fixarray
238
- }
239
- else if (len <= 0xFFFF) {
240
- chunks.push(new Uint8Array([0xDC, len >> 8, len & 0xFF])); // array16
241
- }
242
- else {
243
- const header = new Uint8Array(5);
244
- header[0] = 0xDD;
245
- new DataView(header.buffer).setUint32(1, len, false);
246
- chunks.push(header);
247
- }
248
- for (const item of value) {
249
- this.encodeValue(item, chunks);
250
- }
251
- }
252
- encodeObject(value, chunks) {
253
- const keys = Object.keys(value);
254
- const len = keys.length;
255
- if (len <= 15) {
256
- chunks.push(new Uint8Array([0x80 | len])); // fixmap
257
- }
258
- else if (len <= 0xFFFF) {
259
- chunks.push(new Uint8Array([0xDE, len >> 8, len & 0xFF])); // map16
260
- }
261
- else {
262
- const header = new Uint8Array(5);
263
- header[0] = 0xDF;
264
- new DataView(header.buffer).setUint32(1, len, false);
265
- chunks.push(header);
266
- }
267
- for (const key of keys) {
268
- this.encodeValue(key, chunks);
269
- this.encodeValue(value[key], chunks);
270
- }
271
- }
272
- // Minimal MessagePack decoder (subset implementation)
273
- decode(data) {
274
- const state = { offset: 0 };
275
- return this.decodeValue(data, state);
276
- }
277
- decodeValue(data, state) {
278
- if (state.offset >= data.length) {
279
- throw new Error('Unexpected end of data');
280
- }
281
- const byte = data[state.offset++];
282
- if (byte === undefined) {
283
- throw new Error('Unexpected end of data');
284
- }
285
- // Positive fixint (0x00 - 0x7F)
286
- if (byte <= 0x7F)
287
- return byte;
288
- // Fixmap (0x80 - 0x8F)
289
- if (byte >= 0x80 && byte <= 0x8F) {
290
- const len = byte & 0x0F;
291
- return this.decodeMap(data, state, len);
292
- }
293
- // Fixarray (0x90 - 0x9F)
294
- if (byte >= 0x90 && byte <= 0x9F) {
295
- const len = byte & 0x0F;
296
- return this.decodeArray(data, state, len);
297
- }
298
- // Fixstr (0xA0 - 0xBF)
299
- if (byte >= 0xA0 && byte <= 0xBF) {
300
- const len = byte & 0x1F;
301
- return this.decodeString(data, state, len);
302
- }
303
- // Negative fixint (0xE0 - 0xFF)
304
- if (byte >= 0xE0)
305
- return (byte & 0x1F) - 32;
306
- // Other types
307
- switch (byte) {
308
- case 0xC0: return null; // nil
309
- case 0xC2: return false;
310
- case 0xC3: return true;
311
- case 0xC4: { // bin8
312
- const len = data[state.offset++];
313
- if (len === undefined)
314
- throw new Error('Unexpected end of data');
315
- return this.decodeBinary(data, state, len);
316
- }
317
- case 0xC5: return this.decodeBinary(data, state, this.readUint16(data, state)); // bin16
318
- case 0xC6: return this.decodeBinary(data, state, this.readUint32(data, state)); // bin32
319
- case 0xCA: return this.readFloat32(data, state);
320
- case 0xCB: return this.readFloat64(data, state);
321
- case 0xCC: { // uint8
322
- const value = data[state.offset++];
323
- if (value === undefined)
324
- throw new Error('Unexpected end of data');
325
- return value;
326
- }
327
- case 0xCD: return this.readUint16(data, state); // uint16
328
- case 0xCE: return this.readUint32(data, state); // uint32
329
- case 0xD0: return this.readInt8(data, state); // int8
330
- case 0xD1: return this.readInt16(data, state); // int16
331
- case 0xD2: return this.readInt32(data, state); // int32
332
- case 0xD9: { // str8
333
- const len = data[state.offset++];
334
- if (len === undefined)
335
- throw new Error('Unexpected end of data');
336
- return this.decodeString(data, state, len);
337
- }
338
- case 0xDA: return this.decodeString(data, state, this.readUint16(data, state)); // str16
339
- case 0xDB: return this.decodeString(data, state, this.readUint32(data, state)); // str32
340
- case 0xDC: return this.decodeArray(data, state, this.readUint16(data, state)); // array16
341
- case 0xDD: return this.decodeArray(data, state, this.readUint32(data, state)); // array32
342
- case 0xDE: return this.decodeMap(data, state, this.readUint16(data, state)); // map16
343
- case 0xDF: return this.decodeMap(data, state, this.readUint32(data, state)); // map32
344
- default:
345
- throw new Error(`Unknown MessagePack type: 0x${byte.toString(16)}`);
346
- }
347
- }
348
- decodeString(data, state, len) {
349
- const bytes = data.slice(state.offset, state.offset + len);
350
- state.offset += len;
351
- return new TextDecoder().decode(bytes);
352
- }
353
- decodeBinary(data, state, len) {
354
- const bytes = data.slice(state.offset, state.offset + len);
355
- state.offset += len;
356
- return bytes;
357
- }
358
- decodeArray(data, state, len) {
359
- const result = [];
360
- for (let i = 0; i < len; i++) {
361
- result.push(this.decodeValue(data, state));
362
- }
363
- return result;
364
- }
365
- decodeMap(data, state, len) {
366
- const result = {};
367
- for (let i = 0; i < len; i++) {
368
- const key = this.decodeValue(data, state);
369
- const value = this.decodeValue(data, state);
370
- result[String(key)] = value;
371
- }
372
- return result;
373
- }
374
- readUint16(data, state) {
375
- const value = new DataView(data.buffer, data.byteOffset).getUint16(state.offset, false);
376
- state.offset += 2;
377
- return value;
378
- }
379
- readUint32(data, state) {
380
- const value = new DataView(data.buffer, data.byteOffset).getUint32(state.offset, false);
381
- state.offset += 4;
382
- return value;
383
- }
384
- readInt8(data, state) {
385
- if (state.offset >= data.length)
386
- throw new Error('Unexpected end of data');
387
- const value = new DataView(data.buffer, data.byteOffset).getInt8(state.offset);
388
- state.offset += 1;
389
- return value;
390
- }
391
- readInt16(data, state) {
392
- const value = new DataView(data.buffer, data.byteOffset).getInt16(state.offset, false);
393
- state.offset += 2;
394
- return value;
395
- }
396
- readInt32(data, state) {
397
- const value = new DataView(data.buffer, data.byteOffset).getInt32(state.offset, false);
398
- state.offset += 4;
399
- return value;
400
- }
401
- readFloat32(data, state) {
402
- const value = new DataView(data.buffer, data.byteOffset).getFloat32(state.offset, false);
403
- state.offset += 4;
404
- return value;
405
- }
406
- readFloat64(data, state) {
407
- const value = new DataView(data.buffer, data.byteOffset).getFloat64(state.offset, false);
408
- state.offset += 8;
409
- return value;
410
- }
411
- }
412
- /* ── CBOR Serializer ── */
413
- class CBORSerializer {
414
- format = 'cbor';
415
- contentType = 'application/cbor';
416
- serialize(value, _options) {
417
- try {
418
- return ok(this.encode(value));
419
- }
420
- catch (error) {
421
- return err({
422
- code: 'SERIALIZATION_FAILED',
423
- reason: error instanceof Error ? error.message : String(error),
424
- format: 'cbor',
425
- });
426
- }
427
- }
428
- deserialize(data) {
429
- try {
430
- return ok(this.decode(data));
431
- }
432
- catch (error) {
433
- return err({
434
- code: 'DESERIALIZATION_FAILED',
435
- reason: error instanceof Error ? error.message : String(error),
436
- });
437
- }
438
- }
439
- detect(data) {
440
- if (data.length === 0)
441
- return false;
442
- const first = data[0];
443
- // CBOR major types:
444
- // 0: unsigned integer (0x00-0x1B)
445
- // 1: negative integer (0x20-0x3B)
446
- // 2: byte string (0x40-0x5B)
447
- // 3: text string (0x60-0x7B)
448
- // 4: array (0x80-0x9B)
449
- // 5: map (0xA0-0xBB)
450
- // 6: tag (0xC0-0xDB)
451
- // 7: float/special (0xE0-0xFB, 0xF4-0xF7 for false/true/null/undefined)
452
- // Try to validate structure
453
- try {
454
- const state = { offset: 0 };
455
- this.decodeValue(data, state);
456
- return true; // Successfully decoded
457
- }
458
- catch {
459
- return false; // Decode failed
460
- }
461
- }
462
- // Minimal CBOR encoder (subset implementation)
463
- encode(value) {
464
- const chunks = [];
465
- this.encodeValue(value, chunks);
466
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
467
- const result = new Uint8Array(totalLength);
468
- let offset = 0;
469
- for (const chunk of chunks) {
470
- result.set(chunk, offset);
471
- offset += chunk.length;
472
- }
473
- return result;
474
- }
475
- encodeValue(value, chunks) {
476
- if (value === null || value === undefined) {
477
- chunks.push(new Uint8Array([0xF6])); // null
478
- }
479
- else if (typeof value === 'boolean') {
480
- chunks.push(new Uint8Array([value ? 0xF5 : 0xF4])); // true/false
481
- }
482
- else if (typeof value === 'number') {
483
- this.encodeNumber(value, chunks);
484
- }
485
- else if (typeof value === 'string') {
486
- this.encodeString(value, chunks);
487
- }
488
- else if (value instanceof Uint8Array) {
489
- this.encodeBinary(value, chunks);
490
- }
491
- else if (Array.isArray(value)) {
492
- this.encodeArray(value, chunks);
493
- }
494
- else if (typeof value === 'object') {
495
- this.encodeObject(value, chunks);
496
- }
497
- else {
498
- throw new Error(`Unsupported type: ${typeof value}`);
499
- }
500
- }
501
- encodeNumber(value, chunks) {
502
- if (Number.isInteger(value)) {
503
- if (value >= 0) {
504
- if (value <= 23) {
505
- chunks.push(new Uint8Array([value])); // 0-23 direct
506
- }
507
- else if (value <= 0xFF) {
508
- chunks.push(new Uint8Array([0x18, value])); // uint8
509
- }
510
- else if (value <= 0xFFFF) {
511
- chunks.push(new Uint8Array([0x19, value >> 8, value & 0xFF])); // uint16
512
- }
513
- else if (value <= 0xFFFFFFFF) {
514
- const bytes = new Uint8Array(5);
515
- bytes[0] = 0x1A;
516
- new DataView(bytes.buffer).setUint32(1, value, false);
517
- chunks.push(bytes);
518
- }
519
- else {
520
- // Large integer as float64
521
- const bytes = new Uint8Array(9);
522
- bytes[0] = 0xFB;
523
- new DataView(bytes.buffer).setFloat64(1, value, false);
524
- chunks.push(bytes);
525
- }
526
- }
527
- else {
528
- // Negative integer
529
- const absMinusOne = -1 - value;
530
- if (absMinusOne <= 23) {
531
- chunks.push(new Uint8Array([0x20 | absMinusOne]));
532
- }
533
- else if (absMinusOne <= 0xFF) {
534
- chunks.push(new Uint8Array([0x38, absMinusOne]));
535
- }
536
- else if (absMinusOne <= 0xFFFF) {
537
- chunks.push(new Uint8Array([0x39, absMinusOne >> 8, absMinusOne & 0xFF]));
538
- }
539
- else {
540
- const bytes = new Uint8Array(5);
541
- bytes[0] = 0x3A;
542
- new DataView(bytes.buffer).setUint32(1, absMinusOne, false);
543
- chunks.push(bytes);
544
- }
545
- }
546
- }
547
- else {
548
- // Float
549
- const bytes = new Uint8Array(9);
550
- bytes[0] = 0xFB; // float64
551
- new DataView(bytes.buffer).setFloat64(1, value, false);
552
- chunks.push(bytes);
553
- }
554
- }
555
- encodeString(value, chunks) {
556
- const utf8 = new TextEncoder().encode(value);
557
- const len = utf8.length;
558
- if (len <= 23) {
559
- chunks.push(new Uint8Array([0x60 | len])); // text string 0-23
560
- }
561
- else if (len <= 0xFF) {
562
- chunks.push(new Uint8Array([0x78, len])); // text string uint8
563
- }
564
- else if (len <= 0xFFFF) {
565
- chunks.push(new Uint8Array([0x79, len >> 8, len & 0xFF])); // text string uint16
566
- }
567
- else {
568
- const header = new Uint8Array(5);
569
- header[0] = 0x7A;
570
- new DataView(header.buffer).setUint32(1, len, false);
571
- chunks.push(header);
572
- }
573
- chunks.push(utf8);
574
- }
575
- encodeBinary(value, chunks) {
576
- const len = value.length;
577
- if (len <= 23) {
578
- chunks.push(new Uint8Array([0x40 | len])); // byte string 0-23
579
- }
580
- else if (len <= 0xFF) {
581
- chunks.push(new Uint8Array([0x58, len])); // byte string uint8
582
- }
583
- else if (len <= 0xFFFF) {
584
- chunks.push(new Uint8Array([0x59, len >> 8, len & 0xFF])); // byte string uint16
585
- }
586
- else {
587
- const header = new Uint8Array(5);
588
- header[0] = 0x5A;
589
- new DataView(header.buffer).setUint32(1, len, false);
590
- chunks.push(header);
591
- }
592
- chunks.push(value);
593
- }
594
- encodeArray(value, chunks) {
595
- const len = value.length;
596
- if (len <= 23) {
597
- chunks.push(new Uint8Array([0x80 | len])); // array 0-23
598
- }
599
- else if (len <= 0xFF) {
600
- chunks.push(new Uint8Array([0x98, len])); // array uint8
601
- }
602
- else if (len <= 0xFFFF) {
603
- chunks.push(new Uint8Array([0x99, len >> 8, len & 0xFF])); // array uint16
604
- }
605
- else {
606
- const header = new Uint8Array(5);
607
- header[0] = 0x9A;
608
- new DataView(header.buffer).setUint32(1, len, false);
609
- chunks.push(header);
610
- }
611
- for (const item of value) {
612
- this.encodeValue(item, chunks);
613
- }
614
- }
615
- encodeObject(value, chunks) {
616
- const keys = Object.keys(value);
617
- const len = keys.length;
618
- if (len <= 23) {
619
- chunks.push(new Uint8Array([0xA0 | len])); // map 0-23
620
- }
621
- else if (len <= 0xFF) {
622
- chunks.push(new Uint8Array([0xB8, len])); // map uint8
623
- }
624
- else if (len <= 0xFFFF) {
625
- chunks.push(new Uint8Array([0xB9, len >> 8, len & 0xFF])); // map uint16
626
- }
627
- else {
628
- const header = new Uint8Array(5);
629
- header[0] = 0xBA;
630
- new DataView(header.buffer).setUint32(1, len, false);
631
- chunks.push(header);
632
- }
633
- for (const key of keys) {
634
- this.encodeValue(key, chunks);
635
- this.encodeValue(value[key], chunks);
636
- }
637
- }
638
- // Minimal CBOR decoder
639
- decode(data) {
640
- const state = { offset: 0 };
641
- return this.decodeValue(data, state);
642
- }
643
- decodeValue(data, state) {
644
- if (state.offset >= data.length) {
645
- throw new Error('Unexpected end of data');
646
- }
647
- const byte = data[state.offset++];
648
- if (byte === undefined) {
649
- throw new Error('Unexpected end of data');
650
- }
651
- const majorType = (byte >> 5) & 0x07;
652
- const additionalInfo = byte & 0x1F;
653
- switch (majorType) {
654
- case 0: // unsigned integer
655
- return this.decodeInteger(data, state, additionalInfo);
656
- case 1: // negative integer
657
- return -1 - this.decodeInteger(data, state, additionalInfo);
658
- case 2: // byte string
659
- return this.decodeBinary(data, state, additionalInfo);
660
- case 3: // text string
661
- return this.decodeString(data, state, additionalInfo);
662
- case 4: // array
663
- return this.decodeArray(data, state, additionalInfo);
664
- case 5: // map
665
- return this.decodeMap(data, state, additionalInfo);
666
- case 7: // float/special
667
- return this.decodeSpecial(data, state, additionalInfo);
668
- default:
669
- throw new Error(`Unsupported CBOR major type: ${majorType}`);
670
- }
671
- }
672
- decodeInteger(data, state, additionalInfo) {
673
- if (additionalInfo <= 23) {
674
- return additionalInfo;
675
- }
676
- else if (additionalInfo === 24) {
677
- const value = data[state.offset++];
678
- if (value === undefined)
679
- throw new Error('Unexpected end of data');
680
- return value;
681
- }
682
- else if (additionalInfo === 25) {
683
- return this.readUint16(data, state);
684
- }
685
- else if (additionalInfo === 26) {
686
- return this.readUint32(data, state);
687
- }
688
- else {
689
- throw new Error('Unsupported integer size');
690
- }
691
- }
692
- decodeString(data, state, additionalInfo) {
693
- let len;
694
- if (additionalInfo <= 23) {
695
- len = additionalInfo;
696
- }
697
- else {
698
- len = this.decodeInteger(data, state, additionalInfo);
699
- }
700
- const bytes = data.slice(state.offset, state.offset + len);
701
- state.offset += len;
702
- return new TextDecoder().decode(bytes);
703
- }
704
- decodeBinary(data, state, additionalInfo) {
705
- let len;
706
- if (additionalInfo <= 23) {
707
- len = additionalInfo;
708
- }
709
- else {
710
- len = this.decodeInteger(data, state, additionalInfo);
711
- }
712
- const bytes = data.slice(state.offset, state.offset + len);
713
- state.offset += len;
714
- return bytes;
715
- }
716
- decodeArray(data, state, additionalInfo) {
717
- let len;
718
- if (additionalInfo <= 23) {
719
- len = additionalInfo;
720
- }
721
- else {
722
- len = this.decodeInteger(data, state, additionalInfo);
723
- }
724
- const result = [];
725
- for (let i = 0; i < len; i++) {
726
- result.push(this.decodeValue(data, state));
727
- }
728
- return result;
729
- }
730
- decodeMap(data, state, additionalInfo) {
731
- let len;
732
- if (additionalInfo <= 23) {
733
- len = additionalInfo;
734
- }
735
- else {
736
- len = this.decodeInteger(data, state, additionalInfo);
737
- }
738
- const result = {};
739
- for (let i = 0; i < len; i++) {
740
- const key = this.decodeValue(data, state);
741
- const value = this.decodeValue(data, state);
742
- result[String(key)] = value;
743
- }
744
- return result;
745
- }
746
- decodeSpecial(data, state, additionalInfo) {
747
- switch (additionalInfo) {
748
- case 20: return false;
749
- case 21: return true;
750
- case 22: return null;
751
- case 23: return undefined;
752
- case 27: { // float64
753
- return this.readFloat64(data, state);
754
- }
755
- default:
756
- throw new Error(`Unsupported CBOR special: ${additionalInfo}`);
757
- }
758
- }
759
- readUint16(data, state) {
760
- const value = new DataView(data.buffer, data.byteOffset).getUint16(state.offset, false);
761
- state.offset += 2;
762
- return value;
763
- }
764
- readUint32(data, state) {
765
- const value = new DataView(data.buffer, data.byteOffset).getUint32(state.offset, false);
766
- state.offset += 4;
767
- return value;
768
- }
769
- readFloat64(data, state) {
770
- const value = new DataView(data.buffer, data.byteOffset).getFloat64(state.offset, false);
771
- state.offset += 8;
772
- return value;
773
- }
774
- }
775
- /* ── Serializer Registry ── */
776
- // Order matters for format detection: JSON (most specific), CBOR, MessagePack
777
- const serializers = new Map([
778
- ['json', new JSONSerializer()],
779
- ['cbor', new CBORSerializer()],
780
- ['msgpack', new MessagePackSerializer()],
781
- ]);
782
- /* ── Public API ── */
783
- /**
784
- * Serialize a value using the specified format.
785
- *
786
- * @param value - Value to serialize
787
- * @param options - Serialization options
788
- * @returns Serialized data with metadata
789
- *
790
- * @example
791
- * ```typescript
792
- * const data = { message: 'Hello', timestamp: Date.now() };
793
- *
794
- * // JSON (default, human-readable)
795
- * const json = serialize(data);
796
- *
797
- * // MessagePack (compact binary)
798
- * const msgpack = serialize(data, { format: 'msgpack' });
799
- *
800
- * // CBOR (standard binary)
801
- * const cbor = serialize(data, { format: 'cbor' });
802
- *
803
- * console.log('JSON:', json.value.size, 'bytes');
804
- * console.log('MessagePack:', msgpack.value.size, 'bytes');
805
- * console.log('CBOR:', cbor.value.size, 'bytes');
806
- * ```
807
- */
808
- export function serialize(value, options = {}) {
809
- const format = options.format ?? 'json';
810
- const serializer = serializers.get(format);
811
- if (!serializer) {
812
- return err({ code: 'UNSUPPORTED_FORMAT', format });
813
- }
814
- const startTime = options.collectMetrics ? performance.now() : 0;
815
- const result = serializer.serialize(value, options);
816
- if (!result.ok)
817
- return result;
818
- const metrics = options.collectMetrics ? {
819
- serializeDuration: performance.now() - startTime,
820
- size: result.value.length,
821
- format,
822
- timestamp: Date.now(),
823
- } : undefined;
824
- return ok({
825
- data: result.value,
826
- format,
827
- size: result.value.length,
828
- contentType: serializer.contentType,
829
- metrics,
830
- });
831
- }
832
- /**
833
- * Deserialize bytes using format auto-detection or explicit format.
834
- *
835
- * @param data - Serialized bytes
836
- * @param options - Deserialization options
837
- * @returns Deserialized value with format metadata
838
- *
839
- * @example
840
- * ```typescript
841
- * // Auto-detect format
842
- * const result = deserialize(bytes);
843
- * if (result.ok) {
844
- * console.log('Format:', result.value.format);
845
- * console.log('Data:', result.value.value);
846
- * }
847
- *
848
- * // Explicit format (faster, skips detection)
849
- * const json = deserialize(bytes, { format: 'json' });
850
- * ```
851
- */
852
- export function deserialize(data, options = {}) {
853
- const startTime = options.collectMetrics ? performance.now() : 0;
854
- let format;
855
- let serializer;
856
- if (options.format) {
857
- // Explicit format
858
- format = options.format;
859
- serializer = serializers.get(format);
860
- if (!serializer) {
861
- return err({ code: 'UNSUPPORTED_FORMAT', format });
862
- }
863
- }
864
- else {
865
- // Auto-detect format
866
- const detected = detectFormat(data);
867
- if (!detected.ok)
868
- return detected;
869
- format = detected.value;
870
- serializer = serializers.get(format);
871
- if (!serializer) {
872
- return err({ code: 'UNSUPPORTED_FORMAT', format });
873
- }
874
- }
875
- const result = serializer.deserialize(data);
876
- if (!result.ok)
877
- return result;
878
- const metrics = options.collectMetrics ? {
879
- serializeDuration: performance.now() - startTime,
880
- size: data.length,
881
- format,
882
- timestamp: Date.now(),
883
- } : undefined;
884
- return ok({
885
- value: result.value,
886
- format,
887
- metrics,
888
- });
889
- }
890
- /**
891
- * Detect serialization format from bytes.
892
- *
893
- * @param data - Serialized bytes
894
- * @returns Detected format
895
- *
896
- * @example
897
- * ```typescript
898
- * const format = detectFormat(bytes);
899
- * if (format.ok) {
900
- * console.log('Detected format:', format.value); // 'json' | 'msgpack' | 'cbor'
901
- * }
902
- * ```
903
- */
904
- export function detectFormat(data) {
905
- // Try JSON first (most specific - must start with { [ " or whitespace + those)
906
- const jsonSerializer = serializers.get('json');
907
- if (jsonSerializer?.detect(data)) {
908
- return ok('json');
909
- }
910
- if (data.length === 0) {
911
- return err({
912
- code: 'FORMAT_DETECTION_FAILED',
913
- reason: 'Empty data',
914
- });
915
- }
916
- // CBOR and MessagePack have overlapping byte ranges
917
- // Both formats can successfully decode data but with different interpretations
918
- // Priority: Try CBOR first, then MessagePack
919
- // This matches the serializers Map insertion order
920
- const cborSerializer = serializers.get('cbor');
921
- if (cborSerializer?.detect(data)) {
922
- return ok('cbor');
923
- }
924
- const msgpackSerializer = serializers.get('msgpack');
925
- if (msgpackSerializer?.detect(data)) {
926
- return ok('msgpack');
927
- }
928
- return err({
929
- code: 'FORMAT_DETECTION_FAILED',
930
- reason: 'No serializer recognized the data format',
931
- });
932
- }
933
- /**
934
- * Negotiate format between client and server.
935
- *
936
- * @param clientFormats - Formats accepted by client (in preference order)
937
- * @param serverFormats - Formats supported by server
938
- * @returns Best matching format
939
- *
940
- * @example
941
- * ```typescript
942
- * const client = ['msgpack', 'cbor', 'json'];
943
- * const server = ['json', 'cbor'];
944
- * const format = negotiateFormat(client, server);
945
- * console.log(format.value); // 'cbor' (first match)
946
- * ```
947
- */
948
- export function negotiateFormat(clientFormats, serverFormats) {
949
- for (const format of clientFormats) {
950
- if (serverFormats.includes(format)) {
951
- return ok(format);
952
- }
953
- }
954
- return err({
955
- code: 'UNSUPPORTED_FORMAT',
956
- format: `No common format (client: ${clientFormats.join(',')}, server: ${serverFormats.join(',')})`,
957
- });
958
- }
959
- /**
960
- * Compare serialization performance across formats.
961
- *
962
- * @param value - Value to benchmark
963
- * @param formats - Formats to compare
964
- * @returns Performance comparison
965
- *
966
- * @example
967
- * ```typescript
968
- * const data = { message: 'Hello', items: [1, 2, 3, 4, 5] };
969
- * const comparison = compareFormats(data);
970
- *
971
- * if (comparison.ok) {
972
- * for (const result of comparison.value) {
973
- * console.log(`${result.format}: ${result.size} bytes, ${result.duration}ms`);
974
- * }
975
- * }
976
- * ```
977
- */
978
- export function compareFormats(value, formats = ['json', 'msgpack', 'cbor']) {
979
- const results = [];
980
- for (const format of formats) {
981
- const result = serialize(value, { format, collectMetrics: true });
982
- if (!result.ok)
983
- return result;
984
- results.push({
985
- format,
986
- size: result.value.size,
987
- duration: result.value.metrics?.serializeDuration ?? 0,
988
- });
989
- }
990
- return ok(results);
991
- }
992
- /**
993
- * Get Content-Type header for a serialization format.
994
- *
995
- * @param format - Serialization format
996
- * @returns Content-Type header value
997
- *
998
- * @example
999
- * ```typescript
1000
- * const contentType = getContentType('msgpack');
1001
- * console.log(contentType); // 'application/msgpack'
1002
- * ```
1003
- */
1004
- export function getContentType(format) {
1005
- const serializer = serializers.get(format);
1006
- return serializer?.contentType ?? 'application/octet-stream';
1007
- }
1008
- /**
1009
- * Parse Content-Type header to serialization format.
1010
- *
1011
- * @param contentType - Content-Type header value
1012
- * @returns Serialization format or undefined
1013
- *
1014
- * @example
1015
- * ```typescript
1016
- * const format = parseContentType('application/json');
1017
- * console.log(format); // 'json'
1018
- *
1019
- * const format2 = parseContentType('application/msgpack');
1020
- * console.log(format2); // 'msgpack'
1021
- * ```
1022
- */
1023
- export function parseContentType(contentType) {
1024
- const normalized = contentType.toLowerCase().split(';')[0]?.trim() ?? '';
1025
- for (const serializer of serializers.values()) {
1026
- if (serializer.contentType === normalized) {
1027
- return serializer.format;
1028
- }
1029
- }
1030
- return undefined;
1031
- }
1
+ import{ok,err}from"./_deps/shared/index.js";class JSONSerializer{format="json";contentType="application/json";serialize(e,t){try{const r=t?.pretty?JSON.stringify(e,null,2):JSON.stringify(e);return ok((new TextEncoder).encode(r))}catch(e){return err({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"json"})}}deserialize(e){try{const t=(new TextDecoder).decode(e);return ok(JSON.parse(t))}catch(e){return err({code:"DESERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e)})}}detect(e){if(0===e.length)return!1;const t=e[0];if(void 0===t)return!1;if(123===t||91===t||34===t)return!0;if(32===t||9===t||10===t||13===t)for(let t=1;t<Math.min(e.length,10);t++){const r=e[t];if(void 0===r)return!1;if(123===r||91===r||34===r)return!0;if(32!==r&&9!==r&&10!==r&&13!==r)return!1}return!1}}class MessagePackSerializer{format="msgpack";contentType="application/msgpack";serialize(e,t){try{return ok(this.encode(e))}catch(e){return err({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"msgpack"})}}deserialize(e){try{return ok(this.decode(e))}catch(e){return err({code:"DESERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e)})}}detect(e){if(0===e.length)return!1;const t=e[0];if(void 0===t)return!1;if(t>=224&&t<=255&&e.length<2)return!1;try{const t={offset:0};return this.decodeValue(e,t),!0}catch{return!1}}encode(e){const t=[];this.encodeValue(e,t);const r=t.reduce((e,t)=>e+t.length,0),n=new Uint8Array(r);let s=0;for(const e of t)n.set(e,s),s+=e.length;return n}encodeValue(e,t){if(null==e)t.push(new Uint8Array([192]));else if("boolean"==typeof e)t.push(new Uint8Array([e?195:194]));else if("number"==typeof e)this.encodeNumber(e,t);else if("string"==typeof e)this.encodeString(e,t);else if(e instanceof Uint8Array)this.encodeBinary(e,t);else if(Array.isArray(e))this.encodeArray(e,t);else{if("object"!=typeof e)throw new Error("Unsupported type: "+typeof e);this.encodeObject(e,t)}}encodeNumber(e,t){if(Number.isInteger(e))if(e>=0&&e<=127)t.push(new Uint8Array([e]));else if(e>=-32&&e<0)t.push(new Uint8Array([224|31&e]));else if(e>=0&&e<=255)t.push(new Uint8Array([204,e]));else if(e>=0&&e<=65535)t.push(new Uint8Array([205,e>>8,255&e]));else if(e>=0&&e<=4294967295){const r=new Uint8Array(5);r[0]=206,new DataView(r.buffer).setUint32(1,e,!1),t.push(r)}else{const r=new Uint8Array(9);r[0]=203,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}else{const r=new Uint8Array(9);r[0]=203,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}}encodeString(e,t){const r=(new TextEncoder).encode(e),n=r.length;if(n<=31)t.push(new Uint8Array([160|n]));else if(n<=255)t.push(new Uint8Array([217,n]));else if(n<=65535)t.push(new Uint8Array([218,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=219,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}t.push(r)}encodeBinary(e,t){const r=e.length;if(r<=255)t.push(new Uint8Array([196,r]));else if(r<=65535)t.push(new Uint8Array([197,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=198,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}t.push(e)}encodeArray(e,t){const r=e.length;if(r<=15)t.push(new Uint8Array([144|r]));else if(r<=65535)t.push(new Uint8Array([220,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=221,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}for(const r of e)this.encodeValue(r,t)}encodeObject(e,t){const r=Object.keys(e),n=r.length;if(n<=15)t.push(new Uint8Array([128|n]));else if(n<=65535)t.push(new Uint8Array([222,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=223,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}for(const n of r)this.encodeValue(n,t),this.encodeValue(e[n],t)}decode(e){return this.decodeValue(e,{offset:0})}decodeValue(e,t){if(t.offset>=e.length)throw new Error("Unexpected end of data");const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");if(r<=127)return r;if(r>=128&&r<=143){const n=15&r;return this.decodeMap(e,t,n)}if(r>=144&&r<=159){const n=15&r;return this.decodeArray(e,t,n)}if(r>=160&&r<=191){const n=31&r;return this.decodeString(e,t,n)}if(r>=224)return(31&r)-32;switch(r){case 192:return null;case 194:return!1;case 195:return!0;case 196:{const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return this.decodeBinary(e,t,r)}case 197:return this.decodeBinary(e,t,this.readUint16(e,t));case 198:return this.decodeBinary(e,t,this.readUint32(e,t));case 202:return this.readFloat32(e,t);case 203:return this.readFloat64(e,t);case 204:{const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return r}case 205:return this.readUint16(e,t);case 206:return this.readUint32(e,t);case 208:return this.readInt8(e,t);case 209:return this.readInt16(e,t);case 210:return this.readInt32(e,t);case 217:{const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return this.decodeString(e,t,r)}case 218:return this.decodeString(e,t,this.readUint16(e,t));case 219:return this.decodeString(e,t,this.readUint32(e,t));case 220:return this.decodeArray(e,t,this.readUint16(e,t));case 221:return this.decodeArray(e,t,this.readUint32(e,t));case 222:return this.decodeMap(e,t,this.readUint16(e,t));case 223:return this.decodeMap(e,t,this.readUint32(e,t));default:throw new Error(`Unknown MessagePack type: 0x${r.toString(16)}`)}}decodeString(e,t,r){const n=e.slice(t.offset,t.offset+r);return t.offset+=r,(new TextDecoder).decode(n)}decodeBinary(e,t,r){const n=e.slice(t.offset,t.offset+r);return t.offset+=r,n}decodeArray(e,t,r){const n=[];for(let s=0;s<r;s++)n.push(this.decodeValue(e,t));return n}decodeMap(e,t,r){const n={};for(let s=0;s<r;s++){const r=this.decodeValue(e,t),s=this.decodeValue(e,t);n[String(r)]=s}return n}readUint16(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint16(t.offset,!1);return t.offset+=2,r}readUint32(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint32(t.offset,!1);return t.offset+=4,r}readInt8(e,t){if(t.offset>=e.length)throw new Error("Unexpected end of data");const r=new DataView(e.buffer,e.byteOffset).getInt8(t.offset);return t.offset+=1,r}readInt16(e,t){const r=new DataView(e.buffer,e.byteOffset).getInt16(t.offset,!1);return t.offset+=2,r}readInt32(e,t){const r=new DataView(e.buffer,e.byteOffset).getInt32(t.offset,!1);return t.offset+=4,r}readFloat32(e,t){const r=new DataView(e.buffer,e.byteOffset).getFloat32(t.offset,!1);return t.offset+=4,r}readFloat64(e,t){const r=new DataView(e.buffer,e.byteOffset).getFloat64(t.offset,!1);return t.offset+=8,r}}class CBORSerializer{format="cbor";contentType="application/cbor";serialize(e,t){try{return ok(this.encode(e))}catch(e){return err({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"cbor"})}}deserialize(e){try{return ok(this.decode(e))}catch(e){return err({code:"DESERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e)})}}detect(e){if(0===e.length)return!1;try{const t={offset:0};return this.decodeValue(e,t),!0}catch{return!1}}encode(e){const t=[];this.encodeValue(e,t);const r=t.reduce((e,t)=>e+t.length,0),n=new Uint8Array(r);let s=0;for(const e of t)n.set(e,s),s+=e.length;return n}encodeValue(e,t){if(null==e)t.push(new Uint8Array([246]));else if("boolean"==typeof e)t.push(new Uint8Array([e?245:244]));else if("number"==typeof e)this.encodeNumber(e,t);else if("string"==typeof e)this.encodeString(e,t);else if(e instanceof Uint8Array)this.encodeBinary(e,t);else if(Array.isArray(e))this.encodeArray(e,t);else{if("object"!=typeof e)throw new Error("Unsupported type: "+typeof e);this.encodeObject(e,t)}}encodeNumber(e,t){if(Number.isInteger(e))if(e>=0)if(e<=23)t.push(new Uint8Array([e]));else if(e<=255)t.push(new Uint8Array([24,e]));else if(e<=65535)t.push(new Uint8Array([25,e>>8,255&e]));else if(e<=4294967295){const r=new Uint8Array(5);r[0]=26,new DataView(r.buffer).setUint32(1,e,!1),t.push(r)}else{const r=new Uint8Array(9);r[0]=251,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}else{const r=-1-e;if(r<=23)t.push(new Uint8Array([32|r]));else if(r<=255)t.push(new Uint8Array([56,r]));else if(r<=65535)t.push(new Uint8Array([57,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=58,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}}else{const r=new Uint8Array(9);r[0]=251,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}}encodeString(e,t){const r=(new TextEncoder).encode(e),n=r.length;if(n<=23)t.push(new Uint8Array([96|n]));else if(n<=255)t.push(new Uint8Array([120,n]));else if(n<=65535)t.push(new Uint8Array([121,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=122,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}t.push(r)}encodeBinary(e,t){const r=e.length;if(r<=23)t.push(new Uint8Array([64|r]));else if(r<=255)t.push(new Uint8Array([88,r]));else if(r<=65535)t.push(new Uint8Array([89,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=90,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}t.push(e)}encodeArray(e,t){const r=e.length;if(r<=23)t.push(new Uint8Array([128|r]));else if(r<=255)t.push(new Uint8Array([152,r]));else if(r<=65535)t.push(new Uint8Array([153,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=154,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}for(const r of e)this.encodeValue(r,t)}encodeObject(e,t){const r=Object.keys(e),n=r.length;if(n<=23)t.push(new Uint8Array([160|n]));else if(n<=255)t.push(new Uint8Array([184,n]));else if(n<=65535)t.push(new Uint8Array([185,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=186,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}for(const n of r)this.encodeValue(n,t),this.encodeValue(e[n],t)}decode(e){return this.decodeValue(e,{offset:0})}decodeValue(e,t){if(t.offset>=e.length)throw new Error("Unexpected end of data");const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");const n=r>>5&7,s=31&r;switch(n){case 0:return this.decodeInteger(e,t,s);case 1:return-1-this.decodeInteger(e,t,s);case 2:return this.decodeBinary(e,t,s);case 3:return this.decodeString(e,t,s);case 4:return this.decodeArray(e,t,s);case 5:return this.decodeMap(e,t,s);case 7:return this.decodeSpecial(e,t,s);default:throw new Error(`Unsupported CBOR major type: ${n}`)}}decodeInteger(e,t,r){if(r<=23)return r;if(24===r){const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return r}if(25===r)return this.readUint16(e,t);if(26===r)return this.readUint32(e,t);throw new Error("Unsupported integer size")}decodeString(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s=e.slice(t.offset,t.offset+n);return t.offset+=n,(new TextDecoder).decode(s)}decodeBinary(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s=e.slice(t.offset,t.offset+n);return t.offset+=n,s}decodeArray(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s=[];for(let r=0;r<n;r++)s.push(this.decodeValue(e,t));return s}decodeMap(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s={};for(let r=0;r<n;r++){const r=this.decodeValue(e,t),n=this.decodeValue(e,t);s[String(r)]=n}return s}decodeSpecial(e,t,r){switch(r){case 20:return!1;case 21:return!0;case 22:return null;case 23:return;case 27:return this.readFloat64(e,t);default:throw new Error(`Unsupported CBOR special: ${r}`)}}readUint16(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint16(t.offset,!1);return t.offset+=2,r}readUint32(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint32(t.offset,!1);return t.offset+=4,r}readFloat64(e,t){const r=new DataView(e.buffer,e.byteOffset).getFloat64(t.offset,!1);return t.offset+=8,r}}const serializers=new Map([["json",new JSONSerializer],["cbor",new CBORSerializer],["msgpack",new MessagePackSerializer]]);export function serialize(e,t={}){const r=t.format??"json",n=serializers.get(r);if(!n)return err({code:"UNSUPPORTED_FORMAT",format:r});const s=t.collectMetrics?performance.now():0,o=n.serialize(e,t);if(!o.ok)return o;const i=t.collectMetrics?{serializeDuration:performance.now()-s,size:o.value.length,format:r,timestamp:Date.now()}:void 0;return ok({data:o.value,format:r,size:o.value.length,contentType:n.contentType,metrics:i})}export function deserialize(e,t={}){const r=t.collectMetrics?performance.now():0;let n,s;if(t.format){if(n=t.format,s=serializers.get(n),!s)return err({code:"UNSUPPORTED_FORMAT",format:n})}else{const t=detectFormat(e);if(!t.ok)return t;if(n=t.value,s=serializers.get(n),!s)return err({code:"UNSUPPORTED_FORMAT",format:n})}const o=s.deserialize(e);if(!o.ok)return o;const i=t.collectMetrics?{serializeDuration:performance.now()-r,size:e.length,format:n,timestamp:Date.now()}:void 0;return ok({value:o.value,format:n,metrics:i})}export function detectFormat(e){const t=serializers.get("json");if(t?.detect(e))return ok("json");if(0===e.length)return err({code:"FORMAT_DETECTION_FAILED",reason:"Empty data"});const r=serializers.get("cbor");if(r?.detect(e))return ok("cbor");const n=serializers.get("msgpack");return n?.detect(e)?ok("msgpack"):err({code:"FORMAT_DETECTION_FAILED",reason:"No serializer recognized the data format"})}export function negotiateFormat(e,t){for(const r of e)if(t.includes(r))return ok(r);return err({code:"UNSUPPORTED_FORMAT",format:`No common format (client: ${e.join(",")}, server: ${t.join(",")})`})}export function compareFormats(e,t=["json","msgpack","cbor"]){const r=[];for(const n of t){const t=serialize(e,{format:n,collectMetrics:!0});if(!t.ok)return t;r.push({format:n,size:t.value.size,duration:t.value.metrics?.serializeDuration??0})}return ok(r)}export function getContentType(e){const t=serializers.get(e);return t?.contentType??"application/octet-stream"}export function parseContentType(e){const t=e.toLowerCase().split(";")[0]?.trim()??"";for(const e of serializers.values())if(e.contentType===t)return e.format}