@ikalogic/at1000 0.4.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/build/at1000-DbIvMQUc.cjs +8 -0
- package/build/at1000-DbIvMQUc.cjs.map +1 -0
- package/build/at1000-Zs18VzlP.mjs +8 -0
- package/build/at1000-Zs18VzlP.mjs.map +1 -0
- package/build/{at1000-B3HgANSi.d.mts → at1000-gm586Tc9.d.mts} +10 -16
- package/build/at1000-gm586Tc9.d.mts.map +1 -0
- package/build/{at1000-C6w5G8L4.d.cts → at1000-tUTVczQa.d.cts} +10 -16
- package/build/at1000-tUTVczQa.d.cts.map +1 -0
- package/build/browser.cjs +1 -1
- package/build/browser.cjs.map +1 -1
- package/build/browser.d.cts +5 -4
- package/build/browser.d.cts.map +1 -1
- package/build/browser.d.mts +5 -4
- package/build/browser.d.mts.map +1 -1
- package/build/browser.mjs +1 -1
- package/build/browser.mjs.map +1 -1
- package/build/{com-BLw4CGid.d.cts → com-DN1l6xqC.d.cts} +7 -3
- package/build/com-DN1l6xqC.d.cts.map +1 -0
- package/build/{com-BLw4CGid.d.mts → com-DN1l6xqC.d.mts} +7 -3
- package/build/com-DN1l6xqC.d.mts.map +1 -0
- package/build/com.cjs +1 -1
- package/build/com.cjs.map +1 -1
- package/build/com.d.cts +1 -1
- package/build/com.d.mts +1 -1
- package/build/com.mjs +1 -1
- package/build/com.mjs.map +1 -1
- package/build/common-BSrNhbq_.cjs +2 -0
- package/build/{common-BSabSaAU.cjs.map → common-BSrNhbq_.cjs.map} +1 -1
- package/build/{common-BY1vXz1l.d.cts → common-Cv6nZZS9.d.cts} +1 -2
- package/build/common-Cv6nZZS9.d.cts.map +1 -0
- package/build/{common-BY1vXz1l.d.mts → common-Cv6nZZS9.d.mts} +1 -2
- package/build/common-Cv6nZZS9.d.mts.map +1 -0
- package/build/{events-CBVQfojK.d.cts → events-Cf7iAMZP.d.cts} +4 -3
- package/build/events-Cf7iAMZP.d.cts.map +1 -0
- package/build/{events-CBVQfojK.d.mts → events-Cf7iAMZP.d.mts} +4 -3
- package/build/events-Cf7iAMZP.d.mts.map +1 -0
- package/build/events.cjs +1 -1
- package/build/events.d.cts +1 -1
- package/build/events.d.mts +1 -1
- package/build/events.mjs +1 -1
- package/build/{gpio-BuvDysYa.d.cts → gpio-CsxbjhA_.d.cts} +2 -3
- package/build/gpio-CsxbjhA_.d.cts.map +1 -0
- package/build/{gpio-DgQHE5fr.d.mts → gpio-Dk-s_yMc.d.mts} +2 -3
- package/build/gpio-Dk-s_yMc.d.mts.map +1 -0
- package/build/gpio.cjs +1 -1
- package/build/gpio.cjs.map +1 -1
- package/build/gpio.d.cts +2 -2
- package/build/gpio.d.mts +2 -2
- package/build/{hmi-BrdqKB3o.d.cts → hmi-B-potLdl.d.cts} +1 -2
- package/build/hmi-B-potLdl.d.cts.map +1 -0
- package/build/{hmi-BrdqKB3o.d.mts → hmi-B-potLdl.d.mts} +1 -2
- package/build/hmi-B-potLdl.d.mts.map +1 -0
- package/build/hmi.cjs +1 -1
- package/build/hmi.cjs.map +1 -1
- package/build/hmi.d.cts +1 -1
- package/build/hmi.d.mts +1 -1
- package/build/management.cjs +1 -1
- package/build/management.d.cts +20 -3
- package/build/management.d.cts.map +1 -1
- package/build/management.d.mts +20 -3
- package/build/management.d.mts.map +1 -1
- package/build/management.mjs +1 -1
- package/build/node.cjs +1 -1
- package/build/node.cjs.map +1 -1
- package/build/node.d.cts +16 -11
- package/build/node.d.cts.map +1 -1
- package/build/node.d.mts +16 -11
- package/build/node.d.mts.map +1 -1
- package/build/node.mjs +1 -1
- package/build/node.mjs.map +1 -1
- package/build/package-0hAwYBa1.cjs +2 -0
- package/build/package-0hAwYBa1.cjs.map +1 -0
- package/build/package-CU5MagIg.mjs +2 -0
- package/build/package-CU5MagIg.mjs.map +1 -0
- package/build/{power-FmknBUz2.d.cts → power-B8QFbKdP.d.cts} +2 -3
- package/build/power-B8QFbKdP.d.cts.map +1 -0
- package/build/{power-HWfK-Ybw.d.mts → power-BZmXOJyK.d.mts} +2 -3
- package/build/power-BZmXOJyK.d.mts.map +1 -0
- package/build/power.cjs +1 -1
- package/build/power.cjs.map +1 -1
- package/build/power.d.cts +2 -2
- package/build/power.d.mts +2 -2
- package/build/{relays-8EGNIK1T.d.cts → relays-TADiLsPk.d.cts} +1 -3
- package/build/relays-TADiLsPk.d.cts.map +1 -0
- package/build/{relays-8EGNIK1T.d.mts → relays-TADiLsPk.d.mts} +1 -3
- package/build/relays-TADiLsPk.d.mts.map +1 -0
- package/build/relays.cjs +1 -1
- package/build/relays.cjs.map +1 -1
- package/build/relays.d.cts +1 -1
- package/build/relays.d.mts +1 -1
- package/build/{session-D7TpUd6L.d.cts → session-qWW9mqWH.d.cts} +1 -2
- package/build/session-qWW9mqWH.d.cts.map +1 -0
- package/build/{session-D7TpUd6L.d.mts → session-qWW9mqWH.d.mts} +1 -2
- package/build/session-qWW9mqWH.d.mts.map +1 -0
- package/build/session.cjs +1 -1
- package/build/session.d.cts +1 -1
- package/build/session.d.mts +1 -1
- package/build/session.mjs +1 -1
- package/package.json +6 -2
- package/build/at1000-B3HgANSi.d.mts.map +0 -1
- package/build/at1000-B_udjy0I.cjs +0 -8
- package/build/at1000-B_udjy0I.cjs.map +0 -1
- package/build/at1000-BjVj0Ujk.mjs +0 -8
- package/build/at1000-BjVj0Ujk.mjs.map +0 -1
- package/build/at1000-C6w5G8L4.d.cts.map +0 -1
- package/build/com-BLw4CGid.d.cts.map +0 -1
- package/build/com-BLw4CGid.d.mts.map +0 -1
- package/build/common-BSabSaAU.cjs +0 -2
- package/build/common-BY1vXz1l.d.cts.map +0 -1
- package/build/common-BY1vXz1l.d.mts.map +0 -1
- package/build/events-CBVQfojK.d.cts.map +0 -1
- package/build/events-CBVQfojK.d.mts.map +0 -1
- package/build/gpio-BuvDysYa.d.cts.map +0 -1
- package/build/gpio-DgQHE5fr.d.mts.map +0 -1
- package/build/hmi-BrdqKB3o.d.cts.map +0 -1
- package/build/hmi-BrdqKB3o.d.mts.map +0 -1
- package/build/package-Bcvmz2Lx.cjs +0 -2
- package/build/package-Bcvmz2Lx.cjs.map +0 -1
- package/build/package-CN49oc-F.mjs +0 -2
- package/build/package-CN49oc-F.mjs.map +0 -1
- package/build/power-FmknBUz2.d.cts.map +0 -1
- package/build/power-HWfK-Ybw.d.mts.map +0 -1
- package/build/relays-8EGNIK1T.d.cts.map +0 -1
- package/build/relays-8EGNIK1T.d.mts.map +0 -1
- package/build/session-D7TpUd6L.d.cts.map +0 -1
- package/build/session-D7TpUd6L.d.mts.map +0 -1
- /package/build/{chunk-CMqjfN_6.cjs → rolldown-runtime-CMqjfN_6.cjs} +0 -0
package/build/node.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./package-CN49oc-F.mjs";import{a as t,d as n,i as r,n as i,r as a,t as o}from"./at1000-BjVj0Ujk.mjs";import{up as s}from"up-fetch";import{readFileSync as c}from"node:fs";import l,{hostname as u}from"node:os";import d from"dns-packet";import{EventEmitter as f}from"node:events";import p from"node:util";import m from"ip-address";import h from"node:dgram";const g=`224.0.0.251`,_=5353,v=`IPv4`,y=`IPv6`,b=[v,4,y,6];var x=class e{static getInterfaces(t){return t?e.getInterfacesFromStrings(t):e.getAllInterfaces()}static getAllInterfaces(){let e=[],t=[],n=l.networkInterfaces();for(let[r,i]of Object.entries(n))t.includes(r)||(t.push(r),i?.forEach(t=>{t.internal||!b.includes(t.family)||/^(2002|2001):/gi.exec(t.address)||e.push({name:r,address:t.address,family:t.family,scopeid:t.scopeid})}));if(!e.length)throw Error(`No usable network interfaces returned by OS.`);return e}static getInterfacesFromStrings(t){let n=Array.isArray(t)?t:[t],r=this.getAllInterfaces().filter(t=>n.reduce((n,r)=>n||!!(e.stringMatchesAddress(r,t.address)||t.name===r),!1));if(!r||!r.length)throw Error(`No usable network interfaces returned by OS.`);return r}static stringMatchesAddress(e,t){let n,r;try{n=new m.Address4(e),r=new m.Address4(t)}catch{try{n=new m.Address6(e),r=new m.Address6(t)}catch{return!1}}return n.bigInt()===r.bigInt()}};const S={interfaces:[],reuseAddr:!0,ttl:255,loopback:!0,onMessage:(e,t)=>{console.log(`Message `+e.toString())},socketError:e=>{console.log(`Socket error `+e.message)}};var C=class e{static validateSettings(e){if(!e.multicastAddress)throw Error(`Socket settings require multicastAddress`);if(!e.multicastPort)throw Error(`Socket settings require multicastPort`)}static createMulticastSocket(t){return new Promise((n,r)=>{let i=Object.assign({},S,t);e.validateSettings(i);let a=h.createSocket({type:m.Address4.isValid(i.multicastAddress)?`udp4`:`udp6`,reuseAddr:i.reuseAddr}),o=!1;a.on(`error`,e=>{o?i.socketError(e):(a.close(),n({success:!1,error:e}))}).on(`listening`,()=>{o=!0,a.setMulticastTTL(i.ttl??255),a.setMulticastLoopback(i.loopback??!0);let t=e.addMulticastMemberships(a,i);if(!t.memberships.length){o=!1,a.close(),n({success:!1,error:Error(`No interface memberships for multicast address `+i.multicastAddress)});return}n(Object.assign({success:!0},t,{socket:a}))}).on(`message`,(e,t)=>{i.onMessage(e,t)}),a.bind({port:i.multicastPort,exclusive:!1})})}static addMulticastMemberships(t,n){let r=[],i=[],a=m.Address4.isValid(n.multicastAddress)?[v,4]:[y,6];return n.interfaces.forEach(o=>{if(a.includes(o.family))try{t.addMembership(n.multicastAddress,e.interfaceAddress(o)),r.push(o)}catch{i.push(o)}}),{memberships:r,failedMemberships:i}}static async createSendSocket(t,n,r,i,a){return new Promise(o=>{let s=[`IPv4`,4].includes(t.family)?`udp4`:`udp6`,c=e.interfaceAddress(t),l=n.srcPort??0,u=!1,d=e=>{let l=h.createSocket({type:s,reuseAddr:!!n.reuseAddr,reusePort:!0}),f=!1;l.on(`error`,t=>{f?i(t):(l.close(),e!==0&&!u?(u=!0,a?.(`mDNS send socket bind to ${c}:${e} failed (${t.message}); falling back to ephemeral source port — discovery may be unreliable on strict firewalls.`),d(0)):o({success:!1,error:Error(t.message)}))}).on(`listening`,()=>{f=!0,o({success:!0,iface:t,socket:l,send:l.send.bind(l)})}).on(`message`,(e,n)=>{n.interface=t.name,r(e,n)}).bind(e,c)};d(l)})}static interfaceAddress(e){return[`IPv4`,4].includes(e.family)?e.address:e.scopeid?`${e.address}%${e.name}`:e.address}};const w={reuseAddr:!0,srcPort:5353,interfaces:null,ttl:255,loopback:!0,debug:!1};var T=class extends f{Config;ready;receiveSockets;sendSockets;interfaces;destroyed;constructor(e){super(),this.Config=Object.assign({},w,e),this.ready=!1,this.receiveSockets=[],this.sendSockets=[]}async init(){try{this.interfaces=x.getInterfaces(this.Config.interfaces||void 0)}catch(e){throw this.emitError(e),e}return this.emitDebug(`Scanner interfaces: ${p.inspect(this.interfaces)}`),await this.createReceiveSockets(),await this.createSendSockets(),this.receiveSockets.length&&this.sendSockets.length&&(this.ready=!0),this.ready}async createReceiveSockets(){if(!this.interfaces)return[];let e=this.interfaces.filter(e=>[v,4].includes(e.family)),t=this.interfaces.filter(e=>[y,6].includes(e.family));if(this.emitDebug(`Create receive sockets for${e.length?` IPv4`:``}${e.length&&t.length?` and`:``}${t.length?` IPv6`:``}`),e.length){let t=await C.createMulticastSocket({multicastAddress:g,multicastPort:_,interfaces:e,onMessage:this.onMessage.bind(this),socketError:this.socketError.bind(this)});t.success?this.receiveSockets.push(t):t.error&&this.emitWarn(t.error.message)}if(t.length){let e=await C.createMulticastSocket({multicastAddress:`FF02::FB`,multicastPort:_,interfaces:t,onMessage:this.onMessage.bind(this),socketError:this.socketError.bind(this)});e.success?this.receiveSockets.push(e):e.error&&this.emitWarn(e.error.message)}return this.receiveSockets}async createSendSockets(){if(this.interfaces){this.emitDebug(`Create send sockets on ${this.interfaces.length} interfaces/addresses.`);for(let e=0;e<this.interfaces.length;e++){let t=await C.createSendSocket(this.interfaces[e],this.Config,this.onMessage.bind(this),this.socketError.bind(this),this.emitWarn.bind(this));t.success?this.sendSockets.push(t):t.error&&this.emitWarn(t.error.message)}}}onMessage(e,t){let n;try{n=d.decode(e)}catch(e){return this.emitWarn(e)}this.emit(`packet`,n,t)}socketError(e){e.code===`EACCES`||e.code===`EADDRINUSE`||e.code===`EADDRNOTAVAIL`?this.emitError(e):this.emitWarn(e)}query(e,t){let n;if(typeof e==`string`)n=[{name:e,type:t||`ANY`}];else if(Array.isArray(e))n=e;else throw Error(`Query questions must be an array of mDNS query questions.`);let r={type:`query`,questions:n};this.emitDebug(`Send mDNS query: ${p.inspect(r)}`),this.send(r)}send(e){if(this.destroyed)return;let t=d.encode(e);e.type===`query`&&this.setUnicastResponseBit(t);for(let e=0;e<this.sendSockets.length;e++){let n=this.sendSockets[e];if(n.send&&n.iface)try{n.send(t,0,t.length,_,[`IPv4`,4].includes(n.iface.family)?g:`FF02::FB%`+n.iface.name),this.emitDebug(`Send packet on ${n.iface.address}`)}catch{}}}setUnicastResponseBit(e){let t=e.readUInt16BE(4),n=12;for(let r=0;r<t&&n<e.length;r++){for(;n<e.length&&e[n]!==0;)n+=e[n]+1;n+=1,n+=2,n<e.length&&(e[n]|=128),n+=2}}destroy(){this.destroyed=!0,this.ready=!1,this.removeAllListeners(),this.sendSockets.forEach(e=>{try{e.socket?.close()}catch{}}),this.sendSockets=[],this.receiveSockets.forEach(e=>{try{e.socket?.close()}catch{}}),this.receiveSockets=[]}emitError(e){this.emit(`error`,e)}emitWarn(e){this.emit(`warn`,e)}emitDebug(e){this.Config.debug&&this.emit(`debug`,e)}};const E={debug:!1};var D=class extends f{Config;scanner;types;namedServices;packetListener;constructor(e,t){super(),this.packetListener=this.onPacket.bind(this),this.scanner=e,this.Config=Object.assign({},E,t),this.types=[],this.namedServices={},this.forwardEvents(this.scanner),this.reset()}reset(){this.removeMDNSListener(this.scanner),this.types=[],this.namedServices={},this.listenMDNSEvents(this.scanner)}forwardEvents(e){e.on(`error`,e=>{this.emitError(e)}).on(`warn`,e=>{this.emitWarn(e)}).on(`debug`,e=>{this.emitDebug(e)})}listenMDNSEvents(e){e.on(`packet`,this.packetListener)}removeMDNSListener(e){e.removeListener(`packet`,this.packetListener)}onPacket(e,t){switch(this.emitDebug(`Received packet type ${e.type} from ${t.address}.`),e.type){case`query`:this.emit(`query`,e,t);break;case`response`:this.emitDebug(`Received response packet from ${t.address} with ${e.answers?e.answers.length:0} answers and ${e.additionals?e.additionals.length:0} additionals.`),e.answers&&this.processAnswers(e.answers,t),e.additionals&&this.processAnswers(e.additionals,t);break}}processAnswers(e,t){this.emitDebug(`Processing answers or additionals...`);let n=this.processSRVAnswers(e);this.processTXTAnswers(e),this.processAAnswers(e),this.processAAAAAnswers(e),this.processPTRAnswers(e,t),n.forEach(e=>{this.emit(`discovered`,{type:`service`,data:this.namedServices[e]})})}processSRVAnswers(e){let t=[];return e.forEach(e=>{if(e.type!==`SRV`)return;this.emitDebug(`Processing SRV answer.`);let n=e.name.toString();t.includes(n)||t.push(n),this.namedServices[n]=this.namedServices[n]||{},this.namedServices[n].service=e,this.namedServices[n].host=e.data.target.toString(),this.namedServices[n].port=e.data.port}),t}processTXTAnswers(e){e.forEach(e=>{if(e.type!==`TXT`)return;this.emitDebug(`Processing TXT answer.`);let t=e.data;if(Array.isArray(t)&&t.length>1){let n=e.name.toString();this.namedServices[n]=this.namedServices[n]||{},this.namedServices[n].txt=this.answerDataToKeyValues(Buffer.concat(t))}else if(Buffer.isBuffer(t)){let n=e.name.toString();this.namedServices[n]=this.namedServices[n]||{},this.namedServices[n].txt=this.answerDataToKeyValues(t)}})}processAAnswers(e){e.forEach(e=>{if(e.type!==`A`)return;this.emitDebug(`Processing A answer.`);let t=e.name.toString(),n=e.data.toString();for(let e in this.namedServices)this.namedServices[e].host===t&&(this.namedServices[e].addresses=this.namedServices[e].addresses||[],this.namedServices[e].addresses.reduce((e,t)=>e||t.address===n,!1)||this.namedServices[e].addresses.push({family:v,address:n}))})}processAAAAAnswers(e){e.forEach(e=>{if(e.type!==`AAAA`)return;this.emitDebug(`Processing AAAA answer.`);let t=e.name.toString(),n=e.data.toString();for(let e in this.namedServices)this.namedServices[e].host===t&&(this.namedServices[e].addresses=this.namedServices[e].addresses||[],this.namedServices[e].addresses.reduce((e,t)=>e||t.address===n,!1)||this.namedServices[e].addresses.push({family:y,address:n}))})}processPTRAnswers(e,t){e.forEach(e=>{if(e.type!==`PTR`)return;this.emitDebug(`Processing PTR answer.`);let n=this.serviceTypeFromPTR(e),r=e.data.toString();n!==r&&(this.namedServices[r]=this.namedServices[r]||{},this.namedServices[r].name=r.replace(`.`+n,``),this.namedServices[r].rinfo=t)})}serviceTypeFromPTR(e){let t=e.data,n=/(?:^|^.+?(?:\.))(_.*)$/gm.exec(t.toString()),r=n?n[1]:t.toString();return this.types.includes(r)||(this.types.push(r),this.emit(`discovered`,{type:`type`,data:r}),this.emitDebug(`Scanning service type ${r}.`),this.scanner.query(r,`ANY`)),r}answerDataToKeyValues(e){let t=[],n={},r=0,i=e[r];for(;i;){let a=e.slice(r+1,r+1+i);t.push(a.toString());let o=/^([^=]+)=([^=]*)$/.exec(a.toString());o&&(n[o[1]]=o[2]),r=r+1+i,i=e[r]}return{strings:t,keyValuePairs:n}}emitError(e){this.emit(`error`,e)}emitWarn(e){this.emit(`warn`,e)}emitDebug(e){this.Config.debug&&this.emit(`debug`,e)}};function O(e){return e.startsWith(`192.168.`)?0:e.startsWith(`169.254.`)?1:2}const k=async(e=500)=>{e<10&&(e=10);let r=new T({debug:!0}),i=new D(r);if(i.on(`error`,e=>{if(!e.includes(`bind ENOENT`))throw Error(e)}),!await r.init())throw Error(`Failed to initialize mDNS scanner`);r.query(`_at1000_server._tcp.local`),await new Promise(t=>setTimeout(t,e));let o=[...new Set(Object.values(i.namedServices).filter(e=>e.service!==void 0).filter(e=>(e.service?.name)?.endsWith(`_at1000_server._tcp.local`)).flatMap(e=>{let t=e.addresses??[],n=e.port,r=t.filter(e=>e.family===`IPv4`).map(e=>a(e.address,n)),i=t.filter(e=>e.family===`IPv6`).map(e=>a(e.address,n));return[...r,...i]}))];r.destroy();let c=(await Promise.allSettled(o.map(async e=>({host:e,info:await new n(s(fetch,()=>({baseUrl:`http://${a(e)}/v0`,timeout:1e3,parseRejected:(e,n)=>t(e,n.method)})),e).info()})))).filter(e=>e.status===`fulfilled`).map(e=>e.value),l=new Map;for(let e of c){let t=l.get(e.info.hostname);t?O(e.host)<O(t.host)&&l.set(e.info.hostname,e):l.set(e.info.hostname,e)}return[...l.values()]};var A=class extends o{static apiVersion=e;static findDevices(e=500){return k(e)}static async open(e,t){let n;try{let e=c(`/etc/at1000/project`,`utf8`).trim();n={kind:`project`,project:e,defaultLabel:e}}catch{n={kind:`remote`,defaultLabel:u()}}return await o.openBase(e,t,n)}};function j(){try{return c(`/etc/at1000/hostname`,`utf8`).trim()}catch{return}}export{A as AT1000,i as ApiError,a as format_host_for_url,r as host_without_port,j as readInjectedHostname};
|
|
1
|
+
import{t as e}from"./package-CU5MagIg.mjs";import{a as t,d as n,i as r,n as i,r as a,t as o}from"./at1000-Zs18VzlP.mjs";import{up as s}from"up-fetch";import c,{hostname as l}from"node:os";import{readFileSync as u}from"node:fs";import d from"dns-packet";import{EventEmitter as f}from"node:events";import p from"node:util";import m from"ip-address";import h from"node:dgram";const g=`224.0.0.251`,_=5353,v=`IPv4`,y=`IPv6`,b=[v,4,y,6];var x=class e{static getInterfaces(t){return t?e.getInterfacesFromStrings(t):e.getAllInterfaces()}static getAllInterfaces(){let e=[],t=[],n=c.networkInterfaces();for(let[r,i]of Object.entries(n))t.includes(r)||(t.push(r),i?.forEach(t=>{t.internal||!b.includes(t.family)||/^(2002|2001):/gi.exec(t.address)||e.push({name:r,address:t.address,family:t.family,scopeid:t.scopeid})}));if(!e.length)throw Error(`No usable network interfaces returned by OS.`);return e}static getInterfacesFromStrings(t){let n=Array.isArray(t)?t:[t],r=this.getAllInterfaces().filter(t=>n.reduce((n,r)=>n||!!(e.stringMatchesAddress(r,t.address)||t.name===r),!1));if(!r||!r.length)throw Error(`No usable network interfaces returned by OS.`);return r}static stringMatchesAddress(e,t){let n,r;try{n=new m.Address4(e),r=new m.Address4(t)}catch{try{n=new m.Address6(e),r=new m.Address6(t)}catch{return!1}}return n.bigInt()===r.bigInt()}};const S={interfaces:[],reuseAddr:!0,ttl:255,loopback:!0,onMessage:(e,t)=>{console.log(`Message `+e.toString())},socketError:e=>{console.log(`Socket error `+e.message)}};var C=class e{static validateSettings(e){if(!e.multicastAddress)throw Error(`Socket settings require multicastAddress`);if(!e.multicastPort)throw Error(`Socket settings require multicastPort`)}static createMulticastSocket(t){return new Promise((n,r)=>{let i=Object.assign({},S,t);e.validateSettings(i);let a=h.createSocket({type:m.Address4.isValid(i.multicastAddress)?`udp4`:`udp6`,reuseAddr:i.reuseAddr}),o=!1;a.on(`error`,e=>{o?i.socketError(e):(a.close(),n({success:!1,error:e}))}).on(`listening`,()=>{o=!0,a.setMulticastTTL(i.ttl??255),a.setMulticastLoopback(i.loopback??!0);let t=e.addMulticastMemberships(a,i);if(!t.memberships.length){o=!1,a.close(),n({success:!1,error:Error(`No interface memberships for multicast address `+i.multicastAddress)});return}n(Object.assign({success:!0},t,{socket:a}))}).on(`message`,(e,t)=>{i.onMessage(e,t)}),a.bind({port:i.multicastPort,exclusive:!1})})}static addMulticastMemberships(t,n){let r=[],i=[],a=m.Address4.isValid(n.multicastAddress)?[v,4]:[y,6];return n.interfaces.forEach(o=>{if(a.includes(o.family))try{t.addMembership(n.multicastAddress,e.interfaceAddress(o)),r.push(o)}catch{i.push(o)}}),{memberships:r,failedMemberships:i}}static async createSendSocket(t,n,r,i,a){return new Promise(o=>{let s=[`IPv4`,4].includes(t.family)?`udp4`:`udp6`,c=e.interfaceAddress(t),l=n.srcPort??0,u=!1,d=e=>{let l=h.createSocket({type:s,reuseAddr:!!n.reuseAddr,reusePort:!0}),f=!1;l.on(`error`,t=>{f?i(t):(l.close(),e!==0&&!u?(u=!0,a?.(`mDNS send socket bind to ${c}:${e} failed (${t.message}); falling back to ephemeral source port — discovery may be unreliable on strict firewalls.`),d(0)):o({success:!1,error:Error(t.message)}))}).on(`listening`,()=>{f=!0,o({success:!0,iface:t,socket:l,send:l.send.bind(l)})}).on(`message`,(e,n)=>{n.interface=t.name,r(e,n)}).bind(e,c)};d(l)})}static interfaceAddress(e){return[`IPv4`,4].includes(e.family)?e.address:e.scopeid?`${e.address}%${e.name}`:e.address}};const w={reuseAddr:!0,srcPort:5353,interfaces:null,ttl:255,loopback:!0,debug:!1};var T=class extends f{Config;ready;receiveSockets;sendSockets;interfaces;destroyed;constructor(e){super(),this.Config=Object.assign({},w,e),this.ready=!1,this.receiveSockets=[],this.sendSockets=[]}async init(){try{this.interfaces=x.getInterfaces(this.Config.interfaces||void 0)}catch(e){throw this.emitError(e),e}return this.emitDebug(`Scanner interfaces: ${p.inspect(this.interfaces)}`),await this.createReceiveSockets(),await this.createSendSockets(),this.receiveSockets.length&&this.sendSockets.length&&(this.ready=!0),this.ready}async createReceiveSockets(){if(!this.interfaces)return[];let e=this.interfaces.filter(e=>[v,4].includes(e.family)),t=this.interfaces.filter(e=>[y,6].includes(e.family));if(this.emitDebug(`Create receive sockets for${e.length?` IPv4`:``}${e.length&&t.length?` and`:``}${t.length?` IPv6`:``}`),e.length){let t=await C.createMulticastSocket({multicastAddress:g,multicastPort:_,interfaces:e,onMessage:this.onMessage.bind(this),socketError:this.socketError.bind(this)});t.success?this.receiveSockets.push(t):t.error&&this.emitWarn(t.error.message)}if(t.length){let e=await C.createMulticastSocket({multicastAddress:`FF02::FB`,multicastPort:_,interfaces:t,onMessage:this.onMessage.bind(this),socketError:this.socketError.bind(this)});e.success?this.receiveSockets.push(e):e.error&&this.emitWarn(e.error.message)}return this.receiveSockets}async createSendSockets(){if(this.interfaces){this.emitDebug(`Create send sockets on ${this.interfaces.length} interfaces/addresses.`);for(let e=0;e<this.interfaces.length;e++){let t=await C.createSendSocket(this.interfaces[e],this.Config,this.onMessage.bind(this),this.socketError.bind(this),this.emitWarn.bind(this));t.success?this.sendSockets.push(t):t.error&&this.emitWarn(t.error.message)}}}onMessage(e,t){let n;try{n=d.decode(e)}catch(e){return this.emitWarn(e)}this.emit(`packet`,n,t)}socketError(e){e.code===`EACCES`||e.code===`EADDRINUSE`||e.code===`EADDRNOTAVAIL`?this.emitError(e):this.emitWarn(e)}query(e,t){let n;if(typeof e==`string`)n=[{name:e,type:t||`ANY`}];else if(Array.isArray(e))n=e;else throw Error(`Query questions must be an array of mDNS query questions.`);let r={type:`query`,questions:n};this.emitDebug(`Send mDNS query: ${p.inspect(r)}`),this.send(r)}send(e){if(this.destroyed)return;let t=d.encode(e);e.type===`query`&&this.setUnicastResponseBit(t);for(let e=0;e<this.sendSockets.length;e++){let n=this.sendSockets[e];if(n.send&&n.iface)try{n.send(t,0,t.length,_,[`IPv4`,4].includes(n.iface.family)?g:`FF02::FB%`+n.iface.name),this.emitDebug(`Send packet on ${n.iface.address}`)}catch{}}}setUnicastResponseBit(e){let t=e.readUInt16BE(4),n=12;for(let r=0;r<t&&n<e.length;r++){for(;n<e.length&&e[n]!==0;)n+=e[n]+1;n+=1,n+=2,n<e.length&&(e[n]|=128),n+=2}}destroy(){this.destroyed=!0,this.ready=!1,this.removeAllListeners(),this.sendSockets.forEach(e=>{try{e.socket?.close()}catch{}}),this.sendSockets=[],this.receiveSockets.forEach(e=>{try{e.socket?.close()}catch{}}),this.receiveSockets=[]}emitError(e){this.emit(`error`,e)}emitWarn(e){this.emit(`warn`,e)}emitDebug(e){this.Config.debug&&this.emit(`debug`,e)}};const E={debug:!1};var D=class extends f{Config;scanner;types;namedServices;packetListener;constructor(e,t){super(),this.packetListener=this.onPacket.bind(this),this.scanner=e,this.Config=Object.assign({},E,t),this.types=[],this.namedServices={},this.forwardEvents(this.scanner),this.reset()}reset(){this.removeMDNSListener(this.scanner),this.types=[],this.namedServices={},this.listenMDNSEvents(this.scanner)}forwardEvents(e){e.on(`error`,e=>{this.emitError(e)}).on(`warn`,e=>{this.emitWarn(e)}).on(`debug`,e=>{this.emitDebug(e)})}listenMDNSEvents(e){e.on(`packet`,this.packetListener)}removeMDNSListener(e){e.removeListener(`packet`,this.packetListener)}onPacket(e,t){switch(this.emitDebug(`Received packet type ${e.type} from ${t.address}.`),e.type){case`query`:this.emit(`query`,e,t);break;case`response`:this.emitDebug(`Received response packet from ${t.address} with ${e.answers?e.answers.length:0} answers and ${e.additionals?e.additionals.length:0} additionals.`),e.answers&&this.processAnswers(e.answers,t),e.additionals&&this.processAnswers(e.additionals,t);break}}processAnswers(e,t){this.emitDebug(`Processing answers or additionals...`);let n=this.processSRVAnswers(e);this.processTXTAnswers(e),this.processAAnswers(e),this.processAAAAAnswers(e),this.processPTRAnswers(e,t),n.forEach(e=>{this.emit(`discovered`,{type:`service`,data:this.namedServices[e]})})}processSRVAnswers(e){let t=[];return e.forEach(e=>{if(e.type!==`SRV`)return;this.emitDebug(`Processing SRV answer.`);let n=e.name.toString();t.includes(n)||t.push(n),this.namedServices[n]=this.namedServices[n]||{},this.namedServices[n].service=e,this.namedServices[n].host=e.data.target.toString(),this.namedServices[n].port=e.data.port}),t}processTXTAnswers(e){e.forEach(e=>{if(e.type!==`TXT`)return;this.emitDebug(`Processing TXT answer.`);let t=e.data;if(Array.isArray(t)&&t.length>1){let n=e.name.toString();this.namedServices[n]=this.namedServices[n]||{},this.namedServices[n].txt=this.answerDataToKeyValues(Buffer.concat(t))}else if(Buffer.isBuffer(t)){let n=e.name.toString();this.namedServices[n]=this.namedServices[n]||{},this.namedServices[n].txt=this.answerDataToKeyValues(t)}})}processAAnswers(e){e.forEach(e=>{if(e.type!==`A`)return;this.emitDebug(`Processing A answer.`);let t=e.name.toString(),n=e.data.toString();for(let e in this.namedServices)this.namedServices[e].host===t&&(this.namedServices[e].addresses=this.namedServices[e].addresses||[],this.namedServices[e].addresses.reduce((e,t)=>e||t.address===n,!1)||this.namedServices[e].addresses.push({family:v,address:n}))})}processAAAAAnswers(e){e.forEach(e=>{if(e.type!==`AAAA`)return;this.emitDebug(`Processing AAAA answer.`);let t=e.name.toString(),n=e.data.toString();for(let e in this.namedServices)this.namedServices[e].host===t&&(this.namedServices[e].addresses=this.namedServices[e].addresses||[],this.namedServices[e].addresses.reduce((e,t)=>e||t.address===n,!1)||this.namedServices[e].addresses.push({family:y,address:n}))})}processPTRAnswers(e,t){e.forEach(e=>{if(e.type!==`PTR`)return;this.emitDebug(`Processing PTR answer.`);let n=this.serviceTypeFromPTR(e),r=e.data.toString();n!==r&&(this.namedServices[r]=this.namedServices[r]||{},this.namedServices[r].name=r.replace(`.`+n,``),this.namedServices[r].rinfo=t)})}serviceTypeFromPTR(e){let t=e.data,n=/(?:^|^.+?(?:\.))(_.*)$/gm.exec(t.toString()),r=n?n[1]:t.toString();return this.types.includes(r)||(this.types.push(r),this.emit(`discovered`,{type:`type`,data:r}),this.emitDebug(`Scanning service type ${r}.`),this.scanner.query(r,`ANY`)),r}answerDataToKeyValues(e){let t=[],n={},r=0,i=e[r];for(;i;){let a=e.slice(r+1,r+1+i);t.push(a.toString());let o=/^([^=]+)=([^=]*)$/.exec(a.toString());o&&(n[o[1]]=o[2]),r=r+1+i,i=e[r]}return{strings:t,keyValuePairs:n}}emitError(e){this.emit(`error`,e)}emitWarn(e){this.emit(`warn`,e)}emitDebug(e){this.Config.debug&&this.emit(`debug`,e)}};function O(e){return e.startsWith(`192.168.`)?0:e.startsWith(`169.254.`)?1:2}function k(){try{return u(`/etc/at1000/hostname`,`utf8`).trim()||void 0}catch{return}}function A(){try{return u(`/etc/at1000/project`,`utf8`).trim()||void 0}catch{return}}async function j(e){return{host:e,info:await new n(s(fetch,()=>({baseUrl:`http://${a(e)}/v0`,timeout:1e3,parseRejected:(e,n)=>t(e,n.method)})),e).info()}}const M=async()=>{let e=k();if(e)for(let t of[`${e}.local`,`host.containers.internal`])try{if((await j(t)).info.hostname===e)return t}catch{}},N=async(e=500)=>{e<10&&(e=10);let t=new T({debug:!0}),n=new D(t);if(n.on(`error`,e=>{if(!e.includes(`bind ENOENT`))throw Error(e)}),!await t.init())throw Error(`Failed to initialize mDNS scanner`);t.query(`_at1000_server._tcp.local`),await new Promise(t=>setTimeout(t,e));let r=[...new Set(Object.values(n.namedServices).filter(e=>e.service!==void 0).filter(e=>(e.service?.name)?.endsWith(`_at1000_server._tcp.local`)).flatMap(e=>{let t=e.addresses??[],n=e.port,r=t.filter(e=>e.family===`IPv4`).map(e=>a(e.address,n)),i=t.filter(e=>e.family===`IPv6`).map(e=>a(e.address,n));return[...r,...i]}))];t.destroy();let i=(await Promise.allSettled(r.map(j))).filter(e=>e.status===`fulfilled`).map(e=>e.value),o=new Map;for(let e of i){let t=o.get(e.info.hostname);t?O(e.host)<O(t.host)&&o.set(e.info.hostname,e):o.set(e.info.hostname,e)}let s=[...o.values()],c=k();if(!c)return s.map(e=>e.host);let l=s.findIndex(e=>e.info.hostname===c);if(l>=0)return s.unshift(...s.splice(l,1)),s.map(e=>e.host);let u=await M();return u?[u,...s.map(e=>e.host)]:s.map(e=>e.host)};var P=class extends o{static apiVersion=e;static findDevices(e=500){return N(e)}static isStandalone(){return A()!==void 0}static findLocalDevice(){return M()}static async open(e,t){let n=A(),r=n?{kind:`project`,project:n,defaultLabel:n}:{kind:`remote`,defaultLabel:l()};return await o.openBase(e,t,r)}};export{P as AT1000,i as ApiError,a as format_host_for_url,r as host_without_port};
|
|
2
2
|
//# sourceMappingURL=node.mjs.map
|
package/build/node.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.mjs","names":["Constants.IPv4","Constants.IPv6","Constants.IPv4","Constants.IPv6","Defaults","Constants.IPv4","Constants.IPv6","Constants.MDNS_IPV4","Constants.MDNS_PORT","Constants.MDNS_IPV6","Constants.IPv4","Constants.IPv6","Scanner","Services"],"sources":["../src/mdns-scanner/constants.ts","../src/mdns-scanner/interfaces.ts","../src/mdns-scanner/sockets.ts","../src/mdns-scanner/scanner.ts","../src/mdns-scanner/services.ts","../src/discovery.ts","../src/node.ts"],"sourcesContent":["export const MDNS_IPV4 = '224.0.0.251';\nexport const MDNS_IPV6 = 'FF02::FB';\nexport const MDNS_PORT = 5353;\nexport const IPv4 = 'IPv4';\nexport const IPv4_INT = 4; // beginning in node 18 family is integer\nexport const IPv6 = 'IPv6';\nexport const IPv6_INT = 6; // beginning in node 18 family is integer\nexport const ANY_IPV4 = '0.0.0.0';\nexport const ANY_IPV6 = '::';\n\nexport const ErrorMessages = { NO_INTERFACES: 'No available interfaces.' };\n","import IP from 'ip-address';\nimport OS from 'node:os';\nimport * as Constants from './constants.js';\n\nconst SupportedFamilies = [Constants.IPv4, Constants.IPv4_INT, Constants.IPv6, Constants.IPv6_INT];\n\nexport interface NetworkInterface {\n name: string;\n address: string;\n family: string | number;\n scopeid?: number;\n}\n\nclass Interfaces {\n // select appropriate method based on argument\n static getInterfaces(interfaceStrings?: string | string[]): NetworkInterface[] {\n return (!interfaceStrings\n ? Interfaces.getAllInterfaces()\n : Interfaces.getInterfacesFromStrings(interfaceStrings));\n }\n\n // get all usable interfaces from OS\n static getAllInterfaces(): NetworkInterface[] {\n const interfaces: NetworkInterface[] = [];\n const names: string[] = [];\n const osInterfaces = OS.networkInterfaces();\n for (const [name, iface] of Object.entries(osInterfaces)) {\n if (names.includes(name)) {\n continue;\n }\n names.push(name);\n iface?.forEach((assignment) => {\n // check if interface is usable\n if (\n assignment.internal // cannot use internal\n || !SupportedFamilies.includes(assignment.family) // can only use IPv4 and IPv6 family\n || /^(2002|2001):/ig.exec(assignment.address) // cannot use IPv6 special prefix\n ) return;\n interfaces.push({\n name: name,\n address: assignment.address,\n family: assignment.family,\n scopeid: assignment.scopeid,\n });\n });\n }\n if (!interfaces.length) throw new Error('No usable network interfaces returned by OS.');\n return interfaces;\n }\n\n // get interfaces from configuration strings\n static getInterfacesFromStrings(interfaceStrings: string | string[]): NetworkInterface[] {\n const interfaceArray = Array.isArray(interfaceStrings) ? interfaceStrings : [interfaceStrings];\n const interfaces = this.getAllInterfaces().filter((iface) => {\n return interfaceArray.reduce((result, interfaceString) => {\n // return result || (((IP.isV4Format(interfaceString) || IP.isV6Format(interfaceString)) && IP.isEqual(iface.address, interfaceString)) || iface.name === interfaceString ? true : false);\n return result\n || (Interfaces.stringMatchesAddress(interfaceString, iface.address)\n || iface.name === interfaceString\n ? true\n : false);\n }, false);\n });\n if (!interfaces || !interfaces.length) {\n throw new Error('No usable network interfaces returned by OS.');\n }\n return interfaces;\n }\n\n // compare interface settings string to os interface address\n static stringMatchesAddress(ifaceString: string, address: string): boolean {\n // try to create address objects\n let stringAddress: IP.Address4 | IP.Address6;\n let addressAddress: IP.Address4 | IP.Address6;\n try {\n stringAddress = new IP.Address4(ifaceString);\n addressAddress = new IP.Address4(address);\n // oxlint-disable-next-line no-unused-vars\n } catch (e) {\n try {\n stringAddress = new IP.Address6(ifaceString);\n addressAddress = new IP.Address6(address);\n // oxlint-disable-next-line no-unused-vars\n } catch (e) {\n return false;\n }\n }\n // compare addresses\n return stringAddress.bigInt() === addressAddress.bigInt();\n }\n}\n\nexport default Interfaces;\n","import IP from 'ip-address';\nimport type { RemoteInfo, Socket as DgramSocket } from 'node:dgram';\nimport DGram from 'node:dgram';\nimport * as Constants from './constants.js';\nimport type { NetworkInterface } from './interfaces.js';\n\nexport interface MulticastSettings {\n multicastAddress: string;\n multicastPort: number;\n interfaces: NetworkInterface[];\n reuseAddr?: boolean;\n ttl?: number;\n loopback?: boolean;\n onMessage: (message: Buffer, rinfo: RemoteInfo) => void;\n socketError: (error: Error) => void;\n}\n\nexport interface SendSocketSettings {\n reuseAddr?: boolean;\n srcPort?: number;\n}\n\nexport interface SocketResult {\n success: boolean;\n socket?: DgramSocket;\n memberships?: NetworkInterface[];\n failedMemberships?: NetworkInterface[];\n error?: Error;\n iface?: NetworkInterface;\n send?: (...args: any[]) => void;\n}\n\nconst MulticastDefaults = {\n interfaces: [],\n reuseAddr: true,\n ttl: 255,\n loopback: true,\n onMessage: (message: Buffer, _rinfo: RemoteInfo) => {\n console.log('Message ' + message.toString());\n },\n socketError: (error: Error) => {\n console.log('Socket error ' + error.message);\n },\n};\n\nclass Sockets {\n static validateSettings(settings: Partial<MulticastSettings>): void {\n if (!settings.multicastAddress) {\n throw new Error('Socket settings require multicastAddress');\n }\n if (!settings.multicastPort) {\n throw new Error('Socket settings require multicastPort');\n }\n }\n\n // create a multicast socket and add interfaces to group membership\n static createMulticastSocket(settings: Partial<MulticastSettings>): Promise<SocketResult> {\n return new Promise((resolve, _reject) => {\n const mergedSettings = Object.assign({}, MulticastDefaults, settings) as MulticastSettings;\n Sockets.validateSettings(mergedSettings);\n // create multicast socket to listen for packets\n const socket = DGram.createSocket({\n type: IP.Address4.isValid(mergedSettings.multicastAddress) ? 'udp4' : 'udp6',\n reuseAddr: mergedSettings.reuseAddr,\n });\n // track bind status with local variable\n let isListening = false;\n // add event listeners to socket\n socket\n .on('error', (error) => {\n if (isListening) {\n mergedSettings.socketError(error);\n } else {\n socket.close();\n resolve({ success: false, error: error });\n }\n })\n .on('listening', () => {\n isListening = true;\n socket.setMulticastTTL(mergedSettings.ttl ?? 255);\n socket.setMulticastLoopback(mergedSettings.loopback ?? true);\n const result = Sockets.addMulticastMemberships(socket, mergedSettings);\n if (!result.memberships.length) {\n isListening = false;\n socket.close();\n resolve({\n success: false,\n error: new Error(\n 'No interface memberships for multicast address ' + mergedSettings.multicastAddress,\n ),\n });\n return;\n }\n resolve(Object.assign({ success: true }, result, { socket }));\n })\n .on('message', (msg, rinfo) => {\n mergedSettings.onMessage(msg, rinfo);\n });\n // bind socket\n socket.bind({ port: mergedSettings.multicastPort, exclusive: false });\n });\n }\n\n // add interfaces to multicast membership group on socket\n static addMulticastMemberships(\n socket: DgramSocket,\n settings: MulticastSettings,\n ): { memberships: NetworkInterface[]; failedMemberships: NetworkInterface[] } {\n const memberships: NetworkInterface[] = [];\n const failedMemberships: NetworkInterface[] = [];\n const family = IP.Address4.isValid(settings.multicastAddress)\n ? [Constants.IPv4, Constants.IPv4_INT]\n : [Constants.IPv6, Constants.IPv6_INT];\n settings.interfaces.forEach((iface) => {\n if (!family.includes(iface.family)) return; // unsupported family\n try {\n socket.addMembership(settings.multicastAddress, Sockets.interfaceAddress(iface));\n memberships.push(iface);\n // oxlint-disable-next-line no-unused-vars\n } catch (error) {\n failedMemberships.push(iface);\n }\n });\n return { memberships, failedMemberships };\n }\n\n // create a socket to be used when sending mDNS packets\n static async createSendSocket(\n iface: NetworkInterface,\n settings: SendSocketSettings,\n onMessage: (message: Buffer, rinfo: RemoteInfo) => void,\n socketError: (error: Error) => void,\n emitWarn?: (message: string) => void,\n ): Promise<SocketResult> {\n return new Promise((resolve) => {\n const type = [Constants.IPv4, Constants.IPv4_INT].includes(iface.family) ? 'udp4' : 'udp6';\n const ifaceAddr = Sockets.interfaceAddress(iface);\n const desiredPort = settings.srcPort ?? 0;\n let fellBack = false;\n\n const attempt = (port: number): void => {\n // RFC 6762 §5/§6: full mDNS participants send from sport=5353 so responders\n // multicast the reply back to 224.0.0.251:5353. Binding to the interface\n // address with SO_REUSEADDR+SO_REUSEPORT lets us coexist with avahi/Bonjour\n // already holding 0.0.0.0:5353.\n const socket = DGram.createSocket({\n type,\n reuseAddr: settings.reuseAddr ? true : false,\n reusePort: true,\n });\n let bound = false;\n socket\n .on('error', (error) => {\n if (!bound) {\n socket.close();\n if (port !== 0 && !fellBack) {\n fellBack = true;\n emitWarn?.(\n `mDNS send socket bind to ${ifaceAddr}:${port} failed (${error.message}); falling back to ephemeral source port — discovery may be unreliable on strict firewalls.`,\n );\n attempt(0);\n } else {\n resolve({ success: false, error: new Error(error.message) });\n }\n } else {\n socketError(error);\n }\n })\n .on('listening', () => {\n bound = true;\n resolve({ success: true, iface, socket, send: socket.send.bind(socket) });\n })\n .on('message', (msg, rinfo: RemoteInfo & { interface?: string }) => {\n // include interface name so we know where the message came in\n rinfo.interface = iface.name;\n onMessage(msg, rinfo);\n })\n .bind(port, ifaceAddr);\n };\n\n attempt(desiredPort);\n });\n }\n\n // format an interface address for mDNS socket\n static interfaceAddress(iface: NetworkInterface): string {\n // IPv4 addresses don't need scope\n if ([Constants.IPv4, Constants.IPv4_INT].includes(iface.family)) {\n return iface.address;\n }\n // For IPv6 link-local addresses (scopeid > 0), append the interface NAME as the\n // zone. Node/libuv uv_ip6_addr resolves the zone via if_nametoindex() on\n // Linux/macOS, which fails for a numeric scope id (yields scope 0 -> bind EINVAL).\n if (iface.scopeid) {\n return `${iface.address}%${iface.name}`;\n }\n return iface.address;\n }\n}\n\nexport default Sockets;\n","import type { Packet, Question, RecordType } from 'dns-packet';\nimport DNSPacket from 'dns-packet';\nimport type { RemoteInfo } from 'node:dgram';\nimport { EventEmitter } from 'node:events';\nimport Util from 'node:util';\nimport * as Constants from './constants.js';\nimport type { NetworkInterface } from './interfaces.js';\nimport Interfaces from './interfaces.js';\nimport type { SocketResult } from './sockets.js';\nimport Sockets from './sockets.js';\n\nexport interface ScannerConfig {\n reuseAddr?: boolean;\n srcPort?: number;\n interfaces?: string | string[] | null;\n ttl?: number;\n loopback?: boolean;\n debug?: boolean;\n}\n\ntype Socket = SocketResult;\n\nconst Defaults: Required<ScannerConfig> = {\n reuseAddr: true,\n srcPort: 5353,\n interfaces: null,\n ttl: 255,\n loopback: true,\n debug: false,\n};\n\nclass MDNSScanner extends EventEmitter {\n Config: Required<ScannerConfig>;\n ready: boolean;\n receiveSockets: Socket[];\n sendSockets: Socket[];\n interfaces?: NetworkInterface[];\n destroyed?: boolean;\n\n constructor(config?: ScannerConfig) {\n super();\n this.Config = Object.assign({}, Defaults, config);\n this.ready = false;\n this.receiveSockets = [];\n this.sendSockets = [];\n }\n\n // initialize the scanner\n async init(): Promise<boolean> {\n try {\n this.interfaces = Interfaces.getInterfaces(this.Config.interfaces || undefined);\n } catch (error) {\n this.emitError(error);\n throw error;\n }\n this.emitDebug(`Scanner interfaces: ${Util.inspect(this.interfaces)}`);\n await this.createReceiveSockets();\n await this.createSendSockets();\n if (this.receiveSockets.length && this.sendSockets.length) this.ready = true;\n return this.ready;\n }\n\n // create sockets that will receive mDNS packets\n async createReceiveSockets(): Promise<Socket[]> {\n if (!this.interfaces) return [];\n const ipv4 = this.interfaces.filter(i =>\n [Constants.IPv4, Constants.IPv4_INT].includes(i.family)\n );\n const ipv6 = this.interfaces.filter(i =>\n [Constants.IPv6, Constants.IPv6_INT].includes(i.family)\n );\n this.emitDebug(\n `Create receive sockets for${ipv4.length ? ' ' + Constants.IPv4 : ''}${\n ipv4.length && ipv6.length\n ? ' and'\n : ''\n }${ipv6.length ? ' ' + Constants.IPv6 : ''}`,\n );\n if (ipv4.length) {\n const ipv4Socket = await Sockets.createMulticastSocket({\n multicastAddress: Constants.MDNS_IPV4,\n multicastPort: Constants.MDNS_PORT,\n interfaces: ipv4,\n onMessage: this.onMessage.bind(this),\n socketError: this.socketError.bind(this),\n });\n if (ipv4Socket.success) this.receiveSockets.push(ipv4Socket);\n else if (ipv4Socket.error) this.emitWarn(ipv4Socket.error.message);\n }\n if (ipv6.length) {\n const ipv6Socket = await Sockets.createMulticastSocket({\n multicastAddress: Constants.MDNS_IPV6,\n multicastPort: Constants.MDNS_PORT,\n interfaces: ipv6,\n onMessage: this.onMessage.bind(this),\n socketError: this.socketError.bind(this),\n });\n if (ipv6Socket.success) this.receiveSockets.push(ipv6Socket);\n else if (ipv6Socket.error) this.emitWarn(ipv6Socket.error.message);\n }\n return this.receiveSockets;\n }\n\n // create sockets used to send out mDNS packets\n async createSendSockets(): Promise<void> {\n if (!this.interfaces) return;\n this.emitDebug(`Create send sockets on ${this.interfaces.length} interfaces/addresses.`);\n for (let i = 0; i < this.interfaces.length; i++) {\n const sendSocket = await Sockets.createSendSocket(\n this.interfaces[i],\n this.Config,\n this.onMessage.bind(this),\n this.socketError.bind(this),\n this.emitWarn.bind(this),\n );\n if (sendSocket.success) this.sendSockets.push(sendSocket);\n else if (sendSocket.error) this.emitWarn(sendSocket.error.message);\n }\n }\n\n // handle receive socket message\n onMessage(message: Buffer, rinfo: RemoteInfo): void {\n let packet: Packet;\n try {\n packet = DNSPacket.decode(message);\n } catch (error) {\n return this.emitWarn(error);\n }\n this.emit('packet', packet, rinfo);\n }\n\n // handle socket errors\n socketError(error: any): void {\n if (error.code === 'EACCES' || error.code === 'EADDRINUSE' || error.code === 'EADDRNOTAVAIL') {\n this.emitError(error);\n } else {\n this.emitWarn(error);\n }\n }\n\n // send an mDNS query, questions can be an array of formatted questions or a single question name string, qtype is optionally used with name string\n // oxlint-disable-next-line no-redundant-type-constituents\n query(questions: string | Question[], qtype?: RecordType | string): void {\n let questionArray: Question[];\n if (typeof questions === 'string') {\n questionArray = [{ name: questions, type: (qtype || 'ANY') as RecordType }];\n } else if (Array.isArray(questions)) {\n questionArray = questions;\n } else {\n throw new Error('Query questions must be an array of mDNS query questions.');\n }\n const query = { type: 'query' as const, questions: questionArray };\n this.emitDebug(`Send mDNS query: ${Util.inspect(query)}`);\n this.send(query);\n }\n\n // send mDNS packet\n send(value: Packet): void {\n if (this.destroyed) return;\n const packet = DNSPacket.encode(value);\n // RFC 6762 §5.4 + §6: ask responders to answer this query via UNICAST (set the\n // QU bit on each question's qclass). Unicast responses are exempt from the\n // one-answer-per-second multicast rate limit (§6), so back-to-back one-shot\n // discoveries are answered every time instead of every other window. We keep\n // our source port at 5353, so replies arrive on the multicast receive sockets.\n // dns-packet's question encoder cannot set the QU bit, so we patch the buffer.\n if (value.type === 'query') this.setUnicastResponseBit(packet);\n for (let i = 0; i < this.sendSockets.length; i++) {\n const socket = this.sendSockets[i];\n if (socket.send && socket.iface) {\n try {\n socket.send(\n packet,\n 0,\n packet.length,\n Constants.MDNS_PORT,\n [Constants.IPv4, Constants.IPv4_INT].includes(socket.iface.family)\n ? Constants.MDNS_IPV4\n : Constants.MDNS_IPV6 + '%' + socket.iface.name,\n );\n this.emitDebug(`Send packet on ${socket.iface.address}`);\n } catch {\n // Socket was closed between check and send — skip silently\n }\n }\n }\n }\n\n // Set the QU (unicast-response-requested) bit on every question in an already\n // encoded query packet. Layout: 12-byte header, then each question is\n // <name><2-byte QTYPE><2-byte QCLASS>; the QU bit is the top bit of QCLASS.\n private setUnicastResponseBit(packet: Buffer): void {\n const questionCount = packet.readUInt16BE(4);\n let offset = 12;\n for (let q = 0; q < questionCount && offset < packet.length; q++) {\n // Walk the name's length-prefixed labels to the zero terminator.\n while (offset < packet.length && packet[offset] !== 0) {\n offset += packet[offset] + 1;\n }\n offset += 1; // zero terminator\n offset += 2; // QTYPE\n if (offset < packet.length) {\n packet[offset] |= 0x80; // top bit of the QCLASS high byte = QU bit\n }\n offset += 2; // QCLASS\n }\n }\n\n // destroy this scanner\n destroy(): void {\n this.destroyed = true;\n this.ready = false;\n this.removeAllListeners();\n this.sendSockets.forEach(s => {\n try {\n s.socket?.close();\n } catch {}\n });\n this.sendSockets = [];\n this.receiveSockets.forEach(s => {\n try {\n s.socket?.close();\n } catch {}\n });\n this.receiveSockets = [];\n }\n\n ////////////////////////\n // emit event methods //\n ////////////////////////\n\n emitError(error: any): void {\n this.emit('error', error);\n }\n\n emitWarn(message: any): void {\n this.emit('warn', message);\n }\n\n emitDebug(message: string): void {\n if (this.Config.debug) this.emit('debug', message);\n }\n}\n\nexport default MDNSScanner;\n","import type { Answer, Packet } from 'dns-packet';\nimport type { RemoteInfo } from 'node:dgram';\nimport { EventEmitter } from 'node:events';\nimport * as Constants from './constants.js';\nimport type MDNSScanner from './scanner.js';\n\nexport interface ServicesConfig {\n debug?: boolean;\n}\n\nexport interface NamedService {\n service?: Answer;\n host?: string;\n port?: number;\n txt?: { strings: string[]; keyValuePairs: Record<string, string> };\n addresses?: Array<{ family: string; address: string }>;\n name?: string;\n rinfo?: RemoteInfo;\n}\n\nconst Defaults: Required<ServicesConfig> = { debug: false };\n\nclass MDNSServices extends EventEmitter {\n Config: Required<ServicesConfig>;\n scanner: MDNSScanner;\n types: string[];\n namedServices: Record<string, NamedService>;\n private packetListener: (packet: Packet, rinfo: RemoteInfo) => void;\n\n constructor(scanner: MDNSScanner, config?: ServicesConfig) {\n super();\n this.packetListener = this.onPacket.bind(this);\n this.scanner = scanner;\n this.Config = Object.assign({}, Defaults, config);\n this.types = [];\n this.namedServices = {};\n this.forwardEvents(this.scanner);\n this.reset();\n }\n\n // reset services\n reset(): void {\n this.removeMDNSListener(this.scanner);\n this.types = [];\n this.namedServices = {};\n this.listenMDNSEvents(this.scanner);\n }\n\n // forward events received from scanner\n forwardEvents(scanner: MDNSScanner): void {\n scanner\n .on('error', (error: any) => {\n this.emitError(error);\n })\n .on('warn', (message: any) => {\n this.emitWarn(message);\n })\n .on('debug', (message: string) => {\n this.emitDebug(message);\n });\n }\n\n // handle packets from scanner\n listenMDNSEvents(scanner: MDNSScanner): void {\n scanner.on('packet', this.packetListener);\n }\n\n // remove packet listener\n removeMDNSListener(scanner: MDNSScanner): void {\n scanner.removeListener('packet', this.packetListener);\n }\n\n // on scanner packet handler\n onPacket(packet: Packet, rinfo: RemoteInfo): void {\n this.emitDebug(`Received packet type ${packet.type} from ${rinfo.address}.`);\n switch (packet.type) {\n case 'query':\n this.emit('query', packet, rinfo);\n break;\n\n case 'response':\n this.emitDebug(\n `Received response packet from ${rinfo.address} with ${\n packet.answers\n ? packet.answers.length\n : 0\n } answers and ${packet.additionals ? packet.additionals.length : 0} additionals.`,\n );\n if (packet.answers) this.processAnswers(packet.answers, rinfo);\n if (packet.additionals) this.processAnswers(packet.additionals, rinfo);\n\n break;\n }\n }\n\n // process answers or additionals in a response type packet\n processAnswers(answers: Answer[], rinfo: RemoteInfo): void {\n this.emitDebug('Processing answers or additionals...');\n // process service answers\n const serviceNames = this.processSRVAnswers(answers);\n this.processTXTAnswers(answers);\n this.processAAnswers(answers);\n this.processAAAAAnswers(answers);\n this.processPTRAnswers(answers, rinfo);\n serviceNames.forEach(name => {\n this.emit('discovered', { type: 'service', data: this.namedServices[name] });\n });\n }\n\n processSRVAnswers(answers: Answer[]): string[] {\n const serviceNames: string[] = [];\n answers.forEach(answer => {\n if (answer.type !== 'SRV') return;\n this.emitDebug(`Processing SRV answer.`);\n const fullName = answer.name.toString();\n if (!serviceNames.includes(fullName)) serviceNames.push(fullName);\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].service = answer;\n this.namedServices[fullName].host = (answer.data as any).target.toString();\n this.namedServices[fullName].port = (answer.data as any).port;\n });\n return serviceNames;\n }\n\n processTXTAnswers(answers: Answer[]): void {\n answers.forEach(answer => {\n if (answer.type !== 'TXT') return;\n this.emitDebug(`Processing TXT answer.`);\n const data = answer.data as Buffer | Buffer[];\n if (Array.isArray(data) && data.length > 1) {\n const fullName = answer.name.toString();\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].txt = this.answerDataToKeyValues(Buffer.concat(data));\n } else if (Buffer.isBuffer(data)) {\n const fullName = answer.name.toString();\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].txt = this.answerDataToKeyValues(data);\n }\n });\n }\n\n processAAnswers(answers: Answer[]): void {\n answers.forEach(answer => {\n if (answer.type !== 'A') return;\n this.emitDebug(`Processing A answer.`);\n const hostName = answer.name.toString();\n const address = (answer as any).data.toString();\n for (const serviceName in this.namedServices) {\n if (this.namedServices[serviceName].host !== hostName) continue;\n this.namedServices[serviceName].addresses = this.namedServices[serviceName].addresses || [];\n const exists = this.namedServices[serviceName].addresses!.reduce((e, a) => {\n return e || a.address === address;\n }, false);\n if (!exists) {\n this.namedServices[serviceName].addresses!.push({ family: Constants.IPv4, address });\n }\n }\n });\n }\n\n processAAAAAnswers(answers: Answer[]): void {\n answers.forEach(answer => {\n if (answer.type !== 'AAAA') return;\n this.emitDebug(`Processing AAAA answer.`);\n const hostName = answer.name.toString();\n const address = (answer as any).data.toString();\n for (const serviceName in this.namedServices) {\n if (this.namedServices[serviceName].host !== hostName) continue;\n this.namedServices[serviceName].addresses = this.namedServices[serviceName].addresses || [];\n const exists = this.namedServices[serviceName].addresses!.reduce((e, a) => {\n return e || a.address === address;\n }, false);\n if (!exists) {\n this.namedServices[serviceName].addresses!.push({ family: Constants.IPv6, address });\n }\n }\n });\n }\n\n processPTRAnswers(answers: Answer[], rinfo: RemoteInfo): void {\n answers.forEach(answer => {\n if (answer.type !== 'PTR') return;\n this.emitDebug(`Processing PTR answer.`);\n const serviceType = this.serviceTypeFromPTR(answer);\n const fullName = (answer as any).data.toString();\n // build host service definition if fullName is a host service\n if (serviceType !== fullName) {\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].name = fullName.replace('.' + serviceType, '');\n this.namedServices[fullName].rinfo = rinfo;\n }\n });\n }\n\n // extract service type from answer data\n serviceTypeFromPTR(answer: Answer): string {\n const data = (answer as any).data;\n const match = /(?:^|^.+?(?:\\.))(_.*)$/mg.exec(data.toString()); // get service type without hostname\n const serviceType = match ? match[1] : data.toString();\n if (!this.types.includes(serviceType)) {\n this.types.push(serviceType);\n this.emit('discovered', { type: 'type', data: serviceType });\n this.emitDebug(`Scanning service type ${serviceType}.`);\n this.scanner.query(serviceType, 'ANY');\n }\n return serviceType;\n }\n\n // extract the key=value pairs from a TXT data buffer\n answerDataToKeyValues(\n data: Buffer,\n ): { strings: string[]; keyValuePairs: Record<string, string> } {\n const strings: string[] = [];\n const kvPairs: Record<string, string> = {};\n let kvPointer = 0;\n let kvLen = data[kvPointer];\n while (kvLen) {\n const pair = data.slice(kvPointer + 1, kvPointer + 1 + kvLen);\n strings.push(pair.toString());\n const kvMatch = /^([^=]+)=([^=]*)$/.exec(pair.toString());\n if (kvMatch) {\n kvPairs[kvMatch[1]] = kvMatch[2];\n }\n kvPointer = kvPointer + 1 + kvLen;\n kvLen = data[kvPointer];\n }\n return { strings: strings, keyValuePairs: kvPairs };\n }\n\n ////////////////////////\n // emit event methods //\n ////////////////////////\n\n emitError(error: any): void {\n this.emit('error', error);\n }\n\n emitWarn(message: any): void {\n this.emit('warn', message);\n }\n\n emitDebug(message: string): void {\n if (this.Config.debug) this.emit('debug', message);\n }\n}\n\nexport default MDNSServices;\n","import { up } from 'up-fetch';\n\nimport { ManagementApi } from './api/management';\nimport { type DiscoveredDevice, format_host_for_url, parseApiError } from './at1000';\n\nimport { Scanner, Services } from './mdns-scanner';\n\n/** Lower = higher priority. Private IPs preferred over link-local over others. */\nfunction address_priority(host: string): number {\n if (host.startsWith('192.168.')) return 0;\n if (host.startsWith('169.254.')) return 1;\n return 2;\n}\n\nexport const findDevices = async (timeout: number = 500): Promise<DiscoveredDevice[]> => {\n if (timeout < 10) {\n timeout = 10;\n }\n\n let scanner = new Scanner({ debug: true });\n let services = new Services(scanner);\n\n services.on('error', (error: string) => {\n if (!error.includes('bind ENOENT')) {\n throw Error(error);\n }\n });\n\n let ready = await scanner.init();\n if (!ready) {\n throw new Error('Failed to initialize mDNS scanner');\n }\n scanner.query('_at1000_server._tcp.local');\n\n await new Promise((r) => setTimeout(r, timeout));\n\n // Extract all candidate addresses from discovered services, IPv4 before IPv6\n const addresses = [\n ...new Set(\n Object\n .values(services.namedServices)\n .filter((s) => s.service !== undefined)\n .filter((s) =>\n (s.service?.name as string | undefined)?.endsWith('_at1000_server._tcp.local')\n )\n .flatMap((s) => {\n const addrs: { family: string; address: string }[] = s.addresses ?? [];\n const port: number | undefined = s.port;\n // IPv4 addresses first, then IPv6 — so faster/simpler addresses are tried first\n const ipv4 = addrs.filter((a) => a.family === 'IPv4').map((a) =>\n format_host_for_url(a.address, port)\n );\n const ipv6 = addrs.filter((a) => a.family === 'IPv6').map((a) =>\n format_host_for_url(a.address, port)\n );\n return [...ipv4, ...ipv6];\n }),\n ),\n ];\n\n scanner.destroy();\n\n // Probe each candidate address with a bare info fetch (no session header).\n const results = await Promise.allSettled(\n addresses.map(async (address): Promise<DiscoveredDevice> => {\n const bare = up(\n fetch,\n () => ({\n baseUrl: `http://${format_host_for_url(address)}/v0`,\n timeout: 1000,\n parseRejected: (response, request) =>\n parseApiError(response, request.method),\n }),\n );\n const info = await new ManagementApi(bare, address).info();\n return { host: address, info };\n }),\n );\n const devices = results\n .filter((r): r is PromiseFulfilledResult<DiscoveredDevice> => r.status === 'fulfilled')\n .map((r) => r.value);\n\n // Deduplicate by hostname — prefer private IPs over link-local over other addresses\n const best = new Map<string, DiscoveredDevice>();\n for (const device of devices) {\n const existing = best.get(device.info.hostname);\n if (!existing) {\n best.set(device.info.hostname, device);\n } else if (address_priority(device.host) < address_priority(existing.host)) {\n best.set(device.info.hostname, device);\n }\n }\n return [...best.values()];\n};\n","import { readFileSync } from 'node:fs';\nimport { hostname } from 'node:os';\n\nimport { version } from '../package.json';\nimport { AT1000Base, type DiscoveredDevice, type OpenOptions } from './at1000';\nimport { findDevices } from './discovery';\n\nexport type { ProjectTemplate } from './api/management';\nexport { ApiError } from './at1000';\nexport { format_host_for_url, host_without_port } from './at1000';\nexport type { DiscoveredDevice, OpenOptions } from './at1000';\n\n/** @hideconstructor */\nexport class AT1000 extends AT1000Base {\n static readonly apiVersion = version;\n\n /** Discovers AT1000 devices on the local network via mDNS. */\n static findDevices(timeout: number = 500): Promise<DiscoveredDevice[]> {\n return findDevices(timeout);\n }\n\n /**\n * Opens a device, taking exclusive access (last-open-wins). When running inside\n * an AT1000 project container the open is project-kind (from `/etc/at1000/project`),\n * otherwise remote-kind labelled with the local hostname.\n */\n static async open(device: DiscoveredDevice | string, options?: OpenOptions): Promise<AT1000> {\n let session: { kind: 'remote' | 'project'; project?: string; defaultLabel?: string };\n try {\n const project = readFileSync('/etc/at1000/project', 'utf8').trim();\n session = { kind: 'project', project, defaultLabel: project };\n } catch {\n session = { kind: 'remote', defaultLabel: hostname() };\n }\n // AT1000 adds no instance state over AT1000Base; the cast is the create-era convention.\n return (await AT1000Base.openBase(device, options, session)) as AT1000;\n }\n}\n\n/**\n * Reads the device hostname injected into an AT1000 project container\n * (`/etc/at1000/hostname`). Returns `undefined` when run off-device.\n */\nexport function readInjectedHostname(): string | undefined {\n try {\n return readFileSync('/etc/at1000/hostname', 'utf8').trim();\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"node.mjs","names":["Constants.IPv4","Constants.IPv6","Constants.IPv4","Constants.IPv6","Defaults","Constants.IPv4","Constants.IPv6","Constants.MDNS_IPV4","Constants.MDNS_PORT","Constants.MDNS_IPV6","Constants.IPv4","Constants.IPv6","Scanner","Services"],"sources":["../src/mdns-scanner/constants.ts","../src/mdns-scanner/interfaces.ts","../src/mdns-scanner/sockets.ts","../src/mdns-scanner/scanner.ts","../src/mdns-scanner/services.ts","../src/discovery.ts","../src/node.ts"],"sourcesContent":["export const MDNS_IPV4 = '224.0.0.251';\nexport const MDNS_IPV6 = 'FF02::FB';\nexport const MDNS_PORT = 5353;\nexport const IPv4 = 'IPv4';\nexport const IPv4_INT = 4; // beginning in node 18 family is integer\nexport const IPv6 = 'IPv6';\nexport const IPv6_INT = 6; // beginning in node 18 family is integer\nexport const ANY_IPV4 = '0.0.0.0';\nexport const ANY_IPV6 = '::';\n\nexport const ErrorMessages = { NO_INTERFACES: 'No available interfaces.' };\n","import IP from 'ip-address';\nimport OS from 'node:os';\nimport * as Constants from './constants.js';\n\nconst SupportedFamilies = [Constants.IPv4, Constants.IPv4_INT, Constants.IPv6, Constants.IPv6_INT];\n\nexport interface NetworkInterface {\n name: string;\n address: string;\n family: string | number;\n scopeid?: number;\n}\n\nclass Interfaces {\n // select appropriate method based on argument\n static getInterfaces(interfaceStrings?: string | string[]): NetworkInterface[] {\n return (!interfaceStrings\n ? Interfaces.getAllInterfaces()\n : Interfaces.getInterfacesFromStrings(interfaceStrings));\n }\n\n // get all usable interfaces from OS\n static getAllInterfaces(): NetworkInterface[] {\n const interfaces: NetworkInterface[] = [];\n const names: string[] = [];\n const osInterfaces = OS.networkInterfaces();\n for (const [name, iface] of Object.entries(osInterfaces)) {\n if (names.includes(name)) {\n continue;\n }\n names.push(name);\n iface?.forEach((assignment) => {\n // check if interface is usable\n if (\n assignment.internal // cannot use internal\n || !SupportedFamilies.includes(assignment.family) // can only use IPv4 and IPv6 family\n || /^(2002|2001):/ig.exec(assignment.address) // cannot use IPv6 special prefix\n ) return;\n interfaces.push({\n name: name,\n address: assignment.address,\n family: assignment.family,\n scopeid: assignment.scopeid,\n });\n });\n }\n if (!interfaces.length) throw new Error('No usable network interfaces returned by OS.');\n return interfaces;\n }\n\n // get interfaces from configuration strings\n static getInterfacesFromStrings(interfaceStrings: string | string[]): NetworkInterface[] {\n const interfaceArray = Array.isArray(interfaceStrings) ? interfaceStrings : [interfaceStrings];\n const interfaces = this.getAllInterfaces().filter((iface) => {\n return interfaceArray.reduce((result, interfaceString) => {\n // return result || (((IP.isV4Format(interfaceString) || IP.isV6Format(interfaceString)) && IP.isEqual(iface.address, interfaceString)) || iface.name === interfaceString ? true : false);\n return result\n || (Interfaces.stringMatchesAddress(interfaceString, iface.address)\n || iface.name === interfaceString\n ? true\n : false);\n }, false);\n });\n if (!interfaces || !interfaces.length) {\n throw new Error('No usable network interfaces returned by OS.');\n }\n return interfaces;\n }\n\n // compare interface settings string to os interface address\n static stringMatchesAddress(ifaceString: string, address: string): boolean {\n // try to create address objects\n let stringAddress: IP.Address4 | IP.Address6;\n let addressAddress: IP.Address4 | IP.Address6;\n try {\n stringAddress = new IP.Address4(ifaceString);\n addressAddress = new IP.Address4(address);\n // oxlint-disable-next-line no-unused-vars\n } catch (e) {\n try {\n stringAddress = new IP.Address6(ifaceString);\n addressAddress = new IP.Address6(address);\n // oxlint-disable-next-line no-unused-vars\n } catch (e) {\n return false;\n }\n }\n // compare addresses\n return stringAddress.bigInt() === addressAddress.bigInt();\n }\n}\n\nexport default Interfaces;\n","import IP from 'ip-address';\nimport type { RemoteInfo, Socket as DgramSocket } from 'node:dgram';\nimport DGram from 'node:dgram';\nimport * as Constants from './constants.js';\nimport type { NetworkInterface } from './interfaces.js';\n\nexport interface MulticastSettings {\n multicastAddress: string;\n multicastPort: number;\n interfaces: NetworkInterface[];\n reuseAddr?: boolean;\n ttl?: number;\n loopback?: boolean;\n onMessage: (message: Buffer, rinfo: RemoteInfo) => void;\n socketError: (error: Error) => void;\n}\n\nexport interface SendSocketSettings {\n reuseAddr?: boolean;\n srcPort?: number;\n}\n\nexport interface SocketResult {\n success: boolean;\n socket?: DgramSocket;\n memberships?: NetworkInterface[];\n failedMemberships?: NetworkInterface[];\n error?: Error;\n iface?: NetworkInterface;\n send?: (...args: any[]) => void;\n}\n\nconst MulticastDefaults = {\n interfaces: [],\n reuseAddr: true,\n ttl: 255,\n loopback: true,\n onMessage: (message: Buffer, _rinfo: RemoteInfo) => {\n console.log('Message ' + message.toString());\n },\n socketError: (error: Error) => {\n console.log('Socket error ' + error.message);\n },\n};\n\nclass Sockets {\n static validateSettings(settings: Partial<MulticastSettings>): void {\n if (!settings.multicastAddress) {\n throw new Error('Socket settings require multicastAddress');\n }\n if (!settings.multicastPort) {\n throw new Error('Socket settings require multicastPort');\n }\n }\n\n // create a multicast socket and add interfaces to group membership\n static createMulticastSocket(settings: Partial<MulticastSettings>): Promise<SocketResult> {\n return new Promise((resolve, _reject) => {\n const mergedSettings = Object.assign({}, MulticastDefaults, settings) as MulticastSettings;\n Sockets.validateSettings(mergedSettings);\n // create multicast socket to listen for packets\n const socket = DGram.createSocket({\n type: IP.Address4.isValid(mergedSettings.multicastAddress) ? 'udp4' : 'udp6',\n reuseAddr: mergedSettings.reuseAddr,\n });\n // track bind status with local variable\n let isListening = false;\n // add event listeners to socket\n socket\n .on('error', (error) => {\n if (isListening) {\n mergedSettings.socketError(error);\n } else {\n socket.close();\n resolve({ success: false, error: error });\n }\n })\n .on('listening', () => {\n isListening = true;\n socket.setMulticastTTL(mergedSettings.ttl ?? 255);\n socket.setMulticastLoopback(mergedSettings.loopback ?? true);\n const result = Sockets.addMulticastMemberships(socket, mergedSettings);\n if (!result.memberships.length) {\n isListening = false;\n socket.close();\n resolve({\n success: false,\n error: new Error(\n 'No interface memberships for multicast address ' + mergedSettings.multicastAddress,\n ),\n });\n return;\n }\n resolve(Object.assign({ success: true }, result, { socket }));\n })\n .on('message', (msg, rinfo) => {\n mergedSettings.onMessage(msg, rinfo);\n });\n // bind socket\n socket.bind({ port: mergedSettings.multicastPort, exclusive: false });\n });\n }\n\n // add interfaces to multicast membership group on socket\n static addMulticastMemberships(\n socket: DgramSocket,\n settings: MulticastSettings,\n ): { memberships: NetworkInterface[]; failedMemberships: NetworkInterface[] } {\n const memberships: NetworkInterface[] = [];\n const failedMemberships: NetworkInterface[] = [];\n const family = IP.Address4.isValid(settings.multicastAddress)\n ? [Constants.IPv4, Constants.IPv4_INT]\n : [Constants.IPv6, Constants.IPv6_INT];\n settings.interfaces.forEach((iface) => {\n if (!family.includes(iface.family)) return; // unsupported family\n try {\n socket.addMembership(settings.multicastAddress, Sockets.interfaceAddress(iface));\n memberships.push(iface);\n // oxlint-disable-next-line no-unused-vars\n } catch (error) {\n failedMemberships.push(iface);\n }\n });\n return { memberships, failedMemberships };\n }\n\n // create a socket to be used when sending mDNS packets\n static async createSendSocket(\n iface: NetworkInterface,\n settings: SendSocketSettings,\n onMessage: (message: Buffer, rinfo: RemoteInfo) => void,\n socketError: (error: Error) => void,\n emitWarn?: (message: string) => void,\n ): Promise<SocketResult> {\n return new Promise((resolve) => {\n const type = [Constants.IPv4, Constants.IPv4_INT].includes(iface.family) ? 'udp4' : 'udp6';\n const ifaceAddr = Sockets.interfaceAddress(iface);\n const desiredPort = settings.srcPort ?? 0;\n let fellBack = false;\n\n const attempt = (port: number): void => {\n // RFC 6762 §5/§6: full mDNS participants send from sport=5353 so responders\n // multicast the reply back to 224.0.0.251:5353. Binding to the interface\n // address with SO_REUSEADDR+SO_REUSEPORT lets us coexist with avahi/Bonjour\n // already holding 0.0.0.0:5353.\n const socket = DGram.createSocket({\n type,\n reuseAddr: settings.reuseAddr ? true : false,\n reusePort: true,\n });\n let bound = false;\n socket\n .on('error', (error) => {\n if (!bound) {\n socket.close();\n if (port !== 0 && !fellBack) {\n fellBack = true;\n emitWarn?.(\n `mDNS send socket bind to ${ifaceAddr}:${port} failed (${error.message}); falling back to ephemeral source port — discovery may be unreliable on strict firewalls.`,\n );\n attempt(0);\n } else {\n resolve({ success: false, error: new Error(error.message) });\n }\n } else {\n socketError(error);\n }\n })\n .on('listening', () => {\n bound = true;\n resolve({ success: true, iface, socket, send: socket.send.bind(socket) });\n })\n .on('message', (msg, rinfo: RemoteInfo & { interface?: string }) => {\n // include interface name so we know where the message came in\n rinfo.interface = iface.name;\n onMessage(msg, rinfo);\n })\n .bind(port, ifaceAddr);\n };\n\n attempt(desiredPort);\n });\n }\n\n // format an interface address for mDNS socket\n static interfaceAddress(iface: NetworkInterface): string {\n // IPv4 addresses don't need scope\n if ([Constants.IPv4, Constants.IPv4_INT].includes(iface.family)) {\n return iface.address;\n }\n // For IPv6 link-local addresses (scopeid > 0), append the interface NAME as the\n // zone. Node/libuv uv_ip6_addr resolves the zone via if_nametoindex() on\n // Linux/macOS, which fails for a numeric scope id (yields scope 0 -> bind EINVAL).\n if (iface.scopeid) {\n return `${iface.address}%${iface.name}`;\n }\n return iface.address;\n }\n}\n\nexport default Sockets;\n","import type { Packet, Question, RecordType } from 'dns-packet';\nimport DNSPacket from 'dns-packet';\nimport type { RemoteInfo } from 'node:dgram';\nimport { EventEmitter } from 'node:events';\nimport Util from 'node:util';\nimport * as Constants from './constants.js';\nimport type { NetworkInterface } from './interfaces.js';\nimport Interfaces from './interfaces.js';\nimport type { SocketResult } from './sockets.js';\nimport Sockets from './sockets.js';\n\nexport interface ScannerConfig {\n reuseAddr?: boolean;\n srcPort?: number;\n interfaces?: string | string[] | null;\n ttl?: number;\n loopback?: boolean;\n debug?: boolean;\n}\n\ntype Socket = SocketResult;\n\nconst Defaults: Required<ScannerConfig> = {\n reuseAddr: true,\n srcPort: 5353,\n interfaces: null,\n ttl: 255,\n loopback: true,\n debug: false,\n};\n\nclass MDNSScanner extends EventEmitter {\n Config: Required<ScannerConfig>;\n ready: boolean;\n receiveSockets: Socket[];\n sendSockets: Socket[];\n interfaces?: NetworkInterface[];\n destroyed?: boolean;\n\n constructor(config?: ScannerConfig) {\n super();\n this.Config = Object.assign({}, Defaults, config);\n this.ready = false;\n this.receiveSockets = [];\n this.sendSockets = [];\n }\n\n // initialize the scanner\n async init(): Promise<boolean> {\n try {\n this.interfaces = Interfaces.getInterfaces(this.Config.interfaces || undefined);\n } catch (error) {\n this.emitError(error);\n throw error;\n }\n this.emitDebug(`Scanner interfaces: ${Util.inspect(this.interfaces)}`);\n await this.createReceiveSockets();\n await this.createSendSockets();\n if (this.receiveSockets.length && this.sendSockets.length) this.ready = true;\n return this.ready;\n }\n\n // create sockets that will receive mDNS packets\n async createReceiveSockets(): Promise<Socket[]> {\n if (!this.interfaces) return [];\n const ipv4 = this.interfaces.filter(i =>\n [Constants.IPv4, Constants.IPv4_INT].includes(i.family)\n );\n const ipv6 = this.interfaces.filter(i =>\n [Constants.IPv6, Constants.IPv6_INT].includes(i.family)\n );\n this.emitDebug(\n `Create receive sockets for${ipv4.length ? ' ' + Constants.IPv4 : ''}${\n ipv4.length && ipv6.length\n ? ' and'\n : ''\n }${ipv6.length ? ' ' + Constants.IPv6 : ''}`,\n );\n if (ipv4.length) {\n const ipv4Socket = await Sockets.createMulticastSocket({\n multicastAddress: Constants.MDNS_IPV4,\n multicastPort: Constants.MDNS_PORT,\n interfaces: ipv4,\n onMessage: this.onMessage.bind(this),\n socketError: this.socketError.bind(this),\n });\n if (ipv4Socket.success) this.receiveSockets.push(ipv4Socket);\n else if (ipv4Socket.error) this.emitWarn(ipv4Socket.error.message);\n }\n if (ipv6.length) {\n const ipv6Socket = await Sockets.createMulticastSocket({\n multicastAddress: Constants.MDNS_IPV6,\n multicastPort: Constants.MDNS_PORT,\n interfaces: ipv6,\n onMessage: this.onMessage.bind(this),\n socketError: this.socketError.bind(this),\n });\n if (ipv6Socket.success) this.receiveSockets.push(ipv6Socket);\n else if (ipv6Socket.error) this.emitWarn(ipv6Socket.error.message);\n }\n return this.receiveSockets;\n }\n\n // create sockets used to send out mDNS packets\n async createSendSockets(): Promise<void> {\n if (!this.interfaces) return;\n this.emitDebug(`Create send sockets on ${this.interfaces.length} interfaces/addresses.`);\n for (let i = 0; i < this.interfaces.length; i++) {\n const sendSocket = await Sockets.createSendSocket(\n this.interfaces[i],\n this.Config,\n this.onMessage.bind(this),\n this.socketError.bind(this),\n this.emitWarn.bind(this),\n );\n if (sendSocket.success) this.sendSockets.push(sendSocket);\n else if (sendSocket.error) this.emitWarn(sendSocket.error.message);\n }\n }\n\n // handle receive socket message\n onMessage(message: Buffer, rinfo: RemoteInfo): void {\n let packet: Packet;\n try {\n packet = DNSPacket.decode(message);\n } catch (error) {\n return this.emitWarn(error);\n }\n this.emit('packet', packet, rinfo);\n }\n\n // handle socket errors\n socketError(error: any): void {\n if (error.code === 'EACCES' || error.code === 'EADDRINUSE' || error.code === 'EADDRNOTAVAIL') {\n this.emitError(error);\n } else {\n this.emitWarn(error);\n }\n }\n\n // send an mDNS query, questions can be an array of formatted questions or a single question name string, qtype is optionally used with name string\n // oxlint-disable-next-line no-redundant-type-constituents\n query(questions: string | Question[], qtype?: RecordType | string): void {\n let questionArray: Question[];\n if (typeof questions === 'string') {\n questionArray = [{ name: questions, type: (qtype || 'ANY') as RecordType }];\n } else if (Array.isArray(questions)) {\n questionArray = questions;\n } else {\n throw new Error('Query questions must be an array of mDNS query questions.');\n }\n const query = { type: 'query' as const, questions: questionArray };\n this.emitDebug(`Send mDNS query: ${Util.inspect(query)}`);\n this.send(query);\n }\n\n // send mDNS packet\n send(value: Packet): void {\n if (this.destroyed) return;\n const packet = DNSPacket.encode(value);\n // RFC 6762 §5.4 + §6: ask responders to answer this query via UNICAST (set the\n // QU bit on each question's qclass). Unicast responses are exempt from the\n // one-answer-per-second multicast rate limit (§6), so back-to-back one-shot\n // discoveries are answered every time instead of every other window. We keep\n // our source port at 5353, so replies arrive on the multicast receive sockets.\n // dns-packet's question encoder cannot set the QU bit, so we patch the buffer.\n if (value.type === 'query') this.setUnicastResponseBit(packet);\n for (let i = 0; i < this.sendSockets.length; i++) {\n const socket = this.sendSockets[i];\n if (socket.send && socket.iface) {\n try {\n socket.send(\n packet,\n 0,\n packet.length,\n Constants.MDNS_PORT,\n [Constants.IPv4, Constants.IPv4_INT].includes(socket.iface.family)\n ? Constants.MDNS_IPV4\n : Constants.MDNS_IPV6 + '%' + socket.iface.name,\n );\n this.emitDebug(`Send packet on ${socket.iface.address}`);\n } catch {\n // Socket was closed between check and send — skip silently\n }\n }\n }\n }\n\n // Set the QU (unicast-response-requested) bit on every question in an already\n // encoded query packet. Layout: 12-byte header, then each question is\n // <name><2-byte QTYPE><2-byte QCLASS>; the QU bit is the top bit of QCLASS.\n private setUnicastResponseBit(packet: Buffer): void {\n const questionCount = packet.readUInt16BE(4);\n let offset = 12;\n for (let q = 0; q < questionCount && offset < packet.length; q++) {\n // Walk the name's length-prefixed labels to the zero terminator.\n while (offset < packet.length && packet[offset] !== 0) {\n offset += packet[offset] + 1;\n }\n offset += 1; // zero terminator\n offset += 2; // QTYPE\n if (offset < packet.length) {\n packet[offset] |= 0x80; // top bit of the QCLASS high byte = QU bit\n }\n offset += 2; // QCLASS\n }\n }\n\n // destroy this scanner\n destroy(): void {\n this.destroyed = true;\n this.ready = false;\n this.removeAllListeners();\n this.sendSockets.forEach(s => {\n try {\n s.socket?.close();\n } catch {}\n });\n this.sendSockets = [];\n this.receiveSockets.forEach(s => {\n try {\n s.socket?.close();\n } catch {}\n });\n this.receiveSockets = [];\n }\n\n ////////////////////////\n // emit event methods //\n ////////////////////////\n\n emitError(error: any): void {\n this.emit('error', error);\n }\n\n emitWarn(message: any): void {\n this.emit('warn', message);\n }\n\n emitDebug(message: string): void {\n if (this.Config.debug) this.emit('debug', message);\n }\n}\n\nexport default MDNSScanner;\n","import type { Answer, Packet } from 'dns-packet';\nimport type { RemoteInfo } from 'node:dgram';\nimport { EventEmitter } from 'node:events';\nimport * as Constants from './constants.js';\nimport type MDNSScanner from './scanner.js';\n\nexport interface ServicesConfig {\n debug?: boolean;\n}\n\nexport interface NamedService {\n service?: Answer;\n host?: string;\n port?: number;\n txt?: { strings: string[]; keyValuePairs: Record<string, string> };\n addresses?: Array<{ family: string; address: string }>;\n name?: string;\n rinfo?: RemoteInfo;\n}\n\nconst Defaults: Required<ServicesConfig> = { debug: false };\n\nclass MDNSServices extends EventEmitter {\n Config: Required<ServicesConfig>;\n scanner: MDNSScanner;\n types: string[];\n namedServices: Record<string, NamedService>;\n private packetListener: (packet: Packet, rinfo: RemoteInfo) => void;\n\n constructor(scanner: MDNSScanner, config?: ServicesConfig) {\n super();\n this.packetListener = this.onPacket.bind(this);\n this.scanner = scanner;\n this.Config = Object.assign({}, Defaults, config);\n this.types = [];\n this.namedServices = {};\n this.forwardEvents(this.scanner);\n this.reset();\n }\n\n // reset services\n reset(): void {\n this.removeMDNSListener(this.scanner);\n this.types = [];\n this.namedServices = {};\n this.listenMDNSEvents(this.scanner);\n }\n\n // forward events received from scanner\n forwardEvents(scanner: MDNSScanner): void {\n scanner\n .on('error', (error: any) => {\n this.emitError(error);\n })\n .on('warn', (message: any) => {\n this.emitWarn(message);\n })\n .on('debug', (message: string) => {\n this.emitDebug(message);\n });\n }\n\n // handle packets from scanner\n listenMDNSEvents(scanner: MDNSScanner): void {\n scanner.on('packet', this.packetListener);\n }\n\n // remove packet listener\n removeMDNSListener(scanner: MDNSScanner): void {\n scanner.removeListener('packet', this.packetListener);\n }\n\n // on scanner packet handler\n onPacket(packet: Packet, rinfo: RemoteInfo): void {\n this.emitDebug(`Received packet type ${packet.type} from ${rinfo.address}.`);\n switch (packet.type) {\n case 'query':\n this.emit('query', packet, rinfo);\n break;\n\n case 'response':\n this.emitDebug(\n `Received response packet from ${rinfo.address} with ${\n packet.answers\n ? packet.answers.length\n : 0\n } answers and ${packet.additionals ? packet.additionals.length : 0} additionals.`,\n );\n if (packet.answers) this.processAnswers(packet.answers, rinfo);\n if (packet.additionals) this.processAnswers(packet.additionals, rinfo);\n\n break;\n }\n }\n\n // process answers or additionals in a response type packet\n processAnswers(answers: Answer[], rinfo: RemoteInfo): void {\n this.emitDebug('Processing answers or additionals...');\n // process service answers\n const serviceNames = this.processSRVAnswers(answers);\n this.processTXTAnswers(answers);\n this.processAAnswers(answers);\n this.processAAAAAnswers(answers);\n this.processPTRAnswers(answers, rinfo);\n serviceNames.forEach(name => {\n this.emit('discovered', { type: 'service', data: this.namedServices[name] });\n });\n }\n\n processSRVAnswers(answers: Answer[]): string[] {\n const serviceNames: string[] = [];\n answers.forEach(answer => {\n if (answer.type !== 'SRV') return;\n this.emitDebug(`Processing SRV answer.`);\n const fullName = answer.name.toString();\n if (!serviceNames.includes(fullName)) serviceNames.push(fullName);\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].service = answer;\n this.namedServices[fullName].host = (answer.data as any).target.toString();\n this.namedServices[fullName].port = (answer.data as any).port;\n });\n return serviceNames;\n }\n\n processTXTAnswers(answers: Answer[]): void {\n answers.forEach(answer => {\n if (answer.type !== 'TXT') return;\n this.emitDebug(`Processing TXT answer.`);\n const data = answer.data as Buffer | Buffer[];\n if (Array.isArray(data) && data.length > 1) {\n const fullName = answer.name.toString();\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].txt = this.answerDataToKeyValues(Buffer.concat(data));\n } else if (Buffer.isBuffer(data)) {\n const fullName = answer.name.toString();\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].txt = this.answerDataToKeyValues(data);\n }\n });\n }\n\n processAAnswers(answers: Answer[]): void {\n answers.forEach(answer => {\n if (answer.type !== 'A') return;\n this.emitDebug(`Processing A answer.`);\n const hostName = answer.name.toString();\n const address = (answer as any).data.toString();\n for (const serviceName in this.namedServices) {\n if (this.namedServices[serviceName].host !== hostName) continue;\n this.namedServices[serviceName].addresses = this.namedServices[serviceName].addresses || [];\n const exists = this.namedServices[serviceName].addresses!.reduce((e, a) => {\n return e || a.address === address;\n }, false);\n if (!exists) {\n this.namedServices[serviceName].addresses!.push({ family: Constants.IPv4, address });\n }\n }\n });\n }\n\n processAAAAAnswers(answers: Answer[]): void {\n answers.forEach(answer => {\n if (answer.type !== 'AAAA') return;\n this.emitDebug(`Processing AAAA answer.`);\n const hostName = answer.name.toString();\n const address = (answer as any).data.toString();\n for (const serviceName in this.namedServices) {\n if (this.namedServices[serviceName].host !== hostName) continue;\n this.namedServices[serviceName].addresses = this.namedServices[serviceName].addresses || [];\n const exists = this.namedServices[serviceName].addresses!.reduce((e, a) => {\n return e || a.address === address;\n }, false);\n if (!exists) {\n this.namedServices[serviceName].addresses!.push({ family: Constants.IPv6, address });\n }\n }\n });\n }\n\n processPTRAnswers(answers: Answer[], rinfo: RemoteInfo): void {\n answers.forEach(answer => {\n if (answer.type !== 'PTR') return;\n this.emitDebug(`Processing PTR answer.`);\n const serviceType = this.serviceTypeFromPTR(answer);\n const fullName = (answer as any).data.toString();\n // build host service definition if fullName is a host service\n if (serviceType !== fullName) {\n this.namedServices[fullName] = this.namedServices[fullName] || {};\n this.namedServices[fullName].name = fullName.replace('.' + serviceType, '');\n this.namedServices[fullName].rinfo = rinfo;\n }\n });\n }\n\n // extract service type from answer data\n serviceTypeFromPTR(answer: Answer): string {\n const data = (answer as any).data;\n const match = /(?:^|^.+?(?:\\.))(_.*)$/mg.exec(data.toString()); // get service type without hostname\n const serviceType = match ? match[1] : data.toString();\n if (!this.types.includes(serviceType)) {\n this.types.push(serviceType);\n this.emit('discovered', { type: 'type', data: serviceType });\n this.emitDebug(`Scanning service type ${serviceType}.`);\n this.scanner.query(serviceType, 'ANY');\n }\n return serviceType;\n }\n\n // extract the key=value pairs from a TXT data buffer\n answerDataToKeyValues(\n data: Buffer,\n ): { strings: string[]; keyValuePairs: Record<string, string> } {\n const strings: string[] = [];\n const kvPairs: Record<string, string> = {};\n let kvPointer = 0;\n let kvLen = data[kvPointer];\n while (kvLen) {\n const pair = data.slice(kvPointer + 1, kvPointer + 1 + kvLen);\n strings.push(pair.toString());\n const kvMatch = /^([^=]+)=([^=]*)$/.exec(pair.toString());\n if (kvMatch) {\n kvPairs[kvMatch[1]] = kvMatch[2];\n }\n kvPointer = kvPointer + 1 + kvLen;\n kvLen = data[kvPointer];\n }\n return { strings: strings, keyValuePairs: kvPairs };\n }\n\n ////////////////////////\n // emit event methods //\n ////////////////////////\n\n emitError(error: any): void {\n this.emit('error', error);\n }\n\n emitWarn(message: any): void {\n this.emit('warn', message);\n }\n\n emitDebug(message: string): void {\n if (this.Config.debug) this.emit('debug', message);\n }\n}\n\nexport default MDNSServices;\n","import { readFileSync } from 'node:fs';\n\nimport { up } from 'up-fetch';\n\nimport { type Information, ManagementApi } from './api/management';\nimport { format_host_for_url, parseApiError } from './at1000';\n\nimport { Scanner, Services } from './mdns-scanner';\n\n/** Lower = higher priority. Private IPs preferred over link-local over others. */\nfunction address_priority(host: string): number {\n if (host.startsWith('192.168.')) return 0;\n if (host.startsWith('169.254.')) return 1;\n return 2;\n}\n\nfunction readInjectedHostname(): string | undefined {\n try {\n return readFileSync('/etc/at1000/hostname', 'utf8').trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Reads the injected project marker; `undefined` off-device or on any error. */\nexport function readInjectedProject(): string | undefined {\n try {\n return readFileSync('/etc/at1000/project', 'utf8').trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\n/** A device probed during discovery (module-internal). */\ninterface ProbedDevice {\n host: string;\n info: Information;\n}\n\nasync function probeDevice(address: string): Promise<ProbedDevice> {\n const bare = up(\n fetch,\n () => ({\n baseUrl: `http://${format_host_for_url(address)}/v0`,\n timeout: 1000,\n parseRejected: (response, request) => parseApiError(response, request.method),\n }),\n );\n const info = await new ManagementApi(bare, address).info();\n return { host: address, info };\n}\n\n/**\n * Resolves this device's own address without mDNS when running standalone.\n * Reads the injected hostname and probes `<hostname>.local` then\n * `host.containers.internal`, returning the first candidate whose reported\n * hostname matches. Returns `undefined` off-device or when the local server\n * is unreachable.\n */\nexport const findLocalDevice = async (): Promise<string | undefined> => {\n const injected = readInjectedHostname();\n if (!injected) return undefined;\n for (const candidate of [`${injected}.local`, 'host.containers.internal']) {\n try {\n const device = await probeDevice(candidate);\n if (device.info.hostname === injected) return candidate;\n } catch {\n // unreachable candidate — try the next one\n }\n }\n return undefined;\n};\n\n/**\n * Discovers AT1000 devices on the local network via mDNS, returning their host\n * strings. Results are deduplicated by hostname. Inside an AT1000 project\n * container the device's own entry is always first.\n */\nexport const findDevices = async (timeout: number = 500): Promise<string[]> => {\n if (timeout < 10) {\n timeout = 10;\n }\n\n let scanner = new Scanner({ debug: true });\n let services = new Services(scanner);\n\n services.on('error', (error: string) => {\n if (!error.includes('bind ENOENT')) {\n throw Error(error);\n }\n });\n\n let ready = await scanner.init();\n if (!ready) {\n throw new Error('Failed to initialize mDNS scanner');\n }\n scanner.query('_at1000_server._tcp.local');\n\n await new Promise((r) => setTimeout(r, timeout));\n\n // Extract all candidate addresses from discovered services, IPv4 before IPv6\n const addresses = [\n ...new Set(\n Object\n .values(services.namedServices)\n .filter((s) => s.service !== undefined)\n .filter((s) =>\n (s.service?.name as string | undefined)?.endsWith('_at1000_server._tcp.local')\n )\n .flatMap((s) => {\n const addrs: { family: string; address: string }[] = s.addresses ?? [];\n const port: number | undefined = s.port;\n // IPv4 addresses first, then IPv6 — so faster/simpler addresses are tried first\n const ipv4 = addrs.filter((a) => a.family === 'IPv4').map((a) =>\n format_host_for_url(a.address, port)\n );\n const ipv6 = addrs.filter((a) => a.family === 'IPv6').map((a) =>\n format_host_for_url(a.address, port)\n );\n return [...ipv4, ...ipv6];\n }),\n ),\n ];\n\n scanner.destroy();\n\n // Probe each candidate address with a bare info fetch (no session header).\n const results = await Promise.allSettled(addresses.map(probeDevice));\n const devices = results\n .filter((r): r is PromiseFulfilledResult<ProbedDevice> => r.status === 'fulfilled')\n .map((r) => r.value);\n\n // Deduplicate by hostname — prefer private IPs over link-local over other addresses\n const best = new Map<string, ProbedDevice>();\n for (const device of devices) {\n const existing = best.get(device.info.hostname);\n if (!existing) {\n best.set(device.info.hostname, device);\n } else if (address_priority(device.host) < address_priority(existing.host)) {\n best.set(device.info.hostname, device);\n }\n }\n const ordered = [...best.values()];\n const injected = readInjectedHostname();\n if (!injected) return ordered.map((d) => d.host);\n\n const index = ordered.findIndex((d) => d.info.hostname === injected);\n if (index >= 0) {\n ordered.unshift(...ordered.splice(index, 1));\n return ordered.map((d) => d.host);\n }\n // Scan missed the local device (bridge networking can drop multicast in\n // project containers): fall back to a direct probe of the local device.\n const local = await findLocalDevice();\n return local ? [local, ...ordered.map((d) => d.host)] : ordered.map((d) => d.host);\n};\n","import { hostname } from 'node:os';\n\nimport { version } from '../package.json';\nimport { AT1000Base, type OpenOptions } from './at1000';\nimport { findDevices, findLocalDevice, readInjectedProject } from './discovery';\n\nexport type { ProjectTemplate } from './api/management';\nexport { ApiError } from './at1000';\nexport { format_host_for_url, host_without_port } from './at1000';\nexport type { OpenOptions } from './at1000';\n\n/** @hideconstructor */\nexport class AT1000 extends AT1000Base {\n static readonly apiVersion = version;\n\n /**\n * Discovers AT1000 devices on the local network via mDNS, returning their host\n * strings. Results are deduplicated by hostname. Inside an AT1000 project\n * container the device's own entry is always first.\n */\n static findDevices(timeout: number = 500): Promise<string[]> {\n return findDevices(timeout);\n }\n\n /** True when running inside an AT1000 project container (standalone mode). */\n static isStandalone(): boolean {\n return readInjectedProject() !== undefined;\n }\n\n /**\n * Resolves this device's own address without mDNS when running standalone.\n * Returns undefined off-device or when the local server is unreachable.\n */\n static findLocalDevice(): Promise<string | undefined> {\n return findLocalDevice();\n }\n\n /**\n * Opens a device, taking exclusive access (last-open-wins). When running inside\n * an AT1000 project container the open is project-kind (from `/etc/at1000/project`),\n * otherwise remote-kind labelled with the local hostname.\n */\n static async open(host: string, options?: OpenOptions): Promise<AT1000> {\n const project = readInjectedProject();\n const session = project\n ? { kind: 'project' as const, project, defaultLabel: project }\n : { kind: 'remote' as const, defaultLabel: hostname() };\n // AT1000 adds no instance state over AT1000Base; the cast is the create-era convention.\n return (await AT1000Base.openBase(host, options, session)) as AT1000;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-0hAwYBa1.cjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-CU5MagIg.mjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { t as AnalogOutputLevel } from "./common-
|
|
1
|
+
import { t as AnalogOutputLevel } from "./common-Cv6nZZS9.cjs";
|
|
2
2
|
import { Information } from "./management.cjs";
|
|
3
3
|
import { UpFetch } from "up-fetch";
|
|
4
4
|
import * as v from "valibot";
|
|
5
|
-
|
|
6
5
|
//#region src/api/power.d.ts
|
|
7
6
|
declare const dutState: v.ObjectSchema<{
|
|
8
7
|
readonly enabled: v.BooleanSchema<undefined>;
|
|
@@ -340,4 +339,4 @@ declare class RelayPower {
|
|
|
340
339
|
}
|
|
341
340
|
//#endregion
|
|
342
341
|
export { RelayPower as a, UsbConfiguration as c, usbState as d, PowerApi as i, UsbState as l, DutConfiguration as n, RelayState as o, DutState as r, Usb as s, Dut as t, dutState as u };
|
|
343
|
-
//# sourceMappingURL=power-
|
|
342
|
+
//# sourceMappingURL=power-B8QFbKdP.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-B8QFbKdP.d.cts","names":[],"sources":["../src/api/power.ts"],"mappings":";;;;;cAQa,UAAQ,EAAA;;;;;;KAMT,WAAW,EAAE,mBAAmB;cAEtC,kBAAgB,KAAA,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACV,mBAAmB,EAAE,mBAAmB;cAEvC,UAAQ,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACT,WAAW,EAAE,mBAAmB;cAEtC,kBAAgB,KAAA,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACV,mBAAmB,EAAE,mBAAmB;cAE9C,YAAU,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACJ,aAAa,EAAE,mBAAmB;;cAGjC;mBAIkB;mBAHZ;mBACA;EAEY,YAAA,OAAO,SAAS,MAAM;;;;EAOnD,SAAS;;;;;;EAST,IAAI,aAAa;;;;;;EAiBjB,IAAI,aAAa;;;;;EAgBjB,WAAW;;;cAMA;mBACkB;WAAgC;EAAhC,YAAA,OAAO,SAAyB;;;;EAK7D,SAAS;;;;;;EAST,UAAU,QAAQ,mBAAmB,QAAQ;;;;;;EAa7C,OAAO,SAAS,oBAAoB,QAAQ;;;;;EAQ5C,WAAW,QAAQ;;;;;EAQnB,QAAQ,QAAQ;;;;;EAQV,gBAAgB;;;;;EAQhB,gBAAgB;;;cAMX;mBACkB;WAAgC;EAAhC,YAAA,OAAO,SAAyB;;;;EAK7D,SAAS;;;;;;EAST,UAAU,QAAQ,mBAAmB,QAAQ;;;;;EAY7C,UAAU,QAAQ;;;;;EAQlB,WAAW,QAAQ;;;;;EAQnB,QAAQ,QAAQ;;;;;EAQV,gBAAgB;;;;;EAQhB,gBAAgB;;;cAMX;mBACkB;WAAgC;EAAhC,YAAA,OAAO,SAAyB;;;;;EAM7D,QAAQ,QAAQ;;;;;EAQV,gBAAgB"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { t as AnalogOutputLevel } from "./common-
|
|
1
|
+
import { t as AnalogOutputLevel } from "./common-Cv6nZZS9.mjs";
|
|
2
2
|
import { Information } from "./management.mjs";
|
|
3
3
|
import { UpFetch } from "up-fetch";
|
|
4
4
|
import * as v from "valibot";
|
|
5
|
-
|
|
6
5
|
//#region src/api/power.d.ts
|
|
7
6
|
declare const dutState: v.ObjectSchema<{
|
|
8
7
|
readonly enabled: v.BooleanSchema<undefined>;
|
|
@@ -340,4 +339,4 @@ declare class RelayPower {
|
|
|
340
339
|
}
|
|
341
340
|
//#endregion
|
|
342
341
|
export { RelayPower as a, UsbConfiguration as c, usbState as d, PowerApi as i, UsbState as l, DutConfiguration as n, RelayState as o, DutState as r, Usb as s, Dut as t, dutState as u };
|
|
343
|
-
//# sourceMappingURL=power-
|
|
342
|
+
//# sourceMappingURL=power-BZmXOJyK.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-BZmXOJyK.d.mts","names":[],"sources":["../src/api/power.ts"],"mappings":";;;;;cAQa,UAAQ,EAAA;;;;;;KAMT,WAAW,EAAE,mBAAmB;cAEtC,kBAAgB,KAAA,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACV,mBAAmB,EAAE,mBAAmB;cAEvC,UAAQ,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACT,WAAW,EAAE,mBAAmB;cAEtC,kBAAgB,KAAA,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACV,mBAAmB,EAAE,mBAAmB;cAE9C,YAAU,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACJ,aAAa,EAAE,mBAAmB;;cAGjC;mBAIkB;mBAHZ;mBACA;EAEY,YAAA,OAAO,SAAS,MAAM;;;;EAOnD,SAAS;;;;;;EAST,IAAI,aAAa;;;;;;EAiBjB,IAAI,aAAa;;;;;EAgBjB,WAAW;;;cAMA;mBACkB;WAAgC;EAAhC,YAAA,OAAO,SAAyB;;;;EAK7D,SAAS;;;;;;EAST,UAAU,QAAQ,mBAAmB,QAAQ;;;;;;EAa7C,OAAO,SAAS,oBAAoB,QAAQ;;;;;EAQ5C,WAAW,QAAQ;;;;;EAQnB,QAAQ,QAAQ;;;;;EAQV,gBAAgB;;;;;EAQhB,gBAAgB;;;cAMX;mBACkB;WAAgC;EAAhC,YAAA,OAAO,SAAyB;;;;EAK7D,SAAS;;;;;;EAST,UAAU,QAAQ,mBAAmB,QAAQ;;;;;EAY7C,UAAU,QAAQ;;;;;EAQlB,WAAW,QAAQ;;;;;EAQnB,QAAQ,QAAQ;;;;;EAQV,gBAAgB;;;;;EAQhB,gBAAgB;;;cAMX;mBACkB;WAAgC;EAAhC,YAAA,OAAO,SAAyB;;;;;EAM7D,QAAQ,QAAQ;;;;;EAQV,gBAAgB"}
|
package/build/power.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-CMqjfN_6.cjs"),t=require("./common-BSrNhbq_.cjs");let n=require("valibot");n=e.t(n,1);const r=n.object({enabled:n.boolean(),target_voltage:t.t,voltage:t.t,current:n.number()}),i=n.partial(n.pick(r,[`enabled`,`target_voltage`])),a=n.pick(r,[`enabled`,`current`,`voltage`]),o=n.pick(a,[`enabled`]),s=n.pick(r,[`current`]);var c=class{fetch;usb_count;dut_count=1;constructor(e,t){this.fetch=e,this.usb_count=t.capabilities.usb_ports.reduce((e,t)=>e+t.count,0)}reset(){return this.fetch(`/power/reset`,{method:`POST`,parseResponse:()=>{}})}dut(e){if(e<0||e>=this.dut_count)throw Error(`Invalid DUT id ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a DUT ID between 0 and ${this.dut_count-1}\n Path: /power/dut/${e}`);return new l(this.fetch,e)}usb(e){if(e<0||e>=this.usb_count)throw Error(`Invalid USB port ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a USB port ID between 0 and ${this.usb_count-1}\n Path: /power/usb/${e}`);return new u(this.fetch,e)}relay_0(){return new d(this.fetch,0)}},l=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}reset(){return this.fetch(`/power/dut/${this.id}/reset`,{method:`POST`,parseResponse:()=>{}})}configure(e){return this.fetch(`/power/dut/${this.id}`,{method:`PATCH`,body:n.parse(i,e),schema:r})}enable(e){return this.configure({enabled:!0,target_voltage:e})}disable(){return this.configure({enabled:!1})}read(){return this.fetch(`/power/dut/${this.id}`,{schema:r})}async read_current(){return(await this.read()).current}async read_voltage(){return(await this.read()).voltage}},u=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}reset(){return this.fetch(`/power/usb/${this.id}/reset`,{method:`POST`,parseResponse:()=>{}})}configure(e){return this.fetch(`/power/usb/${this.id}`,{method:`PATCH`,body:n.parse(o,e),schema:a})}enable(){return this.configure({enabled:!0})}disable(){return this.configure({enabled:!1})}read(){return this.fetch(`/power/usb/${this.id}`,{schema:a})}async read_current(){return(await this.read()).current}async read_voltage(){return(await this.read()).voltage}},d=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}read(){return this.fetch(`/power/relay/${this.id}`,{schema:s})}async read_current(){return(await this.read()).current}};exports.Dut=l,exports.PowerApi=c,exports.RelayPower=d,exports.Usb=u,exports.dutState=r,exports.usbState=a;
|
|
2
2
|
//# sourceMappingURL=power.cjs.map
|
package/build/power.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"power.cjs","names":["v","analogLevel"],"sources":["../src/api/power.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nimport { analogLevel, type AnalogOutputLevel } from './common';\nimport type { Information } from './management';\n\nexport type { AnalogOutputLevel };\n\nexport const dutState = v.object({\n enabled: v.boolean(),\n target_voltage: analogLevel,\n voltage: analogLevel,\n current: v.number(),\n});\nexport type DutState = v.InferOutput<typeof dutState>;\n\nconst dutConfiguration = v.partial(v.pick(dutState, ['enabled', 'target_voltage']));\nexport type DutConfiguration = v.InferOutput<typeof dutConfiguration>;\n\nexport const usbState = v.pick(dutState, ['enabled', 'current', 'voltage']);\nexport type UsbState = v.InferOutput<typeof usbState>;\n\nconst usbConfiguration = v.pick(usbState, ['enabled']);\nexport type UsbConfiguration = v.InferOutput<typeof usbConfiguration>;\n\nconst relayState = v.pick(dutState, ['current']);\nexport type RelayState = v.InferOutput<typeof relayState>;\n\n/** @hideconstructor */\nexport class PowerApi {\n private readonly usb_count: number;\n private readonly dut_count = 1;\n\n constructor(private readonly fetch: UpFetch, info: Information) {\n this.usb_count = info.capabilities.usb_ports.reduce((a, b) => a + b.count, 0);\n }\n\n /**\n * Resets the power API.\n */\n reset(): Promise<void> {\n return this.fetch('/power/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific DUT by id.\n * @param id The DUT id.\n * @returns The DUT instance.\n */\n dut(id: number): Dut {\n if (id < 0 || id >= this.dut_count) {\n throw new Error(\n `Invalid DUT id ${id} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a DUT ID between 0 and ${\n this.dut_count - 1\n }\\n Path: /power/dut/${id}`,\n );\n }\n\n return new Dut(this.fetch, id);\n }\n\n /**\n * Access a specific USB port by id.\n * @param id The USB port id.\n * @returns The USB port instance.\n */\n usb(id: number): Usb {\n if (id < 0 || id >= this.usb_count) {\n throw new Error(\n `Invalid USB port ${id} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a USB port ID between 0 and ${\n this.usb_count - 1\n }\\n Path: /power/usb/${id}`,\n );\n }\n\n return new Usb(this.fetch, id);\n }\n\n /**\n * Access the relay at index 0.\n * @returns The relay instance.\n */\n relay_0(): RelayPower {\n return new RelayPower(this.fetch, 0);\n }\n}\n\n/** @hideconstructor */\nexport class Dut {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Resets the DUT.\n */\n reset(): Promise<void> {\n return this.fetch(`/power/dut/${this.id}/reset`, { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Configures the DUT.\n * @param config The configuration to apply.\n * @returns The updated DUT state.\n */\n configure(config: DutConfiguration): Promise<DutState> {\n return this.fetch(`/power/dut/${this.id}`, {\n method: 'PATCH',\n body: v.parse(dutConfiguration, config),\n schema: dutState,\n });\n }\n\n /**\n * Enables the DUT power supply at the specified voltage.\n * @param voltage The target voltage to set.\n * @returns The updated DUT state.\n */\n enable(voltage: AnalogOutputLevel): Promise<DutState> {\n return this.configure({ enabled: true, target_voltage: voltage });\n }\n\n /**\n * Disables the DUT power supply.\n * @returns The updated DUT state.\n */\n disable(): Promise<DutState> {\n return this.configure({ enabled: false });\n }\n\n /**\n * Reads the current DUT state.\n * @returns The current DUT state.\n */\n read(): Promise<DutState> {\n return this.fetch(`/power/dut/${this.id}`, { schema: dutState });\n }\n\n /**\n * Reads the current drawn by the DUT.\n * @returns The current drawn by the DUT.\n */\n async read_current(): Promise<number> {\n return (await this.read()).current;\n }\n\n /**\n * Reads the voltage supplied to the DUT.\n * @returns The voltage supplied to the DUT.\n */\n async read_voltage(): Promise<number> {\n return (await this.read()).voltage;\n }\n}\n\n/** @hideconstructor */\nexport class Usb {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Resets the USB port.\n */\n reset(): Promise<void> {\n return this.fetch(`/power/usb/${this.id}/reset`, { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Configures the USB port.\n * @param config The configuration to apply.\n * @returns The updated USB state.\n */\n configure(config: UsbConfiguration): Promise<UsbState> {\n return this.fetch(`/power/usb/${this.id}`, {\n method: 'PATCH',\n body: v.parse(usbConfiguration, config),\n schema: usbState,\n });\n }\n\n /**\n * Enables the USB port power.\n * @returns The updated USB state.\n */\n enable(): Promise<UsbState> {\n return this.configure({ enabled: true });\n }\n\n /**\n * Disables the USB port power.\n * @returns The updated USB state.\n */\n disable(): Promise<UsbState> {\n return this.configure({ enabled: false });\n }\n\n /**\n * Reads the current state of the USB port.\n * @returns The current USB state.\n */\n read(): Promise<UsbState> {\n return this.fetch(`/power/usb/${this.id}`, { schema: usbState });\n }\n\n /**\n * Reads the current drawn by the USB port.\n * @returns The current drawn by the USB port.\n */\n async read_current(): Promise<number> {\n return (await this.read()).current;\n }\n\n /**\n * Reads the voltage at the USB port.\n * @returns The voltage at the USB port.\n */\n async read_voltage(): Promise<number> {\n return (await this.read()).voltage;\n }\n}\n\n/** @hideconstructor */\nexport class RelayPower {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Reads the current state of the relay.\n * @returns The current relay state.\n */\n read(): Promise<RelayState> {\n return this.fetch(`/power/relay/${this.id}`, { schema: relayState });\n }\n\n /**\n * Reads the current drawn through the relay.\n * @returns The current drawn through the relay.\n */\n async read_current(): Promise<number> {\n return (await this.read()).current;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"power.cjs","names":["v","analogLevel"],"sources":["../src/api/power.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nimport { analogLevel, type AnalogOutputLevel } from './common';\nimport type { Information } from './management';\n\nexport type { AnalogOutputLevel };\n\nexport const dutState = v.object({\n enabled: v.boolean(),\n target_voltage: analogLevel,\n voltage: analogLevel,\n current: v.number(),\n});\nexport type DutState = v.InferOutput<typeof dutState>;\n\nconst dutConfiguration = v.partial(v.pick(dutState, ['enabled', 'target_voltage']));\nexport type DutConfiguration = v.InferOutput<typeof dutConfiguration>;\n\nexport const usbState = v.pick(dutState, ['enabled', 'current', 'voltage']);\nexport type UsbState = v.InferOutput<typeof usbState>;\n\nconst usbConfiguration = v.pick(usbState, ['enabled']);\nexport type UsbConfiguration = v.InferOutput<typeof usbConfiguration>;\n\nconst relayState = v.pick(dutState, ['current']);\nexport type RelayState = v.InferOutput<typeof relayState>;\n\n/** @hideconstructor */\nexport class PowerApi {\n private readonly usb_count: number;\n private readonly dut_count = 1;\n\n constructor(private readonly fetch: UpFetch, info: Information) {\n this.usb_count = info.capabilities.usb_ports.reduce((a, b) => a + b.count, 0);\n }\n\n /**\n * Resets the power API.\n */\n reset(): Promise<void> {\n return this.fetch('/power/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific DUT by id.\n * @param id The DUT id.\n * @returns The DUT instance.\n */\n dut(id: number): Dut {\n if (id < 0 || id >= this.dut_count) {\n throw new Error(\n `Invalid DUT id ${id} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a DUT ID between 0 and ${\n this.dut_count - 1\n }\\n Path: /power/dut/${id}`,\n );\n }\n\n return new Dut(this.fetch, id);\n }\n\n /**\n * Access a specific USB port by id.\n * @param id The USB port id.\n * @returns The USB port instance.\n */\n usb(id: number): Usb {\n if (id < 0 || id >= this.usb_count) {\n throw new Error(\n `Invalid USB port ${id} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a USB port ID between 0 and ${\n this.usb_count - 1\n }\\n Path: /power/usb/${id}`,\n );\n }\n\n return new Usb(this.fetch, id);\n }\n\n /**\n * Access the relay at index 0.\n * @returns The relay instance.\n */\n relay_0(): RelayPower {\n return new RelayPower(this.fetch, 0);\n }\n}\n\n/** @hideconstructor */\nexport class Dut {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Resets the DUT.\n */\n reset(): Promise<void> {\n return this.fetch(`/power/dut/${this.id}/reset`, { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Configures the DUT.\n * @param config The configuration to apply.\n * @returns The updated DUT state.\n */\n configure(config: DutConfiguration): Promise<DutState> {\n return this.fetch(`/power/dut/${this.id}`, {\n method: 'PATCH',\n body: v.parse(dutConfiguration, config),\n schema: dutState,\n });\n }\n\n /**\n * Enables the DUT power supply at the specified voltage.\n * @param voltage The target voltage to set.\n * @returns The updated DUT state.\n */\n enable(voltage: AnalogOutputLevel): Promise<DutState> {\n return this.configure({ enabled: true, target_voltage: voltage });\n }\n\n /**\n * Disables the DUT power supply.\n * @returns The updated DUT state.\n */\n disable(): Promise<DutState> {\n return this.configure({ enabled: false });\n }\n\n /**\n * Reads the current DUT state.\n * @returns The current DUT state.\n */\n read(): Promise<DutState> {\n return this.fetch(`/power/dut/${this.id}`, { schema: dutState });\n }\n\n /**\n * Reads the current drawn by the DUT.\n * @returns The current drawn by the DUT.\n */\n async read_current(): Promise<number> {\n return (await this.read()).current;\n }\n\n /**\n * Reads the voltage supplied to the DUT.\n * @returns The voltage supplied to the DUT.\n */\n async read_voltage(): Promise<number> {\n return (await this.read()).voltage;\n }\n}\n\n/** @hideconstructor */\nexport class Usb {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Resets the USB port.\n */\n reset(): Promise<void> {\n return this.fetch(`/power/usb/${this.id}/reset`, { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Configures the USB port.\n * @param config The configuration to apply.\n * @returns The updated USB state.\n */\n configure(config: UsbConfiguration): Promise<UsbState> {\n return this.fetch(`/power/usb/${this.id}`, {\n method: 'PATCH',\n body: v.parse(usbConfiguration, config),\n schema: usbState,\n });\n }\n\n /**\n * Enables the USB port power.\n * @returns The updated USB state.\n */\n enable(): Promise<UsbState> {\n return this.configure({ enabled: true });\n }\n\n /**\n * Disables the USB port power.\n * @returns The updated USB state.\n */\n disable(): Promise<UsbState> {\n return this.configure({ enabled: false });\n }\n\n /**\n * Reads the current state of the USB port.\n * @returns The current USB state.\n */\n read(): Promise<UsbState> {\n return this.fetch(`/power/usb/${this.id}`, { schema: usbState });\n }\n\n /**\n * Reads the current drawn by the USB port.\n * @returns The current drawn by the USB port.\n */\n async read_current(): Promise<number> {\n return (await this.read()).current;\n }\n\n /**\n * Reads the voltage at the USB port.\n * @returns The voltage at the USB port.\n */\n async read_voltage(): Promise<number> {\n return (await this.read()).voltage;\n }\n}\n\n/** @hideconstructor */\nexport class RelayPower {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Reads the current state of the relay.\n * @returns The current relay state.\n */\n read(): Promise<RelayState> {\n return this.fetch(`/power/relay/${this.id}`, { schema: relayState });\n }\n\n /**\n * Reads the current drawn through the relay.\n * @returns The current drawn through the relay.\n */\n async read_current(): Promise<number> {\n return (await this.read()).current;\n }\n}\n"],"mappings":"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"}
|
package/build/power.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as AnalogOutputLevel } from "./common-
|
|
2
|
-
import { a as RelayPower, c as UsbConfiguration, d as usbState, i as PowerApi, l as UsbState, n as DutConfiguration, o as RelayState, r as DutState, s as Usb, t as Dut, u as dutState } from "./power-
|
|
1
|
+
import { t as AnalogOutputLevel } from "./common-Cv6nZZS9.cjs";
|
|
2
|
+
import { a as RelayPower, c as UsbConfiguration, d as usbState, i as PowerApi, l as UsbState, n as DutConfiguration, o as RelayState, r as DutState, s as Usb, t as Dut, u as dutState } from "./power-B8QFbKdP.cjs";
|
|
3
3
|
export { type AnalogOutputLevel, Dut, DutConfiguration, DutState, PowerApi, RelayPower, RelayState, Usb, UsbConfiguration, UsbState, dutState, usbState };
|
package/build/power.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as AnalogOutputLevel } from "./common-
|
|
2
|
-
import { a as RelayPower, c as UsbConfiguration, d as usbState, i as PowerApi, l as UsbState, n as DutConfiguration, o as RelayState, r as DutState, s as Usb, t as Dut, u as dutState } from "./power-
|
|
1
|
+
import { t as AnalogOutputLevel } from "./common-Cv6nZZS9.mjs";
|
|
2
|
+
import { a as RelayPower, c as UsbConfiguration, d as usbState, i as PowerApi, l as UsbState, n as DutConfiguration, o as RelayState, r as DutState, s as Usb, t as Dut, u as dutState } from "./power-BZmXOJyK.mjs";
|
|
3
3
|
export { type AnalogOutputLevel, Dut, DutConfiguration, DutState, PowerApi, RelayPower, RelayState, Usb, UsbConfiguration, UsbState, dutState, usbState };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { UpFetch } from "up-fetch";
|
|
2
2
|
import * as v from "valibot";
|
|
3
|
-
|
|
4
3
|
//#region src/api/relays.d.ts
|
|
5
4
|
declare const state: v.PicklistSchema<["open", "closed"], undefined>;
|
|
6
5
|
type State = v.InferOutput<typeof state>;
|
|
@@ -50,7 +49,6 @@ declare class Relay {
|
|
|
50
49
|
/**
|
|
51
50
|
* The relay id.
|
|
52
51
|
*/
|
|
53
|
-
|
|
54
52
|
id: number);
|
|
55
53
|
/**
|
|
56
54
|
* Reads the state of the relay.
|
|
@@ -80,4 +78,4 @@ declare class Relay {
|
|
|
80
78
|
}
|
|
81
79
|
//#endregion
|
|
82
80
|
export { relayState as a, States as i, RelaysApi as n, states as o, State as r, Relay as t };
|
|
83
|
-
//# sourceMappingURL=relays-
|
|
81
|
+
//# sourceMappingURL=relays-TADiLsPk.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relays-TADiLsPk.d.cts","names":[],"sources":["../src/api/relays.ts"],"mappings":";;;cAGM,OAAK,EAAA;KACC,QAAQ,EAAE,mBAAmB;cAC5B,QAAM,EAAA,YAAA,EAAA;KACP,SAAS,EAAE,mBAAmB;cAC7B,YAAU,EAAA;kBAAV,EAAA;;;cAOA;mBACkB;EAAA,YAAA,OAAO;;;;EAKpC,SAAK;;;;;;EASL,MAAM,aAAa;;;;;EAQnB,QAAQ,QAAQ;;;;;EAQhB,QAAQ,QAAQ;;;;;EAYhB,SAAS,QAAQ;;;cAUN;mBAEQ;;;;WAID;EAJC,YAAA,OAAO,SAIR;;;;EAAA;;;;;EAOZ,QAAQ,QAAQ;;;;;EAQhB,WAAW;;;;;EAQX,aAAa;;;;;EAQb,QAAQ,QAAQ;;;;;EAahB,SAAS,QAAQ"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { UpFetch } from "up-fetch";
|
|
2
2
|
import * as v from "valibot";
|
|
3
|
-
|
|
4
3
|
//#region src/api/relays.d.ts
|
|
5
4
|
declare const state: v.PicklistSchema<["open", "closed"], undefined>;
|
|
6
5
|
type State = v.InferOutput<typeof state>;
|
|
@@ -50,7 +49,6 @@ declare class Relay {
|
|
|
50
49
|
/**
|
|
51
50
|
* The relay id.
|
|
52
51
|
*/
|
|
53
|
-
|
|
54
52
|
id: number);
|
|
55
53
|
/**
|
|
56
54
|
* Reads the state of the relay.
|
|
@@ -80,4 +78,4 @@ declare class Relay {
|
|
|
80
78
|
}
|
|
81
79
|
//#endregion
|
|
82
80
|
export { relayState as a, States as i, RelaysApi as n, states as o, State as r, Relay as t };
|
|
83
|
-
//# sourceMappingURL=relays-
|
|
81
|
+
//# sourceMappingURL=relays-TADiLsPk.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relays-TADiLsPk.d.mts","names":[],"sources":["../src/api/relays.ts"],"mappings":";;;cAGM,OAAK,EAAA;KACC,QAAQ,EAAE,mBAAmB;cAC5B,QAAM,EAAA,YAAA,EAAA;KACP,SAAS,EAAE,mBAAmB;cAC7B,YAAU,EAAA;kBAAV,EAAA;;;cAOA;mBACkB;EAAA,YAAA,OAAO;;;;EAKpC,SAAK;;;;;;EASL,MAAM,aAAa;;;;;EAQnB,QAAQ,QAAQ;;;;;EAQhB,QAAQ,QAAQ;;;;;EAYhB,SAAS,QAAQ;;;cAUN;mBAEQ;;;;WAID;EAJC,YAAA,OAAO,SAIR;;;;EAAA;;;;;EAOZ,QAAQ,QAAQ;;;;;EAQhB,WAAW;;;;;EAQX,aAAa;;;;;EAQb,QAAQ,QAAQ;;;;;EAahB,SAAS,QAAQ"}
|
package/build/relays.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-CMqjfN_6.cjs");let t=require("valibot");t=e.t(t,1);const n=t.picklist([`open`,`closed`]),r=t.array(n),i=t.object({state:n}),a=t.picklist([`open`,`close`]);t.object({action:a});var o=class{fetch;constructor(e){this.fetch=e}reset(){return this.fetch(`/relays/reset`,{method:`POST`,parseResponse:()=>{}})}relay(e){return new s(this.fetch,e)}read(){return this.fetch(`/relays`,{schema:r})}open(){return this.fetch(`/relays`,{method:`POST`,body:{action:`open`},schema:r})}close(){return this.fetch(`/relays`,{method:`POST`,body:{action:`close`},schema:r})}},s=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}async read(){return(await this.fetch(`/relays/${this.id}`,{schema:i})).state}async is_open(){return await this.read()===`open`}async is_closed(){return await this.read()===`closed`}async open(){return(await this.fetch(`/relays/${this.id}`,{method:`POST`,body:{action:`open`},schema:i})).state}async close(){return(await this.fetch(`/relays/${this.id}`,{method:`POST`,body:{action:`close`},schema:i})).state}};exports.Relay=s,exports.RelaysApi=o,exports.relayState=i,exports.states=r;
|
|
2
2
|
//# sourceMappingURL=relays.cjs.map
|
package/build/relays.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relays.cjs","names":["v"],"sources":["../src/api/relays.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nconst state = v.picklist(['open', 'closed']);\nexport type State = v.InferOutput<typeof state>;\nexport const states = v.array(state);\nexport type States = v.InferOutput<typeof states>;\nexport const relayState = v.object({ state: state });\n\nconst action = v.picklist(['open', 'close']);\nconst relayAction = v.object({ action: action });\ntype RelayAction = v.InferOutput<typeof relayAction>;\n\n/** @hideconstructor */\nexport class RelaysApi {\n constructor(private readonly fetch: UpFetch) {}\n\n /**\n * Resets all relays to their default state.\n */\n reset() {\n return this.fetch('/relays/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific relay by id.\n * @param id The relay id.\n * @returns The relay instance.\n */\n relay(id: number): Relay {\n return new Relay(this.fetch, id);\n }\n\n /**\n * Reads the state of all relays.\n * @returns The state of all relays.\n */\n read(): Promise<States> {\n return this.fetch(`/relays`, { schema: states });\n }\n\n /**\n * Opens all the relays.\n * @returns The new state of all relays.\n */\n open(): Promise<States> {\n return this.fetch(`/relays`, {\n method: 'POST',\n body: { action: 'open' } satisfies RelayAction,\n schema: states,\n });\n }\n\n /**\n * Closes all the relays.\n * @returns The new state of all relays.\n */\n close(): Promise<States> {\n return this.fetch(`/relays`, {\n method: 'POST',\n body: { action: 'close' } satisfies RelayAction,\n schema: states,\n });\n }\n}\n\n/** @hideconstructor */\nexport class Relay {\n constructor(\n private readonly fetch: UpFetch,\n /**\n * The relay id.\n */\n public readonly id: number,\n ) {}\n\n /**\n * Reads the state of the relay.\n * @returns The relay state.\n */\n async read(): Promise<State> {\n return (await this.fetch(`/relays/${this.id}`, { schema: relayState })).state;\n }\n\n /**\n * Returns whether the relay is open.\n * @returns True if the relay is open, false otherwise.\n */\n async is_open(): Promise<boolean> {\n return (await this.read()) === 'open';\n }\n\n /**\n * Returns whether the relay is closed.\n * @returns True if the relay is closed, false otherwise.\n */\n async is_closed(): Promise<boolean> {\n return (await this.read()) === 'closed';\n }\n\n /**\n * Opens the relay.\n * @returns The new relay state.\n */\n async open(): Promise<State> {\n return (await this.fetch(`/relays/${this.id}`, {\n method: 'POST',\n body: { action: 'open' } satisfies RelayAction,\n schema: relayState,\n }))\n .state;\n }\n\n /**\n * Closes the relay.\n * @returns The new relay state.\n */\n async close(): Promise<State> {\n return (await this.fetch(`/relays/${this.id}`, {\n method: 'POST',\n body: { action: 'close' } satisfies RelayAction,\n schema: relayState,\n }))\n .state;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"relays.cjs","names":["v"],"sources":["../src/api/relays.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nconst state = v.picklist(['open', 'closed']);\nexport type State = v.InferOutput<typeof state>;\nexport const states = v.array(state);\nexport type States = v.InferOutput<typeof states>;\nexport const relayState = v.object({ state: state });\n\nconst action = v.picklist(['open', 'close']);\nconst relayAction = v.object({ action: action });\ntype RelayAction = v.InferOutput<typeof relayAction>;\n\n/** @hideconstructor */\nexport class RelaysApi {\n constructor(private readonly fetch: UpFetch) {}\n\n /**\n * Resets all relays to their default state.\n */\n reset() {\n return this.fetch('/relays/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific relay by id.\n * @param id The relay id.\n * @returns The relay instance.\n */\n relay(id: number): Relay {\n return new Relay(this.fetch, id);\n }\n\n /**\n * Reads the state of all relays.\n * @returns The state of all relays.\n */\n read(): Promise<States> {\n return this.fetch(`/relays`, { schema: states });\n }\n\n /**\n * Opens all the relays.\n * @returns The new state of all relays.\n */\n open(): Promise<States> {\n return this.fetch(`/relays`, {\n method: 'POST',\n body: { action: 'open' } satisfies RelayAction,\n schema: states,\n });\n }\n\n /**\n * Closes all the relays.\n * @returns The new state of all relays.\n */\n close(): Promise<States> {\n return this.fetch(`/relays`, {\n method: 'POST',\n body: { action: 'close' } satisfies RelayAction,\n schema: states,\n });\n }\n}\n\n/** @hideconstructor */\nexport class Relay {\n constructor(\n private readonly fetch: UpFetch,\n /**\n * The relay id.\n */\n public readonly id: number,\n ) {}\n\n /**\n * Reads the state of the relay.\n * @returns The relay state.\n */\n async read(): Promise<State> {\n return (await this.fetch(`/relays/${this.id}`, { schema: relayState })).state;\n }\n\n /**\n * Returns whether the relay is open.\n * @returns True if the relay is open, false otherwise.\n */\n async is_open(): Promise<boolean> {\n return (await this.read()) === 'open';\n }\n\n /**\n * Returns whether the relay is closed.\n * @returns True if the relay is closed, false otherwise.\n */\n async is_closed(): Promise<boolean> {\n return (await this.read()) === 'closed';\n }\n\n /**\n * Opens the relay.\n * @returns The new relay state.\n */\n async open(): Promise<State> {\n return (await this.fetch(`/relays/${this.id}`, {\n method: 'POST',\n body: { action: 'open' } satisfies RelayAction,\n schema: relayState,\n }))\n .state;\n }\n\n /**\n * Closes the relay.\n * @returns The new relay state.\n */\n async close(): Promise<State> {\n return (await this.fetch(`/relays/${this.id}`, {\n method: 'POST',\n body: { action: 'close' } satisfies RelayAction,\n schema: relayState,\n }))\n .state;\n }\n}\n"],"mappings":"0JAGA,MAAM,EAAQA,EAAE,SAAS,CAAC,OAAQ,QAAQ,CAAC,EAE9B,EAASA,EAAE,MAAM,CAAK,EAEtB,EAAaA,EAAE,OAAO,CAAS,OAAM,CAAC,EAE7C,EAASA,EAAE,SAAS,CAAC,OAAQ,OAAO,CAAC,EACvBA,EAAE,OAAO,CAAU,QAAO,CAAC,EAI/C,IAAa,EAAb,KAAuB,CACQ,MAA7B,YAAY,EAAiC,CAAhB,KAAA,MAAA,CAAiB,CAK9C,OAAQ,CACN,OAAO,KAAK,MAAM,gBAAiB,CAAE,OAAQ,OAAQ,kBAAqB,CAAC,CAAE,CAAC,CAChF,CAOA,MAAM,EAAmB,CACvB,OAAO,IAAI,EAAM,KAAK,MAAO,CAAE,CACjC,CAMA,MAAwB,CACtB,OAAO,KAAK,MAAM,UAAW,CAAE,OAAQ,CAAO,CAAC,CACjD,CAMA,MAAwB,CACtB,OAAO,KAAK,MAAM,UAAW,CAC3B,OAAQ,OACR,KAAM,CAAE,OAAQ,MAAO,EACvB,OAAQ,CACV,CAAC,CACH,CAMA,OAAyB,CACvB,OAAO,KAAK,MAAM,UAAW,CAC3B,OAAQ,OACR,KAAM,CAAE,OAAQ,OAAQ,EACxB,OAAQ,CACV,CAAC,CACH,CACF,EAGa,EAAb,KAAmB,CAEE,MAID,GALlB,YACE,EAIA,EACA,CALiB,KAAA,MAAA,EAID,KAAA,GAAA,CACf,CAMH,MAAM,MAAuB,CAC3B,OAAQ,MAAM,KAAK,MAAM,WAAW,KAAK,KAAM,CAAE,OAAQ,CAAW,CAAC,EAAA,CAAG,KAC1E,CAMA,MAAM,SAA4B,CAChC,OAAQ,MAAM,KAAK,KAAK,IAAO,MACjC,CAMA,MAAM,WAA8B,CAClC,OAAQ,MAAM,KAAK,KAAK,IAAO,QACjC,CAMA,MAAM,MAAuB,CAC3B,OAAQ,MAAM,KAAK,MAAM,WAAW,KAAK,KAAM,CAC7C,OAAQ,OACR,KAAM,CAAE,OAAQ,MAAO,EACvB,OAAQ,CACV,CAAC,EAAA,CACE,KACL,CAMA,MAAM,OAAwB,CAC5B,OAAQ,MAAM,KAAK,MAAM,WAAW,KAAK,KAAM,CAC7C,OAAQ,OACR,KAAM,CAAE,OAAQ,OAAQ,EACxB,OAAQ,CACV,CAAC,EAAA,CACE,KACL,CACF"}
|
package/build/relays.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as relayState, i as States, n as RelaysApi, o as states, r as State, t as Relay } from "./relays-
|
|
1
|
+
import { a as relayState, i as States, n as RelaysApi, o as states, r as State, t as Relay } from "./relays-TADiLsPk.cjs";
|
|
2
2
|
export { Relay, RelaysApi, State, States, relayState, states };
|
package/build/relays.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as relayState, i as States, n as RelaysApi, o as states, r as State, t as Relay } from "./relays-
|
|
1
|
+
import { a as relayState, i as States, n as RelaysApi, o as states, r as State, t as Relay } from "./relays-TADiLsPk.mjs";
|
|
2
2
|
export { Relay, RelaysApi, State, States, relayState, states };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { UpFetch } from "up-fetch";
|
|
2
2
|
import * as v from "valibot";
|
|
3
|
-
|
|
4
3
|
//#region src/api/session.d.ts
|
|
5
4
|
declare const sessionState: v.ObjectSchema<{
|
|
6
5
|
readonly active: v.BooleanSchema<undefined>;
|
|
@@ -41,4 +40,4 @@ declare class SessionApi {
|
|
|
41
40
|
}
|
|
42
41
|
//#endregion
|
|
43
42
|
export { sessionState as a, open_session as i, SessionOpenBody as n, SessionState as r, SessionApi as t };
|
|
44
|
-
//# sourceMappingURL=session-
|
|
43
|
+
//# sourceMappingURL=session-qWW9mqWH.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-qWW9mqWH.d.cts","names":[],"sources":["../src/api/session.ts"],"mappings":";;;cAKa,cAAY,EAAA;;;;;;;KAOb,eAAe,EAAE,mBAAmB;;KAGpC;EAAoB;EAA4B;EAAgB;;;;;;;;;;;;;;iBAgBtD,aACpB,iBACA,MAAM,kBACL;;cAmBU;mBACkB;EAAA,YAAA,OAAO;;;;;EAMpC,SAAS,QAAQ"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { UpFetch } from "up-fetch";
|
|
2
2
|
import * as v from "valibot";
|
|
3
|
-
|
|
4
3
|
//#region src/api/session.d.ts
|
|
5
4
|
declare const sessionState: v.ObjectSchema<{
|
|
6
5
|
readonly active: v.BooleanSchema<undefined>;
|
|
@@ -41,4 +40,4 @@ declare class SessionApi {
|
|
|
41
40
|
}
|
|
42
41
|
//#endregion
|
|
43
42
|
export { sessionState as a, open_session as i, SessionOpenBody as n, SessionState as r, SessionApi as t };
|
|
44
|
-
//# sourceMappingURL=session-
|
|
43
|
+
//# sourceMappingURL=session-qWW9mqWH.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-qWW9mqWH.d.mts","names":[],"sources":["../src/api/session.ts"],"mappings":";;;cAKa,cAAY,EAAA;;;;;;;KAOb,eAAe,EAAE,mBAAmB;;KAGpC;EAAoB;EAA4B;EAAgB;;;;;;;;;;;;;;iBAgBtD,aACpB,iBACA,MAAM,kBACL;;cAmBU;mBACkB;EAAA,YAAA,OAAO;;;;;EAMpC,SAAS,QAAQ"}
|
package/build/session.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./at1000-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./at1000-DbIvMQUc.cjs");exports.SessionApi=e.s,exports.open_session=e.c,exports.sessionState=e.l;
|
package/build/session.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as sessionState, i as open_session, n as SessionOpenBody, r as SessionState, t as SessionApi } from "./session-
|
|
1
|
+
import { a as sessionState, i as open_session, n as SessionOpenBody, r as SessionState, t as SessionApi } from "./session-qWW9mqWH.cjs";
|
|
2
2
|
export { SessionApi, SessionOpenBody, SessionState, open_session, sessionState };
|
package/build/session.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as sessionState, i as open_session, n as SessionOpenBody, r as SessionState, t as SessionApi } from "./session-
|
|
1
|
+
import { a as sessionState, i as open_session, n as SessionOpenBody, r as SessionState, t as SessionApi } from "./session-qWW9mqWH.mjs";
|
|
2
2
|
export { SessionApi, SessionOpenBody, SessionState, open_session, sessionState };
|