hbsig 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/commit.js CHANGED
@@ -15,11 +15,15 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
15
15
  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; }
16
16
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
17
17
  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); }
18
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
19
+ 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; } }
20
+ 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; }
18
21
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
19
22
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
23
+ // todo: handle @
20
24
  var commit = exports.commit = /*#__PURE__*/function () {
21
25
  var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(obj, opts) {
22
- var msg, hmacId, rsaId, pub, committer, meta, meta2, sigs;
26
+ var msg, _yield$verify, components, body, inlineBodyKey, _iterator, _step, v, key, bodyContent, arrayBuffer, hmacId, rsaId, pub, committer, meta, meta2, sigs, committed;
23
27
  return _regenerator().w(function (_context) {
24
28
  while (1) switch (_context.n) {
25
29
  case 0:
@@ -27,6 +31,54 @@ var commit = exports.commit = /*#__PURE__*/function () {
27
31
  return opts.signer(obj, opts);
28
32
  case 1:
29
33
  msg = _context.v;
34
+ _context.n = 2;
35
+ return (0, _signerUtils.verify)(msg);
36
+ case 2:
37
+ _yield$verify = _context.v;
38
+ components = _yield$verify.decodedSignatureInput.components;
39
+ body = {}; // Check for inline-body-key
40
+ inlineBodyKey = msg.headers["inline-body-key"]; // Build body from components
41
+ _iterator = _createForOfIteratorHelper(components);
42
+ try {
43
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
44
+ v = _step.value;
45
+ key = v === "@path" ? "path" : v;
46
+ body[key] = msg.headers[key];
47
+ }
48
+
49
+ // Handle body resolution
50
+ } catch (err) {
51
+ _iterator.e(err);
52
+ } finally {
53
+ _iterator.f();
54
+ }
55
+ if (!msg.body) {
56
+ _context.n = 6;
57
+ break;
58
+ }
59
+ if (!(msg.body instanceof Blob)) {
60
+ _context.n = 4;
61
+ break;
62
+ }
63
+ _context.n = 3;
64
+ return msg.body.arrayBuffer();
65
+ case 3:
66
+ arrayBuffer = _context.v;
67
+ bodyContent = Buffer.from(arrayBuffer);
68
+ _context.n = 5;
69
+ break;
70
+ case 4:
71
+ bodyContent = msg.body;
72
+ case 5:
73
+ // If inline-body-key is "data", put content in data field
74
+ if (inlineBodyKey === "data") {
75
+ body.data = bodyContent;
76
+ } else {
77
+ body.body = bodyContent;
78
+ }
79
+ case 6:
80
+ // Remove inline-body-key from the final body as it's just metadata
81
+ delete body["inline-body-key"];
30
82
  hmacId = (0, _id.hmacid)(msg.headers);
31
83
  rsaId = (0, _id.rsaid)(msg.headers);
32
84
  pub = (0, _signerUtils.extractPubKey)(msg.headers);
@@ -43,11 +95,12 @@ var commit = exports.commit = /*#__PURE__*/function () {
43
95
  signature: msg.headers.signature,
44
96
  "signature-input": msg.headers["signature-input"]
45
97
  };
46
- return _context.a(2, _objectSpread({
98
+ committed = _objectSpread({
47
99
  commitments: _defineProperty(_defineProperty({}, rsaId, _objectSpread(_objectSpread({}, meta), {}, {
48
100
  committer: committer
49
101
  }, sigs)), hmacId, _objectSpread(_objectSpread({}, meta2), sigs))
50
- }, obj));
102
+ }, body);
103
+ return _context.a(2, committed);
51
104
  }
52
105
  }, _callee);
53
106
  }));
package/cjs/signer.js CHANGED
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.createSigner = void 0;
7
7
  exports.sign = sign;
8
- exports.signInternal = void 0;
9
8
  exports.signer = signer;
10
9
  Object.defineProperty(exports, "verify", {
11
10
  enumerable: true,
@@ -21,8 +20,9 @@ var _encodeUtils = require("./encode-utils.js");
21
20
  var _aoconnect = require("@permaweb/aoconnect");
22
21
  var _send = require("./send.js");
23
22
  var _signerUtils = require("./signer-utils.js");
24
- var _excluded = ["path", "method"],
25
- _excluded2 = ["body"];
23
+ var _excluded = ["body"],
24
+ _excluded2 = ["path", "method"],
25
+ _excluded3 = ["body"];
26
26
  function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
27
27
  function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
28
28
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
@@ -226,9 +226,8 @@ var smartSign = /*#__PURE__*/function () {
226
226
  break;
227
227
  }
228
228
  // Build a simple message that won't trigger multipart
229
- message = {
230
- path: path || filtered.path || "/~wao@1.0/httpsig"
231
- };
229
+ message = {};
230
+ if (path) message.path = path;
232
231
  types = [];
233
232
  _i5 = 0, _Object$entries5 = Object.entries(filtered);
234
233
  case 7:
@@ -275,8 +274,8 @@ var smartSign = /*#__PURE__*/function () {
275
274
  return _context.a(2, (0, _httpsig.httpsig_to)(message));
276
275
  case 11:
277
276
  // For complex structures that need multipart, use enc()
278
- normalized = (0, _erl_json.normalize)(_objectSpread(_objectSpread({}, filtered), {}, {
279
- path: path || "/~wao@1.0/httpsig"
277
+ normalized = (0, _erl_json.normalize)(_objectSpread(_objectSpread({}, filtered), path && {
278
+ path: path
280
279
  }));
281
280
  _context.n = 12;
282
281
  return (0, _encode.enc)(normalized);
@@ -285,8 +284,9 @@ var smartSign = /*#__PURE__*/function () {
285
284
  // enc() returns { headers: {...}, body: ... }
286
285
  // We need to flatten this for httpsig_to
287
286
  flattened = _objectSpread(_objectSpread({}, result.headers), {}, {
288
- body: result.body,
289
- path: normalized.path || path || "/~wao@1.0/httpsig"
287
+ body: result.body
288
+ }, path && {
289
+ path: path
290
290
  }); // httpsig_to expects the structured format
291
291
  encoded = (0, _httpsig.httpsig_to)(flattened);
292
292
  return _context.a(2, encoded);
@@ -296,9 +296,8 @@ var smartSign = /*#__PURE__*/function () {
296
296
  console.error("Encoding failed:", _t);
297
297
 
298
298
  // Fallback: create a simple structure
299
- _result = {
300
- path: path || "/~wao@1.0/httpsig"
301
- };
299
+ _result = {};
300
+ if (path) _result.path = path;
302
301
  _i6 = 0, _Object$entries6 = Object.entries(obj);
303
302
  case 14:
304
303
  if (!(_i6 < _Object$entries6.length)) {
@@ -329,10 +328,10 @@ var smartSign = /*#__PURE__*/function () {
329
328
  };
330
329
  }();
331
330
 
332
- // Internal sign function that matches the original signature
333
- var _sign = exports.signInternal = /*#__PURE__*/function () {
331
+ // Internal encode function that uses the original impl as much as possible
332
+ var encode = /*#__PURE__*/function () {
334
333
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(obj, path) {
335
- var filtered, encoded;
334
+ var filtered, fields, encoded, body, headers;
336
335
  return _regenerator().w(function (_context2) {
337
336
  while (1) switch (_context2.n) {
338
337
  case 0:
@@ -343,28 +342,36 @@ var _sign = exports.signInternal = /*#__PURE__*/function () {
343
342
  break;
344
343
  }
345
344
  _context2.n = 1;
346
- return smartSign(filtered, path);
345
+ return (0, _encode.enc)(filtered);
347
346
  case 1:
348
347
  return _context2.a(2, _context2.v);
349
348
  case 2:
350
349
  // Otherwise use the standard pipeline
351
- encoded = (0, _httpsig.httpsig_to)((0, _erl_json.normalize)((0, _structured.structured_from)((0, _erl_json.normalize)(_objectSpread(_objectSpread({}, filtered), {}, {
352
- path: path || "/~wao@1.0/httpsig"
353
- }))))); // Check if the encoded result is valid for HTTP headers
350
+ fields = _objectSpread({}, filtered); // Only add path if explicitly provided
351
+ if (path) fields.path = path;
352
+
353
+ // Try the standard encoding pipeline
354
+ encoded = (0, _httpsig.httpsig_to)((0, _erl_json.normalize)((0, _structured.structured_from)((0, _erl_json.normalize)(fields)))); // Check if the encoded result is valid for HTTP headers
354
355
  if (isValid(encoded)) {
355
356
  _context2.n = 4;
356
357
  break;
357
358
  }
358
359
  _context2.n = 3;
359
- return smartSign(filtered, path);
360
+ return (0, _encode.enc)(filtered);
360
361
  case 3:
361
362
  return _context2.a(2, _context2.v);
362
363
  case 4:
363
- return _context2.a(2, encoded);
364
+ // For non-binary data, return in the same format as enc()
365
+ // httpsig_to returns a flattened object, so we need to separate headers and body
366
+ body = encoded.body, headers = _objectWithoutProperties(encoded, _excluded);
367
+ return _context2.a(2, {
368
+ headers: headers,
369
+ body: body
370
+ });
364
371
  }
365
372
  }, _callee2);
366
373
  }));
367
- return function _sign(_x3, _x4) {
374
+ return function encode(_x3, _x4) {
368
375
  return _ref2.apply(this, arguments);
369
376
  };
370
377
  }();
@@ -384,32 +391,79 @@ function sign(_x5) {
384
391
  } // Helper function to recursively filter out undefined values
385
392
  function _sign2() {
386
393
  _sign2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(_ref4) {
387
- var url, path, encoded, jwk, _ref4$signPath, signPath, signer, _encoded$body, body, headers, _enc, headersObj, bodyData, url_path, _url, bodySize, lowercaseHeaders, _i0, _Object$entries0, _Object$entries0$_i, key, value, bodyKeys, isPath, signingFields, signedRequest, finalHeaders, _i1, _Object$entries1, _Object$entries1$_i, _key4, _value4, result;
394
+ var url, path, encoded, jwk, _ref4$signPath, signPath, signer, _encoded$body, body, headers, _enc;
388
395
  return _regenerator().w(function (_context4) {
389
396
  while (1) switch (_context4.n) {
390
397
  case 0:
391
398
  url = _ref4.url, path = _ref4.path, encoded = _ref4.msg, jwk = _ref4.jwk, _ref4$signPath = _ref4.signPath, signPath = _ref4$signPath === void 0 ? true : _ref4$signPath;
392
399
  signer = (0, _aoconnect.createSigner)(jwk, url);
393
- _encoded$body = encoded.body, body = _encoded$body === void 0 ? null : _encoded$body, headers = _objectWithoutProperties(encoded, _excluded2);
400
+ _encoded$body = encoded.body, body = _encoded$body === void 0 ? null : _encoded$body, headers = _objectWithoutProperties(encoded, _excluded3);
394
401
  _enc = {
395
402
  headers: headers
396
403
  };
397
404
  if (body) _enc.body = new Blob([body]);
398
- headersObj = _enc.headers || {};
399
- bodyData = _enc.body || undefined;
405
+ _context4.n = 1;
406
+ return _sign({
407
+ path: path,
408
+ signPath: signPath,
409
+ encoded: encoded,
410
+ signer: signer,
411
+ url: url
412
+ });
413
+ case 1:
414
+ return _context4.a(2, _context4.v);
415
+ }
416
+ }, _callee4);
417
+ }));
418
+ return _sign2.apply(this, arguments);
419
+ }
420
+ var _filterUndefined = function filterUndefined(obj) {
421
+ if (obj === null || obj === undefined) return obj;
422
+ if (Array.isArray(obj)) {
423
+ return obj.map(_filterUndefined).filter(function (item) {
424
+ return item !== undefined;
425
+ });
426
+ }
427
+ if (_typeof(obj) === "object" && obj.constructor === Object) {
428
+ var filtered = {};
429
+ for (var _i7 = 0, _Object$entries7 = Object.entries(obj); _i7 < _Object$entries7.length; _i7++) {
430
+ var _Object$entries7$_i = _slicedToArray(_Object$entries7[_i7], 2),
431
+ key = _Object$entries7$_i[0],
432
+ value = _Object$entries7$_i[1];
433
+ var filteredValue = _filterUndefined(value);
434
+ if (filteredValue !== undefined) {
435
+ filtered[key] = filteredValue;
436
+ }
437
+ }
438
+ return filtered;
439
+ }
440
+ return obj;
441
+ };
442
+ function _sign(_x6) {
443
+ return _sign3.apply(this, arguments);
444
+ }
445
+ function _sign3() {
446
+ _sign3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(_ref5) {
447
+ var path, _ref5$signPath, signPath, _ref5$method, method, encoded, signer, url, headersObj, body, url_path, _url, bodySize, lowercaseHeaders, _i8, _Object$entries8, _Object$entries8$_i, key, value, bodyKeys, isPath, signingFields, signedRequest, finalHeaders, _i9, _Object$entries9, _Object$entries9$_i, _key3, _value3, result;
448
+ return _regenerator().w(function (_context5) {
449
+ while (1) switch (_context5.n) {
450
+ case 0:
451
+ path = _ref5.path, _ref5$signPath = _ref5.signPath, signPath = _ref5$signPath === void 0 ? true : _ref5$signPath, _ref5$method = _ref5.method, method = _ref5$method === void 0 ? "POST" : _ref5$method, encoded = _ref5.encoded, signer = _ref5.signer, url = _ref5.url;
452
+ headersObj = encoded ? encoded.headers : {};
453
+ body = encoded ? encoded.body : undefined;
400
454
  url_path = typeof signPath === "string" ? signPath : path;
401
455
  _url = joinUrl({
402
456
  url: url,
403
457
  path: url_path
404
- });
405
- headersObj["path"] = path;
406
- if (bodyData && !headersObj["content-length"]) {
407
- bodySize = bodyData.size || bodyData.byteLength || 0;
458
+ }); // Only add path header if path is provided
459
+ if (path) headersObj["path"] = path;
460
+ if (body && !headersObj["content-length"]) {
461
+ bodySize = body.size || body.byteLength || 0;
408
462
  if (bodySize > 0) headersObj["content-length"] = String(bodySize);
409
463
  }
410
464
  lowercaseHeaders = {};
411
- for (_i0 = 0, _Object$entries0 = Object.entries(headersObj); _i0 < _Object$entries0.length; _i0++) {
412
- _Object$entries0$_i = _slicedToArray(_Object$entries0[_i0], 2), key = _Object$entries0$_i[0], value = _Object$entries0$_i[1];
465
+ for (_i8 = 0, _Object$entries8 = Object.entries(headersObj); _i8 < _Object$entries8.length; _i8++) {
466
+ _Object$entries8$_i = _slicedToArray(_Object$entries8[_i8], 2), key = _Object$entries8$_i[0], value = _Object$entries8$_i[1];
413
467
  lowercaseHeaders[key.toLowerCase()] = value;
414
468
  }
415
469
  bodyKeys = headersObj["body-keys"] ? headersObj["body-keys"].replace(/"/g, "").split(",").map(function (k) {
@@ -419,23 +473,23 @@ function _sign2() {
419
473
  signingFields = Object.keys(lowercaseHeaders).filter(function (key) {
420
474
  if (key === "path") isPath = true;
421
475
  return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key);
422
- });
476
+ }); // Only add @path if signPath is enabled AND path header exists
423
477
  if (signPath !== false && isPath) signingFields.push("@path");
424
- _context4.n = 1;
478
+ _context5.n = 1;
425
479
  return (0, _send.toHttpSigner)(signer)({
426
480
  request: {
427
481
  url: _url,
428
- method: "POST",
482
+ method: method,
429
483
  headers: lowercaseHeaders
430
484
  },
431
485
  fields: signingFields
432
486
  });
433
487
  case 1:
434
- signedRequest = _context4.v;
488
+ signedRequest = _context5.v;
435
489
  finalHeaders = {};
436
- for (_i1 = 0, _Object$entries1 = Object.entries(headersObj); _i1 < _Object$entries1.length; _i1++) {
437
- _Object$entries1$_i = _slicedToArray(_Object$entries1[_i1], 2), _key4 = _Object$entries1$_i[0], _value4 = _Object$entries1$_i[1];
438
- finalHeaders[_key4] = _value4;
490
+ for (_i9 = 0, _Object$entries9 = Object.entries(headersObj); _i9 < _Object$entries9.length; _i9++) {
491
+ _Object$entries9$_i = _slicedToArray(_Object$entries9[_i9], 2), _key3 = _Object$entries9$_i[0], _value3 = _Object$entries9$_i[1];
492
+ finalHeaders[_key3] = _value3;
439
493
  }
440
494
  finalHeaders["signature"] = signedRequest.headers["signature"];
441
495
  finalHeaders["signature-input"] = signedRequest.headers["signature-input"];
@@ -444,52 +498,28 @@ function _sign2() {
444
498
  }
445
499
  result = {
446
500
  url: _url,
447
- method: "POST",
501
+ method: method,
448
502
  headers: finalHeaders
449
503
  };
450
- if (bodyData) result.body = bodyData;
451
- return _context4.a(2, result);
504
+ if (body) result.body = body;
505
+ return _context5.a(2, result);
452
506
  }
453
- }, _callee4);
507
+ }, _callee5);
454
508
  }));
455
- return _sign2.apply(this, arguments);
509
+ return _sign3.apply(this, arguments);
456
510
  }
457
- var _filterUndefined = function filterUndefined(obj) {
458
- if (obj === null || obj === undefined) return obj;
459
- if (Array.isArray(obj)) {
460
- return obj.map(_filterUndefined).filter(function (item) {
461
- return item !== undefined;
462
- });
463
- }
464
- if (_typeof(obj) === "object" && obj.constructor === Object) {
465
- var filtered = {};
466
- for (var _i7 = 0, _Object$entries7 = Object.entries(obj); _i7 < _Object$entries7.length; _i7++) {
467
- var _Object$entries7$_i = _slicedToArray(_Object$entries7[_i7], 2),
468
- key = _Object$entries7$_i[0],
469
- value = _Object$entries7$_i[1];
470
- var filteredValue = _filterUndefined(value);
471
- if (filteredValue !== undefined) {
472
- filtered[key] = filteredValue;
473
- }
474
- }
475
- return filtered;
476
- }
477
- return obj;
478
- };
479
-
480
- // Signer factory function that matches signer.js API
481
511
  function signer(config) {
482
512
  var signer = config.signer,
483
513
  _config$url = config.url,
484
514
  url = _config$url === void 0 ? "http://localhost:10001" : _config$url;
485
515
  if (!signer) throw new Error("Signer is required for mainnet mode");
486
516
  return /*#__PURE__*/function () {
487
- var _ref5 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(fields) {
488
- var _ref6,
489
- _ref6$encoded,
517
+ var _ref6 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(fields) {
518
+ var _ref7,
519
+ _ref7$encoded,
490
520
  _encoded,
491
- _ref6$path,
492
- _path,
521
+ _ref7$path,
522
+ signPath,
493
523
  _fields$path,
494
524
  path,
495
525
  _fields$method,
@@ -497,35 +527,13 @@ function signer(config) {
497
527
  aoFields,
498
528
  filteredFields,
499
529
  encoded,
500
- headersObj,
501
- body,
502
- url_path,
503
- _url,
504
- bodySize,
505
- lowercaseHeaders,
506
- _i8,
507
- _Object$entries8,
508
- _Object$entries8$_i,
509
- key,
510
- value,
511
- bodyKeys,
512
- isPath,
513
- signingFields,
514
- signedRequest,
515
- finalHeaders,
516
- _i9,
517
- _Object$entries9,
518
- _Object$entries9$_i,
519
- _key3,
520
- _value3,
521
- result,
522
530
  _args3 = arguments,
523
531
  _t2;
524
532
  return _regenerator().w(function (_context3) {
525
533
  while (1) switch (_context3.n) {
526
534
  case 0:
527
- _ref6 = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : {}, _ref6$encoded = _ref6.encoded, _encoded = _ref6$encoded === void 0 ? false : _ref6$encoded, _ref6$path = _ref6.path, _path = _ref6$path === void 0 ? true : _ref6$path;
528
- _fields$path = fields.path, path = _fields$path === void 0 ? "/relay/process" : _fields$path, _fields$method = fields.method, method = _fields$method === void 0 ? "POST" : _fields$method, aoFields = _objectWithoutProperties(fields, _excluded); // Filter out undefined values before encoding
535
+ _ref7 = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : {}, _ref7$encoded = _ref7.encoded, _encoded = _ref7$encoded === void 0 ? false : _ref7$encoded, _ref7$path = _ref7.path, signPath = _ref7$path === void 0 ? true : _ref7$path;
536
+ _fields$path = fields.path, path = _fields$path === void 0 ? "/relay/process" : _fields$path, _fields$method = fields.method, method = _fields$method === void 0 ? "POST" : _fields$method, aoFields = _objectWithoutProperties(fields, _excluded2);
529
537
  filteredFields = _filterUndefined(aoFields);
530
538
  if (!_encoded) {
531
539
  _context3.n = 1;
@@ -536,70 +544,27 @@ function signer(config) {
536
544
  break;
537
545
  case 1:
538
546
  _context3.n = 2;
539
- return (0, _encode.enc)(filteredFields);
547
+ return encode(filteredFields, path);
540
548
  case 2:
541
549
  _t2 = _context3.v;
542
550
  case 3:
543
551
  encoded = _t2;
544
- headersObj = encoded ? encoded.headers : {};
545
- body = encoded ? encoded.body : undefined;
546
- url_path = typeof _path === "string" ? _path : path;
547
- _url = joinUrl({
548
- url: url,
549
- path: url_path
550
- });
551
- headersObj["path"] = path;
552
- if (body && !headersObj["content-length"]) {
553
- bodySize = body.size || body.byteLength || 0;
554
- if (bodySize > 0) headersObj["content-length"] = String(bodySize);
555
- }
556
- lowercaseHeaders = {};
557
- for (_i8 = 0, _Object$entries8 = Object.entries(headersObj); _i8 < _Object$entries8.length; _i8++) {
558
- _Object$entries8$_i = _slicedToArray(_Object$entries8[_i8], 2), key = _Object$entries8$_i[0], value = _Object$entries8$_i[1];
559
- lowercaseHeaders[key.toLowerCase()] = value;
560
- }
561
- bodyKeys = headersObj["body-keys"] ? headersObj["body-keys"].replace(/"/g, "").split(",").map(function (k) {
562
- return k.trim();
563
- }) : [];
564
- isPath = false;
565
- signingFields = Object.keys(lowercaseHeaders).filter(function (key) {
566
- if (key === "path") isPath = true;
567
- return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key);
568
- });
569
- if (_path !== false && isPath) signingFields.push("@path");
570
552
  _context3.n = 4;
571
- return (0, _send.toHttpSigner)(signer)({
572
- request: {
573
- url: _url,
574
- method: method,
575
- headers: lowercaseHeaders
576
- },
577
- fields: signingFields
553
+ return _sign({
554
+ path: path,
555
+ signPath: signPath,
556
+ method: method,
557
+ encoded: encoded,
558
+ signer: signer,
559
+ url: url
578
560
  });
579
561
  case 4:
580
- signedRequest = _context3.v;
581
- finalHeaders = {};
582
- for (_i9 = 0, _Object$entries9 = Object.entries(headersObj); _i9 < _Object$entries9.length; _i9++) {
583
- _Object$entries9$_i = _slicedToArray(_Object$entries9[_i9], 2), _key3 = _Object$entries9$_i[0], _value3 = _Object$entries9$_i[1];
584
- finalHeaders[_key3] = _value3;
585
- }
586
- finalHeaders["signature"] = signedRequest.headers["signature"];
587
- finalHeaders["signature-input"] = signedRequest.headers["signature-input"];
588
- if (headersObj["body-keys"]) {
589
- finalHeaders["body-keys"] = headersObj["body-keys"];
590
- }
591
- result = {
592
- url: _url,
593
- method: method,
594
- headers: finalHeaders
595
- };
596
- if (body) result.body = body;
597
- return _context3.a(2, result);
562
+ return _context3.a(2, _context3.v);
598
563
  }
599
564
  }, _callee3);
600
565
  }));
601
- return function (_x6) {
602
- return _ref5.apply(this, arguments);
566
+ return function (_x7) {
567
+ return _ref6.apply(this, arguments);
603
568
  };
604
569
  }();
605
570
  }
package/esm/commit.js CHANGED
@@ -1,9 +1,48 @@
1
1
  import { id, base, hashpath, rsaid, hmacid } from "./id.js"
2
2
  import { toAddr } from "./utils.js"
3
3
  import { extractPubKey } from "./signer-utils.js"
4
+ import { verify } from "./signer-utils.js"
4
5
 
6
+ // todo: handle @
5
7
  export const commit = async (obj, opts) => {
6
8
  const msg = await opts.signer(obj, opts)
9
+ const {
10
+ decodedSignatureInput: { components },
11
+ } = await verify(msg)
12
+
13
+ let body = {}
14
+
15
+ // Check for inline-body-key
16
+ const inlineBodyKey = msg.headers["inline-body-key"]
17
+
18
+ // Build body from components
19
+ for (const v of components) {
20
+ const key = v === "@path" ? "path" : v
21
+ body[key] = msg.headers[key]
22
+ }
23
+
24
+ // Handle body resolution
25
+ if (msg.body) {
26
+ let bodyContent
27
+
28
+ if (msg.body instanceof Blob) {
29
+ const arrayBuffer = await msg.body.arrayBuffer()
30
+ bodyContent = Buffer.from(arrayBuffer)
31
+ } else {
32
+ bodyContent = msg.body
33
+ }
34
+
35
+ // If inline-body-key is "data", put content in data field
36
+ if (inlineBodyKey === "data") {
37
+ body.data = bodyContent
38
+ } else {
39
+ body.body = bodyContent
40
+ }
41
+ }
42
+
43
+ // Remove inline-body-key from the final body as it's just metadata
44
+ delete body["inline-body-key"]
45
+
7
46
  const hmacId = hmacid(msg.headers)
8
47
  const rsaId = rsaid(msg.headers)
9
48
  const pub = extractPubKey(msg.headers)
@@ -14,11 +53,12 @@ export const commit = async (obj, opts) => {
14
53
  signature: msg.headers.signature,
15
54
  "signature-input": msg.headers["signature-input"],
16
55
  }
17
- return {
56
+ const committed = {
18
57
  commitments: {
19
58
  [rsaId]: { ...meta, committer, ...sigs },
20
59
  [hmacId]: { ...meta2, ...sigs },
21
60
  },
22
- ...obj,
61
+ ...body,
23
62
  }
63
+ return committed
24
64
  }
package/esm/signer.js CHANGED
@@ -183,7 +183,9 @@ const smartSign = async (obj, path) => {
183
183
 
184
184
  if (canUseSimpleEncoding) {
185
185
  // Build a simple message that won't trigger multipart
186
- const message = { path: path || filtered.path || "/~wao@1.0/httpsig" }
186
+ const message = {}
187
+ if (path) message.path = path
188
+
187
189
  const types = []
188
190
 
189
191
  for (const [key, value] of Object.entries(filtered)) {
@@ -204,7 +206,7 @@ const smartSign = async (obj, path) => {
204
206
  message[key] = encodeAsStructuredFieldList(value)
205
207
  } else if (typeof value === "number") {
206
208
  types.push(
207
- `${key}="${Number.isInteger(value) ? "integer" : "float"}"`,
209
+ `${key}="${Number.isInteger(value) ? "integer" : "float"}"`
208
210
  )
209
211
  message[key] = String(value)
210
212
  } else if (typeof value === "boolean") {
@@ -228,7 +230,7 @@ const smartSign = async (obj, path) => {
228
230
  // For complex structures that need multipart, use enc()
229
231
  const normalized = normalize({
230
232
  ...filtered,
231
- path: path || "/~wao@1.0/httpsig",
233
+ ...(path && { path }),
232
234
  })
233
235
  const result = await enc(normalized)
234
236
 
@@ -237,7 +239,7 @@ const smartSign = async (obj, path) => {
237
239
  const flattened = {
238
240
  ...result.headers,
239
241
  body: result.body,
240
- path: normalized.path || path || "/~wao@1.0/httpsig",
242
+ ...(path && { path }),
241
243
  }
242
244
 
243
245
  // httpsig_to expects the structured format
@@ -248,7 +250,8 @@ const smartSign = async (obj, path) => {
248
250
  console.error("Encoding failed:", error)
249
251
 
250
252
  // Fallback: create a simple structure
251
- const result = { path: path || "/~wao@1.0/httpsig" }
253
+ const result = {}
254
+ if (path) result.path = path
252
255
 
253
256
  for (const [key, value] of Object.entries(obj)) {
254
257
  if (key === "path") continue
@@ -262,31 +265,35 @@ const smartSign = async (obj, path) => {
262
265
  }
263
266
  }
264
267
 
265
- // Internal sign function that matches the original signature
266
- const _sign = async (obj, path) => {
268
+ // Internal encode function that uses the original impl as much as possible
269
+ const encode = async (obj, path) => {
267
270
  // Filter out undefined values before processing
268
271
  const filtered = filterUndefined(obj)
269
272
 
270
273
  // If object contains binary data, use enc() directly
271
274
  if (hasBinaryData(filtered)) {
272
- return await smartSign(filtered, path)
275
+ // For binary data, use enc() which handles multipart
276
+ return await enc(filtered)
273
277
  }
274
278
 
275
279
  // Otherwise use the standard pipeline
276
- const encoded = httpsig_to(
277
- normalize(
278
- structured_from(
279
- normalize({ ...filtered, path: path || "/~wao@1.0/httpsig" }),
280
- ),
281
- ),
282
- )
280
+ let fields = { ...filtered }
281
+ // Only add path if explicitly provided
282
+ if (path) fields.path = path
283
+
284
+ // Try the standard encoding pipeline
285
+ const encoded = httpsig_to(normalize(structured_from(normalize(fields))))
283
286
 
284
287
  // Check if the encoded result is valid for HTTP headers
285
288
  if (!isValid(encoded)) {
286
- return await smartSign(filtered, path)
289
+ // If invalid, fall back to enc()
290
+ return await enc(filtered)
287
291
  }
288
292
 
289
- return encoded
293
+ // For non-binary data, return in the same format as enc()
294
+ // httpsig_to returns a flattened object, so we need to separate headers and body
295
+ const { body, ...headers } = encoded
296
+ return { headers, body }
290
297
  }
291
298
 
292
299
  // Helper to join URL and path
@@ -304,15 +311,46 @@ export async function sign({ url, path, msg: encoded, jwk, signPath = true }) {
304
311
  const { body = null, ...headers } = encoded
305
312
  let _enc = { headers }
306
313
  if (body) _enc.body = new Blob([body])
314
+ return await _sign({ path, signPath, encoded, signer, url })
315
+ }
316
+
317
+ // Helper function to recursively filter out undefined values
318
+ const filterUndefined = obj => {
319
+ if (obj === null || obj === undefined) return obj
320
+ if (Array.isArray(obj)) {
321
+ return obj.map(filterUndefined).filter(item => item !== undefined)
322
+ }
323
+ if (typeof obj === "object" && obj.constructor === Object) {
324
+ const filtered = {}
325
+ for (const [key, value] of Object.entries(obj)) {
326
+ const filteredValue = filterUndefined(value)
327
+ if (filteredValue !== undefined) {
328
+ filtered[key] = filteredValue
329
+ }
330
+ }
331
+ return filtered
332
+ }
333
+ return obj
334
+ }
307
335
 
308
- const headersObj = _enc.headers || {}
309
- const bodyData = _enc.body || undefined
336
+ async function _sign({
337
+ path,
338
+ signPath = true,
339
+ method = "POST",
340
+ encoded,
341
+ signer,
342
+ url,
343
+ }) {
344
+ const headersObj = encoded ? encoded.headers : {}
345
+ const body = encoded ? encoded.body : undefined
310
346
  let url_path = typeof signPath === "string" ? signPath : path
311
347
  const _url = joinUrl({ url, path: url_path })
312
348
 
313
- headersObj["path"] = path
314
- if (bodyData && !headersObj["content-length"]) {
315
- const bodySize = bodyData.size || bodyData.byteLength || 0
349
+ // Only add path header if path is provided
350
+ if (path) headersObj["path"] = path
351
+
352
+ if (body && !headersObj["content-length"]) {
353
+ const bodySize = body.size || body.byteLength || 0
316
354
  if (bodySize > 0) headersObj["content-length"] = String(bodySize)
317
355
  }
318
356
 
@@ -334,10 +372,11 @@ export async function sign({ url, path, msg: encoded, jwk, signPath = true }) {
334
372
  return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key)
335
373
  })
336
374
 
375
+ // Only add @path if signPath is enabled AND path header exists
337
376
  if (signPath !== false && isPath) signingFields.push("@path")
338
377
 
339
378
  const signedRequest = await toHttpSigner(signer)({
340
- request: { url: _url, method: "POST", headers: lowercaseHeaders },
379
+ request: { url: _url, method, headers: lowercaseHeaders },
341
380
  fields: signingFields,
342
381
  })
343
382
 
@@ -353,98 +392,25 @@ export async function sign({ url, path, msg: encoded, jwk, signPath = true }) {
353
392
  finalHeaders["body-keys"] = headersObj["body-keys"]
354
393
  }
355
394
 
356
- const result = { url: _url, method: "POST", headers: finalHeaders }
357
- if (bodyData) result.body = bodyData
395
+ const result = { url: _url, method, headers: finalHeaders }
396
+ if (body) result.body = body
358
397
 
359
398
  return result
360
399
  }
361
400
 
362
- // Helper function to recursively filter out undefined values
363
- const filterUndefined = obj => {
364
- if (obj === null || obj === undefined) return obj
365
- if (Array.isArray(obj)) {
366
- return obj.map(filterUndefined).filter(item => item !== undefined)
367
- }
368
- if (typeof obj === "object" && obj.constructor === Object) {
369
- const filtered = {}
370
- for (const [key, value] of Object.entries(obj)) {
371
- const filteredValue = filterUndefined(value)
372
- if (filteredValue !== undefined) {
373
- filtered[key] = filteredValue
374
- }
375
- }
376
- return filtered
377
- }
378
- return obj
379
- }
380
-
381
- // Signer factory function that matches signer.js API
382
401
  export function signer(config) {
383
402
  const { signer, url = "http://localhost:10001" } = config
384
403
  if (!signer) throw new Error("Signer is required for mainnet mode")
385
-
386
404
  return async (
387
405
  fields,
388
- { encoded: _encoded = false, path: _path = true } = {},
406
+ { encoded: _encoded = false, path: signPath = true } = {}
389
407
  ) => {
390
408
  const { path = "/relay/process", method = "POST", ...aoFields } = fields
391
-
392
- // Filter out undefined values before encoding
393
409
  const filteredFields = filterUndefined(aoFields)
394
- const encoded = _encoded ? filteredFields : await enc(filteredFields)
395
-
396
- const headersObj = encoded ? encoded.headers : {}
397
- const body = encoded ? encoded.body : undefined
398
- let url_path = typeof _path === "string" ? _path : path
399
- const _url = joinUrl({ url, path: url_path })
400
-
401
- headersObj["path"] = path
402
- if (body && !headersObj["content-length"]) {
403
- const bodySize = body.size || body.byteLength || 0
404
- if (bodySize > 0) headersObj["content-length"] = String(bodySize)
405
- }
406
-
407
- const lowercaseHeaders = {}
408
- for (const [key, value] of Object.entries(headersObj)) {
409
- lowercaseHeaders[key.toLowerCase()] = value
410
- }
411
-
412
- const bodyKeys = headersObj["body-keys"]
413
- ? headersObj["body-keys"]
414
- .replace(/"/g, "")
415
- .split(",")
416
- .map(k => k.trim())
417
- : []
418
-
419
- let isPath = false
420
- const signingFields = Object.keys(lowercaseHeaders).filter(key => {
421
- if (key === "path") isPath = true
422
- return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key)
423
- })
424
-
425
- if (_path !== false && isPath) signingFields.push("@path")
426
-
427
- const signedRequest = await toHttpSigner(signer)({
428
- request: { url: _url, method, headers: lowercaseHeaders },
429
- fields: signingFields,
430
- })
431
-
432
- const finalHeaders = {}
433
- for (const [key, value] of Object.entries(headersObj)) {
434
- finalHeaders[key] = value
435
- }
436
-
437
- finalHeaders["signature"] = signedRequest.headers["signature"]
438
- finalHeaders["signature-input"] = signedRequest.headers["signature-input"]
439
-
440
- if (headersObj["body-keys"]) {
441
- finalHeaders["body-keys"] = headersObj["body-keys"]
442
- }
443
-
444
- const result = { url: _url, method, headers: finalHeaders }
445
- if (body) result.body = body
446
-
447
- return result
410
+ const encoded = _encoded
411
+ ? filteredFields
412
+ : await encode(filteredFields, path)
413
+ return await _sign({ path, signPath, method, encoded, signer, url })
448
414
  }
449
415
  }
450
416
 
@@ -452,5 +418,3 @@ export const createSigner = (jwk, url) => {
452
418
  const _signer = _createSigner(jwk, url)
453
419
  return signer({ signer: _signer, url })
454
420
  }
455
-
456
- export { _sign as signInternal }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hbsig",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "main": "cjs/index.js",
5
5
  "license": "MIT",
6
6
  "devDependencies": {