@silasdevs/transport 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -328,11 +328,7 @@ function createConnection(deps) {
|
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
330
|
const message = normalizeIncoming(parsed, schema);
|
|
331
|
-
log("(Received) \u2190 ",
|
|
332
|
-
raw,
|
|
333
|
-
parsed,
|
|
334
|
-
normalized: message
|
|
335
|
-
});
|
|
331
|
+
log("(Received) \u2190 ", parsed);
|
|
336
332
|
emitter.emit("message:parsed", message);
|
|
337
333
|
if (!message.channel && message.messageId === 0) {
|
|
338
334
|
log("Message missing channel and messageId, dropping");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocol.ts","../src/events.ts","../src/handlers.ts","../src/connection.ts","../src/transport.ts"],"names":["error"],"mappings":";AAkBA,SAAS,iBAAA,GAA4B;AACnC,EAAA,OAAO,OAAO,eAAA,CAAgB,IAAI,YAAY,CAAC,CAAC,EAAE,CAAC,CAAA;AACrD;AAEA,SAAS,cAAc,OAAA,EAA0C;AAC/D,EAAA,OAAO,IAAA,CAAK,UAAU,OAAO,CAAA;AAC/B;AAEA,SAAS,cAAc,GAAA,EAA6C;AAClE,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAQO,SAAS,cAAc,KAAA,EAAgD;AAC5E,EAAA,OAAO;AAAA,IACL,MAAA,EAAoB,KAAA,EAAO,MAAA,IAAsB,EAAC;AAAA,IAClD,OAAoB,KAAA,EAAO,KAAA;AAAA,IAC3B,UAAA,EAAoB,OAAO,UAAA,IAAsB,iBAAA;AAAA,IACjD,MAAA,EAAoB,OAAO,MAAA,IAAsB,aAAA;AAAA,IACjD,MAAA,EAAoB,OAAO,MAAA,IAAsB,aAAA;AAAA,IACjD,eAAA,EAAoB,OAAO,eAAA,IAAsB,KAAA;AAAA,IACjD,kBAAA,EAAoB,OAAO,kBAAA,IAAsB;AAAA,GACnD;AACF;AASO,SAAS,iBAAA,CACd,KACA,MAAA,EACiB;AACjB,EAAA,MAAM,IAAI,MAAA,CAAO,MAAA;AAGjB,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,IAAI,EAAE,eAAA,EAAiB;AACrB,IAAA,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,eAAe,KAAK,EAAE,CAAA;AAAA,EAC/C;AACA,EAAA,IAAI,CAAC,OAAA,IAAW,CAAA,CAAE,mBAAA,EAAqB;AACrC,IAAA,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,mBAAmB,KAAK,EAAE,CAAA;AAAA,EACnD;AACA,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAA,GAAU,GAAA;AAAA,EACZ;AAEA,EAAA,MAAM,KAAA,GAAQ,EAAE,SAAA,GAAY,MAAA,CAAO,IAAI,CAAA,CAAE,SAAS,CAAA,IAAK,CAAC,CAAA,GAAI,CAAA;AAC5D,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,KAAK,IAAI,CAAA,GAAI,KAAA;AAI5C,EAAA,MAAM,OAAA,GAAU,CAAC,SAAA,IAAa,OAAA,KAAY,GAAA;AAC1C,EAAA,MAAM,YAAY,OAAA,IAAW,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,YAAY,CAAA,CAAE,IAAA;AAE3D,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA,EAAa,EAAE,IAAA,GAAc,MAAA,CAAO,IAAI,CAAA,CAAE,IAAI,CAAA,IAAK,EAAE,CAAA,GAAe,EAAA;AAAA,IACpE,WAAA,EAAa,EAAE,WAAA,GAAc,MAAA,CAAO,IAAI,CAAA,CAAE,WAAW,CAAA,IAAK,EAAE,CAAA,GAAO,EAAA;AAAA,IACnE,OAAa,CAAA,CAAE,KAAA,GAAc,GAAA,CAAI,CAAA,CAAE,KAAK,CAAA,GAA2B,MAAA;AAAA,IACnE,MAAa,SAAA,GAAiB,GAAA,CAAI,SAAS,CAAA,IAAiC,KAAK,EAAC;AAAA,IAClF;AAAA,GACF;AACF;AAaO,SAAS,aAAA,CACd,GAAA,EACA,SAAA,EACA,MAAA,EACA,eAAA,EACyB;AACzB,EAAA,MAAM,IAAI,MAAA,CAAO,MAAA;AACjB,EAAA,MAAM,OAAgC,EAAC;AAGvC,EAAA,IAAI,EAAE,cAAA,EAAgB;AACpB,IAAA,IAAA,CAAK,CAAA,CAAE,cAAc,CAAA,GAAI,GAAA,CAAI,OAAA,IAAW,GAAA;AAAA,EAC1C;AAGA,EAAA,IAAI,OAAO,kBAAA,EAAoB;AAC7B,IAAA,IAAA,CAAK,CAAA,CAAE,SAAA,IAAa,IAAI,CAAA,GAAI,SAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,IAAI,IAAA,EAAM;AACZ,IAAA,MAAM,OAAO,GAAA,CAAI,IAAA;AACjB,IAAA,MAAM,aAAA,GAAgB,mBAAmB,MAAA,CAAO,eAAA;AAChD,IAAA,IAAI,aAAA,EAAe;AAEjB,MAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG;AACnC,QAAA,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA,CAAK,GAAG,CAAA;AAAA,MACtB;AAAA,IACF,CAAA,MAAA,IAAW,EAAE,OAAA,EAAS;AAEpB,MAAA,IAAA,CAAK,CAAA,CAAE,OAAO,CAAA,GAAI,IAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;;;AClGO,SAAS,aAAA,GAEM;AACpB,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAkC;AAExD,EAAA,SAAS,OAAO,KAAA,EAAqC;AACnD,IAAA,IAAI,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAC7B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,uBAAU,GAAA,EAAI;AACd,MAAA,SAAA,CAAU,GAAA,CAAI,OAAO,GAAG,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,SAAS,EAAA,CACP,OACA,QAAA,EACY;AACZ,IAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,IAAA,MAAM,EAAA,GAAK,QAAA;AACX,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACV,IAAA,OAAO,MAAM;AAAE,MAAA,GAAA,CAAI,OAAO,EAAE,CAAA;AAAA,IAAG,CAAA;AAAA,EACjC;AAEA,EAAA,SAAS,IAAA,CACP,OACA,QAAA,EACY;AACZ,IAAA,MAAM,OAAA,GAAU,CAAC,IAAA,KAA2B;AAC1C,MAAA,GAAA,CAAI,OAAO,OAAO,CAAA;AAClB,MAAA,QAAA,CAAS,IAAI,CAAA;AAAA,IACf,CAAA;AACA,IAAA,OAAO,EAAA,CAAG,OAAO,OAAO,CAAA;AAAA,EAC1B;AAEA,EAAA,SAAS,IAAA,CAA8B,OAAU,IAAA,EAAwB;AACvE,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAC/B,IAAA,IAAI,CAAC,GAAA,EAAK;AAEV,IAAA,KAAA,MAAW,EAAA,IAAM,CAAC,GAAG,GAAG,CAAA,EAAG;AACzB,MAAC,GAAkC,IAAI,CAAA;AAAA,IACzC;AAAA,EACF;AAEA,EAAA,SAAS,GAAA,CACP,OACA,QAAA,EACM;AACN,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAC/B,IAAA,IAAI,GAAA,EAAK,GAAA,CAAI,MAAA,CAAO,QAAoB,CAAA;AAAA,EAC1C;AAEA,EAAA,SAAS,UAAU,KAAA,EAA6B;AAC9C,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,SAAA,CAAU,OAAO,KAAK,CAAA;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,SAAA,CAAU,KAAA,EAAM;AAAA,IAClB;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,KAAK,SAAA,EAAU;AAC1C;;;AC3CO,SAAS,kBAAA,GAAmC;AACjD,EAAA,MAAM,SAAA,uBAAiB,GAAA,EAAkC;AACzD,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAkC;AAEzD,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAoB;AAI5C,EAAA,SAAS,gBAAgB,OAAA,EAAuC;AAC9D,IAAA,IAAI,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AAC/B,IAAA,IAAI,CAAC,GAAA,EAAK;AAAE,MAAA,GAAA,uBAAU,GAAA,EAAI;AAAG,MAAA,SAAA,CAAU,GAAA,CAAI,SAAS,GAAG,CAAA;AAAA,IAAG;AAC1D,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,SAAS,iBAAiB,OAAA,EAAuC;AAC/D,IAAA,IAAI,GAAA,GAAM,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AAChC,IAAA,IAAI,CAAC,GAAA,EAAK;AAAE,MAAA,GAAA,uBAAU,GAAA,EAAI;AAAG,MAAA,UAAA,CAAW,GAAA,CAAI,SAAS,GAAG,CAAA;AAAA,IAAG;AAC3D,IAAA,OAAO,GAAA;AAAA,EACT;AAIA,EAAA,SAAS,GAAA,CACP,OAAA,EACA,GAAA,EACA,OAAA,EACY;AACZ,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,WAAA,IAAe,OAAO,QAAQ,QAAA,EAAU;AAC3D,MAAA,eAAA,CAAgB,OAAO,CAAA,CAAE,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AACzC,MAAA,WAAA,CAAY,GAAA,CAAI,KAAK,OAAO,CAAA;AAAA,IAC9B,WAAW,OAAA,CAAQ,IAAA,KAAS,YAAA,IAAgB,OAAO,QAAQ,QAAA,EAAU;AACnE,MAAA,gBAAA,CAAiB,OAAO,CAAA,CAAE,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AAAA,IAC5C,CAAA,MAAO;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,mCAAA,EAAsC,OAAA,CAAQ,IAAI,CAAA,WAAA,EAAc,OAAO,GAAG,CAAA,+FAAA;AAAA,OAE5E;AAAA,IACF;AAGA,IAAA,OAAO,MAAM;AAAE,MAAA,MAAA,CAAO,SAAS,GAAG,CAAA;AAAA,IAAG,CAAA;AAAA,EACvC;AAEA,EAAA,SAAS,MAAA,CAAO,SAAiB,GAAA,EAA+B;AAC9D,IAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,MAAA,MAAM,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AACjC,MAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,MAAA,CAAO,GAAG,CAAA;AAC9B,MAAA,IAAI,OAAA,EAAS,WAAA,CAAY,MAAA,CAAO,GAAG,CAAA;AACnC,MAAA,IAAI,GAAA,CAAI,IAAA,KAAS,CAAA,EAAG,SAAA,CAAU,OAAO,OAAO,CAAA;AAC5C,MAAA,OAAO,OAAA;AAAA,IACT,CAAA,MAAO;AACL,MAAA,MAAM,GAAA,GAAM,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AAClC,MAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,MAAA,CAAO,GAAG,CAAA;AAC9B,MAAA,IAAI,GAAA,CAAI,IAAA,KAAS,CAAA,EAAG,UAAA,CAAW,OAAO,OAAO,CAAA;AAC7C,MAAA,OAAO,OAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,OAAA,EAAmC;AAClD,IAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,IAAA,MAAM,QAAQ,OAAA,CAAQ,SAAA;AAGtB,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AACpC,IAAA,IAAI,MAAA,IAAU,UAAU,CAAA,EAAG;AACzB,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAChC,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA;AAEvC,QAAA,IAAI,WAAW,KAAA,EAAO;AACpB,UAAA,MAAA,CAAO,OAAO,KAAK,CAAA;AACnB,UAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AACxB,UAAA,IAAI,MAAA,CAAO,IAAA,KAAS,CAAA,EAAG,SAAA,CAAU,OAAO,OAAO,CAAA;AAAA,QACjD;AACA,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AACrC,IAAA,IAAI,MAAA,IAAU,MAAA,CAAO,IAAA,GAAO,CAAA,EAAG;AAC7B,MAAA,KAAA,MAAW,OAAA,IAAW,MAAA,CAAO,MAAA,EAAO,EAAG;AACrC,QAAA,OAAA,CAAQ,SAAS,OAAO,CAAA;AAAA,MAC1B;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAIA,IAAA,IAAI,UAAU,CAAA,EAAG;AACf,MAAA,MAAM,eAAA,GAAkB,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA;AAC7C,MAAA,IAAI,eAAA,IAAmB,oBAAoB,OAAA,EAAS;AAClD,QAAA,MAAM,WAAA,GAAc,SAAA,CAAU,GAAA,CAAI,eAAe,CAAA;AACjD,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,MAAM,OAAA,GAAU,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA;AACrC,UAAA,IAAI,OAAA,EAAS;AACX,YAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA;AACvC,YAAA,IAAI,WAAW,KAAA,EAAO;AACpB,cAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AACxB,cAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AACxB,cAAA,IAAI,WAAA,CAAY,IAAA,KAAS,CAAA,EAAG,SAAA,CAAU,OAAO,eAAe,CAAA;AAAA,YAC9D;AACA,YAAA,OAAO,IAAA;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,SAAS,YAAA,CAAa,SAAiB,SAAA,EAA4B;AACjE,IAAA,OAAO,UAAU,GAAA,CAAI,OAAO,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,IAAK,KAAA;AAAA,EACnD;AAEA,EAAA,SAAS,KAAA,GAAc;AACrB,IAAA,SAAA,CAAU,KAAA,EAAM;AAChB,IAAA,UAAA,CAAW,KAAA,EAAM;AACjB,IAAA,WAAA,CAAY,KAAA,EAAM;AAAA,EACpB;AAEA,EAAA,SAAS,WAAW,OAAA,EAAwB;AAC1C,IAAA,IAAI,OAAA,EAAS;AAEX,MAAA,MAAM,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AACjC,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,KAAA,MAAW,KAAA,IAAS,GAAA,CAAI,IAAA,EAAK,EAAG;AAC9B,UAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AAAA,QAC1B;AAAA,MACF;AACA,MAAA,SAAA,CAAU,OAAO,OAAO,CAAA;AAAA,IAC1B,CAAA,MAAO;AAEL,MAAA,SAAA,CAAU,KAAA,EAAM;AAChB,MAAA,WAAA,CAAY,KAAA,EAAM;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,SAAS,uBAAuB,SAAA,EAAuC;AACrE,IAAA,OAAO,WAAA,CAAY,IAAI,SAAS,CAAA;AAAA,EAClC;AAEA,EAAA,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,SAAS,YAAA,EAAc,sBAAA,EAAwB,OAAO,UAAA,EAAW;AACzF;;;AC1JA,IAAM,aAAA,GAAgB,CAAA;AACtB,IAAM,OAAA,GAAgB,CAAA;AACtB,IAAM,UAAA,GAAgB,CAAA;AACtB,IAAM,SAAA,GAAgB,CAAA;AAEf,SAAS,iBAAiB,IAAA,EAAkC;AACjE,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,QAAA,EAAS,GAAI,IAAA;AAEtC,EAAA,IAAI,EAAA,GAAuB,IAAA;AAC3B,EAAA,IAAI,KAAA,GAAwB,cAAA;AAC5B,EAAA,IAAI,cAAA,GAAuD,IAAA;AAC3D,EAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,EAAA,IAAI,SAAA,GAAY,KAAA;AAIhB,EAAA,SAAS,UAAA,GAAqB;AAC5B,IAAA,OAAO,OAAO,IAAA,CAAK,GAAA,KAAQ,aAAa,IAAA,CAAK,GAAA,KAAQ,IAAA,CAAK,GAAA;AAAA,EAC5D;AAEA,EAAA,SAAS,OAAO,IAAA,EAAuB;AACrC,IAAA,IAAI,IAAA,CAAK,SAAQ,EAAG;AAClB,MAAA,OAAA,CAAQ,GAAA,CAAI,mBAAA,EAAqB,GAAG,IAAI,CAAA;AAAA,IAC1C;AAAA,EACF;AAEA,EAAA,SAAS,SAAS,IAAA,EAA4B;AAC5C,IAAA,KAAA,GAAQ,IAAA;AAAA,EACV;AAEA,EAAA,SAAS,mBAAA,GAA4B;AACnC,IAAA,IAAI,mBAAmB,IAAA,EAAM;AAC3B,MAAA,YAAA,CAAa,cAAc,CAAA;AAC3B,MAAA,cAAA,GAAiB,IAAA;AAAA,IACnB;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,GAAuB;AAC9B,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,EAAW,OAAO,CAAA;AAC5B,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAQ,GAAI,IAAA,CAAK,SAAA;AAClC,IAAA,IAAI,YAAY,aAAA,EAAe;AAE7B,MAAA,OAAO,IAAA,CAAK,IAAI,OAAA,GAAU,IAAA,CAAK,IAAI,CAAA,EAAG,gBAAgB,GAAG,GAAM,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,SAAS,iBAAA,GAA0B;AACjC,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,IAAa,CAAC,IAAA,CAAK,SAAA,CAAU,QAAQ,SAAA,EAAW;AAC1D,IAAA,IAAI,gBAAA,IAAoB,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa;AAClD,MAAA,GAAA,CAAI,iCAAA,EAAmC,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AACjE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,YAAA,EAAa;AAC3B,IAAA,gBAAA,EAAA;AACA,IAAA,QAAA,CAAS,cAAc,CAAA;AACvB,IAAA,OAAA,CAAQ,KAAK,cAAA,EAAgB,EAAE,SAAS,gBAAA,EAAkB,OAAA,EAAS,OAAO,CAAA;AAC1E,IAAA,GAAA,CAAI,CAAA,gBAAA,EAAmB,KAAK,CAAA,YAAA,EAAe,gBAAgB,CAAA,CAAA,CAAG,CAAA;AAE9D,IAAA,cAAA,GAAiB,WAAW,MAAM;AAChC,MAAA,cAAA,GAAiB,IAAA;AACjB,MAAA,OAAA,EAAQ;AAAA,IACV,GAAG,KAAK,CAAA;AAAA,EACV;AAIA,EAAA,SAAS,OAAO,GAAA,EAAkB;AAChC,IAAA,gBAAA,GAAmB,CAAA;AACnB,IAAA,QAAA,CAAS,WAAW,CAAA;AACpB,IAAA,GAAA,CAAI,WAAW,CAAA;AACf,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAa,GAAG,CAAA;AAAA,EAC/B;AAEA,EAAA,SAAS,QAAQ,GAAA,EAAuB;AACtC,IAAA,EAAA,GAAK,IAAA;AACL,IAAA,MAAM,IAAA,GAAO,KAAA;AACb,IAAA,QAAA,CAAS,cAAc,CAAA;AACvB,IAAA,GAAA,CAAI,cAAA,EAAgB,GAAA,CAAI,IAAA,EAAM,GAAA,CAAI,MAAM,CAAA;AACxC,IAAA,OAAA,CAAQ,KAAK,cAAA,EAAgB;AAAA,MAC3B,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAGD,IAAA,IAAI,IAAA,KAAS,cAAA,IAAkB,CAAC,SAAA,EAAW;AACzC,MAAA,iBAAA,EAAkB;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,GAAA,EAAkB;AACjC,IAAA,GAAA,CAAI,mBAAmB,GAAG,CAAA;AAC1B,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,GAAG,CAAA;AAAA,EAC3B;AAEA,EAAA,SAAS,UAAU,GAAA,EAAyB;AAC1C,IAAA,MAAM,GAAA,GAAM,OAAO,GAAA,CAAI,IAAA,KAAS,WAAW,GAAA,CAAI,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AACrE,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,IAAA,EAAM,KAAK,CAAA;AAGzC,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA;AAChC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,GAAA,CAAI,6BAA6B,GAAG,CAAA;AACpC,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAA2B,iBAAA,CAAkB,MAAA,EAAQ,MAAM,CAAA;AACjE,IAAA,GAAA,CAAI,oBAAA,EAAiB;AAAA,MACnB,GAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA,EAAY;AAAA,KACb,CAAA;AACD,IAAA,OAAA,CAAQ,IAAA,CAAK,kBAAkB,OAAO,CAAA;AAKtC,IAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,IAAW,OAAA,CAAQ,cAAc,CAAA,EAAG;AAC/C,MAAA,GAAA,CAAI,iDAAiD,CAAA;AACrD,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA;AACxC,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,CAAI,kBAAA,EAAoB,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC5D,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,CAAK,qBAAqB,OAAO,CAAA;AACzC,MAAA,GAAA,CAAI,oBAAA,EAAsB,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC9D;AAAA,EACF;AAIA,EAAA,SAAS,OAAA,GAAgB;AACvB,IAAA,IAAI,SAAA,EAAW;AAGf,IAAA,IAAI,EAAA,EAAI;AACN,MAAA,MAAM,KAAK,EAAA,CAAG,UAAA;AACd,MAAA,IAAI,EAAA,KAAO,OAAA,IAAW,EAAA,KAAO,aAAA,EAAe;AAC1C,QAAA,GAAA,CAAI,wCAAwC,CAAA;AAC5C,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,mBAAA,EAAoB;AACpB,IAAA,MAAM,MAAM,UAAA,EAAW;AACvB,IAAA,GAAA,CAAI,iBAAiB,GAAG,CAAA;AACxB,IAAA,QAAA,CAAS,YAAY,CAAA;AACrB,IAAA,OAAA,CAAQ,IAAA,CAAK,cAAc,MAAS,CAAA;AAEpC,IAAA,IAAI;AACF,MAAA,EAAA,GAAK,IAAI,UAAU,GAAG,CAAA;AAAA,IACxB,SAAS,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,gCAAgC,GAAG,CAAA;AACvC,MAAA,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,IAAI,KAAA,CAAM,OAAO,CAAC,CAAA;AACxC,MAAA,iBAAA,EAAkB;AAClB,MAAA;AAAA,IACF;AAEA,IAAA,EAAA,CAAG,MAAA,GAAY,MAAA;AACf,IAAA,EAAA,CAAG,OAAA,GAAY,OAAA;AACf,IAAA,EAAA,CAAG,OAAA,GAAY,OAAA;AACf,IAAA,EAAA,CAAG,SAAA,GAAY,SAAA;AAAA,EACjB;AAEA,EAAA,SAAS,WAAW,OAAA,EAAqC;AACvD,IAAA,mBAAA,EAAoB;AACpB,IAAA,gBAAA,GAAmB,CAAA;AAEnB,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,QAAA,CAAS,UAAA,EAAW;AAAA,IACtB;AAEA,IAAA,IAAI,EAAA,EAAI;AACN,MAAA,MAAM,KAAK,EAAA,CAAG,UAAA;AACd,MAAA,IAAI,EAAA,KAAO,SAAA,IAAa,EAAA,KAAO,UAAA,EAAY;AACzC,QAAA,GAAA,CAAI,mBAAmB,CAAA;AACvB,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX;AACA,MAAA,EAAA,GAAK,IAAA;AAAA,IACP;AAEA,IAAA,QAAA,CAAS,cAAc,CAAA;AAAA,EACzB;AAEA,EAAA,SAAS,KAAK,OAAA,EAAwC;AACpD,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,OAAA,EAAS,CAAA;AAEvC,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,UAAA,KAAe,OAAA,EAAS;AACpC,MAAA,MAAM,MAAA,GAAS,EAAA,GACX,CAAA,qBAAA,EAAwB,EAAA,CAAG,UAAU,CAAA,CAAA,GACrC,uBAAA;AACJ,MAAA,GAAA,CAAI,gBAAgB,MAAM,CAAA;AAC1B,MAAA,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,EAAE,OAAA,EAAS,QAAQ,CAAA;AAG9C,MAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,eAAe,SAAA,IAAa,EAAA,CAAG,eAAe,UAAA,EAAY;AACtE,QAAA,IAAI,IAAA,CAAK,SAAA,EAAW,IAAA,IAAQ,CAAC,SAAA,EAAW;AACtC,UAAA,mBAAA,EAAoB;AACpB,UAAA,cAAA,GAAiB,WAAW,MAAM;AAChC,YAAA,cAAA,GAAiB,IAAA;AACjB,YAAA,OAAA,EAAQ;AAAA,UACV,GAAG,GAAK,CAAA;AAAA,QACV;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AACrC,IAAA,GAAA,CAAI,iBAAY,OAAO,CAAA;AACvB,IAAA,EAAA,CAAG,KAAK,OAAO,CAAA;AACf,IAAA,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,EAAE,OAAA,EAAS,CAAA;AAAA,EACxC;AAEA,EAAA,SAAS,QAAA,GAA2B;AAClC,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,SAAS,OAAA,GAAgB;AACvB,IAAA,SAAA,GAAY,IAAA;AACZ,IAAA,UAAA,EAAW;AACX,IAAA,QAAA,CAAS,KAAA,EAAM;AAAA,EACjB;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,UAAA,EAAY,IAAA,EAAM,UAAU,OAAA,EAAQ;AACxD;;;AC3PA,IAAM,iBAAA,GAAgD;AAAA,EACpD,IAAA,EAAM,IAAA;AAAA,EACN,OAAA,EAAS,GAAA;AAAA,EACT,WAAA,EAAa,QAAA;AAAA,EACb,OAAA,EAAS;AACX,CAAA;AAiBO,SAAS,gBAAgB,OAAA,EAAsC;AAEpE,EAAA,MAAM,MAAA,GAAU,aAAA,CAAc,OAAA,CAAQ,QAAQ,CAAA;AAC9C,EAAA,MAAM,UAAU,aAAA,EAA+B;AAC/C,EAAA,MAAM,WAAW,kBAAA,EAAmB;AAEpC,EAAA,IAAI,YAAA,GAAe,QAAQ,KAAA,IAAS,KAAA;AAEpC,EAAA,MAAM,eAAA,GACJ,OAAA,CAAQ,SAAA,KAAc,KAAA,GAClB,MAAA,GACA,EAAE,GAAG,iBAAA,EAAmB,GAAI,OAAA,CAAQ,SAAA,IAAa,EAAC,EAAG;AAE3D,EAAA,MAAM,aAAa,gBAAA,CAAiB;AAAA,IAClC,MAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA,EAAW,eAAA;AAAA,IACX,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,SAAS,MAAM;AAAA,GAChB,CAAA;AAID,EAAA,SAAS,eAAe,GAAA,EAAuC;AAC7D,IAAA,OAAO,IAAI,OAAA,IAAW,GAAA;AAAA,EACxB;AAEA,EAAA,SAAS,aAAa,OAAA,EAAyB;AAC7C,IAAA,MAAM,YAAA,GAAe,EAAA;AACrB,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,GAAU,YAAA,EAAc,OAAA,EAAA,EAAW;AACvD,MAAA,MAAM,EAAA,GAAK,OAAO,UAAA,EAAW;AAC7B,MAAA,IAAI,KAAK,CAAA,IAAK,QAAA,CAAS,sBAAA,CAAuB,EAAE,MAAM,MAAA,EAAW;AAC/D,QAAA,OAAO,EAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oDAAA,EAAuD,OAAO,CAAA,QAAA,EAAW,YAAY,CAAA,kDAAA;AAAA,KAEvF;AAAA,EACF;AAIA,EAAA,SAAS,IAAA,CAAsC,KAA6B,IAAA,EAA0B;AACpG,IAAA,MAAM,OAAA,GAAU,eAAe,GAAG,CAAA;AAClC,IAAA,MAAM,EAAA,GAAK,aAAa,OAAO,CAAA;AAC/B,IAAA,MAAM,OAAO,aAAA,CAAc,GAAA,EAAK,EAAA,EAAI,MAAA,EAAQ,MAAM,eAAe,CAAA;AACjE,IAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,EACtB;AAEA,EAAA,SAAS,OAAA,CACP,KACA,IAAA,EACoC;AACpC,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,IAAW,GAAA;AAEjC,IAAA,OAAO,IAAI,OAAA,CAAmC,CAAC,OAAA,EAAS,MAAA,KAAW;AACjE,MAAA,MAAM,OAAA,GAAU,eAAe,GAAG,CAAA;AAClC,MAAA,MAAM,EAAA,GAAK,aAAa,OAAO,CAAA;AAE/B,MAAA,IAAI,KAAA,GAA8C,IAAA;AAElD,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,OAAA,EAAS,EAAA,EAAI;AAAA,QACtC,IAAA,EAAM,WAAA;AAAA,QACN,SAAS,QAAA,EAA2C;AAClD,UAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AAGrB,UAAA,IAAI,KAAA,EAAO,OAAA,IAAW,QAAA,CAAS,IAAA,KAAS,MAAM,OAAA,EAAS;AACrD,YAAA,OAAO,KAAA;AAAA,UACT;AAGA,UAAA,IAAI,UAAU,IAAA,EAAM;AAClB,YAAA,YAAA,CAAa,KAAK,CAAA;AAClB,YAAA,KAAA,GAAQ,IAAA;AAAA,UACV;AAGA,UAAA,IAAI,OAAO,KAAA,IAAS,KAAA,CAAM,MAAM,QAAA,CAAS,QAAA,CAAS,IAAI,CAAA,EAAG;AACvD,YAAA,MAAMA,MAAAA,GAAwB;AAAA,cAC5B,MAAM,QAAA,CAAS,IAAA;AAAA,cACf,OAAO,QAAA,CAAS,KAAA;AAAA,cAChB,MAAM,QAAA,CAAS,IAAA;AAAA,cACf;AAAA,aACF;AACA,YAAA,MAAA,CAAOA,MAAK,CAAA;AACZ,YAAA;AAAA,UACF;AAGA,UAAA,IAAI,CAAC,KAAA,EAAO,OAAA,IAAW,QAAA,CAAS,IAAA,KAAS,MAAM,OAAA,EAAS;AACtD,YAAA,OAAA,CAAQ,QAAqC,CAAA;AAC7C,YAAA;AAAA,UACF;AAGA,UAAA,MAAM,KAAA,GAAwB;AAAA,YAC5B,MAAM,QAAA,CAAS,IAAA;AAAA,YACf,OAAO,QAAA,CAAS,KAAA;AAAA,YAChB,MAAM,QAAA,CAAS,IAAA;AAAA,YACf;AAAA,WACF;AACA,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QAEd;AAAA,OACD,CAAA;AAGD,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,KAAA,GAAQ,WAAW,MAAM;AACvB,UAAA,KAAA,GAAQ,IAAA;AACR,UAAA,KAAA,EAAM;AACN,UAAA,MAAA,CAAO,IAAI,KAAA;AAAA,YACT,CAAA,sBAAA,EAAyB,OAAO,CAAA,IAAA,EAAO,OAAO,CAAA;AAAA,WAC/C,CAAA;AAAA,QACH,GAAG,OAAO,CAAA;AAAA,MACZ;AAGA,MAAA,MAAM,OAAO,aAAA,CAAc,GAAA,EAAK,EAAA,EAAI,MAAA,EAAQ,MAAM,eAAe,CAAA;AACjE,MAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,IACtB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,IAAA,CACP,GAAA,EACA,QAAA,EACA,IAAA,EACY;AACZ,IAAA,MAAM,OAAA,GAAU,eAAe,GAAG,CAAA;AAClC,IAAA,MAAM,EAAA,GAAK,aAAa,OAAO,CAAA;AAE/B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,OAAA,EAAS,EAAA,EAAI;AAAA,MACtC,IAAA,EAAM,WAAA;AAAA,MACN;AAAA,KACD,CAAA;AAED,IAAA,MAAM,OAAO,aAAA,CAAc,GAAA,EAAK,EAAA,EAAI,MAAA,EAAQ,MAAM,eAAe,CAAA;AACjE,IAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAEpB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,SAAS,UAAA,CACP,OAAA,EACA,IAAA,EACA,QAAA,EACY;AACZ,IAAA,OAAO,QAAA,CAAS,GAAA,CAAI,OAAA,EAAS,IAAA,EAAM;AAAA,MACjC,IAAA,EAAM,YAAA;AAAA,MACN,QAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,aAAA,CAAc,SAAiB,IAAA,EAAuB;AAC7D,IAAA,OAAO,QAAA,CAAS,MAAA,CAAO,OAAA,EAAS,IAAI,CAAA;AAAA,EACtC;AAEA,EAAA,SAAS,EAAA,CACP,OACA,QAAA,EACY;AACZ,IAAA,OAAO,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,QAAQ,CAAA;AAAA,EACnC;AAEA,EAAA,SAAS,IAAA,CACP,OACA,QAAA,EACY;AACZ,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,QAAQ,CAAA;AAAA,EACrC;AAEA,EAAA,SAAS,MAAM,OAAA,EAAwB;AACrC,IAAA,YAAA,GAAe,OAAA;AAAA,EACjB;AAEA,EAAA,SAAS,OAAA,GAAgB;AACvB,IAAA,UAAA,CAAW,OAAA,EAAQ;AACnB,IAAA,OAAA,CAAQ,SAAA,EAAU;AAAA,EACpB;AAIA,EAAA,MAAM,SAAA,GAAuB;AAAA,IAC3B,OAAA,EAAS,MAAM,UAAA,CAAW,OAAA,EAAQ;AAAA,IAClC,UAAA,EAAY,CAAC,IAAA,KAAS,UAAA,CAAW,WAAW,IAAI,CAAA;AAAA,IAChD,IAAI,KAAA,GAAQ;AAAE,MAAA,OAAO,WAAW,QAAA,EAAS;AAAA,IAAG,CAAA;AAAA,IAE5C,IAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA;AAAA,IAEA,UAAA;AAAA,IACA,aAAA;AAAA,IAEA,EAAA;AAAA,IACA,IAAA;AAAA,IAEA,QAAA,EAAU,MAAA;AAAA,IACV,KAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,SAAA;AACT","file":"index.js","sourcesContent":["// =============================================================================\n// @silas/transport — Protocol\n//\n// Protocol schema helpers for normalizing incoming and building outgoing\n// wire-format messages. Includes `resolveSchema()` which applies sensible\n// defaults so consumers can provide a minimal (or empty) schema.\n// =============================================================================\n\nimport type {\n ProtocolSchema,\n ResolvedProtocolSchema,\n IncomingMessage,\n OutgoingMessage,\n} from './types.js';\n\n// ======================== DEFAULTS ===========================================\n\n/** Cryptographically random 32-bit unsigned integer. */\nfunction defaultGenerateId(): number {\n return crypto.getRandomValues(new Uint32Array(1))[0];\n}\n\nfunction defaultEncode(message: Record<string, unknown>): string {\n return JSON.stringify(message);\n}\n\nfunction defaultDecode(raw: string): Record<string, unknown> | null {\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n// ======================== RESOLVE ============================================\n\n/**\n * Apply defaults to a partial `ProtocolSchema`, producing a fully\n * resolved schema ready for internal use.\n */\nexport function resolveSchema(input?: ProtocolSchema): ResolvedProtocolSchema {\n return {\n fields: input?.fields ?? {},\n codes: input?.codes,\n generateId: input?.generateId ?? defaultGenerateId,\n encode: input?.encode ?? defaultEncode,\n decode: input?.decode ?? defaultDecode,\n flattenOutgoing: input?.flattenOutgoing ?? false,\n includeIdInRequest: input?.includeIdInRequest ?? false,\n };\n}\n\n// ======================== NORMALIZE / BUILD ==================================\n\n/**\n * Transform a raw wire message into the canonical IncomingMessage shape.\n * Reads field names from the protocol schema so the rest of the library\n * can work with a stable, protocol-agnostic structure.\n */\nexport function normalizeIncoming(\n raw: Record<string, unknown>,\n schema: ResolvedProtocolSchema,\n): IncomingMessage {\n const f = schema.fields;\n\n // Channel resolution: responseChannel → subscriptionChannel → '*'\n let channel = '';\n if (f.responseChannel) {\n channel = String(raw[f.responseChannel] ?? '');\n }\n if (!channel && f.subscriptionChannel) {\n channel = String(raw[f.subscriptionChannel] ?? '');\n }\n if (!channel) {\n channel = '*';\n }\n\n const rawId = f.messageId ? Number(raw[f.messageId] ?? 0) : 0;\n const messageId = Number.isNaN(rawId) ? 0 : rawId;\n\n // Event detection: has a resolved channel but no messageId.\n // For events, prefer eventBody over body.\n const isEvent = !messageId && channel !== '*';\n const bodyField = isEvent && f.eventBody ? f.eventBody : f.body;\n\n return {\n channel,\n messageId,\n code: f.code ? String(raw[f.code] ?? '') : '',\n description: f.description ? String(raw[f.description] ?? '') : '',\n error: f.error ? raw[f.error] : undefined,\n data: bodyField ? (raw[bodyField] as Record<string, unknown>) ?? {} : {},\n raw,\n };\n}\n\n/**\n * Build a wire-format message object from an OutgoingMessage.\n *\n * If `flattenOutgoing` is true, data keys are spread onto the root\n * alongside the channel and message ID fields.\n *\n * If false, data is nested under the data field name.\n *\n * The optional `flattenOutgoing` parameter overrides the schema-level default\n * for a single call. When omitted, `schema.flattenOutgoing` is used.\n */\nexport function buildOutgoing<PData = Record<string, unknown>>(\n msg: OutgoingMessage<PData>,\n messageId: number,\n schema: ResolvedProtocolSchema,\n flattenOutgoing?: boolean,\n): Record<string, unknown> {\n const f = schema.fields;\n const wire: Record<string, unknown> = {};\n\n // Only include the channel field when the schema defines a requestChannel.\n if (f.requestChannel) {\n wire[f.requestChannel] = msg.channel ?? '*';\n }\n\n // Only include the messageId on the wire when the schema opts in or use a default \"id\" falback field.\n if (schema.includeIdInRequest) {\n wire[f.messageId ?? 'id'] = messageId;\n }\n\n if (msg.data) {\n const data = msg.data as Record<string, unknown>;\n const shouldFlatten = flattenOutgoing ?? schema.flattenOutgoing;\n if (shouldFlatten) {\n // Flatten: spread data keys onto the root object.\n for (const key of Object.keys(data)) {\n wire[key] = data[key];\n }\n } else if (f.payload) {\n // Nested: data goes under its own field.\n wire[f.payload] = data;\n }\n }\n\n return wire;\n}\n","// =============================================================================\n// @silas/transport — Typed Event Emitter\n//\n// Minimal typed emitter (~50 lines). Replaces the 16 hook/set_hook pairs\n// Replaces setter-based hooks (e.g. set_hook / hook pattern)\n// with a standard event system:\n// transport.on('connected', fn) instead of set_al_abrir_conexion(fn)\n// =============================================================================\n\n/** Generic typed event emitter. */\nexport interface Emitter<TEvents extends object = Record<string, unknown>> {\n on<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void;\n\n once<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void;\n\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;\n\n off<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): void;\n\n removeAll(event?: keyof TEvents): void;\n}\n\ntype Listener = (data: never) => void;\n\n/**\n * Create a minimal typed event emitter.\n *\n * ```ts\n * const ee = createEmitter<TransportEvents>();\n * const unsub = ee.on('connected', (evt) => { ... });\n * ee.emit('connected', evt);\n * unsub(); // or ee.off('connected', callback)\n * ```\n */\nexport function createEmitter<\n TEvents extends object = Record<string, unknown>,\n>(): Emitter<TEvents> {\n const listeners = new Map<keyof TEvents, Set<Listener>>();\n\n function getSet(event: keyof TEvents): Set<Listener> {\n let set = listeners.get(event);\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n return set;\n }\n\n function on<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void {\n const set = getSet(event);\n const cb = callback as Listener;\n set.add(cb);\n return () => { set.delete(cb); };\n }\n\n function once<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void {\n const wrapper = (data: TEvents[K]): void => {\n off(event, wrapper);\n callback(data);\n };\n return on(event, wrapper);\n }\n\n function emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\n const set = listeners.get(event);\n if (!set) return;\n // Iterate a snapshot so listeners can safely remove themselves.\n for (const cb of [...set]) {\n (cb as (data: TEvents[K]) => void)(data);\n }\n }\n\n function off<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): void {\n const set = listeners.get(event);\n if (set) set.delete(callback as Listener);\n }\n\n function removeAll(event?: keyof TEvents): void {\n if (event !== undefined) {\n listeners.delete(event);\n } else {\n listeners.clear();\n }\n }\n\n return { on, once, emit, off, removeAll };\n}\n","// =============================================================================\n// @silas/transport — Unified Handler Registry\n//\n// Replaces separate persistent and ephemeral handler systems with a single\n// registry.\n//\n// Routing priority:\n// 1. Ephemeral handler matched by (channel, messageId) — exact match\n// 2. Persistent handlers matched by (channel) — all executed\n// 3. If nothing matched → message is unhandled\n//\n// Ephemeral handlers auto-remove after a definitive response (callback\n// returns true or void). Return false to keep alive (interim pattern).\n// =============================================================================\n\nimport type { Handler, IncomingMessage } from './types.js';\n\n// ======================== HANDLER STORE ======================================\n\nexport interface HandlerStore {\n /**\n * Register a handler.\n * - Persistent: key is the handler name (string).\n * - Ephemeral: key is the messageId (number).\n * Returns an unsubscribe function.\n */\n add(channel: string, key: string | number, handler: Handler): () => void;\n\n /** Remove a handler by channel + key. */\n remove(channel: string, key: string | number): boolean;\n\n /**\n * Route an incoming message to the appropriate handler(s).\n * Returns true if at least one handler processed the message.\n */\n execute(message: IncomingMessage): boolean;\n\n /** Check if an ephemeral handler exists for (channel, messageId). */\n hasEphemeral(channel: string, messageId: number): boolean;\n\n /** Look up the channel for a given messageId via the secondary index. */\n findChannelByMessageId(messageId: number): string | undefined;\n\n /** Clear all handlers. */\n clear(): void;\n\n /**\n * Clear stale ephemeral handlers for a given channel (or all channels).\n */\n clearStale(channel?: string): void;\n}\n\n// ======================== IMPLEMENTATION =====================================\n\n/**\n * Create a new handler store.\n *\n * Internal structure:\n * ephemeral: Map< channel, Map< messageId (number), Handler > >\n * persistent: Map< channel, Map< name (string), Handler > >\n */\nexport function createHandlerStore(): HandlerStore {\n const ephemeral = new Map<string, Map<number, Handler>>();\n const persistent = new Map<string, Map<string, Handler>>();\n /** Secondary index: messageId → channel for O(1) ID-only lookups. */\n const idToChannel = new Map<number, string>();\n\n // ---- helpers ----\n\n function getEphemeralMap(channel: string): Map<number, Handler> {\n let map = ephemeral.get(channel);\n if (!map) { map = new Map(); ephemeral.set(channel, map); }\n return map;\n }\n\n function getPersistentMap(channel: string): Map<string, Handler> {\n let map = persistent.get(channel);\n if (!map) { map = new Map(); persistent.set(channel, map); }\n return map;\n }\n\n // ---- public API ----\n\n function add(\n channel: string,\n key: string | number,\n handler: Handler,\n ): () => void {\n if (handler.type === 'ephemeral' && typeof key === 'number') {\n getEphemeralMap(channel).set(key, handler);\n idToChannel.set(key, channel);\n } else if (handler.type === 'persistent' && typeof key === 'string') {\n getPersistentMap(channel).set(key, handler);\n } else {\n throw new Error(\n `Invalid handler registration: type=${handler.type}, key type=${typeof key}. ` +\n `Ephemeral handlers require a numeric key (messageId), persistent require a string key (name).`,\n );\n }\n\n // Return unsubscribe.\n return () => { remove(channel, key); };\n }\n\n function remove(channel: string, key: string | number): boolean {\n if (typeof key === 'number') {\n const map = ephemeral.get(channel);\n if (!map) return false;\n const deleted = map.delete(key);\n if (deleted) idToChannel.delete(key);\n if (map.size === 0) ephemeral.delete(channel);\n return deleted;\n } else {\n const map = persistent.get(channel);\n if (!map) return false;\n const deleted = map.delete(key);\n if (map.size === 0) persistent.delete(channel);\n return deleted;\n }\n }\n\n function execute(message: IncomingMessage): boolean {\n const channel = message.channel;\n const msgId = message.messageId;\n\n // 1. Try ephemeral handler (exact channel + messageId match).\n const ephMap = ephemeral.get(channel);\n if (ephMap && msgId !== 0) {\n const handler = ephMap.get(msgId);\n if (handler) {\n const result = handler.callback(message);\n // Auto-remove unless callback explicitly returns false (interim).\n if (result !== false) {\n ephMap.delete(msgId);\n idToChannel.delete(msgId);\n if (ephMap.size === 0) ephemeral.delete(channel);\n }\n return true;\n }\n }\n\n // 2. Fall through to persistent handlers.\n const perMap = persistent.get(channel);\n if (perMap && perMap.size > 0) {\n for (const handler of perMap.values()) {\n handler.callback(message);\n }\n return true;\n }\n\n // 3. ID-only fallback: response arrived with no channel (or wrong channel)\n // but has a messageId — look up the original channel via secondary index.\n if (msgId !== 0) {\n const resolvedChannel = idToChannel.get(msgId);\n if (resolvedChannel && resolvedChannel !== channel) {\n const fallbackMap = ephemeral.get(resolvedChannel);\n if (fallbackMap) {\n const handler = fallbackMap.get(msgId);\n if (handler) {\n const result = handler.callback(message);\n if (result !== false) {\n fallbackMap.delete(msgId);\n idToChannel.delete(msgId);\n if (fallbackMap.size === 0) ephemeral.delete(resolvedChannel);\n }\n return true;\n }\n }\n }\n }\n\n // 4. Unhandled.\n return false;\n }\n\n function hasEphemeral(channel: string, messageId: number): boolean {\n return ephemeral.get(channel)?.has(messageId) ?? false;\n }\n\n function clear(): void {\n ephemeral.clear();\n persistent.clear();\n idToChannel.clear();\n }\n\n function clearStale(channel?: string): void {\n if (channel) {\n // Remove index entries for this channel's ephemeral handlers.\n const map = ephemeral.get(channel);\n if (map) {\n for (const msgId of map.keys()) {\n idToChannel.delete(msgId);\n }\n }\n ephemeral.delete(channel);\n } else {\n // Clear all ephemeral + index.\n ephemeral.clear();\n idToChannel.clear();\n }\n }\n\n function findChannelByMessageId(messageId: number): string | undefined {\n return idToChannel.get(messageId);\n }\n\n return { add, remove, execute, hasEphemeral, findChannelByMessageId, clear, clearStale };\n}\n","// =============================================================================\n// @silas/transport — Connection Manager\n//\n// Encapsulates all WebSocket lifecycle: connect, disconnect, send, receive,\n// auto-reconnect.\n//\n// Features:\n// - Configurable reconnect (delay, max attempts, backoff)\n// - Event-based lifecycle\n// - Idempotent connect\n// - Stale handler cleanup on disconnect\n// =============================================================================\n\nimport type {\n ResolvedProtocolSchema,\n TransportState,\n TransportEvents,\n ReconnectOptions,\n IncomingMessage,\n} from './types.js';\nimport type { Emitter } from './events.js';\nimport type { HandlerStore } from './handlers.js';\nimport { normalizeIncoming } from './protocol.js';\n\n// ======================== TYPES ==============================================\n\n/** @internal */\nexport interface ConnectionDeps {\n /** Resolved protocol schema. */\n schema: ResolvedProtocolSchema;\n /** Event emitter. */\n emitter: Emitter<TransportEvents>;\n /** Handler store for routing inbound messages. */\n handlers: HandlerStore;\n /** Resolved reconnect config (undefined = disabled). */\n reconnect: Required<ReconnectOptions> | undefined;\n /** URL string or lazy getter. */\n url: string | (() => string);\n /** Debug flag reference (getter so it reads the live value). */\n isDebug: () => boolean;\n}\n\nexport interface Connection {\n connect(): void;\n disconnect(options?: { clean?: boolean }): void;\n send(payload: Record<string, unknown>): void;\n getState(): TransportState;\n destroy(): void;\n}\n\n// ======================== IMPLEMENTATION =====================================\n\n/** WebSocket readyState constants (mirrors the spec). */\nconst WS_CONNECTING = 0;\nconst WS_OPEN = 1;\nconst WS_CLOSING = 2;\nconst WS_CLOSED = 3;\n\nexport function createConnection(deps: ConnectionDeps): Connection {\n const { schema, emitter, handlers } = deps;\n\n let ws: WebSocket | null = null;\n let state: TransportState = 'disconnected';\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let reconnectAttempt = 0;\n let destroyed = false;\n\n // ---- helpers ----\n\n function resolveUrl(): string {\n return typeof deps.url === 'function' ? deps.url() : deps.url;\n }\n\n function log(...args: unknown[]): void {\n if (deps.isDebug()) {\n console.log('[silas/transport]', ...args);\n }\n }\n\n function setState(next: TransportState): void {\n state = next;\n }\n\n function clearReconnectTimer(): void {\n if (reconnectTimer !== null) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n }\n\n function computeDelay(): number {\n if (!deps.reconnect) return 0;\n const { delayMs, backoff } = deps.reconnect;\n if (backoff === 'exponential') {\n // Exponential backoff capped at 60s.\n return Math.min(delayMs * Math.pow(2, reconnectAttempt), 60_000);\n }\n return delayMs;\n }\n\n function scheduleReconnect(): void {\n if (!deps.reconnect || !deps.reconnect.auto || destroyed) return;\n if (reconnectAttempt >= deps.reconnect.maxAttempts) {\n log('Max reconnect attempts reached:', deps.reconnect.maxAttempts);\n return;\n }\n\n const delay = computeDelay();\n reconnectAttempt++;\n setState('reconnecting');\n emitter.emit('reconnecting', { attempt: reconnectAttempt, delayMs: delay });\n log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempt})`);\n\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect();\n }, delay);\n }\n\n // ---- WebSocket event handlers ----\n\n function onOpen(evt: Event): void {\n reconnectAttempt = 0;\n setState('connected');\n log('Connected');\n emitter.emit('connected', evt);\n }\n\n function onClose(evt: CloseEvent): void {\n ws = null;\n const prev = state;\n setState('disconnected');\n log('Disconnected', evt.code, evt.reason);\n emitter.emit('disconnected', {\n code: evt.code,\n reason: evt.reason,\n wasClean: evt.wasClean,\n });\n\n // Auto-reconnect if not intentionally disconnected.\n if (prev !== 'disconnected' && !destroyed) {\n scheduleReconnect();\n }\n }\n\n function onError(evt: Event): void {\n log('WebSocket error', evt);\n emitter.emit('error', evt);\n }\n\n function onMessage(evt: MessageEvent): void {\n const raw = typeof evt.data === 'string' ? evt.data : String(evt.data);\n emitter.emit('message:raw', { data: raw });\n\n // Decode.\n const parsed = schema.decode(raw);\n if (!parsed) {\n log('Failed to decode message:', raw);\n return;\n }\n\n // Normalize to canonical shape.\n const message: IncomingMessage = normalizeIncoming(parsed, schema);\n log('(Received) ← ', {\n raw: raw,\n parsed: parsed,\n normalized: message,\n });\n emitter.emit('message:parsed', message);\n\n // Validate minimum fields.\n // Allow messages through if they have a channel OR a messageId (for ID-only\n // fallback routing — e.g. responses that omit the channel field).\n if (!message.channel && message.messageId === 0) {\n log('Message missing channel and messageId, dropping');\n return;\n }\n\n // Route to handlers.\n const handled = handlers.execute(message);\n if (handled) {\n log('Handler matched:', message.channel, message.messageId);\n } else {\n emitter.emit('message:unhandled', message);\n log('Unhandled message:', message.channel, message.messageId);\n }\n }\n\n // ---- public API ----\n\n function connect(): void {\n if (destroyed) return;\n\n // Idempotent: don't re-open if already connecting or connected.\n if (ws) {\n const rs = ws.readyState;\n if (rs === WS_OPEN || rs === WS_CONNECTING) {\n log('Already connected/connecting, skipping');\n return;\n }\n }\n\n clearReconnectTimer();\n const url = resolveUrl();\n log('Connecting to', url);\n setState('connecting');\n emitter.emit('connecting', undefined);\n\n try {\n ws = new WebSocket(url);\n } catch (err) {\n log('WebSocket constructor error:', err);\n emitter.emit('error', new Event('error'));\n scheduleReconnect();\n return;\n }\n\n ws.onopen = onOpen;\n ws.onclose = onClose;\n ws.onerror = onError;\n ws.onmessage = onMessage;\n }\n\n function disconnect(options?: { clean?: boolean }): void {\n clearReconnectTimer();\n reconnectAttempt = 0;\n\n if (options?.clean) {\n handlers.clearStale();\n }\n\n if (ws) {\n const rs = ws.readyState;\n if (rs !== WS_CLOSED && rs !== WS_CLOSING) {\n log('Closing WebSocket');\n ws.close();\n }\n ws = null;\n }\n\n setState('disconnected');\n }\n\n function send(payload: Record<string, unknown>): void {\n emitter.emit('send:before', { payload });\n\n if (!ws || ws.readyState !== WS_OPEN) {\n const reason = ws\n ? `WebSocket readyState=${ws.readyState}`\n : 'No WebSocket instance';\n log('Send failed:', reason);\n emitter.emit('send:error', { payload, reason });\n\n // Attempt reconnect on send failure.\n if (!ws || ws.readyState === WS_CLOSED || ws.readyState === WS_CLOSING) {\n if (deps.reconnect?.auto && !destroyed) {\n clearReconnectTimer();\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect();\n }, 1_000);\n }\n }\n return;\n }\n\n const encoded = schema.encode(payload);\n log('(Sent) →', payload);\n ws.send(encoded);\n emitter.emit('send:after', { payload });\n }\n\n function getState(): TransportState {\n return state;\n }\n\n function destroy(): void {\n destroyed = true;\n disconnect();\n handlers.clear();\n }\n\n return { connect, disconnect, send, getState, destroy };\n}\n","// =============================================================================\n// @silas/transport — Main Factory\n//\n// createTransport() composes connection + handlers + events + protocol into\n// the unified Transport API. This is the primary public entry point.\n//\n// Three sending modes:\n// request(msg) → Promise<IncomingMessage> (modern async)\n// fire(msg, callback) → () => void (callback pattern)\n// send(msg) → void (fire-and-forget)\n// =============================================================================\n\nimport type {\n Transport,\n TransportOptions,\n TransportEvents,\n TransportError,\n IncomingMessage,\n OutgoingMessage,\n RequestOptions,\n FireOptions,\n SendOptions,\n HandlerCallback,\n ReconnectOptions,\n} from './types.js';\nimport { buildOutgoing, resolveSchema } from './protocol.js';\nimport { createEmitter } from './events.js';\nimport { createHandlerStore } from './handlers.js';\nimport { createConnection } from './connection.js';\n\n// ======================== DEFAULT RECONNECT ==================================\n\nconst DEFAULT_RECONNECT: Required<ReconnectOptions> = {\n auto: true,\n delayMs: 10_000,\n maxAttempts: Infinity,\n backoff: 'fixed',\n};\n\n// ======================== FACTORY ============================================\n\n/**\n * Create a Transport instance.\n *\n * ```ts\n * const transport = createTransport({\n * url: 'wss://api.example.com/ws',\n * protocol: myProtocol,\n * });\n *\n * transport.connect();\n * const res = await transport.request({ channel: 'getUser', data: { id: 5 } });\n * ```\n */\nexport function createTransport(options: TransportOptions): Transport {\n // ---- resolve config ----\n const schema = resolveSchema(options.protocol);\n const emitter = createEmitter<TransportEvents>();\n const handlers = createHandlerStore();\n\n let debugEnabled = options.debug ?? false;\n\n const reconnectConfig: Required<ReconnectOptions> | undefined =\n options.reconnect === false\n ? undefined\n : { ...DEFAULT_RECONNECT, ...(options.reconnect ?? {}) };\n\n const connection = createConnection({\n schema,\n emitter,\n handlers,\n reconnect: reconnectConfig,\n url: options.url,\n isDebug: () => debugEnabled,\n });\n\n // ---- generate unique message ID with collision avoidance ----\n\n function resolveChannel(msg: OutgoingMessage<unknown>): string {\n return msg.channel ?? '*';\n }\n\n function newMessageId(channel: string): number {\n const MAX_ATTEMPTS = 10;\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n const id = schema.generateId();\n if (id > 0 && handlers.findChannelByMessageId(id) === undefined) {\n return id;\n }\n }\n throw new Error(\n `Failed to generate a unique message ID for channel \"${channel}\" after ${MAX_ATTEMPTS} attempts. ` +\n `Check your generateId() implementation.`,\n );\n }\n\n // ---- public API ----\n\n function send<PData = Record<string, unknown>>(msg: OutgoingMessage<PData>, opts?: SendOptions): void {\n const channel = resolveChannel(msg);\n const id = newMessageId(channel);\n const wire = buildOutgoing(msg, id, schema, opts?.flattenOutgoing);\n connection.send(wire);\n }\n\n function request<BData = Record<string, unknown>, PData = Record<string, unknown>, E = unknown>(\n msg: OutgoingMessage<PData>,\n opts?: RequestOptions,\n ): Promise<IncomingMessage<BData, E>> {\n const timeout = opts?.timeout ?? 30_000;\n\n return new Promise<IncomingMessage<BData, E>>((resolve, reject) => {\n const channel = resolveChannel(msg);\n const id = newMessageId(channel);\n \n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const unsub = handlers.add(channel, id, {\n type: 'ephemeral',\n callback(response: IncomingMessage): boolean | void {\n const codes = schema.codes;\n\n // 1. Interim — keep listening.\n if (codes?.interim && response.code === codes.interim) {\n return false;\n }\n\n // Definitive response — clean up timer.\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n // 2. Explicit error match — reject.\n if (codes?.error && codes.error.includes(response.code)) {\n const error: TransportError = {\n code: response.code,\n error: response.error,\n data: response.data,\n response,\n };\n reject(error);\n return; // auto-remove\n }\n\n // 3. Success: explicit match OR no success code defined (treat all as success).\n if (!codes?.success || response.code === codes.success) {\n resolve(response as IncomingMessage<BData, E>);\n return; // auto-remove\n }\n\n // 4. Success code is defined but response doesn't match — treat as error.\n const error: TransportError = {\n code: response.code,\n error: response.error,\n data: response.data,\n response,\n };\n reject(error);\n // Return void → auto-remove handler.\n },\n });\n\n // Timeout.\n if (timeout > 0) {\n timer = setTimeout(() => {\n timer = null;\n unsub();\n reject(new Error(\n `Request timeout after ${timeout}ms: ${channel}`,\n ));\n }, timeout);\n }\n\n // Send.\n const wire = buildOutgoing(msg, id, schema, opts?.flattenOutgoing);\n connection.send(wire);\n });\n }\n\n function fire<BData = Record<string, unknown>, PData = Record<string, unknown>, E = unknown>(\n msg: OutgoingMessage<PData>,\n callback: HandlerCallback<BData, E>,\n opts?: FireOptions,\n ): () => void {\n const channel = resolveChannel(msg);\n const id = newMessageId(channel);\n\n const unsub = handlers.add(channel, id, {\n type: 'ephemeral',\n callback: callback as HandlerCallback,\n });\n\n const wire = buildOutgoing(msg, id, schema, opts?.flattenOutgoing);\n connection.send(wire);\n\n return unsub;\n }\n\n function addHandler<BData = Record<string, unknown>, E = unknown>(\n channel: string,\n name: string,\n callback: HandlerCallback<BData, E>,\n ): () => void {\n return handlers.add(channel, name, {\n type: 'persistent',\n callback: callback as HandlerCallback,\n name,\n });\n }\n\n function removeHandler(channel: string, name: string): boolean {\n return handlers.remove(channel, name);\n }\n\n function on<K extends keyof TransportEvents>(\n event: K,\n callback: (data: TransportEvents[K]) => void,\n ): () => void {\n return emitter.on(event, callback);\n }\n\n function once<K extends keyof TransportEvents>(\n event: K,\n callback: (data: TransportEvents[K]) => void,\n ): () => void {\n return emitter.once(event, callback);\n }\n\n function debug(enabled: boolean): void {\n debugEnabled = enabled;\n }\n\n function destroy(): void {\n connection.destroy();\n emitter.removeAll();\n }\n\n // ---- compose the Transport object ----\n\n const transport: Transport = {\n connect: () => connection.connect(),\n disconnect: (opts) => connection.disconnect(opts),\n get state() { return connection.getState(); },\n\n send,\n request,\n fire,\n\n addHandler,\n removeHandler,\n\n on,\n once,\n\n protocol: schema,\n debug,\n destroy,\n };\n\n return transport;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/protocol.ts","../src/events.ts","../src/handlers.ts","../src/connection.ts","../src/transport.ts"],"names":["error"],"mappings":"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","file":"index.js","sourcesContent":["// =============================================================================\n// @silas/transport — Protocol\n//\n// Protocol schema helpers for normalizing incoming and building outgoing\n// wire-format messages. Includes `resolveSchema()` which applies sensible\n// defaults so consumers can provide a minimal (or empty) schema.\n// =============================================================================\n\nimport type {\n ProtocolSchema,\n ResolvedProtocolSchema,\n IncomingMessage,\n OutgoingMessage,\n} from './types.js';\n\n// ======================== DEFAULTS ===========================================\n\n/** Cryptographically random 32-bit unsigned integer. */\nfunction defaultGenerateId(): number {\n return crypto.getRandomValues(new Uint32Array(1))[0];\n}\n\nfunction defaultEncode(message: Record<string, unknown>): string {\n return JSON.stringify(message);\n}\n\nfunction defaultDecode(raw: string): Record<string, unknown> | null {\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n// ======================== RESOLVE ============================================\n\n/**\n * Apply defaults to a partial `ProtocolSchema`, producing a fully\n * resolved schema ready for internal use.\n */\nexport function resolveSchema(input?: ProtocolSchema): ResolvedProtocolSchema {\n return {\n fields: input?.fields ?? {},\n codes: input?.codes,\n generateId: input?.generateId ?? defaultGenerateId,\n encode: input?.encode ?? defaultEncode,\n decode: input?.decode ?? defaultDecode,\n flattenOutgoing: input?.flattenOutgoing ?? false,\n includeIdInRequest: input?.includeIdInRequest ?? false,\n };\n}\n\n// ======================== NORMALIZE / BUILD ==================================\n\n/**\n * Transform a raw wire message into the canonical IncomingMessage shape.\n * Reads field names from the protocol schema so the rest of the library\n * can work with a stable, protocol-agnostic structure.\n */\nexport function normalizeIncoming(\n raw: Record<string, unknown>,\n schema: ResolvedProtocolSchema,\n): IncomingMessage {\n const f = schema.fields;\n\n // Channel resolution: responseChannel → subscriptionChannel → '*'\n let channel = '';\n if (f.responseChannel) {\n channel = String(raw[f.responseChannel] ?? '');\n }\n if (!channel && f.subscriptionChannel) {\n channel = String(raw[f.subscriptionChannel] ?? '');\n }\n if (!channel) {\n channel = '*';\n }\n\n const rawId = f.messageId ? Number(raw[f.messageId] ?? 0) : 0;\n const messageId = Number.isNaN(rawId) ? 0 : rawId;\n\n // Event detection: has a resolved channel but no messageId.\n // For events, prefer eventBody over body.\n const isEvent = !messageId && channel !== '*';\n const bodyField = isEvent && f.eventBody ? f.eventBody : f.body;\n\n return {\n channel,\n messageId,\n code: f.code ? String(raw[f.code] ?? '') : '',\n description: f.description ? String(raw[f.description] ?? '') : '',\n error: f.error ? raw[f.error] : undefined,\n data: bodyField ? (raw[bodyField] as Record<string, unknown>) ?? {} : {},\n raw,\n };\n}\n\n/**\n * Build a wire-format message object from an OutgoingMessage.\n *\n * If `flattenOutgoing` is true, data keys are spread onto the root\n * alongside the channel and message ID fields.\n *\n * If false, data is nested under the data field name.\n *\n * The optional `flattenOutgoing` parameter overrides the schema-level default\n * for a single call. When omitted, `schema.flattenOutgoing` is used.\n */\nexport function buildOutgoing<PData = Record<string, unknown>>(\n msg: OutgoingMessage<PData>,\n messageId: number,\n schema: ResolvedProtocolSchema,\n flattenOutgoing?: boolean,\n): Record<string, unknown> {\n const f = schema.fields;\n const wire: Record<string, unknown> = {};\n\n // Only include the channel field when the schema defines a requestChannel.\n if (f.requestChannel) {\n wire[f.requestChannel] = msg.channel ?? '*';\n }\n\n // Only include the messageId on the wire when the schema opts in or use a default \"id\" falback field.\n if (schema.includeIdInRequest) {\n wire[f.messageId ?? 'id'] = messageId;\n }\n\n if (msg.data) {\n const data = msg.data as Record<string, unknown>;\n const shouldFlatten = flattenOutgoing ?? schema.flattenOutgoing;\n if (shouldFlatten) {\n // Flatten: spread data keys onto the root object.\n for (const key of Object.keys(data)) {\n wire[key] = data[key];\n }\n } else if (f.payload) {\n // Nested: data goes under its own field.\n wire[f.payload] = data;\n }\n }\n\n return wire;\n}\n","// =============================================================================\n// @silas/transport — Typed Event Emitter\n//\n// Minimal typed emitter (~50 lines). Replaces the 16 hook/set_hook pairs\n// Replaces setter-based hooks (e.g. set_hook / hook pattern)\n// with a standard event system:\n// transport.on('connected', fn) instead of set_al_abrir_conexion(fn)\n// =============================================================================\n\n/** Generic typed event emitter. */\nexport interface Emitter<TEvents extends object = Record<string, unknown>> {\n on<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void;\n\n once<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void;\n\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;\n\n off<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): void;\n\n removeAll(event?: keyof TEvents): void;\n}\n\ntype Listener = (data: never) => void;\n\n/**\n * Create a minimal typed event emitter.\n *\n * ```ts\n * const ee = createEmitter<TransportEvents>();\n * const unsub = ee.on('connected', (evt) => { ... });\n * ee.emit('connected', evt);\n * unsub(); // or ee.off('connected', callback)\n * ```\n */\nexport function createEmitter<\n TEvents extends object = Record<string, unknown>,\n>(): Emitter<TEvents> {\n const listeners = new Map<keyof TEvents, Set<Listener>>();\n\n function getSet(event: keyof TEvents): Set<Listener> {\n let set = listeners.get(event);\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n return set;\n }\n\n function on<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void {\n const set = getSet(event);\n const cb = callback as Listener;\n set.add(cb);\n return () => { set.delete(cb); };\n }\n\n function once<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): () => void {\n const wrapper = (data: TEvents[K]): void => {\n off(event, wrapper);\n callback(data);\n };\n return on(event, wrapper);\n }\n\n function emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\n const set = listeners.get(event);\n if (!set) return;\n // Iterate a snapshot so listeners can safely remove themselves.\n for (const cb of [...set]) {\n (cb as (data: TEvents[K]) => void)(data);\n }\n }\n\n function off<K extends keyof TEvents>(\n event: K,\n callback: (data: TEvents[K]) => void,\n ): void {\n const set = listeners.get(event);\n if (set) set.delete(callback as Listener);\n }\n\n function removeAll(event?: keyof TEvents): void {\n if (event !== undefined) {\n listeners.delete(event);\n } else {\n listeners.clear();\n }\n }\n\n return { on, once, emit, off, removeAll };\n}\n","// =============================================================================\n// @silas/transport — Unified Handler Registry\n//\n// Replaces separate persistent and ephemeral handler systems with a single\n// registry.\n//\n// Routing priority:\n// 1. Ephemeral handler matched by (channel, messageId) — exact match\n// 2. Persistent handlers matched by (channel) — all executed\n// 3. If nothing matched → message is unhandled\n//\n// Ephemeral handlers auto-remove after a definitive response (callback\n// returns true or void). Return false to keep alive (interim pattern).\n// =============================================================================\n\nimport type { Handler, IncomingMessage } from './types.js';\n\n// ======================== HANDLER STORE ======================================\n\nexport interface HandlerStore {\n /**\n * Register a handler.\n * - Persistent: key is the handler name (string).\n * - Ephemeral: key is the messageId (number).\n * Returns an unsubscribe function.\n */\n add(channel: string, key: string | number, handler: Handler): () => void;\n\n /** Remove a handler by channel + key. */\n remove(channel: string, key: string | number): boolean;\n\n /**\n * Route an incoming message to the appropriate handler(s).\n * Returns true if at least one handler processed the message.\n */\n execute(message: IncomingMessage): boolean;\n\n /** Check if an ephemeral handler exists for (channel, messageId). */\n hasEphemeral(channel: string, messageId: number): boolean;\n\n /** Look up the channel for a given messageId via the secondary index. */\n findChannelByMessageId(messageId: number): string | undefined;\n\n /** Clear all handlers. */\n clear(): void;\n\n /**\n * Clear stale ephemeral handlers for a given channel (or all channels).\n */\n clearStale(channel?: string): void;\n}\n\n// ======================== IMPLEMENTATION =====================================\n\n/**\n * Create a new handler store.\n *\n * Internal structure:\n * ephemeral: Map< channel, Map< messageId (number), Handler > >\n * persistent: Map< channel, Map< name (string), Handler > >\n */\nexport function createHandlerStore(): HandlerStore {\n const ephemeral = new Map<string, Map<number, Handler>>();\n const persistent = new Map<string, Map<string, Handler>>();\n /** Secondary index: messageId → channel for O(1) ID-only lookups. */\n const idToChannel = new Map<number, string>();\n\n // ---- helpers ----\n\n function getEphemeralMap(channel: string): Map<number, Handler> {\n let map = ephemeral.get(channel);\n if (!map) { map = new Map(); ephemeral.set(channel, map); }\n return map;\n }\n\n function getPersistentMap(channel: string): Map<string, Handler> {\n let map = persistent.get(channel);\n if (!map) { map = new Map(); persistent.set(channel, map); }\n return map;\n }\n\n // ---- public API ----\n\n function add(\n channel: string,\n key: string | number,\n handler: Handler,\n ): () => void {\n if (handler.type === 'ephemeral' && typeof key === 'number') {\n getEphemeralMap(channel).set(key, handler);\n idToChannel.set(key, channel);\n } else if (handler.type === 'persistent' && typeof key === 'string') {\n getPersistentMap(channel).set(key, handler);\n } else {\n throw new Error(\n `Invalid handler registration: type=${handler.type}, key type=${typeof key}. ` +\n `Ephemeral handlers require a numeric key (messageId), persistent require a string key (name).`,\n );\n }\n\n // Return unsubscribe.\n return () => { remove(channel, key); };\n }\n\n function remove(channel: string, key: string | number): boolean {\n if (typeof key === 'number') {\n const map = ephemeral.get(channel);\n if (!map) return false;\n const deleted = map.delete(key);\n if (deleted) idToChannel.delete(key);\n if (map.size === 0) ephemeral.delete(channel);\n return deleted;\n } else {\n const map = persistent.get(channel);\n if (!map) return false;\n const deleted = map.delete(key);\n if (map.size === 0) persistent.delete(channel);\n return deleted;\n }\n }\n\n function execute(message: IncomingMessage): boolean {\n const channel = message.channel;\n const msgId = message.messageId;\n\n // 1. Try ephemeral handler (exact channel + messageId match).\n const ephMap = ephemeral.get(channel);\n if (ephMap && msgId !== 0) {\n const handler = ephMap.get(msgId);\n if (handler) {\n const result = handler.callback(message);\n // Auto-remove unless callback explicitly returns false (interim).\n if (result !== false) {\n ephMap.delete(msgId);\n idToChannel.delete(msgId);\n if (ephMap.size === 0) ephemeral.delete(channel);\n }\n return true;\n }\n }\n\n // 2. Fall through to persistent handlers.\n const perMap = persistent.get(channel);\n if (perMap && perMap.size > 0) {\n for (const handler of perMap.values()) {\n handler.callback(message);\n }\n return true;\n }\n\n // 3. ID-only fallback: response arrived with no channel (or wrong channel)\n // but has a messageId — look up the original channel via secondary index.\n if (msgId !== 0) {\n const resolvedChannel = idToChannel.get(msgId);\n if (resolvedChannel && resolvedChannel !== channel) {\n const fallbackMap = ephemeral.get(resolvedChannel);\n if (fallbackMap) {\n const handler = fallbackMap.get(msgId);\n if (handler) {\n const result = handler.callback(message);\n if (result !== false) {\n fallbackMap.delete(msgId);\n idToChannel.delete(msgId);\n if (fallbackMap.size === 0) ephemeral.delete(resolvedChannel);\n }\n return true;\n }\n }\n }\n }\n\n // 4. Unhandled.\n return false;\n }\n\n function hasEphemeral(channel: string, messageId: number): boolean {\n return ephemeral.get(channel)?.has(messageId) ?? false;\n }\n\n function clear(): void {\n ephemeral.clear();\n persistent.clear();\n idToChannel.clear();\n }\n\n function clearStale(channel?: string): void {\n if (channel) {\n // Remove index entries for this channel's ephemeral handlers.\n const map = ephemeral.get(channel);\n if (map) {\n for (const msgId of map.keys()) {\n idToChannel.delete(msgId);\n }\n }\n ephemeral.delete(channel);\n } else {\n // Clear all ephemeral + index.\n ephemeral.clear();\n idToChannel.clear();\n }\n }\n\n function findChannelByMessageId(messageId: number): string | undefined {\n return idToChannel.get(messageId);\n }\n\n return { add, remove, execute, hasEphemeral, findChannelByMessageId, clear, clearStale };\n}\n","// =============================================================================\n// @silas/transport — Connection Manager\n//\n// Encapsulates all WebSocket lifecycle: connect, disconnect, send, receive,\n// auto-reconnect.\n//\n// Features:\n// - Configurable reconnect (delay, max attempts, backoff)\n// - Event-based lifecycle\n// - Idempotent connect\n// - Stale handler cleanup on disconnect\n// =============================================================================\n\nimport type {\n ResolvedProtocolSchema,\n TransportState,\n TransportEvents,\n ReconnectOptions,\n IncomingMessage,\n} from './types.js';\nimport type { Emitter } from './events.js';\nimport type { HandlerStore } from './handlers.js';\nimport { normalizeIncoming } from './protocol.js';\n\n// ======================== TYPES ==============================================\n\n/** @internal */\nexport interface ConnectionDeps {\n /** Resolved protocol schema. */\n schema: ResolvedProtocolSchema;\n /** Event emitter. */\n emitter: Emitter<TransportEvents>;\n /** Handler store for routing inbound messages. */\n handlers: HandlerStore;\n /** Resolved reconnect config (undefined = disabled). */\n reconnect: Required<ReconnectOptions> | undefined;\n /** URL string or lazy getter. */\n url: string | (() => string);\n /** Debug flag reference (getter so it reads the live value). */\n isDebug: () => boolean;\n}\n\nexport interface Connection {\n connect(): void;\n disconnect(options?: { clean?: boolean }): void;\n send(payload: Record<string, unknown>): void;\n getState(): TransportState;\n destroy(): void;\n}\n\n// ======================== IMPLEMENTATION =====================================\n\n/** WebSocket readyState constants (mirrors the spec). */\nconst WS_CONNECTING = 0;\nconst WS_OPEN = 1;\nconst WS_CLOSING = 2;\nconst WS_CLOSED = 3;\n\nexport function createConnection(deps: ConnectionDeps): Connection {\n const { schema, emitter, handlers } = deps;\n\n let ws: WebSocket | null = null;\n let state: TransportState = 'disconnected';\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let reconnectAttempt = 0;\n let destroyed = false;\n\n // ---- helpers ----\n\n function resolveUrl(): string {\n return typeof deps.url === 'function' ? deps.url() : deps.url;\n }\n\n function log(...args: unknown[]): void {\n if (deps.isDebug()) {\n console.log('[silas/transport]', ...args);\n }\n }\n\n function setState(next: TransportState): void {\n state = next;\n }\n\n function clearReconnectTimer(): void {\n if (reconnectTimer !== null) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n }\n\n function computeDelay(): number {\n if (!deps.reconnect) return 0;\n const { delayMs, backoff } = deps.reconnect;\n if (backoff === 'exponential') {\n // Exponential backoff capped at 60s.\n return Math.min(delayMs * Math.pow(2, reconnectAttempt), 60_000);\n }\n return delayMs;\n }\n\n function scheduleReconnect(): void {\n if (!deps.reconnect || !deps.reconnect.auto || destroyed) return;\n if (reconnectAttempt >= deps.reconnect.maxAttempts) {\n log('Max reconnect attempts reached:', deps.reconnect.maxAttempts);\n return;\n }\n\n const delay = computeDelay();\n reconnectAttempt++;\n setState('reconnecting');\n emitter.emit('reconnecting', { attempt: reconnectAttempt, delayMs: delay });\n log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempt})`);\n\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect();\n }, delay);\n }\n\n // ---- WebSocket event handlers ----\n\n function onOpen(evt: Event): void {\n reconnectAttempt = 0;\n setState('connected');\n log('Connected');\n emitter.emit('connected', evt);\n }\n\n function onClose(evt: CloseEvent): void {\n ws = null;\n const prev = state;\n setState('disconnected');\n log('Disconnected', evt.code, evt.reason);\n emitter.emit('disconnected', {\n code: evt.code,\n reason: evt.reason,\n wasClean: evt.wasClean,\n });\n\n // Auto-reconnect if not intentionally disconnected.\n if (prev !== 'disconnected' && !destroyed) {\n scheduleReconnect();\n }\n }\n\n function onError(evt: Event): void {\n log('WebSocket error', evt);\n emitter.emit('error', evt);\n }\n\n function onMessage(evt: MessageEvent): void {\n const raw = typeof evt.data === 'string' ? evt.data : String(evt.data);\n emitter.emit('message:raw', { data: raw });\n\n // Decode.\n const parsed = schema.decode(raw);\n if (!parsed) {\n log('Failed to decode message:', raw);\n return;\n }\n\n // Normalize to canonical shape.\n const message: IncomingMessage = normalizeIncoming(parsed, schema);\n log('(Received) ← ', parsed);\n emitter.emit('message:parsed', message);\n\n // Validate minimum fields.\n // Allow messages through if they have a channel OR a messageId (for ID-only\n // fallback routing — e.g. responses that omit the channel field).\n if (!message.channel && message.messageId === 0) {\n log('Message missing channel and messageId, dropping');\n return;\n }\n\n // Route to handlers.\n const handled = handlers.execute(message);\n if (handled) {\n log('Handler matched:', message.channel, message.messageId);\n } else {\n emitter.emit('message:unhandled', message);\n log('Unhandled message:', message.channel, message.messageId);\n }\n }\n\n // ---- public API ----\n\n function connect(): void {\n if (destroyed) return;\n\n // Idempotent: don't re-open if already connecting or connected.\n if (ws) {\n const rs = ws.readyState;\n if (rs === WS_OPEN || rs === WS_CONNECTING) {\n log('Already connected/connecting, skipping');\n return;\n }\n }\n\n clearReconnectTimer();\n const url = resolveUrl();\n log('Connecting to', url);\n setState('connecting');\n emitter.emit('connecting', undefined);\n\n try {\n ws = new WebSocket(url);\n } catch (err) {\n log('WebSocket constructor error:', err);\n emitter.emit('error', new Event('error'));\n scheduleReconnect();\n return;\n }\n\n ws.onopen = onOpen;\n ws.onclose = onClose;\n ws.onerror = onError;\n ws.onmessage = onMessage;\n }\n\n function disconnect(options?: { clean?: boolean }): void {\n clearReconnectTimer();\n reconnectAttempt = 0;\n\n if (options?.clean) {\n handlers.clearStale();\n }\n\n if (ws) {\n const rs = ws.readyState;\n if (rs !== WS_CLOSED && rs !== WS_CLOSING) {\n log('Closing WebSocket');\n ws.close();\n }\n ws = null;\n }\n\n setState('disconnected');\n }\n\n function send(payload: Record<string, unknown>): void {\n emitter.emit('send:before', { payload });\n\n if (!ws || ws.readyState !== WS_OPEN) {\n const reason = ws\n ? `WebSocket readyState=${ws.readyState}`\n : 'No WebSocket instance';\n log('Send failed:', reason);\n emitter.emit('send:error', { payload, reason });\n\n // Attempt reconnect on send failure.\n if (!ws || ws.readyState === WS_CLOSED || ws.readyState === WS_CLOSING) {\n if (deps.reconnect?.auto && !destroyed) {\n clearReconnectTimer();\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect();\n }, 1_000);\n }\n }\n return;\n }\n\n const encoded = schema.encode(payload);\n log('(Sent) →', payload);\n ws.send(encoded);\n emitter.emit('send:after', { payload });\n }\n\n function getState(): TransportState {\n return state;\n }\n\n function destroy(): void {\n destroyed = true;\n disconnect();\n handlers.clear();\n }\n\n return { connect, disconnect, send, getState, destroy };\n}\n","// =============================================================================\n// @silas/transport — Main Factory\n//\n// createTransport() composes connection + handlers + events + protocol into\n// the unified Transport API. This is the primary public entry point.\n//\n// Three sending modes:\n// request(msg) → Promise<IncomingMessage> (modern async)\n// fire(msg, callback) → () => void (callback pattern)\n// send(msg) → void (fire-and-forget)\n// =============================================================================\n\nimport type {\n Transport,\n TransportOptions,\n TransportEvents,\n TransportError,\n IncomingMessage,\n OutgoingMessage,\n RequestOptions,\n FireOptions,\n SendOptions,\n HandlerCallback,\n ReconnectOptions,\n} from './types.js';\nimport { buildOutgoing, resolveSchema } from './protocol.js';\nimport { createEmitter } from './events.js';\nimport { createHandlerStore } from './handlers.js';\nimport { createConnection } from './connection.js';\n\n// ======================== DEFAULT RECONNECT ==================================\n\nconst DEFAULT_RECONNECT: Required<ReconnectOptions> = {\n auto: true,\n delayMs: 10_000,\n maxAttempts: Infinity,\n backoff: 'fixed',\n};\n\n// ======================== FACTORY ============================================\n\n/**\n * Create a Transport instance.\n *\n * ```ts\n * const transport = createTransport({\n * url: 'wss://api.example.com/ws',\n * protocol: myProtocol,\n * });\n *\n * transport.connect();\n * const res = await transport.request({ channel: 'getUser', data: { id: 5 } });\n * ```\n */\nexport function createTransport(options: TransportOptions): Transport {\n // ---- resolve config ----\n const schema = resolveSchema(options.protocol);\n const emitter = createEmitter<TransportEvents>();\n const handlers = createHandlerStore();\n\n let debugEnabled = options.debug ?? false;\n\n const reconnectConfig: Required<ReconnectOptions> | undefined =\n options.reconnect === false\n ? undefined\n : { ...DEFAULT_RECONNECT, ...(options.reconnect ?? {}) };\n\n const connection = createConnection({\n schema,\n emitter,\n handlers,\n reconnect: reconnectConfig,\n url: options.url,\n isDebug: () => debugEnabled,\n });\n\n // ---- generate unique message ID with collision avoidance ----\n\n function resolveChannel(msg: OutgoingMessage<unknown>): string {\n return msg.channel ?? '*';\n }\n\n function newMessageId(channel: string): number {\n const MAX_ATTEMPTS = 10;\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n const id = schema.generateId();\n if (id > 0 && handlers.findChannelByMessageId(id) === undefined) {\n return id;\n }\n }\n throw new Error(\n `Failed to generate a unique message ID for channel \"${channel}\" after ${MAX_ATTEMPTS} attempts. ` +\n `Check your generateId() implementation.`,\n );\n }\n\n // ---- public API ----\n\n function send<PData = Record<string, unknown>>(msg: OutgoingMessage<PData>, opts?: SendOptions): void {\n const channel = resolveChannel(msg);\n const id = newMessageId(channel);\n const wire = buildOutgoing(msg, id, schema, opts?.flattenOutgoing);\n connection.send(wire);\n }\n\n function request<BData = Record<string, unknown>, PData = Record<string, unknown>, E = unknown>(\n msg: OutgoingMessage<PData>,\n opts?: RequestOptions,\n ): Promise<IncomingMessage<BData, E>> {\n const timeout = opts?.timeout ?? 30_000;\n\n return new Promise<IncomingMessage<BData, E>>((resolve, reject) => {\n const channel = resolveChannel(msg);\n const id = newMessageId(channel);\n \n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const unsub = handlers.add(channel, id, {\n type: 'ephemeral',\n callback(response: IncomingMessage): boolean | void {\n const codes = schema.codes;\n\n // 1. Interim — keep listening.\n if (codes?.interim && response.code === codes.interim) {\n return false;\n }\n\n // Definitive response — clean up timer.\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n // 2. Explicit error match — reject.\n if (codes?.error && codes.error.includes(response.code)) {\n const error: TransportError = {\n code: response.code,\n error: response.error,\n data: response.data,\n response,\n };\n reject(error);\n return; // auto-remove\n }\n\n // 3. Success: explicit match OR no success code defined (treat all as success).\n if (!codes?.success || response.code === codes.success) {\n resolve(response as IncomingMessage<BData, E>);\n return; // auto-remove\n }\n\n // 4. Success code is defined but response doesn't match — treat as error.\n const error: TransportError = {\n code: response.code,\n error: response.error,\n data: response.data,\n response,\n };\n reject(error);\n // Return void → auto-remove handler.\n },\n });\n\n // Timeout.\n if (timeout > 0) {\n timer = setTimeout(() => {\n timer = null;\n unsub();\n reject(new Error(\n `Request timeout after ${timeout}ms: ${channel}`,\n ));\n }, timeout);\n }\n\n // Send.\n const wire = buildOutgoing(msg, id, schema, opts?.flattenOutgoing);\n connection.send(wire);\n });\n }\n\n function fire<BData = Record<string, unknown>, PData = Record<string, unknown>, E = unknown>(\n msg: OutgoingMessage<PData>,\n callback: HandlerCallback<BData, E>,\n opts?: FireOptions,\n ): () => void {\n const channel = resolveChannel(msg);\n const id = newMessageId(channel);\n\n const unsub = handlers.add(channel, id, {\n type: 'ephemeral',\n callback: callback as HandlerCallback,\n });\n\n const wire = buildOutgoing(msg, id, schema, opts?.flattenOutgoing);\n connection.send(wire);\n\n return unsub;\n }\n\n function addHandler<BData = Record<string, unknown>, E = unknown>(\n channel: string,\n name: string,\n callback: HandlerCallback<BData, E>,\n ): () => void {\n return handlers.add(channel, name, {\n type: 'persistent',\n callback: callback as HandlerCallback,\n name,\n });\n }\n\n function removeHandler(channel: string, name: string): boolean {\n return handlers.remove(channel, name);\n }\n\n function on<K extends keyof TransportEvents>(\n event: K,\n callback: (data: TransportEvents[K]) => void,\n ): () => void {\n return emitter.on(event, callback);\n }\n\n function once<K extends keyof TransportEvents>(\n event: K,\n callback: (data: TransportEvents[K]) => void,\n ): () => void {\n return emitter.once(event, callback);\n }\n\n function debug(enabled: boolean): void {\n debugEnabled = enabled;\n }\n\n function destroy(): void {\n connection.destroy();\n emitter.removeAll();\n }\n\n // ---- compose the Transport object ----\n\n const transport: Transport = {\n connect: () => connection.connect(),\n disconnect: (opts) => connection.disconnect(opts),\n get state() { return connection.getState(); },\n\n send,\n request,\n fire,\n\n addHandler,\n removeHandler,\n\n on,\n once,\n\n protocol: schema,\n debug,\n destroy,\n };\n\n return transport;\n}\n"]}
|