hbsig 0.0.1

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 (44) hide show
  1. package/cjs/bin_to_str.js +44 -0
  2. package/cjs/collect-body-keys.js +470 -0
  3. package/cjs/encode-array-item.js +110 -0
  4. package/cjs/encode-utils.js +236 -0
  5. package/cjs/encode.js +1318 -0
  6. package/cjs/erl_json.js +317 -0
  7. package/cjs/erl_str.js +1037 -0
  8. package/cjs/flat.js +222 -0
  9. package/cjs/http-message-signatures/httpbis.js +489 -0
  10. package/cjs/http-message-signatures/index.js +25 -0
  11. package/cjs/http-message-signatures/structured-header.js +129 -0
  12. package/cjs/httpsig.js +716 -0
  13. package/cjs/httpsig2.js +1160 -0
  14. package/cjs/id.js +470 -0
  15. package/cjs/index.js +63 -0
  16. package/cjs/send.js +194 -0
  17. package/cjs/signer-utils.js +617 -0
  18. package/cjs/signer.js +606 -0
  19. package/cjs/structured.js +296 -0
  20. package/cjs/test.js +27 -0
  21. package/cjs/utils.js +42 -0
  22. package/esm/bin_to_str.js +46 -0
  23. package/esm/collect-body-keys.js +436 -0
  24. package/esm/encode-array-item.js +112 -0
  25. package/esm/encode-utils.js +185 -0
  26. package/esm/encode.js +1219 -0
  27. package/esm/erl_json.js +289 -0
  28. package/esm/erl_str.js +1139 -0
  29. package/esm/flat.js +196 -0
  30. package/esm/http-message-signatures/httpbis.js +438 -0
  31. package/esm/http-message-signatures/index.js +4 -0
  32. package/esm/http-message-signatures/structured-header.js +105 -0
  33. package/esm/httpsig.js +658 -0
  34. package/esm/httpsig2.js +1097 -0
  35. package/esm/id.js +459 -0
  36. package/esm/index.js +4 -0
  37. package/esm/package.json +3 -0
  38. package/esm/send.js +124 -0
  39. package/esm/signer-utils.js +494 -0
  40. package/esm/signer.js +452 -0
  41. package/esm/structured.js +269 -0
  42. package/esm/test.js +6 -0
  43. package/esm/utils.js +28 -0
  44. package/package.json +28 -0
package/cjs/erl_str.js ADDED
@@ -0,0 +1,1037 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.erl_str_from = erl_str_from;
7
+ exports.erl_str_to = erl_str_to;
8
+ exports.parse_body = parse_body;
9
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
10
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
11
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
13
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
14
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
15
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
16
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
17
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
18
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
19
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
20
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
21
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
22
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
23
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
24
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
25
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
26
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
27
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
28
+ /**
29
+ * Erlang term string parser and formatter
30
+ * Converts between Erlang term strings and JavaScript values
31
+ */
32
+
33
+ /**
34
+ * Parse an Erlang term string into JavaScript values
35
+ * @param {string} str - Erlang term string
36
+ * @param {boolean} binaryMode - If true, keep binaries as Buffers; if false, convert to strings
37
+ * @returns {*} JavaScript value
38
+ */
39
+ function erl_str_from(str) {
40
+ var binaryMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
41
+ // Handle the new response format
42
+ if (str.startsWith("#erl_response{")) {
43
+ var rawMatch = str.match(/#erl_response\{raw=([^]*?),formatted=([^]*?)\}$/);
44
+ if (rawMatch && rawMatch[1] && rawMatch[2]) {
45
+ var rawStr = rawMatch[1];
46
+ var formattedStr = rawMatch[2];
47
+ if (binaryMode) {
48
+ // In binary mode, just parse formatted
49
+ var _parser = new ErlangParser(formattedStr, true);
50
+ return _parser.parse();
51
+ } else {
52
+ // Build a type map from raw, then parse formatted with type info
53
+ var typeMap = buildTypeMap(rawStr);
54
+ var _parser2 = new TypeAwareParser(formattedStr, typeMap);
55
+ return _parser2.parse();
56
+ }
57
+ }
58
+ }
59
+
60
+ // Fallback for non-response format
61
+ var parser = new ErlangParser(str, binaryMode);
62
+ return parser.parse();
63
+ }
64
+
65
+ /**
66
+ * Parse body field specially - convert to string only for multipart bodies
67
+ * @param {*} parsed - Parsed Erlang term object
68
+ * @returns {*} Object with body field potentially converted to string
69
+ */
70
+ function parse_body(parsed) {
71
+ if (!parsed || _typeof(parsed) !== "object") {
72
+ return parsed;
73
+ }
74
+
75
+ // If there's a body field
76
+ if ("body" in parsed) {
77
+ if (Buffer.isBuffer(parsed.body)) {
78
+ // Check if this looks like a multipart body
79
+ // Multipart bodies start with "--" boundary
80
+ var bodyStart = parsed.body.toString("binary", 0, Math.min(100, parsed.body.length));
81
+ if (bodyStart.startsWith("--") && parsed["content-type"] && parsed["content-type"].includes("multipart")) {
82
+ // It's a multipart body, convert to string
83
+ return _objectSpread(_objectSpread({}, parsed), {}, {
84
+ body: parsed.body.toString("binary")
85
+ });
86
+ }
87
+ // Not multipart, keep as Buffer
88
+ return parsed;
89
+ }
90
+ // Already a string, return as-is
91
+ return parsed;
92
+ }
93
+ return parsed;
94
+ }
95
+
96
+ // Build a map of paths to types by analyzing the raw string
97
+ function buildTypeMap(rawStr) {
98
+ var typeMap = new Map();
99
+ function detectBinaryType(str, startPos) {
100
+ // Check what follows <<
101
+ var pos = startPos + 2;
102
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
103
+ if (pos < str.length && str[pos] === '"') {
104
+ // It looks like a string, but check if it has escape sequences
105
+ // If it has \NNN octal escapes, it's actually a binary that Erlang formatted as string
106
+ var scanPos = pos + 1;
107
+ var hasOctalEscapes = false;
108
+ while (scanPos < str.length && !(str[scanPos] === '"' && str[scanPos + 1] === ">" && str[scanPos + 2] === ">")) {
109
+ if (str[scanPos] === "\\" && scanPos + 1 < str.length) {
110
+ var nextChar = str[scanPos + 1];
111
+ // Check for octal escape \NNN
112
+ if (/[0-7]/.test(nextChar)) {
113
+ hasOctalEscapes = true;
114
+ break;
115
+ }
116
+ scanPos += 2;
117
+ } else {
118
+ scanPos++;
119
+ }
120
+ }
121
+
122
+ // If it has octal escapes, treat as binary
123
+ if (hasOctalEscapes) {
124
+ return "binary";
125
+ }
126
+ return "string";
127
+ }
128
+ return "binary";
129
+ }
130
+ function scanValue(str, pos, path) {
131
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
132
+ if (pos >= str.length) return pos;
133
+ if (str[pos] === "#" && str[pos + 1] === "{") {
134
+ // Map
135
+ pos += 2;
136
+ var mapIndex = 0;
137
+ while (pos < str.length) {
138
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
139
+ if (str[pos] === "}") return pos + 1;
140
+
141
+ // Parse key
142
+ var keyStart = pos;
143
+ if (str[pos] === "<" && str[pos + 1] === "<") {
144
+ // Binary key
145
+ var keyType = detectBinaryType(str, pos);
146
+ var keyEnd = pos + 2;
147
+ if (keyType === "string") {
148
+ keyEnd++; // skip "
149
+ while (keyEnd < str.length && !(str[keyEnd] === '"' && str[keyEnd + 1] === ">" && str[keyEnd + 2] === ">")) {
150
+ if (str[keyEnd] === "\\") keyEnd++;
151
+ keyEnd++;
152
+ }
153
+ keyEnd += 3;
154
+ } else {
155
+ var depth = 1;
156
+ while (depth > 0 && keyEnd < str.length) {
157
+ if (str[keyEnd] === "<" && str[keyEnd + 1] === "<") {
158
+ depth++;
159
+ keyEnd += 2;
160
+ } else if (str[keyEnd] === ">" && str[keyEnd + 1] === ">") {
161
+ depth--;
162
+ keyEnd += 2;
163
+ } else {
164
+ keyEnd++;
165
+ }
166
+ }
167
+ }
168
+ pos = keyEnd;
169
+ } else {
170
+ // Regular key
171
+ while (pos < str.length && !/[\s=,}]/.test(str[pos])) pos++;
172
+ }
173
+
174
+ // Skip =>
175
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
176
+ if (str[pos] === "=" && str[pos + 1] === ">") pos += 2;
177
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
178
+
179
+ // Parse value and record type if binary
180
+ if (str[pos] === "<" && str[pos + 1] === "<") {
181
+ var type = detectBinaryType(str, pos);
182
+ var pathKey = [].concat(_toConsumableArray(path), [mapIndex]).join(".");
183
+ typeMap.set(pathKey, type);
184
+ }
185
+ pos = scanValue(str, pos, [].concat(_toConsumableArray(path), [mapIndex]));
186
+ mapIndex++;
187
+
188
+ // Skip comma
189
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
190
+ if (str[pos] === ",") pos++;
191
+ }
192
+ } else if (str[pos] === "<" && str[pos + 1] === "<") {
193
+ // Binary
194
+ var _type = detectBinaryType(str, pos);
195
+ var _pathKey = path.join(".");
196
+ typeMap.set(_pathKey, _type);
197
+ pos += 2;
198
+ if (_type === "string" || str[pos] === '"') {
199
+ // Skip past string literal
200
+ if (str[pos] === '"') pos++; // skip opening quote
201
+ while (pos < str.length && !(str[pos] === '"' && str[pos + 1] === ">" && str[pos + 2] === ">")) {
202
+ if (str[pos] === "\\") pos++;
203
+ pos++;
204
+ }
205
+ return pos + 3;
206
+ } else {
207
+ var _depth = 1;
208
+ while (_depth > 0 && pos < str.length) {
209
+ if (str[pos] === "<" && str[pos + 1] === "<") {
210
+ _depth++;
211
+ pos += 2;
212
+ } else if (str[pos] === ">" && str[pos + 1] === ">") {
213
+ _depth--;
214
+ pos += 2;
215
+ } else {
216
+ pos++;
217
+ }
218
+ }
219
+ return pos;
220
+ }
221
+ } else if (str[pos] === "[") {
222
+ // List
223
+ pos++;
224
+ var listIndex = 0;
225
+ while (pos < str.length) {
226
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
227
+ if (str[pos] === "]") return pos + 1;
228
+ pos = scanValue(str, pos, [].concat(_toConsumableArray(path), [listIndex]));
229
+ listIndex++;
230
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
231
+ if (str[pos] === ",") pos++;
232
+ }
233
+ } else {
234
+ // Skip other values
235
+ while (pos < str.length && !/[\s,\]}=>]/.test(str[pos])) {
236
+ pos++;
237
+ }
238
+ return pos;
239
+ }
240
+ return pos;
241
+ }
242
+ scanValue(rawStr, 0, []);
243
+ return typeMap;
244
+ }
245
+
246
+ // Parser that uses type information
247
+ var TypeAwareParser = /*#__PURE__*/function () {
248
+ function TypeAwareParser(str, typeMap) {
249
+ _classCallCheck(this, TypeAwareParser);
250
+ this.str = str;
251
+ this.typeMap = typeMap;
252
+ this.pos = 0;
253
+ this.path = [];
254
+ }
255
+ return _createClass(TypeAwareParser, [{
256
+ key: "parse",
257
+ value: function parse() {
258
+ var result = this.parseValue();
259
+ this.skipWhitespace();
260
+ if (this.pos < this.str.length) {
261
+ throw new Error("Unexpected content at position ".concat(this.pos));
262
+ }
263
+ return result;
264
+ }
265
+ }, {
266
+ key: "peek",
267
+ value: function peek() {
268
+ var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
269
+ return this.str[this.pos + offset] || "";
270
+ }
271
+ }, {
272
+ key: "advance",
273
+ value: function advance() {
274
+ var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
275
+ this.pos += count;
276
+ }
277
+ }, {
278
+ key: "skipWhitespace",
279
+ value: function skipWhitespace() {
280
+ while (this.pos < this.str.length && /\s/.test(this.peek())) {
281
+ this.advance();
282
+ }
283
+ }
284
+ }, {
285
+ key: "parseValue",
286
+ value: function parseValue() {
287
+ this.skipWhitespace();
288
+ var ch = this.peek();
289
+ var ch2 = this.peek(1);
290
+ if (ch === "#" && ch2 === "{") {
291
+ return this.parseMap();
292
+ }
293
+ if (ch === "<" && ch2 === "<") {
294
+ return this.parseBinary();
295
+ }
296
+ if (ch === "[") {
297
+ return this.parseList();
298
+ }
299
+ if (ch === "'") {
300
+ return this.parseQuotedAtom();
301
+ }
302
+ if (ch === '"') {
303
+ return this.parseQuotedString();
304
+ }
305
+ return this.parseAtomOrNumber();
306
+ }
307
+ }, {
308
+ key: "parseMap",
309
+ value: function parseMap() {
310
+ this.advance(2); // skip #{
311
+ var map = {};
312
+ var mapIndex = 0;
313
+ while (true) {
314
+ this.skipWhitespace();
315
+ if (this.peek() === "}") {
316
+ this.advance();
317
+ break;
318
+ }
319
+ this.path.push(mapIndex);
320
+ var key = this.parseValue();
321
+ this.path.pop();
322
+ this.skipWhitespace();
323
+ if (this.peek() !== "=" || this.peek(1) !== ">") {
324
+ throw new Error("Expected =>");
325
+ }
326
+ this.advance(2);
327
+ this.skipWhitespace();
328
+ this.path.push(mapIndex);
329
+ var value = this.parseValue();
330
+ this.path.pop();
331
+ var jsKey = key instanceof Buffer ? key.toString("utf8") : _typeof(key) === "symbol" ? Symbol.keyFor(key) || String(key) : String(key);
332
+ map[jsKey] = value;
333
+ mapIndex++;
334
+ this.skipWhitespace();
335
+ if (this.peek() === ",") {
336
+ this.advance();
337
+ }
338
+ }
339
+ return map;
340
+ }
341
+ }, {
342
+ key: "parseBinary",
343
+ value: function parseBinary() {
344
+ var currentPath = this.path.join(".");
345
+ var type = this.typeMap.get(currentPath) || "binary";
346
+
347
+ // Parse the formatted version (always byte format)
348
+ this.advance(2); // skip <<
349
+
350
+ if (this.peek() === ">" && this.peek(1) === ">") {
351
+ this.advance(2);
352
+ return Buffer.alloc(0);
353
+ }
354
+ var bytes = [];
355
+ while (!(this.peek() === ">" && this.peek(1) === ">")) {
356
+ this.skipWhitespace();
357
+ var num = "";
358
+ while (/\d/.test(this.peek())) {
359
+ num += this.peek();
360
+ this.advance();
361
+ }
362
+ if (num) bytes.push(parseInt(num, 10));
363
+ this.skipWhitespace();
364
+ if (this.peek() === ",") this.advance();
365
+ }
366
+ this.advance(2); // skip >>
367
+
368
+ var buffer = Buffer.from(bytes);
369
+
370
+ // If it was a string literal in raw, convert to string
371
+ if (type === "string") {
372
+ return buffer.toString("utf8");
373
+ }
374
+
375
+ // For binaries that are not explicitly marked as strings, check if they're valid UTF-8
376
+ // that contains reasonable string content (no control characters except \t, \n, \r)
377
+ try {
378
+ var str = buffer.toString("utf8");
379
+ // Check if the string round-trips correctly
380
+ if (Buffer.from(str, "utf8").equals(buffer)) {
381
+ // It's valid UTF-8, but also check if it contains reasonable characters
382
+ var hasReasonableChars = true;
383
+ for (var i = 0; i < str.length; i++) {
384
+ var code = str.charCodeAt(i);
385
+ // Allow printable chars, space, tab, newline, carriage return, and Unicode
386
+ if (code < 0x20 && code !== 0x09 && code !== 0x0a && code !== 0x0d) {
387
+ hasReasonableChars = false;
388
+ break;
389
+ }
390
+ }
391
+ if (hasReasonableChars) {
392
+ return str;
393
+ }
394
+ }
395
+ } catch (e) {
396
+ // Not valid UTF-8, keep as buffer
397
+ }
398
+ return buffer;
399
+ }
400
+ }, {
401
+ key: "parseQuotedString",
402
+ value: function parseQuotedString() {
403
+ this.advance(); // skip opening "
404
+ var str = "";
405
+ while (this.peek() !== '"') {
406
+ if (this.peek() === "\\") {
407
+ this.advance();
408
+ var escaped = this.peek();
409
+ switch (escaped) {
410
+ case '"':
411
+ str += '"';
412
+ break;
413
+ case "\\":
414
+ str += "\\";
415
+ break;
416
+ case "n":
417
+ str += "\n";
418
+ break;
419
+ case "r":
420
+ str += "\r";
421
+ break;
422
+ case "t":
423
+ str += "\t";
424
+ break;
425
+ default:
426
+ str += escaped;
427
+ }
428
+ this.advance();
429
+ } else {
430
+ str += this.peek();
431
+ this.advance();
432
+ }
433
+ }
434
+ this.advance(); // skip closing "
435
+ return str;
436
+ }
437
+ }, {
438
+ key: "parseList",
439
+ value: function parseList() {
440
+ this.advance(); // skip [
441
+ var list = [];
442
+ var listIndex = 0;
443
+ while (true) {
444
+ this.skipWhitespace();
445
+ if (this.peek() === "]") {
446
+ this.advance();
447
+ break;
448
+ }
449
+ this.path.push(listIndex);
450
+ list.push(this.parseValue());
451
+ this.path.pop();
452
+ listIndex++;
453
+ this.skipWhitespace();
454
+ if (this.peek() === ",") {
455
+ this.advance();
456
+ }
457
+ }
458
+ return list;
459
+ }
460
+ }, {
461
+ key: "parseQuotedAtom",
462
+ value: function parseQuotedAtom() {
463
+ this.advance(); // skip '
464
+
465
+ var atom = "";
466
+ while (this.peek() !== "'") {
467
+ if (this.peek() === "\\") {
468
+ this.advance();
469
+ var escaped = this.peek();
470
+ switch (escaped) {
471
+ case "'":
472
+ atom += "'";
473
+ break;
474
+ case "\\":
475
+ atom += "\\";
476
+ break;
477
+ case "n":
478
+ atom += "\n";
479
+ break;
480
+ case "r":
481
+ atom += "\r";
482
+ break;
483
+ case "t":
484
+ atom += "\t";
485
+ break;
486
+ default:
487
+ atom += escaped;
488
+ }
489
+ this.advance();
490
+ } else {
491
+ atom += this.peek();
492
+ this.advance();
493
+ }
494
+ }
495
+ this.advance(); // skip closing '
496
+
497
+ if (atom === "null") return null;
498
+ if (atom === "true") return true;
499
+ if (atom === "false") return false;
500
+ return Symbol["for"](atom);
501
+ }
502
+ }, {
503
+ key: "parseAtomOrNumber",
504
+ value: function parseAtomOrNumber() {
505
+ var token = "";
506
+
507
+ // Parse unquoted atom/number
508
+ while (this.pos < this.str.length) {
509
+ var ch = this.peek();
510
+ if (ch === "," || ch === "]" || ch === "}" || ch === ")" || ch === "=" && this.peek(1) === ">") {
511
+ break;
512
+ }
513
+ if (/\s/.test(ch)) {
514
+ var i = this.pos;
515
+ while (i < this.str.length && /\s/.test(this.str[i])) i++;
516
+ if (i >= this.str.length) break;
517
+ var nextCh = this.str[i];
518
+ if (nextCh === "," || nextCh === "]" || nextCh === "}" || nextCh === ")" || nextCh === "=" && i + 1 < this.str.length && this.str[i + 1] === ">") {
519
+ break;
520
+ }
521
+ }
522
+ token += ch;
523
+ this.advance();
524
+ }
525
+ token = token.trim();
526
+ if (token === "null") return null;
527
+ if (token === "true") return true;
528
+ if (token === "false") return false;
529
+ if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(token)) {
530
+ return parseFloat(token);
531
+ }
532
+ return Symbol["for"](token);
533
+ }
534
+ }]);
535
+ }(); // Parser implementation
536
+ var ErlangParser = /*#__PURE__*/function () {
537
+ function ErlangParser(str) {
538
+ var binaryMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
539
+ _classCallCheck(this, ErlangParser);
540
+ this.str = str;
541
+ this.pos = 0;
542
+ this.binaryMode = binaryMode;
543
+ }
544
+ return _createClass(ErlangParser, [{
545
+ key: "parse",
546
+ value: function parse() {
547
+ var result = this.parseValue();
548
+ this.skipWhitespace();
549
+ if (this.pos < this.str.length) {
550
+ throw new Error("Unexpected content at position ".concat(this.pos, ": ").concat(this.str.slice(this.pos, this.pos + 50)));
551
+ }
552
+ return result;
553
+ }
554
+ }, {
555
+ key: "peek",
556
+ value: function peek() {
557
+ var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
558
+ return this.str[this.pos + offset] || "";
559
+ }
560
+ }, {
561
+ key: "advance",
562
+ value: function advance() {
563
+ var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
564
+ this.pos += count;
565
+ }
566
+ }, {
567
+ key: "skipWhitespace",
568
+ value: function skipWhitespace() {
569
+ while (this.pos < this.str.length && /\s/.test(this.peek())) {
570
+ this.advance();
571
+ }
572
+ }
573
+ }, {
574
+ key: "parseValue",
575
+ value: function parseValue() {
576
+ this.skipWhitespace();
577
+ var ch = this.peek();
578
+ var ch2 = this.peek(1);
579
+
580
+ // Map: #{...}
581
+ if (ch === "#" && ch2 === "{") {
582
+ return this.parseMap();
583
+ }
584
+
585
+ // Binary: <<...>>
586
+ if (ch === "<" && ch2 === "<") {
587
+ return this.parseBinary();
588
+ }
589
+
590
+ // List: [...]
591
+ if (ch === "[") {
592
+ return this.parseList();
593
+ }
594
+
595
+ // Quoted atom: 'atom'
596
+ if (ch === "'") {
597
+ return this.parseQuotedAtom();
598
+ }
599
+
600
+ // Quoted string: "..."
601
+ if (ch === '"') {
602
+ return this.parseQuotedString();
603
+ }
604
+
605
+ // Number or unquoted atom
606
+ return this.parseAtomOrNumber();
607
+ }
608
+ }, {
609
+ key: "parseMap",
610
+ value: function parseMap() {
611
+ this.advance(2); // skip #{
612
+ var map = {};
613
+ while (true) {
614
+ this.skipWhitespace();
615
+ if (this.peek() === "}") {
616
+ this.advance();
617
+ break;
618
+ }
619
+
620
+ // Parse key
621
+ var key = this.parseValue();
622
+ this.skipWhitespace();
623
+
624
+ // Expect =>
625
+ if (this.peek() !== "=" || this.peek(1) !== ">") {
626
+ throw new Error("Expected => at position ".concat(this.pos));
627
+ }
628
+ this.advance(2);
629
+ this.skipWhitespace();
630
+
631
+ // Parse value
632
+ var value = this.parseValue();
633
+
634
+ // Convert key to string
635
+ var jsKey = void 0;
636
+ if (key instanceof Buffer) {
637
+ jsKey = key.toString("utf8");
638
+ } else if (_typeof(key) === "symbol") {
639
+ jsKey = Symbol.keyFor(key) || key.description || String(key);
640
+ } else {
641
+ jsKey = String(key);
642
+ }
643
+ map[jsKey] = value;
644
+ this.skipWhitespace();
645
+ if (this.peek() === ",") {
646
+ this.advance();
647
+ }
648
+ }
649
+ return map;
650
+ }
651
+ }, {
652
+ key: "parseBinary",
653
+ value: function parseBinary() {
654
+ this.advance(2); // skip <<
655
+
656
+ // String binary: <<"...">>
657
+ if (this.peek() === '"') {
658
+ this.advance(); // skip "
659
+ var content = "";
660
+ while (!(this.peek() === '"' && this.peek(1) === ">" && this.peek(2) === ">")) {
661
+ if (this.pos >= this.str.length) {
662
+ throw new Error("Unterminated string binary");
663
+ }
664
+ if (this.peek() === "\\") {
665
+ this.advance();
666
+ var escaped = this.peek();
667
+
668
+ // Check for octal escape sequences \NNN
669
+ if (/[0-7]/.test(escaped)) {
670
+ var octal = escaped;
671
+ this.advance();
672
+
673
+ // Get up to 2 more octal digits
674
+ if (/[0-7]/.test(this.peek())) {
675
+ octal += this.peek();
676
+ this.advance();
677
+ if (/[0-7]/.test(this.peek())) {
678
+ octal += this.peek();
679
+ this.advance();
680
+ }
681
+ }
682
+
683
+ // Convert octal to character
684
+ var charCode = parseInt(octal, 8);
685
+ content += String.fromCharCode(charCode);
686
+ } else {
687
+ // Regular escape sequences
688
+ switch (escaped) {
689
+ case '"':
690
+ content += '"';
691
+ break;
692
+ case "\\":
693
+ content += "\\";
694
+ break;
695
+ case "n":
696
+ content += "\n";
697
+ break;
698
+ case "r":
699
+ content += "\r";
700
+ break;
701
+ case "t":
702
+ content += "\t";
703
+ break;
704
+ default:
705
+ content += escaped;
706
+ }
707
+ this.advance();
708
+ }
709
+ } else {
710
+ content += this.peek();
711
+ this.advance();
712
+ }
713
+ }
714
+ this.advance(3); // skip ">>
715
+
716
+ // Check for structured field format
717
+ if (content.startsWith(":") && content.endsWith(":") && content.length >= 2) {
718
+ if (content === "::") {
719
+ return Buffer.alloc(0);
720
+ }
721
+ try {
722
+ var base64 = content.slice(1, -1);
723
+ return Buffer.from(base64, "base64");
724
+ } catch (e) {
725
+ // Not valid base64, treat as regular string
726
+ }
727
+ }
728
+
729
+ // In binary mode, return as Buffer; otherwise check if it's printable
730
+ if (this.binaryMode) {
731
+ return Buffer.from(content, "utf8");
732
+ } else {
733
+ // Check if the content is printable
734
+ var _bytes = Buffer.from(content, "utf8");
735
+ var isPrintable = Array.from(_bytes).every(function (b) {
736
+ return b >= 32 && b <= 126;
737
+ });
738
+
739
+ // If it contains non-printable characters, return as Buffer
740
+ if (!isPrintable) {
741
+ return _bytes;
742
+ }
743
+
744
+ // Otherwise return as string
745
+ return content;
746
+ }
747
+ }
748
+
749
+ // Empty binary: <<>>
750
+ if (this.peek() === ">" && this.peek(1) === ">") {
751
+ this.advance(2);
752
+ return Buffer.alloc(0);
753
+ }
754
+
755
+ // Byte binary: <<1,2,3>>
756
+ var bytes = [];
757
+ while (!(this.peek() === ">" && this.peek(1) === ">")) {
758
+ if (this.pos >= this.str.length) {
759
+ throw new Error("Unterminated byte binary");
760
+ }
761
+ this.skipWhitespace();
762
+ var num = "";
763
+ while (/\d/.test(this.peek())) {
764
+ num += this.peek();
765
+ this.advance();
766
+ }
767
+ if (num) {
768
+ bytes.push(parseInt(num, 10));
769
+ }
770
+ this.skipWhitespace();
771
+ if (this.peek() === ",") {
772
+ this.advance();
773
+ }
774
+ }
775
+ this.advance(2); // skip >>
776
+ return Buffer.from(bytes);
777
+ }
778
+ }, {
779
+ key: "parseQuotedString",
780
+ value: function parseQuotedString() {
781
+ this.advance(); // skip "
782
+ var str = "";
783
+ while (this.peek() !== '"') {
784
+ if (this.peek() === "\\") {
785
+ this.advance();
786
+ var escaped = this.peek();
787
+ switch (escaped) {
788
+ case '"':
789
+ str += '"';
790
+ break;
791
+ case "\\":
792
+ str += "\\";
793
+ break;
794
+ case "n":
795
+ str += "\n";
796
+ break;
797
+ case "r":
798
+ str += "\r";
799
+ break;
800
+ case "t":
801
+ str += "\t";
802
+ break;
803
+ default:
804
+ str += escaped;
805
+ }
806
+ this.advance();
807
+ } else {
808
+ str += this.peek();
809
+ this.advance();
810
+ }
811
+ }
812
+ this.advance(); // skip closing "
813
+ return str;
814
+ }
815
+ }, {
816
+ key: "parseList",
817
+ value: function parseList() {
818
+ this.advance(); // skip [
819
+ var list = [];
820
+ while (true) {
821
+ this.skipWhitespace();
822
+ if (this.peek() === "]") {
823
+ this.advance();
824
+ break;
825
+ }
826
+ list.push(this.parseValue());
827
+ this.skipWhitespace();
828
+ if (this.peek() === ",") {
829
+ this.advance();
830
+ }
831
+ }
832
+ return list;
833
+ }
834
+ }, {
835
+ key: "parseQuotedAtom",
836
+ value: function parseQuotedAtom() {
837
+ this.advance(); // skip '
838
+ var atom = "";
839
+ while (this.peek() !== "'") {
840
+ if (this.pos >= this.str.length) {
841
+ throw new Error("Unterminated quoted atom");
842
+ }
843
+ if (this.peek() === "\\") {
844
+ this.advance();
845
+ var escaped = this.peek();
846
+ switch (escaped) {
847
+ case "'":
848
+ atom += "'";
849
+ break;
850
+ case "\\":
851
+ atom += "\\";
852
+ break;
853
+ case "n":
854
+ atom += "\n";
855
+ break;
856
+ // Literal newline
857
+ case "r":
858
+ atom += "\r";
859
+ break;
860
+ case "t":
861
+ atom += "\t";
862
+ break;
863
+ default:
864
+ atom += escaped;
865
+ }
866
+ this.advance();
867
+ } else {
868
+ atom += this.peek();
869
+ this.advance();
870
+ }
871
+ }
872
+ this.advance(); // skip closing '
873
+
874
+ // Special atoms that become JS primitives
875
+ if (atom === "null") return null;
876
+ if (atom === "true") return true;
877
+ if (atom === "false") return false;
878
+ return Symbol["for"](atom);
879
+ }
880
+ }, {
881
+ key: "parseAtomOrNumber",
882
+ value: function parseAtomOrNumber() {
883
+ var startPos = this.pos;
884
+ var token = "";
885
+
886
+ // Simple approach: collect until we hit a known delimiter
887
+ while (this.pos < this.str.length) {
888
+ var ch = this.peek();
889
+ var ch2 = this.peek(1);
890
+
891
+ // Stop at these delimiters
892
+ if (ch === ",") break;
893
+ if (ch === "]") break;
894
+ if (ch === "}") break;
895
+ if (ch === ")") break;
896
+ if (ch === "=" && ch2 === ">") break;
897
+
898
+ // Handle backslash specially
899
+ if (ch === "\\") {
900
+ // In unquoted atoms, backslash is just a regular character
901
+ token += ch;
902
+ this.advance();
903
+
904
+ // Don't try to interpret the next character as an escape
905
+ if (this.pos < this.str.length) {
906
+ token += this.peek();
907
+ this.advance();
908
+ }
909
+ continue;
910
+ }
911
+
912
+ // For whitespace, check if it's trailing
913
+ if (/\s/.test(ch)) {
914
+ // Scan ahead to find next non-whitespace
915
+ var i = this.pos;
916
+ while (i < this.str.length && /\s/.test(this.str[i])) {
917
+ i++;
918
+ }
919
+
920
+ // Check what comes after whitespace
921
+ if (i >= this.str.length) {
922
+ // Hit end of string
923
+ break;
924
+ }
925
+ var nextCh = this.str[i];
926
+ if (nextCh === "," || nextCh === "]" || nextCh === "}" || nextCh === ")") {
927
+ // This whitespace is trailing, not part of atom
928
+ break;
929
+ }
930
+ if (nextCh === "=" && i + 1 < this.str.length && this.str[i + 1] === ">") {
931
+ // Whitespace before =>
932
+ break;
933
+ }
934
+ }
935
+
936
+ // Include this character in the atom
937
+ token += ch;
938
+ this.advance();
939
+
940
+ // Safety check to prevent infinite loops
941
+ if (this.pos - startPos > 1000) {
942
+ throw new Error("Atom too long at position ".concat(startPos));
943
+ }
944
+ }
945
+
946
+ // Trim only trailing whitespace
947
+ token = token.trimEnd();
948
+ if (!token) {
949
+ throw new Error("Empty atom at position ".concat(this.pos));
950
+ }
951
+
952
+ // Handle special atoms
953
+ if (token === "null") return null;
954
+ if (token === "true") return true;
955
+ if (token === "false") return false;
956
+
957
+ // Try to parse as number
958
+ if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(token)) {
959
+ return parseFloat(token);
960
+ }
961
+
962
+ // Return as atom
963
+ return Symbol["for"](token);
964
+ }
965
+ }]);
966
+ }();
967
+ /**
968
+ * Format JavaScript values as Erlang term strings
969
+ * @param {*} value - JavaScript value
970
+ * @returns {string} Erlang term string
971
+ */
972
+ function erl_str_to(value) {
973
+ return formatValue(value);
974
+ }
975
+
976
+ // Formatter implementation
977
+ function formatValue(value) {
978
+ if (value === null) return "null";
979
+ if (value === undefined) return "undefined";
980
+ if (typeof value === "boolean") return value.toString();
981
+ if (typeof value === "number") {
982
+ return value.toString();
983
+ }
984
+ if (typeof value === "string") {
985
+ // Format as string binary
986
+ return "<<\"".concat(escapeString(value), "\">>");
987
+ }
988
+ if (_typeof(value) === "symbol") {
989
+ var key = Symbol.keyFor(value);
990
+ var name = key || value.description || "";
991
+
992
+ // Special symbols
993
+ if (name === "null") return "null";
994
+ if (name === "true") return "true";
995
+ if (name === "false") return "false";
996
+ if (name === "undefined") return "undefined";
997
+
998
+ // Check if needs quoting
999
+ if (/^[a-z][a-zA-Z0-9_]*$/.test(name)) {
1000
+ return name;
1001
+ } else {
1002
+ return "'".concat(escapeString(name), "'");
1003
+ }
1004
+ }
1005
+ if (value instanceof Buffer || value instanceof Uint8Array) {
1006
+ var bytes = Array.from(value);
1007
+
1008
+ // Check if it's printable
1009
+ var isPrintable = bytes.every(function (b) {
1010
+ return b >= 32 && b <= 126;
1011
+ });
1012
+ if (isPrintable) {
1013
+ var str = Buffer.from(value).toString();
1014
+ return "<<\"".concat(escapeString(str), "\">>");
1015
+ } else {
1016
+ return "<<".concat(bytes.join(","), ">>");
1017
+ }
1018
+ }
1019
+ if (Array.isArray(value)) {
1020
+ var items = value.map(formatValue);
1021
+ return "[".concat(items.join(","), "]");
1022
+ }
1023
+ if (_typeof(value) === "object" && value !== null) {
1024
+ var entries = Object.entries(value).map(function (_ref) {
1025
+ var _ref2 = _slicedToArray(_ref, 2),
1026
+ k = _ref2[0],
1027
+ v = _ref2[1];
1028
+ var key = "<<\"".concat(escapeString(k), "\">>");
1029
+ return "".concat(key, " => ").concat(formatValue(v));
1030
+ });
1031
+ return "#{".concat(entries.join(","), "}");
1032
+ }
1033
+ return String(value);
1034
+ }
1035
+ function escapeString(str) {
1036
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
1037
+ }