mqtt-plus 0.9.15 → 0.9.16
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/dst-stage1/mqtt-plus-codec.js +1 -1
- package/dst-stage1/mqtt-plus-service.js +10 -3
- package/dst-stage2/mqtt-plus.cjs.js +11 -4
- package/dst-stage2/mqtt-plus.esm.js +11 -4
- package/dst-stage2/mqtt-plus.umd.js +1 -1
- package/package.json +1 -1
- package/src/mqtt-plus-codec.ts +2 -2
- package/src/mqtt-plus-service.ts +10 -3
|
@@ -42,7 +42,7 @@ class JSONX {
|
|
|
42
42
|
: value);
|
|
43
43
|
}
|
|
44
44
|
static parse(json) {
|
|
45
|
-
return JSON.parse(json, (_, value) => value?.__Uint8Array
|
|
45
|
+
return JSON.parse(json, (_, value) => typeof value?.__Uint8Array === "string"
|
|
46
46
|
? this.base64ToUint8Array(value.__Uint8Array)
|
|
47
47
|
: value);
|
|
48
48
|
}
|
|
@@ -147,8 +147,14 @@ export class ServiceTrait extends EventTrait {
|
|
|
147
147
|
if (!this.responseSubscriptions.has(topic)) {
|
|
148
148
|
this.responseSubscriptions.set(topic, 0);
|
|
149
149
|
this.mqtt.subscribe(topic, options, (err) => {
|
|
150
|
-
if (err)
|
|
150
|
+
if (err) {
|
|
151
|
+
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
152
|
+
if (count > 1)
|
|
153
|
+
this.responseSubscriptions.set(topic, count - 1);
|
|
154
|
+
else
|
|
155
|
+
this.responseSubscriptions.delete(topic);
|
|
151
156
|
this.mqtt.emit("error", err);
|
|
157
|
+
}
|
|
152
158
|
});
|
|
153
159
|
}
|
|
154
160
|
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
@@ -163,8 +169,9 @@ export class ServiceTrait extends EventTrait {
|
|
|
163
169
|
return;
|
|
164
170
|
/* unsubscribe from MQTT topic and forget subscription */
|
|
165
171
|
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
166
|
-
|
|
167
|
-
|
|
172
|
+
if (count > 1)
|
|
173
|
+
this.responseSubscriptions.set(topic, count - 1);
|
|
174
|
+
else {
|
|
168
175
|
this.responseSubscriptions.delete(topic);
|
|
169
176
|
this.mqtt.unsubscribe(topic, (err) => {
|
|
170
177
|
if (err)
|
|
@@ -125,7 +125,7 @@ class JSONX {
|
|
|
125
125
|
return JSON.stringify(obj, (_, value) => value instanceof Uint8Array ? { __Uint8Array: this.uint8ArrayToBase64(value) } : value);
|
|
126
126
|
}
|
|
127
127
|
static parse(json) {
|
|
128
|
-
return JSON.parse(json, (_, value) => value?.__Uint8Array ? this.base64ToUint8Array(value.__Uint8Array) : value);
|
|
128
|
+
return JSON.parse(json, (_, value) => typeof value?.__Uint8Array === "string" ? this.base64ToUint8Array(value.__Uint8Array) : value);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
class Codec {
|
|
@@ -570,8 +570,14 @@ class ServiceTrait extends EventTrait {
|
|
|
570
570
|
if (!this.responseSubscriptions.has(topic)) {
|
|
571
571
|
this.responseSubscriptions.set(topic, 0);
|
|
572
572
|
this.mqtt.subscribe(topic, options, (err) => {
|
|
573
|
-
if (err)
|
|
573
|
+
if (err) {
|
|
574
|
+
const count2 = this.responseSubscriptions.get(topic) ?? 0;
|
|
575
|
+
if (count2 > 1)
|
|
576
|
+
this.responseSubscriptions.set(topic, count2 - 1);
|
|
577
|
+
else
|
|
578
|
+
this.responseSubscriptions.delete(topic);
|
|
574
579
|
this.mqtt.emit("error", err);
|
|
580
|
+
}
|
|
575
581
|
});
|
|
576
582
|
}
|
|
577
583
|
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
@@ -583,8 +589,9 @@ class ServiceTrait extends EventTrait {
|
|
|
583
589
|
if (!this.responseSubscriptions.has(topic))
|
|
584
590
|
return;
|
|
585
591
|
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
586
|
-
|
|
587
|
-
|
|
592
|
+
if (count > 1)
|
|
593
|
+
this.responseSubscriptions.set(topic, count - 1);
|
|
594
|
+
else {
|
|
588
595
|
this.responseSubscriptions.delete(topic);
|
|
589
596
|
this.mqtt.unsubscribe(topic, (err) => {
|
|
590
597
|
if (err)
|
|
@@ -107,7 +107,7 @@ class JSONX {
|
|
|
107
107
|
return JSON.stringify(obj, (_, value) => value instanceof Uint8Array ? { __Uint8Array: this.uint8ArrayToBase64(value) } : value);
|
|
108
108
|
}
|
|
109
109
|
static parse(json) {
|
|
110
|
-
return JSON.parse(json, (_, value) => value?.__Uint8Array ? this.base64ToUint8Array(value.__Uint8Array) : value);
|
|
110
|
+
return JSON.parse(json, (_, value) => typeof value?.__Uint8Array === "string" ? this.base64ToUint8Array(value.__Uint8Array) : value);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
class Codec {
|
|
@@ -552,8 +552,14 @@ class ServiceTrait extends EventTrait {
|
|
|
552
552
|
if (!this.responseSubscriptions.has(topic)) {
|
|
553
553
|
this.responseSubscriptions.set(topic, 0);
|
|
554
554
|
this.mqtt.subscribe(topic, options, (err) => {
|
|
555
|
-
if (err)
|
|
555
|
+
if (err) {
|
|
556
|
+
const count2 = this.responseSubscriptions.get(topic) ?? 0;
|
|
557
|
+
if (count2 > 1)
|
|
558
|
+
this.responseSubscriptions.set(topic, count2 - 1);
|
|
559
|
+
else
|
|
560
|
+
this.responseSubscriptions.delete(topic);
|
|
556
561
|
this.mqtt.emit("error", err);
|
|
562
|
+
}
|
|
557
563
|
});
|
|
558
564
|
}
|
|
559
565
|
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
@@ -565,8 +571,9 @@ class ServiceTrait extends EventTrait {
|
|
|
565
571
|
if (!this.responseSubscriptions.has(topic))
|
|
566
572
|
return;
|
|
567
573
|
const count = this.responseSubscriptions.get(topic) ?? 0;
|
|
568
|
-
|
|
569
|
-
|
|
574
|
+
if (count > 1)
|
|
575
|
+
this.responseSubscriptions.set(topic, count - 1);
|
|
576
|
+
else {
|
|
570
577
|
this.responseSubscriptions.delete(topic);
|
|
571
578
|
this.mqtt.unsubscribe(topic, (err) => {
|
|
572
579
|
if (err)
|
|
@@ -10,4 +10,4 @@ ${Fr.repeat(u.depth)}}`:u.close="}";break}case Y.TAG:c+=String(p),c+=tt(Y.POS_IN
|
|
|
10
10
|
`;let g=0;for(const b of t.children){if(zn(b)){let p=String(g);t.mt===Y.MAP?p=g%2?`val ${(g-1)/2}`:`key ${g/2}`:t.mt===Y.TAG&&(p=""),o+=Vn(b,e,p)}g++}}return o}const vo={...Fe.defaultDecodeOptions,initialDepth:0,noPrefixHex:!1,minCol:0};function Xn(t,e){const r={...vo,...e,ParentType:Ur,saveOriginal:!0},o=new Kt(t,r);let f,u;for(const d of o){if(u=Fe.create(d,f,r,o),d[2]===Ie.BREAK)if(f?.isStreaming)f.left=1;else throw new Error("Unexpected BREAK");if(!zn(u)){const p=new Ur(d,0,f,r);p.leaf=!0,p.children.push(u),Tt(p,o.toHere(d[3])),u=p}let g=(u.depth+1)*2;const b=u.numBytes();for(b&&(g+=1,g+=b*2),r.minCol=Math.max(r.minCol,g),f&&f.push(u,o,d[3]),f=u;f?.done;)u=f,u.leaf||Tt(u,o.toHere(u.offset)),{parent:f}=f}e&&(e.minCol=r.minCol);let c=r.noPrefixHex?"":`0x${Ne(o.toHere(0))}
|
|
11
11
|
`;return c+=Vn(u,r),c}const Jn=!$i();function zt(t){if(typeof t=="object"&&t){if(t.constructor!==Number)throw new Error(`Expected number: ${t}`)}else if(typeof t!="number")throw new Error(`Expected number: ${t}`)}function rt(t){if(typeof t=="object"&&t){if(t.constructor!==String)throw new Error(`Expected string: ${t}`)}else if(typeof t!="string")throw new Error(`Expected string: ${t}`)}function Ze(t){if(!(t instanceof Uint8Array))throw new Error(`Expected Uint8Array: ${t}`)}function Zn(t){if(!Array.isArray(t))throw new Error(`Expected Array: ${t}`)}we(Map,(t,e,r)=>{const o=[...t.entries()].map(f=>[f[0],f[1],mt(f[0],r)]);if(r.rejectDuplicateKeys){const f=new Set;for(const[u,c,d]of o){const g=Ne(d);if(f.has(g))throw new Error(`Duplicate map key: 0x${g}`);f.add(g)}}r.sortKeys&&o.sort(r.sortKeys),Nr(t,t.size,Y.MAP,e,r);for(const[f,u,c]of o)e.write(c),ct(u,e,r)});function Lr(t){return rt(t.contents),new Date(t.contents)}Lr.comment=t=>{rt(t.contents);const e=new Date(t.contents);return`(String ${t.tag===ie.DATE_FULL?"Full ":""}Date) ${e.toISOString()}`},Z.registerDecoder(ie.DATE_STRING,Lr),Z.registerDecoder(ie.DATE_FULL,Lr);function Qn(t){return zt(t.contents),new Date(t.contents*1e3)}Qn.comment=t=>(zt(t.contents),`(Epoch Date) ${new Date(t.contents*1e3).toISOString()}`),Z.registerDecoder(ie.DATE_EPOCH,Qn);const Or=1e3*60*60*24;function ei(t){return zt(t.contents),new Date(t.contents*Or)}ei.comment=t=>(zt(t.contents),`(Epoch Date) ${new Date(t.contents*Or).toISOString()}`),Z.registerDecoder(ie.DATE_EPOCH_DAYS,ei),we(Date,(t,e,r)=>{switch(r.dateTag){case ie.DATE_EPOCH:return[r.dateTag,t.valueOf()/1e3];case ie.DATE_STRING:return[r.dateTag,t.toISOString().replace(/\.000Z$/,"Z")];case ie.DATE_EPOCH_DAYS:return[r.dateTag,Math.floor(t.valueOf()/Or)];case ie.DATE_FULL:return[r.dateTag,t.toISOString().split("T")[0]];default:throw new Error(`Unsupported date tag: ${r.dateTag}`)}});function Vt(t,e,r){if(Ze(e.contents),r.rejectBigInts)throw new Error(`Decoding unwanted big integer: ${e}(h'${Ne(e.contents)}')`);if(r.requirePreferred&&e.contents[0]===0)throw new Error(`Decoding overly-large bigint: ${e.tag}(h'${Ne(e.contents)})`);let o=e.contents.reduce((u,c)=>u<<8n|BigInt(c),0n);t&&(o=-1n-o);const f=o>=Number.MIN_SAFE_INTEGER&&o<=Number.MAX_SAFE_INTEGER;if(r.requirePreferred&&f)throw new Error(`Decoding bigint that could have been int: ${o}n`);return r.collapseBigInts&&f&&(o=Number(o)),r.boxed?xt(o,e.contents):o}const ti=Vt.bind(null,!1),ri=Vt.bind(null,!0);ti.comment=(t,e)=>`(Positive BigInt) ${Vt(!1,t,e)}n`,ri.comment=(t,e)=>`(Negative BigInt) ${Vt(!0,t,e)}n`,Z.registerDecoder(ie.POS_BIGINT,ti),Z.registerDecoder(ie.NEG_BIGINT,ri);function Mr(t,e){return Ze(t.contents),t}Mr.comment=(t,e,r)=>{Ze(t.contents);const o={...e,initialDepth:r+2,noPrefixHex:!0},f=Pt(t);let u=2**((f[0]&31)-24)+1;const c=f[u]&31;let d=Ne(f.subarray(u,++u));c>=24&&(d+=" ",d+=Ne(f.subarray(u,u+2**(c-24)))),o.minCol=Math.max(o.minCol,(r+1)*2+d.length);const g=Xn(t.contents,o);let b=`Embedded CBOR
|
|
12
12
|
`;return b+=`${"".padStart((r+1)*2," ")}${d}`.padEnd(o.minCol+1," "),b+=`-- Bytes (Length: ${t.contents.length})
|
|
13
|
-
`,b+=g,b},Mr.noChildren=!0,Z.registerDecoder(ie.CBOR,Mr),Z.registerDecoder(ie.URI,t=>(rt(t.contents),new URL(t.contents)),"URI"),we(URL,t=>[ie.URI,t.toString()]),Z.registerDecoder(ie.BASE64URL,t=>(rt(t.contents),ki(t.contents)),"Base64url-encoded"),Z.registerDecoder(ie.BASE64,t=>(rt(t.contents),Rr(t.contents)),"Base64-encoded"),Z.registerDecoder(35,t=>(rt(t.contents),new RegExp(t.contents)),"RegExp"),Z.registerDecoder(21065,t=>{rt(t.contents);const e=`^(?:${t.contents})$`;return new RegExp(e,"u")},"I-RegExp"),Z.registerDecoder(ie.REGEXP,t=>{if(Zn(t.contents),t.contents.length<1||t.contents.length>2)throw new Error(`Invalid RegExp Array: ${t.contents}`);return new RegExp(t.contents[0],t.contents[1])},"RegExp"),we(RegExp,t=>[ie.REGEXP,[t.source,t.flags]]),Z.registerDecoder(64,t=>(Ze(t.contents),t.contents),"uint8 Typed Array");function Be(t,e,r){Ze(t.contents);let o=t.contents.length;if(o%e.BYTES_PER_ELEMENT!==0)throw new Error(`Number of bytes must be divisible by ${e.BYTES_PER_ELEMENT}, got: ${o}`);o/=e.BYTES_PER_ELEMENT;const f=new e(o),u=new DataView(t.contents.buffer,t.contents.byteOffset,t.contents.byteLength),c=u[`get${e.name.replace(/Array/,"")}`].bind(u);for(let d=0;d<o;d++)f[d]=c(d*e.BYTES_PER_ELEMENT,r);return f}function nt(t,e,r,o,f){const u=f.forceEndian??Jn;if(It(u?e:r,t,f),Oe(o.byteLength,t,Y.BYTE_STRING),Jn===u)t.write(new Uint8Array(o.buffer,o.byteOffset,o.byteLength));else{const c=`write${o.constructor.name.replace(/Array/,"")}`,d=t[c].bind(t);for(const g of o)d(g,u)}}Z.registerDecoder(65,t=>Be(t,Uint16Array,!1),"uint16, big endian, Typed Array"),Z.registerDecoder(66,t=>Be(t,Uint32Array,!1),"uint32, big endian, Typed Array"),Z.registerDecoder(67,t=>Be(t,BigUint64Array,!1),"uint64, big endian, Typed Array"),Z.registerDecoder(68,t=>(Ze(t.contents),new Uint8ClampedArray(t.contents)),"uint8 Typed Array, clamped arithmetic"),we(Uint8ClampedArray,t=>[68,new Uint8Array(t.buffer,t.byteOffset,t.byteLength)]),Z.registerDecoder(69,t=>Be(t,Uint16Array,!0),"uint16, little endian, Typed Array"),we(Uint16Array,(t,e,r)=>nt(e,69,65,t,r)),Z.registerDecoder(70,t=>Be(t,Uint32Array,!0),"uint32, little endian, Typed Array"),we(Uint32Array,(t,e,r)=>nt(e,70,66,t,r)),Z.registerDecoder(71,t=>Be(t,BigUint64Array,!0),"uint64, little endian, Typed Array"),we(BigUint64Array,(t,e,r)=>nt(e,71,67,t,r)),Z.registerDecoder(72,t=>(Ze(t.contents),new Int8Array(t.contents)),"sint8 Typed Array"),we(Int8Array,t=>[72,new Uint8Array(t.buffer,t.byteOffset,t.byteLength)]),Z.registerDecoder(73,t=>Be(t,Int16Array,!1),"sint16, big endian, Typed Array"),Z.registerDecoder(74,t=>Be(t,Int32Array,!1),"sint32, big endian, Typed Array"),Z.registerDecoder(75,t=>Be(t,BigInt64Array,!1),"sint64, big endian, Typed Array"),Z.registerDecoder(77,t=>Be(t,Int16Array,!0),"sint16, little endian, Typed Array"),we(Int16Array,(t,e,r)=>nt(e,77,73,t,r)),Z.registerDecoder(78,t=>Be(t,Int32Array,!0),"sint32, little endian, Typed Array"),we(Int32Array,(t,e,r)=>nt(e,78,74,t,r)),Z.registerDecoder(79,t=>Be(t,BigInt64Array,!0),"sint64, little endian, Typed Array"),we(BigInt64Array,(t,e,r)=>nt(e,79,75,t,r)),Z.registerDecoder(81,t=>Be(t,Float32Array,!1),"IEEE 754 binary32, big endian, Typed Array"),Z.registerDecoder(82,t=>Be(t,Float64Array,!1),"IEEE 754 binary64, big endian, Typed Array"),Z.registerDecoder(85,t=>Be(t,Float32Array,!0),"IEEE 754 binary32, little endian, Typed Array"),we(Float32Array,(t,e,r)=>nt(e,85,81,t,r)),Z.registerDecoder(86,t=>Be(t,Float64Array,!0),"IEEE 754 binary64, big endian, Typed Array"),we(Float64Array,(t,e,r)=>nt(e,86,82,t,r)),Z.registerDecoder(ie.SET,(t,e)=>{if(Zn(t.contents),e.sortKeys){const r=Fe.decodeToEncodeOpts(e);let o=null;for(const f of t.contents){const u=[f,void 0,mt(f,r)];if(o&&e.sortKeys(o,u)>=0)throw new Error(`Set items out of order in tag #${ie.SET}`);o=u}}return new Set(t.contents)},"Set"),we(Set,(t,e,r)=>{let o=[...t];if(r.sortKeys){const f=o.map(u=>[u,void 0,mt(u,r)]);f.sort(r.sortKeys),o=f.map(([u])=>u)}return[ie.SET,o]}),Z.registerDecoder(ie.JSON,t=>(rt(t.contents),JSON.parse(t.contents)),"JSON-encoded");function ni(t){return Ze(t.contents),new Gt().decode(t.contents)}ni.comment=t=>{Ze(t.contents);const e=new Gt;return`(WTF8 string): ${JSON.stringify(e.decode(t.contents))}`},Z.registerDecoder(ie.WTF8,ni),Z.registerDecoder(ie.SELF_DESCRIBED,t=>t.contents,"Self-Described"),Z.registerDecoder(ie.INVALID_16,()=>{throw new Error(`Tag always invalid: ${ie.INVALID_16}`)},"Invalid"),Z.registerDecoder(ie.INVALID_32,()=>{throw new Error(`Tag always invalid: ${ie.INVALID_32}`)},"Invalid"),Z.registerDecoder(ie.INVALID_64,()=>{throw new Error(`Tag always invalid: ${ie.INVALID_64}`)},"Invalid");function Dr(t){throw new Error(`Encoding ${t.constructor.name} intentionally unimplmented. It is not concrete enough to interoperate. Convert to Uint8Array first.`)}we(ArrayBuffer,Dr),we(DataView,Dr),typeof SharedArrayBuffer<"u"&&we(SharedArrayBuffer,Dr);function Xt(t){return[NaN,t.valueOf()]}we(Boolean,Xt),we(Number,Xt),we(String,Xt),we(BigInt,Xt);function Ro(t){const e={...Fe.defaultDecodeOptions};if(t.dcbor?Object.assign(e,Fe.dcborDecodeOptions):t.cde&&Object.assign(e,Fe.cdeDecodeOptions),Object.assign(e,t),Object.hasOwn(e,"rejectLongNumbers"))throw new TypeError("rejectLongNumbers has changed to requirePreferred");return e.boxed&&(e.saveOriginal=!0),e}let Io=class{parent=void 0;ret=void 0;step(e,r,o){if(this.ret=Fe.create(e,this.parent,r,o),e[2]===Ie.BREAK)if(this.parent?.isStreaming)this.parent.left=0;else throw new Error("Unexpected BREAK");else this.parent&&this.parent.push(this.ret,o,e[3]);for(this.ret instanceof Fe&&(this.parent=this.ret);this.parent?.done;){this.ret=this.parent.convert(o);const f=this.parent.parent;f?.replaceLast(this.ret,this.parent,o),this.parent=f}}};function Bo(t,e={}){const r=Ro(e),o=new Kt(t,r),f=new Io;for(const u of o)f.step(u,r,o);return f.ret}const{cdeDecodeOptions:Go,dcborDecodeOptions:Wo,defaultDecodeOptions:Ho}=Fe;class Ao{constructor(e={}){this.options={id:bt(),codec:"cbor",timeout:10*1e3,chunkSize:16*1024,topicMake:(r,o,f)=>`${r}/${o}/${f??"any"}`,topicMatch:r=>{const o=r.match(/^(.+)\/([^/]+)\/([^/]+)$/);return o?{name:o[1],operation:o[2],peerId:o[3]==="any"?void 0:o[3]}:null},...e}}}class ii{static uint8ArrayToBase64(e){return btoa(String.fromCharCode(...e))}static base64ToUint8Array(e){const r=atob(e),o=new Uint8Array(r.length);for(let f=0;f<r.length;f++)o[f]=r.charCodeAt(f);return o}static stringify(e){return JSON.stringify(e,(r,o)=>o instanceof Uint8Array?{__Uint8Array:this.uint8ArrayToBase64(o)}:o)}static parse(e){return JSON.parse(e,(r,o)=>o?.__Uint8Array?this.base64ToUint8Array(o.__Uint8Array):o)}}class No{constructor(e){this.type=e,this.types=new Rn,this.tags=new Map;const r=64e3;this.types.registerEncoder(tr,o=>[r,new Uint8Array(o.buffer,o.byteOffset,o.byteLength)]),this.tags.set(r,o=>tr.from(o.contents))}encode(e){let r;if(this.type==="cbor")try{r=mt(e,{types:this.types})}catch{throw new Error("failed to encode CBOR format")}else if(this.type==="json")try{r=ii.stringify(e)}catch{throw new Error("failed to encode JSON format")}else throw new Error("invalid format");return r}decode(e){let r;if(this.type==="cbor"&&typeof e=="object"&&e instanceof Uint8Array)try{r=Bo(e,{tags:this.tags})}catch{throw new Error("failed to decode CBOR format")}else if(this.type==="json"&&typeof e=="string")try{r=ii.parse(e)}catch{throw new Error("failed to decode JSON format")}else throw new Error("invalid format or wrong data type");return r}}class Fo extends Ao{constructor(e={}){super(e),this.codec=new No(this.options.codec)}}class At{constructor(e,r,o,f){this.type=e,this.id=r,this.sender=o,this.receiver=f}}class oi extends At{constructor(e,r,o,f,u){super("event-emission",e,f,u),this.event=r,this.params=o}}class si extends At{constructor(e,r,o,f,u){super("service-call-request",e,f,u),this.service=r,this.params=o}}class ai extends At{constructor(e,r,o,f,u){super("service-call-response",e,f,u),this.result=r,this.error=o}}class ui extends At{constructor(e,r,o,f,u){super("resource-transfer-request",e,f,u),this.resource=r,this.params=o}}class fi extends At{constructor(e,r,o,f,u,c,d,g,b){super("resource-transfer-response",e,g,b),this.resource=r,this.params=o,this.chunk=f,this.meta=u,this.error=c,this.final=d}}class Uo{makeEventEmission(e,r,o,f,u){return new oi(e,r,o,f,u)}makeServiceCallRequest(e,r,o,f,u){return new si(e,r,o,f,u)}makeServiceCallResponse(e,r,o,f,u){return new ai(e,r,o,f,u)}makeResourceTransferRequest(e,r,o,f,u){return new ui(e,r,o,f,u)}makeResourceTransferResponse(e,r,o,f,u,c,d,g,b){return new fi(e,r,o,f,u,c,d,g,b)}parse(e){if(typeof e!="object"||e===null)throw new Error("invalid argument: not an object");if(!("type"in e)||typeof e.type!="string")throw new Error('invalid object: missing or invalid "type" field');if(!("id"in e)||typeof e.id!="string")throw new Error('invalid object: missing or invalid "id" field');if("sender"in e&&e.sender!==void 0&&typeof e.sender!="string")throw new Error('invalid object: invalid "sender" field');if("receiver"in e&&e.receiver!==void 0&&typeof e.receiver!="string")throw new Error('invalid object: invalid "receiver" field');const r=(f,u)=>Object.keys(f).some(c=>!u.includes(c)),o=f=>f.params===void 0||typeof f.params=="object"&&Array.isArray(f.params);if(e.type==="event-emission"){if(typeof e.event!="string")throw new Error('invalid EventEmission object: "event" field must be a string');if(r(e,["type","id","event","params","sender","receiver"]))throw new Error("invalid EventEmission object: contains unknown fields");if(!o(e))throw new Error('invalid EventEmission object: "params" field must be an array');return this.makeEventEmission(e.id,e.event,e.params,e.sender,e.receiver)}else if(e.type==="service-call-request"){if(typeof e.service!="string")throw new Error('invalid ServiceCallRequest object: "service" field must be a string');if(r(e,["type","id","service","params","sender","receiver"]))throw new Error("invalid ServiceCallRequest object: contains unknown fields");if(!o(e))throw new Error('invalid ServiceCallRequest object: "params" field must be an array');return this.makeServiceCallRequest(e.id,e.service,e.params,e.sender,e.receiver)}else if(e.type==="service-call-response"){if(r(e,["type","id","result","error","sender","receiver"]))throw new Error("invalid ServiceCallResponse object: contains unknown fields");return this.makeServiceCallResponse(e.id,e.result,e.error,e.sender,e.receiver)}else if(e.type==="resource-transfer-request"){if(typeof e.resource!="string")throw new Error('invalid ResourceTransferRequest object: "resource" field must be a string');if(r(e,["type","id","resource","params","sender","receiver"]))throw new Error("invalid ResourceTransferRequest object: contains unknown fields");if(!o(e))throw new Error('invalid ResourceTransferRequest object: "params" field must be an array');return this.makeResourceTransferRequest(e.id,e.resource,e.params,e.sender,e.receiver)}else if(e.type==="resource-transfer-response"){if(e.resource!==void 0&&typeof e.resource!="string")throw new Error('invalid ResourceTransferResponse object: "resource" field must be a string');if(e.chunk!==void 0&&typeof e.chunk!="object")throw new Error('invalid ResourceTransferResponse object: "chunk" field must be an object');if(e.meta!==void 0&&(typeof e.meta!="object"||e.meta===null||Array.isArray(e.meta)))throw new Error('invalid ResourceTransferResponse object: "meta" field must be an object');if(e.error!==void 0&&typeof e.error!="string")throw new Error('invalid ResourceTransferResponse object: "error" field must be a string');if(e.final!==void 0&&typeof e.final!="boolean")throw new Error('invalid ResourceTransferResponse object: "final" field must be a boolean');if(!o(e))throw new Error('invalid ResourceTransferResponse object: "params" field must be an array');if(r(e,["type","id","resource","params","chunk","meta","error","final","sender","receiver"]))throw new Error("invalid ResourceTransferResponse object: contains unknown fields");return this.makeResourceTransferResponse(e.id,e.resource,e.params,e.chunk,e.meta,e.error,e.final,e.sender,e.receiver)}else throw new Error("invalid object: not of any known type")}}class Lo extends Fo{constructor(){super(...arguments),this.msg=new Uo}}class Oo extends Lo{constructor(e,r={}){super(r),this.mqtt=e,this._messageHandler=(o,f,u)=>{this._onMessage(o,f,u)},this.mqtt.on("message",this._messageHandler)}destroy(){this.mqtt.off("message",this._messageHandler)}async _subscribeTopic(e,r={}){return new Promise((o,f)=>{this.mqtt.subscribe(e,{qos:2,...r},(u,c)=>{u?f(u):o()})})}async _unsubscribeTopic(e){return new Promise((r,o)=>{this.mqtt.unsubscribe(e,(f,u)=>{f?o(f):r()})})}_onMessage(e,r,o){let f;try{let u=r;this.options.codec==="json"&&(u=r.toString());const c=this.codec.decode(u);f=this.msg.parse(c)}catch(u){const c=u instanceof Error?new Error(`failed to parse message: ${u.message}`):new Error("failed to parse message");this.mqtt.emit("error",c);return}this._dispatchMessage(e,f)}_dispatchMessage(e,r){}}class Mo extends Oo{constructor(){super(...arguments),this.subscriptions=new Map}async subscribe(e,...r){let o={},f=r[0];if(r.length===2&&typeof r[0]=="object"&&(o=r[0],f=r[1]),this.subscriptions.has(e))throw new Error(`subscribe: event "${e}" already subscribed`);const u=this.options.topicMake(e,"event-emission"),c=this.options.topicMake(e,"event-emission",this.options.id);await Promise.all([this._subscribeTopic(u,{qos:0,...o}),this._subscribeTopic(c,{qos:0,...o})]).catch(b=>{throw this._unsubscribeTopic(u).catch(()=>{}),this._unsubscribeTopic(c).catch(()=>{}),b}),this.subscriptions.set(e,f);const d=this;return{async unsubscribe(){if(!d.subscriptions.has(e))throw new Error(`unsubscribe: event "${e}" not subscribed`);return d.subscriptions.delete(e),Promise.all([d._unsubscribeTopic(u),d._unsubscribeTopic(c)]).then(()=>{})}}}emit(e,...r){let o,f,u,c={};typeof e=="object"&&e!==null?(o=e.event,f=e.params,u=e.receiver,c=e.options??{}):(o=e,f=r);const d=bt(),g=this.msg.makeEventEmission(d,o,f,this.options.id,u),b=this.codec.encode(g),p=this.options.topicMake(o,"event-emission",u);this.mqtt.publish(p,dt.from(b),{qos:0,...c})}_dispatchMessage(e,r){super._dispatchMessage(e,r);const o=this.options.topicMatch(e);if(o!==null&&o.operation==="event-emission"&&r instanceof oi){const f=r.event,u=this.subscriptions.get(f),c=r.params??[],d={sender:r.sender??""};r.receiver&&(d.receiver=r.receiver),Promise.resolve().then(()=>u?.(...c,d)).catch(g=>{this.mqtt.emit("error",g)})}}}class Do extends Mo{constructor(){super(...arguments),this.registrations=new Map,this.responseCallback=new Map,this.responseSubscriptions=new Map}async register(e,...r){let o={},f=r[0];if(r.length===2&&typeof r[0]=="object"&&(o=r[0],f=r[1]),this.registrations.has(e))throw new Error(`register: service "${e}" already registered`);const u=this.options.topicMake(e,"service-call-request"),c=this.options.topicMake(e,"service-call-request",this.options.id);await Promise.all([this._subscribeTopic(u,{qos:2,...o}),this._subscribeTopic(c,{qos:2,...o})]).catch(b=>{throw this._unsubscribeTopic(u).catch(()=>{}),this._unsubscribeTopic(c).catch(()=>{}),b}),this.registrations.set(e,f);const d=this;return{async unregister(){if(!d.registrations.has(e))throw new Error(`unregister: service "${e}" not registered`);return d.registrations.delete(e),Promise.all([d._unsubscribeTopic(u),d._unsubscribeTopic(c)]).then(()=>{})}}}call(e,...r){let o,f,u,c={};typeof e=="object"&&e!==null?(o=e.service,f=e.params,u=e.receiver,c=e.options??{}):(o=e,f=r);const d=bt();this._responseSubscribe(o,{qos:c.qos??2});const g=new Promise((O,q)=>{let k=setTimeout(()=>{this.responseCallback.delete(d),this._responseUnsubscribe(o),k=null,q(new Error("communication timeout"))},this.options.timeout);this.responseCallback.set(d,{service:o,callback:(W,j)=>{k!==null&&(clearTimeout(k),k=null),W?q(W):O(j)}})}),b=this.msg.makeServiceCallRequest(d,o,f,this.options.id,u),p=this.codec.encode(b),A=this.options.topicMake(o,"service-call-request",u);return this.mqtt.publish(A,dt.from(p),{qos:2,...c},O=>{if(O){const q=this.responseCallback.get(d);q!==void 0&&(this.responseCallback.delete(d),this._responseUnsubscribe(o),q.callback(O,void 0))}}),g}_responseSubscribe(e,r={qos:2}){const o=this.options.topicMake(e,"service-call-response",this.options.id);this.responseSubscriptions.has(o)||(this.responseSubscriptions.set(o,0),this.mqtt.subscribe(o,r,u=>{u&&this.mqtt.emit("error",u)}));const f=this.responseSubscriptions.get(o)??0;this.responseSubscriptions.set(o,f+1)}_responseUnsubscribe(e){const r=this.options.topicMake(e,"service-call-response",this.options.id);if(!this.responseSubscriptions.has(r))return;const o=this.responseSubscriptions.get(r)??0;this.responseSubscriptions.set(r,o-1),this.responseSubscriptions.get(r)===0&&(this.responseSubscriptions.delete(r),this.mqtt.unsubscribe(r,f=>{f&&this.mqtt.emit("error",f)}))}_dispatchMessage(e,r){super._dispatchMessage(e,r);const o=this.options.topicMatch(e);if(o!==null&&o.operation==="service-call-request"&&r instanceof si){const f=r.id,u=r.service,c=this.registrations.get(u);let d;if(c!==void 0){const g=r.params??[],b={sender:r.sender??""};r.receiver&&(b.receiver=r.receiver),d=Promise.resolve().then(()=>c(...g,b))}else d=Promise.reject(new Error(`method not found: ${u}`));d.then(g=>this.msg.makeServiceCallResponse(f,g,void 0,this.options.id,r.sender),g=>{let b;return g==null?b="undefined error":typeof g=="string"?b=g:g instanceof Error?b=g.message:b=String(g),this.msg.makeServiceCallResponse(f,void 0,b,this.options.id,r.sender)}).then(g=>{const b=r.sender;if(b===void 0)throw new Error("invalid request: missing sender");const p=this.codec.encode(g),A=this.options.topicMake(u,"service-call-response",b);this.mqtt.publish(A,dt.from(p),{qos:2})}).catch(g=>{this.mqtt.emit("error",g)})}else if(o!==null&&o.operation==="service-call-response"&&o.peerId===this.options.id&&r instanceof ai){const f=r.id,u=this.responseCallback.get(f);u!==void 0&&(r.error!==void 0?u.callback(new Error(r.error),void 0):u.callback(void 0,r.result),this.responseCallback.delete(f),this._responseUnsubscribe(u.service))}}}class Co extends Do{constructor(){super(...arguments),this.provisionings=new Map,this.callbacks=new Map,this.pushStreams=new Map,this.pushTimers=new Map}async provision(e,...r){let o={},f=r[0];if(r.length===2&&typeof r[0]=="object"&&(o=r[0],f=r[1]),this.provisionings.has(e))throw new Error(`provision: resource "${e}" already provisioned`);const u=this.options.topicMake(e,"resource-transfer-request"),c=this.options.topicMake(e,"resource-transfer-request",this.options.id),d=this.options.topicMake(e,"resource-transfer-response"),g=this.options.topicMake(e,"resource-transfer-response",this.options.id);await Promise.all([this._subscribeTopic(u,{qos:2,...o}),this._subscribeTopic(c,{qos:2,...o}),this._subscribeTopic(d,{qos:2,...o}),this._subscribeTopic(g,{qos:2,...o})]).catch(A=>{throw this._unsubscribeTopic(u).catch(()=>{}),this._unsubscribeTopic(c).catch(()=>{}),this._unsubscribeTopic(d).catch(()=>{}),this._unsubscribeTopic(g).catch(()=>{}),A}),this.provisionings.set(e,f);const b=this;return{async unprovision(){if(!b.provisionings.has(e))throw new Error(`unprovision: resource "${e}" not provisioned`);return b.provisionings.delete(e),Promise.all([b._unsubscribeTopic(u),b._unsubscribeTopic(c),b._unsubscribeTopic(d),b._unsubscribeTopic(g)]).then(()=>{})}}}push(e,...r){let o,f,u,c,d,g={};typeof e=="object"&&e!==null?(o=e.resource,f=e.data,u=e.params,c=e.meta,d=e.receiver,g=e.options??{}):(o=e,f=r[0],u=r.slice(1));const b=bt(),p=this.options.topicMake(o,"resource-transfer-response",d);let A=!0;const O=(q,k,W)=>{const j=A?c:void 0;A=!1;const x=this.msg.makeResourceTransferResponse(b,o,u,q,j,k,W,this.options.id,d),R=this.codec.encode(x);this.mqtt.publish(p,dt.from(R),{qos:2,...g})};return new Promise((q,k)=>{f instanceof Dt.Readable?Tn(f,this.options.chunkSize,O,()=>q(),W=>k(W)):f instanceof Uint8Array&&(_n(f,this.options.chunkSize,O),q())})}async fetch(e,...r){let o,f,u={},c;typeof e=="object"&&e!==null?(o=e.resource,c=e.params,f=e.receiver,u=e.options??{}):(o=e,c=r);const d=bt(),g=this.options.topicMake(o,"resource-transfer-response",this.options.id);await this._subscribeTopic(g,{qos:2});const b=new Dt.Readable({read(I){}}),p=mn(b);let A;const O=new Promise(I=>{A=I});let q=null;const k=(I=!1)=>{q!==null&&(clearTimeout(q),q=null),this._unsubscribeTopic(g).catch(()=>{}),this.callbacks.delete(d),I&&A?.(void 0)};q=setTimeout(()=>{k(),A?.(void 0),b.destroy(new Error("communication timeout"))},this.options.timeout);let W=!0;this.callbacks.set(d,{resource:o,callback:(I,_,v,F)=>{W&&(W=!1,A?.(v)),I!==void 0?(k(!0),b.destroy(I)):(_!==void 0&&b.push(_),F&&(k(),b.push(null)))}});const j=this.msg.makeResourceTransferRequest(d,o,c,this.options.id,f),x=this.codec.encode(j),R=this.options.topicMake(o,"resource-transfer-request",f);return this.mqtt.publish(R,dt.from(x),{qos:2,...u}),{stream:b,buffer:p,meta:O}}_dispatchMessage(e,r){super._dispatchMessage(e,r);const o=this.options.topicMatch(e);if(o!==null&&o.operation==="resource-transfer-request"&&r instanceof ui){const f=r.resource,u=this.provisionings.get(f);if(u!==void 0){const c=r.id,d=r.resource,g=r.params??[],b=r.sender??"",p=r.receiver,A={sender:b};p&&(A.receiver=p);const O=this.options.topicMake(d,"resource-transfer-response",b);let q=!0;const k=(W,j,x)=>{const R=q?A.meta:void 0;q=!1;const I=this.msg.makeResourceTransferResponse(c,d,void 0,W,R,j,x,this.options.id,b),_=dt.from(this.codec.encode(I));this.mqtt.publish(O,_,{qos:2})};Promise.resolve().then(()=>u(...g,A)).then(async()=>{if(A.stream instanceof Dt.Readable)Tn(A.stream,this.options.chunkSize,k,()=>{},W=>k(void 0,W.message,!0));else if(A.buffer!==void 0&&typeof A.buffer.then=="function")_n(await A.buffer,this.options.chunkSize,k);else throw new Error("handler did not provide data via info.stream or info.buffer field")}).catch(W=>{k(void 0,W.message,!0)})}}else if(o!==null&&o.operation==="resource-transfer-response"&&r instanceof fi){const f=r.id,u=r.error,c=r.meta,d=r.final,g=r.chunk!==void 0&&!(r.chunk instanceof Uint8Array)?Uint8Array.from(r.chunk):r.chunk,b=this.callbacks.get(f);if(b!==void 0)b.callback(u?new Error(u):void 0,g,c,d);else if(r.resource!==void 0){const p=r.resource,A=this.provisionings.get(p);if(A!==void 0){let O=this.pushStreams.get(f);if(O===void 0){O=new Dt.Readable({read(R){}}),this.pushStreams.set(f,O);const k=setTimeout(()=>{const R=this.pushStreams.get(f);R!==void 0&&(R.destroy(new Error("push stream timeout")),this.pushStreams.delete(f),this.pushTimers.delete(f))},this.options.timeout);this.pushTimers.set(f,k);const W=mn(O),j=r.params??[],x={sender:r.sender??""};r.receiver&&(x.receiver=r.receiver),r.meta&&(x.meta=c),x.stream=O,x.buffer=W,Promise.resolve().then(()=>A(...j,x)).catch(R=>{this.mqtt.emit("error",R)})}const q=()=>{const k=this.pushTimers.get(f);k!==void 0&&(clearTimeout(k),this.pushTimers.delete(f))};u!==void 0?(q(),O.destroy(new Error(u)),this.pushStreams.delete(f)):(g!==void 0&&O.push(g),d&&(q(),O.push(null),this.pushStreams.delete(f)))}}}}}class Po extends Co{}return Po}));
|
|
13
|
+
`,b+=g,b},Mr.noChildren=!0,Z.registerDecoder(ie.CBOR,Mr),Z.registerDecoder(ie.URI,t=>(rt(t.contents),new URL(t.contents)),"URI"),we(URL,t=>[ie.URI,t.toString()]),Z.registerDecoder(ie.BASE64URL,t=>(rt(t.contents),ki(t.contents)),"Base64url-encoded"),Z.registerDecoder(ie.BASE64,t=>(rt(t.contents),Rr(t.contents)),"Base64-encoded"),Z.registerDecoder(35,t=>(rt(t.contents),new RegExp(t.contents)),"RegExp"),Z.registerDecoder(21065,t=>{rt(t.contents);const e=`^(?:${t.contents})$`;return new RegExp(e,"u")},"I-RegExp"),Z.registerDecoder(ie.REGEXP,t=>{if(Zn(t.contents),t.contents.length<1||t.contents.length>2)throw new Error(`Invalid RegExp Array: ${t.contents}`);return new RegExp(t.contents[0],t.contents[1])},"RegExp"),we(RegExp,t=>[ie.REGEXP,[t.source,t.flags]]),Z.registerDecoder(64,t=>(Ze(t.contents),t.contents),"uint8 Typed Array");function Be(t,e,r){Ze(t.contents);let o=t.contents.length;if(o%e.BYTES_PER_ELEMENT!==0)throw new Error(`Number of bytes must be divisible by ${e.BYTES_PER_ELEMENT}, got: ${o}`);o/=e.BYTES_PER_ELEMENT;const f=new e(o),u=new DataView(t.contents.buffer,t.contents.byteOffset,t.contents.byteLength),c=u[`get${e.name.replace(/Array/,"")}`].bind(u);for(let d=0;d<o;d++)f[d]=c(d*e.BYTES_PER_ELEMENT,r);return f}function nt(t,e,r,o,f){const u=f.forceEndian??Jn;if(It(u?e:r,t,f),Oe(o.byteLength,t,Y.BYTE_STRING),Jn===u)t.write(new Uint8Array(o.buffer,o.byteOffset,o.byteLength));else{const c=`write${o.constructor.name.replace(/Array/,"")}`,d=t[c].bind(t);for(const g of o)d(g,u)}}Z.registerDecoder(65,t=>Be(t,Uint16Array,!1),"uint16, big endian, Typed Array"),Z.registerDecoder(66,t=>Be(t,Uint32Array,!1),"uint32, big endian, Typed Array"),Z.registerDecoder(67,t=>Be(t,BigUint64Array,!1),"uint64, big endian, Typed Array"),Z.registerDecoder(68,t=>(Ze(t.contents),new Uint8ClampedArray(t.contents)),"uint8 Typed Array, clamped arithmetic"),we(Uint8ClampedArray,t=>[68,new Uint8Array(t.buffer,t.byteOffset,t.byteLength)]),Z.registerDecoder(69,t=>Be(t,Uint16Array,!0),"uint16, little endian, Typed Array"),we(Uint16Array,(t,e,r)=>nt(e,69,65,t,r)),Z.registerDecoder(70,t=>Be(t,Uint32Array,!0),"uint32, little endian, Typed Array"),we(Uint32Array,(t,e,r)=>nt(e,70,66,t,r)),Z.registerDecoder(71,t=>Be(t,BigUint64Array,!0),"uint64, little endian, Typed Array"),we(BigUint64Array,(t,e,r)=>nt(e,71,67,t,r)),Z.registerDecoder(72,t=>(Ze(t.contents),new Int8Array(t.contents)),"sint8 Typed Array"),we(Int8Array,t=>[72,new Uint8Array(t.buffer,t.byteOffset,t.byteLength)]),Z.registerDecoder(73,t=>Be(t,Int16Array,!1),"sint16, big endian, Typed Array"),Z.registerDecoder(74,t=>Be(t,Int32Array,!1),"sint32, big endian, Typed Array"),Z.registerDecoder(75,t=>Be(t,BigInt64Array,!1),"sint64, big endian, Typed Array"),Z.registerDecoder(77,t=>Be(t,Int16Array,!0),"sint16, little endian, Typed Array"),we(Int16Array,(t,e,r)=>nt(e,77,73,t,r)),Z.registerDecoder(78,t=>Be(t,Int32Array,!0),"sint32, little endian, Typed Array"),we(Int32Array,(t,e,r)=>nt(e,78,74,t,r)),Z.registerDecoder(79,t=>Be(t,BigInt64Array,!0),"sint64, little endian, Typed Array"),we(BigInt64Array,(t,e,r)=>nt(e,79,75,t,r)),Z.registerDecoder(81,t=>Be(t,Float32Array,!1),"IEEE 754 binary32, big endian, Typed Array"),Z.registerDecoder(82,t=>Be(t,Float64Array,!1),"IEEE 754 binary64, big endian, Typed Array"),Z.registerDecoder(85,t=>Be(t,Float32Array,!0),"IEEE 754 binary32, little endian, Typed Array"),we(Float32Array,(t,e,r)=>nt(e,85,81,t,r)),Z.registerDecoder(86,t=>Be(t,Float64Array,!0),"IEEE 754 binary64, big endian, Typed Array"),we(Float64Array,(t,e,r)=>nt(e,86,82,t,r)),Z.registerDecoder(ie.SET,(t,e)=>{if(Zn(t.contents),e.sortKeys){const r=Fe.decodeToEncodeOpts(e);let o=null;for(const f of t.contents){const u=[f,void 0,mt(f,r)];if(o&&e.sortKeys(o,u)>=0)throw new Error(`Set items out of order in tag #${ie.SET}`);o=u}}return new Set(t.contents)},"Set"),we(Set,(t,e,r)=>{let o=[...t];if(r.sortKeys){const f=o.map(u=>[u,void 0,mt(u,r)]);f.sort(r.sortKeys),o=f.map(([u])=>u)}return[ie.SET,o]}),Z.registerDecoder(ie.JSON,t=>(rt(t.contents),JSON.parse(t.contents)),"JSON-encoded");function ni(t){return Ze(t.contents),new Gt().decode(t.contents)}ni.comment=t=>{Ze(t.contents);const e=new Gt;return`(WTF8 string): ${JSON.stringify(e.decode(t.contents))}`},Z.registerDecoder(ie.WTF8,ni),Z.registerDecoder(ie.SELF_DESCRIBED,t=>t.contents,"Self-Described"),Z.registerDecoder(ie.INVALID_16,()=>{throw new Error(`Tag always invalid: ${ie.INVALID_16}`)},"Invalid"),Z.registerDecoder(ie.INVALID_32,()=>{throw new Error(`Tag always invalid: ${ie.INVALID_32}`)},"Invalid"),Z.registerDecoder(ie.INVALID_64,()=>{throw new Error(`Tag always invalid: ${ie.INVALID_64}`)},"Invalid");function Dr(t){throw new Error(`Encoding ${t.constructor.name} intentionally unimplmented. It is not concrete enough to interoperate. Convert to Uint8Array first.`)}we(ArrayBuffer,Dr),we(DataView,Dr),typeof SharedArrayBuffer<"u"&&we(SharedArrayBuffer,Dr);function Xt(t){return[NaN,t.valueOf()]}we(Boolean,Xt),we(Number,Xt),we(String,Xt),we(BigInt,Xt);function Ro(t){const e={...Fe.defaultDecodeOptions};if(t.dcbor?Object.assign(e,Fe.dcborDecodeOptions):t.cde&&Object.assign(e,Fe.cdeDecodeOptions),Object.assign(e,t),Object.hasOwn(e,"rejectLongNumbers"))throw new TypeError("rejectLongNumbers has changed to requirePreferred");return e.boxed&&(e.saveOriginal=!0),e}let Io=class{parent=void 0;ret=void 0;step(e,r,o){if(this.ret=Fe.create(e,this.parent,r,o),e[2]===Ie.BREAK)if(this.parent?.isStreaming)this.parent.left=0;else throw new Error("Unexpected BREAK");else this.parent&&this.parent.push(this.ret,o,e[3]);for(this.ret instanceof Fe&&(this.parent=this.ret);this.parent?.done;){this.ret=this.parent.convert(o);const f=this.parent.parent;f?.replaceLast(this.ret,this.parent,o),this.parent=f}}};function Bo(t,e={}){const r=Ro(e),o=new Kt(t,r),f=new Io;for(const u of o)f.step(u,r,o);return f.ret}const{cdeDecodeOptions:Go,dcborDecodeOptions:Wo,defaultDecodeOptions:Ho}=Fe;class Ao{constructor(e={}){this.options={id:bt(),codec:"cbor",timeout:10*1e3,chunkSize:16*1024,topicMake:(r,o,f)=>`${r}/${o}/${f??"any"}`,topicMatch:r=>{const o=r.match(/^(.+)\/([^/]+)\/([^/]+)$/);return o?{name:o[1],operation:o[2],peerId:o[3]==="any"?void 0:o[3]}:null},...e}}}class ii{static uint8ArrayToBase64(e){return btoa(String.fromCharCode(...e))}static base64ToUint8Array(e){const r=atob(e),o=new Uint8Array(r.length);for(let f=0;f<r.length;f++)o[f]=r.charCodeAt(f);return o}static stringify(e){return JSON.stringify(e,(r,o)=>o instanceof Uint8Array?{__Uint8Array:this.uint8ArrayToBase64(o)}:o)}static parse(e){return JSON.parse(e,(r,o)=>typeof o?.__Uint8Array=="string"?this.base64ToUint8Array(o.__Uint8Array):o)}}class No{constructor(e){this.type=e,this.types=new Rn,this.tags=new Map;const r=64e3;this.types.registerEncoder(tr,o=>[r,new Uint8Array(o.buffer,o.byteOffset,o.byteLength)]),this.tags.set(r,o=>tr.from(o.contents))}encode(e){let r;if(this.type==="cbor")try{r=mt(e,{types:this.types})}catch{throw new Error("failed to encode CBOR format")}else if(this.type==="json")try{r=ii.stringify(e)}catch{throw new Error("failed to encode JSON format")}else throw new Error("invalid format");return r}decode(e){let r;if(this.type==="cbor"&&typeof e=="object"&&e instanceof Uint8Array)try{r=Bo(e,{tags:this.tags})}catch{throw new Error("failed to decode CBOR format")}else if(this.type==="json"&&typeof e=="string")try{r=ii.parse(e)}catch{throw new Error("failed to decode JSON format")}else throw new Error("invalid format or wrong data type");return r}}class Fo extends Ao{constructor(e={}){super(e),this.codec=new No(this.options.codec)}}class At{constructor(e,r,o,f){this.type=e,this.id=r,this.sender=o,this.receiver=f}}class oi extends At{constructor(e,r,o,f,u){super("event-emission",e,f,u),this.event=r,this.params=o}}class si extends At{constructor(e,r,o,f,u){super("service-call-request",e,f,u),this.service=r,this.params=o}}class ai extends At{constructor(e,r,o,f,u){super("service-call-response",e,f,u),this.result=r,this.error=o}}class ui extends At{constructor(e,r,o,f,u){super("resource-transfer-request",e,f,u),this.resource=r,this.params=o}}class fi extends At{constructor(e,r,o,f,u,c,d,g,b){super("resource-transfer-response",e,g,b),this.resource=r,this.params=o,this.chunk=f,this.meta=u,this.error=c,this.final=d}}class Uo{makeEventEmission(e,r,o,f,u){return new oi(e,r,o,f,u)}makeServiceCallRequest(e,r,o,f,u){return new si(e,r,o,f,u)}makeServiceCallResponse(e,r,o,f,u){return new ai(e,r,o,f,u)}makeResourceTransferRequest(e,r,o,f,u){return new ui(e,r,o,f,u)}makeResourceTransferResponse(e,r,o,f,u,c,d,g,b){return new fi(e,r,o,f,u,c,d,g,b)}parse(e){if(typeof e!="object"||e===null)throw new Error("invalid argument: not an object");if(!("type"in e)||typeof e.type!="string")throw new Error('invalid object: missing or invalid "type" field');if(!("id"in e)||typeof e.id!="string")throw new Error('invalid object: missing or invalid "id" field');if("sender"in e&&e.sender!==void 0&&typeof e.sender!="string")throw new Error('invalid object: invalid "sender" field');if("receiver"in e&&e.receiver!==void 0&&typeof e.receiver!="string")throw new Error('invalid object: invalid "receiver" field');const r=(f,u)=>Object.keys(f).some(c=>!u.includes(c)),o=f=>f.params===void 0||typeof f.params=="object"&&Array.isArray(f.params);if(e.type==="event-emission"){if(typeof e.event!="string")throw new Error('invalid EventEmission object: "event" field must be a string');if(r(e,["type","id","event","params","sender","receiver"]))throw new Error("invalid EventEmission object: contains unknown fields");if(!o(e))throw new Error('invalid EventEmission object: "params" field must be an array');return this.makeEventEmission(e.id,e.event,e.params,e.sender,e.receiver)}else if(e.type==="service-call-request"){if(typeof e.service!="string")throw new Error('invalid ServiceCallRequest object: "service" field must be a string');if(r(e,["type","id","service","params","sender","receiver"]))throw new Error("invalid ServiceCallRequest object: contains unknown fields");if(!o(e))throw new Error('invalid ServiceCallRequest object: "params" field must be an array');return this.makeServiceCallRequest(e.id,e.service,e.params,e.sender,e.receiver)}else if(e.type==="service-call-response"){if(r(e,["type","id","result","error","sender","receiver"]))throw new Error("invalid ServiceCallResponse object: contains unknown fields");return this.makeServiceCallResponse(e.id,e.result,e.error,e.sender,e.receiver)}else if(e.type==="resource-transfer-request"){if(typeof e.resource!="string")throw new Error('invalid ResourceTransferRequest object: "resource" field must be a string');if(r(e,["type","id","resource","params","sender","receiver"]))throw new Error("invalid ResourceTransferRequest object: contains unknown fields");if(!o(e))throw new Error('invalid ResourceTransferRequest object: "params" field must be an array');return this.makeResourceTransferRequest(e.id,e.resource,e.params,e.sender,e.receiver)}else if(e.type==="resource-transfer-response"){if(e.resource!==void 0&&typeof e.resource!="string")throw new Error('invalid ResourceTransferResponse object: "resource" field must be a string');if(e.chunk!==void 0&&typeof e.chunk!="object")throw new Error('invalid ResourceTransferResponse object: "chunk" field must be an object');if(e.meta!==void 0&&(typeof e.meta!="object"||e.meta===null||Array.isArray(e.meta)))throw new Error('invalid ResourceTransferResponse object: "meta" field must be an object');if(e.error!==void 0&&typeof e.error!="string")throw new Error('invalid ResourceTransferResponse object: "error" field must be a string');if(e.final!==void 0&&typeof e.final!="boolean")throw new Error('invalid ResourceTransferResponse object: "final" field must be a boolean');if(!o(e))throw new Error('invalid ResourceTransferResponse object: "params" field must be an array');if(r(e,["type","id","resource","params","chunk","meta","error","final","sender","receiver"]))throw new Error("invalid ResourceTransferResponse object: contains unknown fields");return this.makeResourceTransferResponse(e.id,e.resource,e.params,e.chunk,e.meta,e.error,e.final,e.sender,e.receiver)}else throw new Error("invalid object: not of any known type")}}class Lo extends Fo{constructor(){super(...arguments),this.msg=new Uo}}class Oo extends Lo{constructor(e,r={}){super(r),this.mqtt=e,this._messageHandler=(o,f,u)=>{this._onMessage(o,f,u)},this.mqtt.on("message",this._messageHandler)}destroy(){this.mqtt.off("message",this._messageHandler)}async _subscribeTopic(e,r={}){return new Promise((o,f)=>{this.mqtt.subscribe(e,{qos:2,...r},(u,c)=>{u?f(u):o()})})}async _unsubscribeTopic(e){return new Promise((r,o)=>{this.mqtt.unsubscribe(e,(f,u)=>{f?o(f):r()})})}_onMessage(e,r,o){let f;try{let u=r;this.options.codec==="json"&&(u=r.toString());const c=this.codec.decode(u);f=this.msg.parse(c)}catch(u){const c=u instanceof Error?new Error(`failed to parse message: ${u.message}`):new Error("failed to parse message");this.mqtt.emit("error",c);return}this._dispatchMessage(e,f)}_dispatchMessage(e,r){}}class Mo extends Oo{constructor(){super(...arguments),this.subscriptions=new Map}async subscribe(e,...r){let o={},f=r[0];if(r.length===2&&typeof r[0]=="object"&&(o=r[0],f=r[1]),this.subscriptions.has(e))throw new Error(`subscribe: event "${e}" already subscribed`);const u=this.options.topicMake(e,"event-emission"),c=this.options.topicMake(e,"event-emission",this.options.id);await Promise.all([this._subscribeTopic(u,{qos:0,...o}),this._subscribeTopic(c,{qos:0,...o})]).catch(b=>{throw this._unsubscribeTopic(u).catch(()=>{}),this._unsubscribeTopic(c).catch(()=>{}),b}),this.subscriptions.set(e,f);const d=this;return{async unsubscribe(){if(!d.subscriptions.has(e))throw new Error(`unsubscribe: event "${e}" not subscribed`);return d.subscriptions.delete(e),Promise.all([d._unsubscribeTopic(u),d._unsubscribeTopic(c)]).then(()=>{})}}}emit(e,...r){let o,f,u,c={};typeof e=="object"&&e!==null?(o=e.event,f=e.params,u=e.receiver,c=e.options??{}):(o=e,f=r);const d=bt(),g=this.msg.makeEventEmission(d,o,f,this.options.id,u),b=this.codec.encode(g),p=this.options.topicMake(o,"event-emission",u);this.mqtt.publish(p,dt.from(b),{qos:0,...c})}_dispatchMessage(e,r){super._dispatchMessage(e,r);const o=this.options.topicMatch(e);if(o!==null&&o.operation==="event-emission"&&r instanceof oi){const f=r.event,u=this.subscriptions.get(f),c=r.params??[],d={sender:r.sender??""};r.receiver&&(d.receiver=r.receiver),Promise.resolve().then(()=>u?.(...c,d)).catch(g=>{this.mqtt.emit("error",g)})}}}class Do extends Mo{constructor(){super(...arguments),this.registrations=new Map,this.responseCallback=new Map,this.responseSubscriptions=new Map}async register(e,...r){let o={},f=r[0];if(r.length===2&&typeof r[0]=="object"&&(o=r[0],f=r[1]),this.registrations.has(e))throw new Error(`register: service "${e}" already registered`);const u=this.options.topicMake(e,"service-call-request"),c=this.options.topicMake(e,"service-call-request",this.options.id);await Promise.all([this._subscribeTopic(u,{qos:2,...o}),this._subscribeTopic(c,{qos:2,...o})]).catch(b=>{throw this._unsubscribeTopic(u).catch(()=>{}),this._unsubscribeTopic(c).catch(()=>{}),b}),this.registrations.set(e,f);const d=this;return{async unregister(){if(!d.registrations.has(e))throw new Error(`unregister: service "${e}" not registered`);return d.registrations.delete(e),Promise.all([d._unsubscribeTopic(u),d._unsubscribeTopic(c)]).then(()=>{})}}}call(e,...r){let o,f,u,c={};typeof e=="object"&&e!==null?(o=e.service,f=e.params,u=e.receiver,c=e.options??{}):(o=e,f=r);const d=bt();this._responseSubscribe(o,{qos:c.qos??2});const g=new Promise((O,q)=>{let k=setTimeout(()=>{this.responseCallback.delete(d),this._responseUnsubscribe(o),k=null,q(new Error("communication timeout"))},this.options.timeout);this.responseCallback.set(d,{service:o,callback:(W,j)=>{k!==null&&(clearTimeout(k),k=null),W?q(W):O(j)}})}),b=this.msg.makeServiceCallRequest(d,o,f,this.options.id,u),p=this.codec.encode(b),A=this.options.topicMake(o,"service-call-request",u);return this.mqtt.publish(A,dt.from(p),{qos:2,...c},O=>{if(O){const q=this.responseCallback.get(d);q!==void 0&&(this.responseCallback.delete(d),this._responseUnsubscribe(o),q.callback(O,void 0))}}),g}_responseSubscribe(e,r={qos:2}){const o=this.options.topicMake(e,"service-call-response",this.options.id);this.responseSubscriptions.has(o)||(this.responseSubscriptions.set(o,0),this.mqtt.subscribe(o,r,u=>{if(u){const c=this.responseSubscriptions.get(o)??0;c>1?this.responseSubscriptions.set(o,c-1):this.responseSubscriptions.delete(o),this.mqtt.emit("error",u)}}));const f=this.responseSubscriptions.get(o)??0;this.responseSubscriptions.set(o,f+1)}_responseUnsubscribe(e){const r=this.options.topicMake(e,"service-call-response",this.options.id);if(!this.responseSubscriptions.has(r))return;const o=this.responseSubscriptions.get(r)??0;o>1?this.responseSubscriptions.set(r,o-1):(this.responseSubscriptions.delete(r),this.mqtt.unsubscribe(r,f=>{f&&this.mqtt.emit("error",f)}))}_dispatchMessage(e,r){super._dispatchMessage(e,r);const o=this.options.topicMatch(e);if(o!==null&&o.operation==="service-call-request"&&r instanceof si){const f=r.id,u=r.service,c=this.registrations.get(u);let d;if(c!==void 0){const g=r.params??[],b={sender:r.sender??""};r.receiver&&(b.receiver=r.receiver),d=Promise.resolve().then(()=>c(...g,b))}else d=Promise.reject(new Error(`method not found: ${u}`));d.then(g=>this.msg.makeServiceCallResponse(f,g,void 0,this.options.id,r.sender),g=>{let b;return g==null?b="undefined error":typeof g=="string"?b=g:g instanceof Error?b=g.message:b=String(g),this.msg.makeServiceCallResponse(f,void 0,b,this.options.id,r.sender)}).then(g=>{const b=r.sender;if(b===void 0)throw new Error("invalid request: missing sender");const p=this.codec.encode(g),A=this.options.topicMake(u,"service-call-response",b);this.mqtt.publish(A,dt.from(p),{qos:2})}).catch(g=>{this.mqtt.emit("error",g)})}else if(o!==null&&o.operation==="service-call-response"&&o.peerId===this.options.id&&r instanceof ai){const f=r.id,u=this.responseCallback.get(f);u!==void 0&&(r.error!==void 0?u.callback(new Error(r.error),void 0):u.callback(void 0,r.result),this.responseCallback.delete(f),this._responseUnsubscribe(u.service))}}}class Co extends Do{constructor(){super(...arguments),this.provisionings=new Map,this.callbacks=new Map,this.pushStreams=new Map,this.pushTimers=new Map}async provision(e,...r){let o={},f=r[0];if(r.length===2&&typeof r[0]=="object"&&(o=r[0],f=r[1]),this.provisionings.has(e))throw new Error(`provision: resource "${e}" already provisioned`);const u=this.options.topicMake(e,"resource-transfer-request"),c=this.options.topicMake(e,"resource-transfer-request",this.options.id),d=this.options.topicMake(e,"resource-transfer-response"),g=this.options.topicMake(e,"resource-transfer-response",this.options.id);await Promise.all([this._subscribeTopic(u,{qos:2,...o}),this._subscribeTopic(c,{qos:2,...o}),this._subscribeTopic(d,{qos:2,...o}),this._subscribeTopic(g,{qos:2,...o})]).catch(A=>{throw this._unsubscribeTopic(u).catch(()=>{}),this._unsubscribeTopic(c).catch(()=>{}),this._unsubscribeTopic(d).catch(()=>{}),this._unsubscribeTopic(g).catch(()=>{}),A}),this.provisionings.set(e,f);const b=this;return{async unprovision(){if(!b.provisionings.has(e))throw new Error(`unprovision: resource "${e}" not provisioned`);return b.provisionings.delete(e),Promise.all([b._unsubscribeTopic(u),b._unsubscribeTopic(c),b._unsubscribeTopic(d),b._unsubscribeTopic(g)]).then(()=>{})}}}push(e,...r){let o,f,u,c,d,g={};typeof e=="object"&&e!==null?(o=e.resource,f=e.data,u=e.params,c=e.meta,d=e.receiver,g=e.options??{}):(o=e,f=r[0],u=r.slice(1));const b=bt(),p=this.options.topicMake(o,"resource-transfer-response",d);let A=!0;const O=(q,k,W)=>{const j=A?c:void 0;A=!1;const x=this.msg.makeResourceTransferResponse(b,o,u,q,j,k,W,this.options.id,d),R=this.codec.encode(x);this.mqtt.publish(p,dt.from(R),{qos:2,...g})};return new Promise((q,k)=>{f instanceof Dt.Readable?Tn(f,this.options.chunkSize,O,()=>q(),W=>k(W)):f instanceof Uint8Array&&(_n(f,this.options.chunkSize,O),q())})}async fetch(e,...r){let o,f,u={},c;typeof e=="object"&&e!==null?(o=e.resource,c=e.params,f=e.receiver,u=e.options??{}):(o=e,c=r);const d=bt(),g=this.options.topicMake(o,"resource-transfer-response",this.options.id);await this._subscribeTopic(g,{qos:2});const b=new Dt.Readable({read(I){}}),p=mn(b);let A;const O=new Promise(I=>{A=I});let q=null;const k=(I=!1)=>{q!==null&&(clearTimeout(q),q=null),this._unsubscribeTopic(g).catch(()=>{}),this.callbacks.delete(d),I&&A?.(void 0)};q=setTimeout(()=>{k(),A?.(void 0),b.destroy(new Error("communication timeout"))},this.options.timeout);let W=!0;this.callbacks.set(d,{resource:o,callback:(I,_,v,F)=>{W&&(W=!1,A?.(v)),I!==void 0?(k(!0),b.destroy(I)):(_!==void 0&&b.push(_),F&&(k(),b.push(null)))}});const j=this.msg.makeResourceTransferRequest(d,o,c,this.options.id,f),x=this.codec.encode(j),R=this.options.topicMake(o,"resource-transfer-request",f);return this.mqtt.publish(R,dt.from(x),{qos:2,...u}),{stream:b,buffer:p,meta:O}}_dispatchMessage(e,r){super._dispatchMessage(e,r);const o=this.options.topicMatch(e);if(o!==null&&o.operation==="resource-transfer-request"&&r instanceof ui){const f=r.resource,u=this.provisionings.get(f);if(u!==void 0){const c=r.id,d=r.resource,g=r.params??[],b=r.sender??"",p=r.receiver,A={sender:b};p&&(A.receiver=p);const O=this.options.topicMake(d,"resource-transfer-response",b);let q=!0;const k=(W,j,x)=>{const R=q?A.meta:void 0;q=!1;const I=this.msg.makeResourceTransferResponse(c,d,void 0,W,R,j,x,this.options.id,b),_=dt.from(this.codec.encode(I));this.mqtt.publish(O,_,{qos:2})};Promise.resolve().then(()=>u(...g,A)).then(async()=>{if(A.stream instanceof Dt.Readable)Tn(A.stream,this.options.chunkSize,k,()=>{},W=>k(void 0,W.message,!0));else if(A.buffer!==void 0&&typeof A.buffer.then=="function")_n(await A.buffer,this.options.chunkSize,k);else throw new Error("handler did not provide data via info.stream or info.buffer field")}).catch(W=>{k(void 0,W.message,!0)})}}else if(o!==null&&o.operation==="resource-transfer-response"&&r instanceof fi){const f=r.id,u=r.error,c=r.meta,d=r.final,g=r.chunk!==void 0&&!(r.chunk instanceof Uint8Array)?Uint8Array.from(r.chunk):r.chunk,b=this.callbacks.get(f);if(b!==void 0)b.callback(u?new Error(u):void 0,g,c,d);else if(r.resource!==void 0){const p=r.resource,A=this.provisionings.get(p);if(A!==void 0){let O=this.pushStreams.get(f);if(O===void 0){O=new Dt.Readable({read(R){}}),this.pushStreams.set(f,O);const k=setTimeout(()=>{const R=this.pushStreams.get(f);R!==void 0&&(R.destroy(new Error("push stream timeout")),this.pushStreams.delete(f),this.pushTimers.delete(f))},this.options.timeout);this.pushTimers.set(f,k);const W=mn(O),j=r.params??[],x={sender:r.sender??""};r.receiver&&(x.receiver=r.receiver),r.meta&&(x.meta=c),x.stream=O,x.buffer=W,Promise.resolve().then(()=>A(...j,x)).catch(R=>{this.mqtt.emit("error",R)})}const q=()=>{const k=this.pushTimers.get(f);k!==void 0&&(clearTimeout(k),this.pushTimers.delete(f))};u!==void 0?(q(),O.destroy(new Error(u)),this.pushStreams.delete(f)):(g!==void 0&&O.push(g),d&&(q(),O.push(null),this.pushStreams.delete(f)))}}}}}class Po extends Co{}return Po}));
|
package/package.json
CHANGED
package/src/mqtt-plus-codec.ts
CHANGED
|
@@ -34,7 +34,7 @@ class JSONX {
|
|
|
34
34
|
private static uint8ArrayToBase64 (arr: Uint8Array): string {
|
|
35
35
|
return btoa(String.fromCharCode(...arr))
|
|
36
36
|
}
|
|
37
|
-
private static base64ToUint8Array(base64: string): Uint8Array {
|
|
37
|
+
private static base64ToUint8Array (base64: string): Uint8Array {
|
|
38
38
|
const binary = atob(base64)
|
|
39
39
|
const arr = new Uint8Array(binary.length)
|
|
40
40
|
for (let i = 0; i < binary.length; i++)
|
|
@@ -50,7 +50,7 @@ class JSONX {
|
|
|
50
50
|
}
|
|
51
51
|
static parse (json: string): any {
|
|
52
52
|
return JSON.parse(json, (_, value) =>
|
|
53
|
-
value?.__Uint8Array
|
|
53
|
+
typeof value?.__Uint8Array === "string"
|
|
54
54
|
? this.base64ToUint8Array(value.__Uint8Array)
|
|
55
55
|
: value
|
|
56
56
|
)
|
package/src/mqtt-plus-service.ts
CHANGED
|
@@ -208,8 +208,14 @@ export class ServiceTrait<T extends APISchema = APISchema> extends EventTrait<T>
|
|
|
208
208
|
if (!this.responseSubscriptions.has(topic)) {
|
|
209
209
|
this.responseSubscriptions.set(topic, 0)
|
|
210
210
|
this.mqtt.subscribe(topic, options, (err: Error | null) => {
|
|
211
|
-
if (err)
|
|
211
|
+
if (err) {
|
|
212
|
+
const count = this.responseSubscriptions.get(topic) ?? 0
|
|
213
|
+
if (count > 1)
|
|
214
|
+
this.responseSubscriptions.set(topic, count - 1)
|
|
215
|
+
else
|
|
216
|
+
this.responseSubscriptions.delete(topic)
|
|
212
217
|
this.mqtt.emit("error", err)
|
|
218
|
+
}
|
|
213
219
|
})
|
|
214
220
|
}
|
|
215
221
|
const count = this.responseSubscriptions.get(topic) ?? 0
|
|
@@ -227,8 +233,9 @@ export class ServiceTrait<T extends APISchema = APISchema> extends EventTrait<T>
|
|
|
227
233
|
|
|
228
234
|
/* unsubscribe from MQTT topic and forget subscription */
|
|
229
235
|
const count = this.responseSubscriptions.get(topic) ?? 0
|
|
230
|
-
|
|
231
|
-
|
|
236
|
+
if (count > 1)
|
|
237
|
+
this.responseSubscriptions.set(topic, count - 1)
|
|
238
|
+
else {
|
|
232
239
|
this.responseSubscriptions.delete(topic)
|
|
233
240
|
this.mqtt.unsubscribe(topic, (err?: Error) => {
|
|
234
241
|
if (err)
|