ironflock 1.2.9 → 1.3.3

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 CHANGED
@@ -167,6 +167,85 @@ await ironflock.appendToTable("sensordata", [{ temperature: 22.5, humidity: 60 }
167
167
 
168
168
  ---
169
169
 
170
+ ### `publishRowsToTable(tablename, rows, kwargs?)`
171
+
172
+ Publishes **many rows in a single message** (bulk insert) to the dedicated topic `bulk.<SWARM_KEY>.<APP_KEY>.<tablename>`. The platform inserts the whole batch atomically (all-or-nothing) in one operation. Use this for high-frequency data where one round-trip per row is too costly. Like `publishToTable`, this is fire-and-forget — the ack confirms delivery to the router, not the DB insert.
173
+
174
+ ```ts
175
+ await ironflock.publishRowsToTable("sensordata", [
176
+ { tsp: "2024-01-15T10:30:00.000Z", temperature: 22.5 },
177
+ { tsp: "2024-01-15T10:30:01.000Z", temperature: 22.7 },
178
+ ]);
179
+ ```
180
+
181
+ | Parameter | Type | Description |
182
+ |-----------|------|-------------|
183
+ | `tablename` | `string` | The name of the table, e.g. `"sensordata"` |
184
+ | `rows` | `Record<string, unknown>[]` | Non-empty array of row objects to insert |
185
+ | `kwargs` | `Record<string, unknown>`, optional | Extra arguments shared by the whole batch |
186
+
187
+ **Returns:** `Promise<unknown>` — The publication object (an acknowledged publish receipt).
188
+
189
+ ---
190
+
191
+ ### `appendRowsToTable(tablename, rows, kwargs?)`
192
+
193
+ Appends **many rows in a single RPC** (bulk insert) by calling the dedicated procedure `appendBulk.<SWARM_KEY>.<APP_KEY>.<tablename>`. The platform inserts the whole batch atomically (all-or-nothing): if any row is invalid the entire batch is rejected and nothing is persisted. Prefer this over `publishRowsToTable` when you need the insert outcome.
194
+
195
+ ```ts
196
+ const result = await ironflock.appendRowsToTable("sensordata", [
197
+ { tsp: "2024-01-15T10:30:00.000Z", temperature: 22.5 },
198
+ { tsp: "2024-01-15T10:30:01.000Z", temperature: 22.7 },
199
+ ]);
200
+ // result -> { success: true, count: 2 }
201
+ ```
202
+
203
+ | Parameter | Type | Description |
204
+ |-----------|------|-------------|
205
+ | `tablename` | `string` | The name of the table, e.g. `"sensordata"` |
206
+ | `rows` | `Record<string, unknown>[]` | Non-empty array of row objects to insert |
207
+ | `kwargs` | `Record<string, unknown>`, optional | Extra arguments shared by the whole batch |
208
+
209
+ **Returns:** `Promise<unknown>` — The result of the remote procedure call (e.g. `{ success: true, count: N }`).
210
+
211
+ ---
212
+
213
+ ### `reportError(error, opts?)`
214
+
215
+ Reports an application error into the fleet's `error-logs` table. This is a convenience wrapper over `publishToTable` / `appendToTable`: it stamps the row with `source: "app"`, a severity `level`, and a timestamp, then writes it like any normal table row. The error lands in the same per-databackend `error-logs` table that fleetdb system errors use (tagged `source: "system"`), so it is queryable with `getHistory`, streamable with `subscribeToTable`, usable in board-templates, and delivered in realtime on `transformed.error-logs` — without firing the platform's system-error toast.
216
+
217
+ ```ts
218
+ // Fire-and-forget (default): publishes to the error-logs table
219
+ await ironflock.reportError("Sensor read timed out", { level: "warn" });
220
+
221
+ // Pass an Error to capture its stack (falls back to the message)
222
+ try {
223
+ riskyOperation();
224
+ } catch (err) {
225
+ await ironflock.reportError(err as Error);
226
+ }
227
+
228
+ // Use the append RPC when you want to await the insert outcome
229
+ await ironflock.reportError("Calibration failed", { level: "error", append: true });
230
+ ```
231
+
232
+ | Parameter | Type | Description |
233
+ |-----------|------|-------------|
234
+ | `error` | `string \| Error` | The error message, or an `Error` whose stack (or message) is recorded |
235
+ | `opts` | `ReportErrorOptions`, optional | Options (see below) |
236
+
237
+ **opts fields:**
238
+
239
+ | Field | Type | Description |
240
+ |-------|------|-------------|
241
+ | `level` | `ErrorLevel`, optional | Severity: `"error"`, `"warn"`, `"info"` or `"debug"`. Defaults to `"error"` |
242
+ | `append` | `boolean`, optional | When `true`, use the append RPC (resolves with the insert outcome). Defaults to `false` (fire-and-forget publish) |
243
+ | `tsp` | `string`, optional | ISO-8601 timestamp override. Defaults to the current time |
244
+
245
+ **Returns:** `Promise<unknown>` — The publication object, or — with `append: true` — the result of the remote procedure call.
246
+
247
+ ---
248
+
170
249
  ### `subscribe(topic, handler)`
171
250
 
172
251
  Subscribes to a topic on the IronFlock message router.
@@ -190,7 +269,7 @@ const subscription = await ironflock.subscribe("com.myapp.mytopic", onMessage);
190
269
 
191
270
  ### `subscribeToTable(tablename, handler)`
192
271
 
193
- Convenience function to subscribe to a fleet table. Automatically constructs the correct topic using the `SWARM_KEY` and `APP_KEY` environment variables.
272
+ Convenience function to subscribe to a fleet table. Automatically constructs the correct topic using the `SWARM_KEY` and `APP_KEY` environment variables. Receives rows written via both the single-row and the bulk insert paths — rows from a bulk insert are delivered to your handler one at a time, so handler code stays the same.
194
273
 
195
274
  ```ts
196
275
  function onTableData(...args: any[]) {
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("autobahn");function F(d){return d&&d.__esModule&&Object.prototype.hasOwnProperty.call(d,"default")?d.default:d}var I={exports:{}},N;function W(){return N||(N=1,(function(d){var r=Object.prototype.hasOwnProperty,s="~";function o(){}Object.create&&(o.prototype=Object.create(null),new o().__proto__||(s=!1));function c(a,e,n){this.fn=a,this.context=e,this.once=n||!1}function i(a,e,n,l,h){if(typeof n!="function")throw new TypeError("The listener must be a function");var v=new c(n,l||a,h),g=s?s+e:e;return a._events[g]?a._events[g].fn?a._events[g]=[a._events[g],v]:a._events[g].push(v):(a._events[g]=v,a._eventsCount++),a}function u(a,e){--a._eventsCount===0?a._events=new o:delete a._events[e]}function t(){this._events=new o,this._eventsCount=0}t.prototype.eventNames=function(){var e=[],n,l;if(this._eventsCount===0)return e;for(l in n=this._events)r.call(n,l)&&e.push(s?l.slice(1):l);return Object.getOwnPropertySymbols?e.concat(Object.getOwnPropertySymbols(n)):e},t.prototype.listeners=function(e){var n=s?s+e:e,l=this._events[n];if(!l)return[];if(l.fn)return[l.fn];for(var h=0,v=l.length,g=new Array(v);h<v;h++)g[h]=l[h].fn;return g},t.prototype.listenerCount=function(e){var n=s?s+e:e,l=this._events[n];return l?l.fn?1:l.length:0},t.prototype.emit=function(e,n,l,h,v,g){var w=s?s+e:e;if(!this._events[w])return!1;var f=this._events[w],b=arguments.length,_,y;if(f.fn){switch(f.once&&this.removeListener(e,f.fn,void 0,!0),b){case 1:return f.fn.call(f.context),!0;case 2:return f.fn.call(f.context,n),!0;case 3:return f.fn.call(f.context,n,l),!0;case 4:return f.fn.call(f.context,n,l,h),!0;case 5:return f.fn.call(f.context,n,l,h,v),!0;case 6:return f.fn.call(f.context,n,l,h,v,g),!0}for(y=1,_=new Array(b-1);y<b;y++)_[y-1]=arguments[y];f.fn.apply(f.context,_)}else{var U=f.length,A;for(y=0;y<U;y++)switch(f[y].once&&this.removeListener(e,f[y].fn,void 0,!0),b){case 1:f[y].fn.call(f[y].context);break;case 2:f[y].fn.call(f[y].context,n);break;case 3:f[y].fn.call(f[y].context,n,l);break;case 4:f[y].fn.call(f[y].context,n,l,h);break;default:if(!_)for(A=1,_=new Array(b-1);A<b;A++)_[A-1]=arguments[A];f[y].fn.apply(f[y].context,_)}}return!0},t.prototype.on=function(e,n,l){return i(this,e,n,l,!1)},t.prototype.once=function(e,n,l){return i(this,e,n,l,!0)},t.prototype.removeListener=function(e,n,l,h){var v=s?s+e:e;if(!this._events[v])return this;if(!n)return u(this,v),this;var g=this._events[v];if(g.fn)g.fn===n&&(!h||g.once)&&(!l||g.context===l)&&u(this,v);else{for(var w=0,f=[],b=g.length;w<b;w++)(g[w].fn!==n||h&&!g[w].once||l&&g[w].context!==l)&&f.push(g[w]);f.length?this._events[v]=f.length===1?f[0]:f:u(this,v)}return this},t.prototype.removeAllListeners=function(e){var n;return e?(n=s?s+e:e,this._events[n]&&u(this,n)):(this._events=new o,this._eventsCount=0),this},t.prototype.off=t.prototype.removeListener,t.prototype.addListener=t.prototype.on,t.prefixed=s,t.EventEmitter=t,d.exports=t})(I)),I.exports}var V=W();const Y=F(V),Q="wss://cbw.datapods.io/ws-ua-usr",P="wss://cbw.ironflock.com/ws-ua-usr",J="wss://cbw.ironflock.dev/ws-ua-usr",B="wss://cbw.record-evolution.com/ws-ua-usr",$="ws://localhost:8080/ws-ua-usr",T={"https://studio.datapods.io":Q,"https://studio.ironflock.dev":J,"https://studio.ironflock.com":P,"https://studio.record-evolution.com":B,"http://localhost:8085":$,"http://localhost:8086":$,"http://host.docker.internal:8086":$},H=6e3;class k extends Y{constructor(){super(),this.subscriptions=[],this.registrations=[],this.firstResolver=()=>{},this.firstRejecter=()=>{},this.shouldReconnect=!1,this.isReconnecting=!1,this.hasOpenedOnce=!1}static getWebSocketURI(r){var c;const s=typeof process<"u"?(c=process.env)==null?void 0:c.DEVICE_ENDPOINT_URL:void 0;if(s)try{const i=new URL(s);return i.pathname="/ws-ua-usr",i.toString().replace(/\/$/,"")}catch{}if(!r)return P;const o=T[r];if(o===void 0)throw new Error(`Cannot resolve WebSocket URI for reswarmUrl=${JSON.stringify(r)}. Set DEVICE_ENDPOINT_URL to the deployment's WAMP router URL (e.g. ws://<host>:18080/ws-re-dev) or pass ironFlockUrl=… to IronFlock(). Known cloud URLs: ${JSON.stringify(Object.keys(T))}`);return o}configure(r,s,o,c,i){this.realm=`realm-${r}-${s}-${o}`,this.serial_number=c,this.socketURI=i??k.getWebSocketURI()}async start(){if(!this.realm||!this.serial_number||!this.socketURI)throw new Error("CrossbarConnection must be configured before starting. Call configure() first.");return this.shouldReconnect=!0,this.firstConnection=new Promise((r,s)=>{this.firstResolver=r,this.firstRejecter=s}),this.connection=new x.Connection({realm:this.realm,url:this.socketURI,authmethods:["wampcra"],authid:this.serial_number,max_retries:-1,max_retry_delay:2,initial_retry_delay:1,autoping_interval:2,autoping_timeout:4,onchallenge:(r,s,o)=>x.auth_cra.sign(this.serial_number,o.challenge)}),this.connection.onopen=this.onOpen.bind(this),this.connection.onclose=this.onClose.bind(this),this.connection.open(),this.firstConnection}onOpen(r){this.session=r,this.session.caller_disclose_me=!0,this.hasOpenedOnce=!0,this.resubscribeAll(),this.reregisterAll(),this.emit("connected",this.serial_number),this.firstResolver(),this.firstResolver=()=>{}}onClose(r,s){return this.session=void 0,this.emit("disconnected"),this.firstRejecter(new Error(`Connection failed: ${r} - ${JSON.stringify(s,null,2)}`)),this.firstRejecter=()=>{},console.warn("Connection closed:",{reason:r,details:s,realm:this.realm,url:this.socketURI,authid:this.serial_number}),this.shouldReconnect&&this.hasOpenedOnce&&(s==null?void 0:s.will_retry)===!1&&this.handleManualReconnect((s==null?void 0:s.reason)??r),!1}async handleManualReconnect(r){if(!(this.isReconnecting||!this.shouldReconnect)){for(this.isReconnecting=!0;this.shouldReconnect&&!this.session;)if(await new Promise(s=>setTimeout(s,1e3)),this.shouldReconnect&&this.connection&&!this.session){console.log(`Manually retrying connection after ${r}...`);try{this.connection.open(),await new Promise(s=>setTimeout(s,500))}catch(s){console.error("Error during manual reconnection attempt:",s)}}this.isReconnecting=!1}}async sessionWait(){const r=Date.now();for(;!this.session;){if(Date.now()-r>H)throw new Error("Timeout waiting for session");await new Promise(s=>setTimeout(s,200))}}async waitForConnection(){return this.firstConnection}getSession(){return this.session}get is_open(){var r;return!!((r=this.session)!=null&&r.isOpen)}isConnected(){return this.is_open}stop(){var r;this.shouldReconnect=!1,(r=this.connection)==null||r.close("wamp.close.normal","Connection closed by client")}async subscribe(r,s){var c;await this.sessionWait();const o=await((c=this.session)==null?void 0:c.subscribe(r,s));return o&&this.subscriptions.push(o),o}async unsubscribe(r){var o;await this.sessionWait();const s=this.subscriptions.indexOf(r);s!==-1&&(this.subscriptions.splice(s,1),await((o=this.session)==null?void 0:o.unsubscribe(r)))}async unsubscribeTopic(r){const s=this.subscriptions.filter(o=>o.topic===r);for(const o of s)await this.unsubscribe(o)}async resubscribeAll(){const r=[...this.subscriptions];this.subscriptions=[],await Promise.all(r.map(s=>this.subscribe(s.topic,s.handler)))}async reregisterAll(){const r=[...this.registrations];this.registrations=[],await Promise.all(r.map(s=>this.register(s.procedure,s.endpoint,s.options)))}async register(r,s,o){var u;await this.sessionWait();const c={force_reregister:!0,...o??{}},i=await((u=this.session)==null?void 0:u.register(r,s,c));return i&&this.registrations.push(i),i}async unregister(r){var o;await this.sessionWait(),await((o=this.session)==null?void 0:o.unregister(r));const s=this.registrations.indexOf(r);s!==-1&&this.registrations.splice(s,1)}async call(r,s,o,c){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.call(r,s,o,c)}async publish(r,s,o,c){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.publish(r,s,o,c)}}const M=d=>Math.floor(d)===d&&q<=d&&d<=G,q=0,G=2**32-1,S=d=>X.test(d),X=/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(T|\s)([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$/i,R=d=>{const r=s=>{if(d.length===0)return!0;const o=d[d.length-1].path;return s.length>o.length||o.substring(0,s.length)!==s};return(s,o)=>(s&&r(o.path)&&(o.value===void 0&&(o.description??(o.description=["The value at this path is `undefined`.","",`Please fill the \`${o.expected}\` typed value next time.`].join(`
2
- `))),d.push(o)),!1)},K=d=>Object.assign(d,{"~standard":{version:1,vendor:"typia",validate:r=>{const s=d(r);return s.success?{value:s.data}:{issues:s.errors.map(o=>({message:`expected ${o.expected}, got ${o.value}`,path:Z(o.path)}))}}}});var m;(function(d){d[d.Start=0]="Start",d[d.Property=1]="Property",d[d.StringKey=2]="StringKey",d[d.NumberKey=3]="NumberKey"})(m||(m={}));const Z=d=>{if(!d.startsWith("$input"))throw new Error(`Invalid path: ${JSON.stringify(d)}`);const r=[];let s="",o=m.Start,c=5;for(;c<d.length-1;){c++;const i=d[c];if(o===m.Property?i==="."||i==="["?(r.push({key:s}),o=m.Start):c===d.length-1?(s+=i,r.push({key:s}),c++,o=m.Start):s+=i:o===m.StringKey?i==='"'?(r.push({key:JSON.parse(s+i)}),c+=2,o=m.Start):i==="\\"?(s+=d[c],c++,s+=d[c]):s+=i:o===m.NumberKey&&(i==="]"?(r.push({key:Number.parseInt(s)}),c++,o=m.Start):s+=i),o===m.Start&&c<d.length-1){const u=d[c];if(s="",u==="[")d[c+1]==='"'?(o=m.StringKey,c++,s='"'):o=m.NumberKey;else if(u===".")o=m.Property;else throw new Error("Unreachable: pointer points invalid character")}}if(o!==m.Start)throw new Error(`Failed to parse path: ${JSON.stringify(d)}`);return r};var p=(d=>(d.DEVELOPMENT="dev",d.PRODUCTION="prod",d))(p||{});const L=(()=>{const d=e=>typeof e.limit=="number"&&M(e.limit)&&1<=e.limit&&e.limit<=1e4&&(e.offset===void 0||typeof e.offset=="number"&&M(e.offset)&&0<=e.offset)&&(e.timeRange===void 0||typeof e.timeRange=="object"&&e.timeRange!==null&&r(e.timeRange))&&(e.filterAnd===void 0||Array.isArray(e.filterAnd)&&e.filterAnd.every(n=>typeof n=="object"&&n!==null&&s(n))),r=e=>typeof e.start=="string"&&S(e.start)&&typeof e.end=="string"&&S(e.end),s=e=>typeof e.column=="string"&&1<=e.column.length&&typeof e.operator=="string"&&1<=e.operator.length&&e.value!==null&&e.value!==void 0&&(typeof e.value=="string"||typeof e.value=="number"||typeof e.value=="boolean"||Array.isArray(e.value)&&e.value.every(n=>typeof n=="string"||typeof n=="number")),o=(e,n,l=!0)=>[typeof e.limit=="number"&&(M(e.limit)||a(l,{path:n+".limit",expected:'number & Type<"uint32">',value:e.limit}))&&(1<=e.limit||a(l,{path:n+".limit",expected:"number & Minimum<1>",value:e.limit}))&&(e.limit<=1e4||a(l,{path:n+".limit",expected:"number & Maximum<10000>",value:e.limit}))||a(l,{path:n+".limit",expected:'(number & Type<"uint32"> & Minimum<1> & Maximum<10000>)',value:e.limit}),e.offset===void 0||typeof e.offset=="number"&&(M(e.offset)||a(l,{path:n+".offset",expected:'number & Type<"uint32">',value:e.offset}))&&(0<=e.offset||a(l,{path:n+".offset",expected:"number & Minimum<0>",value:e.offset}))||a(l,{path:n+".offset",expected:'((number & Type<"uint32"> & Minimum<0>) | undefined)',value:e.offset}),e.timeRange===void 0||(typeof e.timeRange=="object"&&e.timeRange!==null||a(l,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:e.timeRange}))&&c(e.timeRange,n+".timeRange",l)||a(l,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:e.timeRange}),e.filterAnd===void 0||(Array.isArray(e.filterAnd)||a(l,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:e.filterAnd}))&&e.filterAnd.map((h,v)=>(typeof h=="object"&&h!==null||a(l,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:h}))&&i(h,n+".filterAnd["+v+"]",l)||a(l,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:h})).every(h=>h)||a(l,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:e.filterAnd})].every(h=>h),c=(e,n,l=!0)=>[typeof e.start=="string"&&(S(e.start)||a(l,{path:n+".start",expected:'string & Format<"date-time">',value:e.start}))||a(l,{path:n+".start",expected:'(string & Format<"date-time">)',value:e.start}),typeof e.end=="string"&&(S(e.end)||a(l,{path:n+".end",expected:'string & Format<"date-time">',value:e.end}))||a(l,{path:n+".end",expected:'(string & Format<"date-time">)',value:e.end})].every(h=>h),i=(e,n,l=!0)=>[typeof e.column=="string"&&(1<=e.column.length||a(l,{path:n+".column",expected:"string & MinLength<1>",value:e.column}))||a(l,{path:n+".column",expected:"(string & MinLength<1>)",value:e.column}),typeof e.operator=="string"&&(1<=e.operator.length||a(l,{path:n+".operator",expected:"string & MinLength<1>",value:e.operator}))||a(l,{path:n+".operator",expected:"(string & MinLength<1>)",value:e.operator}),(e.value!==null||a(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&(e.value!==void 0||a(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&(typeof e.value=="string"||typeof e.value=="number"||typeof e.value=="boolean"||(Array.isArray(e.value)||a(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&e.value.map((h,v)=>typeof h=="string"||typeof h=="number"||a(l,{path:n+".value["+v+"]",expected:"(number | string)",value:h})).every(h=>h)||a(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))].every(h=>h),u=e=>typeof e=="object"&&e!==null&&d(e);let t,a;return K(e=>{if(u(e)===!1){t=[],a=R(t),((l,h,v=!0)=>(typeof l=="object"&&l!==null||a(!0,{path:h+"",expected:"TableQueryParams",value:l}))&&o(l,h+"",!0)||a(!0,{path:h+"",expected:"TableQueryParams",value:l}))(e,"$input",!0);const n=t.length===0;return n?{success:n,data:e}:{success:n,errors:t,data:e}}return{success:!0,data:e}})})(),j=(()=>{const d=i=>typeof i.longitude=="number"&&-180<=i.longitude&&i.longitude<=180&&typeof i.latitude=="number"&&-90<=i.latitude&&i.latitude<=90,r=(i,u,t=!0)=>[typeof i.longitude=="number"&&(-180<=i.longitude||c(t,{path:u+".longitude",expected:"number & Minimum<-180>",value:i.longitude}))&&(i.longitude<=180||c(t,{path:u+".longitude",expected:"number & Maximum<180>",value:i.longitude}))||c(t,{path:u+".longitude",expected:"(number & Minimum<-180> & Maximum<180>)",value:i.longitude}),typeof i.latitude=="number"&&(-90<=i.latitude||c(t,{path:u+".latitude",expected:"number & Minimum<-90>",value:i.latitude}))&&(i.latitude<=90||c(t,{path:u+".latitude",expected:"number & Maximum<90>",value:i.latitude}))||c(t,{path:u+".latitude",expected:"(number & Minimum<-90> & Maximum<90>)",value:i.latitude})].every(a=>a),s=i=>typeof i=="object"&&i!==null&&d(i);let o,c;return K(i=>{if(s(i)===!1){o=[],c=R(o),((t,a,e=!0)=>(typeof t=="object"&&t!==null||c(!0,{path:a+"",expected:"LocationParams",value:t}))&&r(t,a+"",!0)||c(!0,{path:a+"",expected:"LocationParams",value:t}))(i,"$input",!0);const u=o.length===0;return u?{success:u,data:i}:{success:u,errors:o,data:i}}return{success:!0,data:i}})})(),D=(()=>{const d=t=>typeof t.topic=="string"&&1<=t.topic.length&&(t.args===void 0||Array.isArray(t.args))&&(t.kwargs===void 0||typeof t.kwargs=="object"&&t.kwargs!==null&&Array.isArray(t.kwargs)===!1&&r(t.kwargs)),r=t=>Object.keys(t).every(a=>(t[a]===void 0,!0)),s=(t,a,e=!0)=>[typeof t.topic=="string"&&(1<=t.topic.length||u(e,{path:a+".topic",expected:"string & MinLength<1>",value:t.topic}))||u(e,{path:a+".topic",expected:"(string & MinLength<1>)",value:t.topic}),t.args===void 0||Array.isArray(t.args)||u(e,{path:a+".args",expected:"(Array<unknown> | undefined)",value:t.args}),t.kwargs===void 0||(typeof t.kwargs=="object"&&t.kwargs!==null&&Array.isArray(t.kwargs)===!1||u(e,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:t.kwargs}))&&o(t.kwargs,a+".kwargs",e)||u(e,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:t.kwargs})].every(n=>n),o=(t,a,e=!0)=>[e===!1||Object.keys(t).map(n=>(t[n]===void 0,!0)).every(n=>n)].every(n=>n),c=t=>typeof t=="object"&&t!==null&&d(t);let i,u;return K(t=>{if(c(t)===!1){i=[],u=R(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"PublishParams",value:e}))&&s(e,n+"",!0)||u(!0,{path:n+"",expected:"PublishParams",value:e}))(t,"$input",!0);const a=i.length===0;return a?{success:a,data:t}:{success:a,errors:i,data:t}}return{success:!0,data:t}})})(),z=(()=>{const d=t=>typeof t.deviceKey=="string"&&1<=t.deviceKey.length&&typeof t.topic=="string"&&1<=t.topic.length&&(t.args===void 0||Array.isArray(t.args))&&(t.kwargs===void 0||typeof t.kwargs=="object"&&t.kwargs!==null&&Array.isArray(t.kwargs)===!1&&r(t.kwargs)),r=t=>Object.keys(t).every(a=>(t[a]===void 0,!0)),s=(t,a,e=!0)=>[typeof t.deviceKey=="string"&&(1<=t.deviceKey.length||u(e,{path:a+".deviceKey",expected:"string & MinLength<1>",value:t.deviceKey}))||u(e,{path:a+".deviceKey",expected:"(string & MinLength<1>)",value:t.deviceKey}),typeof t.topic=="string"&&(1<=t.topic.length||u(e,{path:a+".topic",expected:"string & MinLength<1>",value:t.topic}))||u(e,{path:a+".topic",expected:"(string & MinLength<1>)",value:t.topic}),t.args===void 0||Array.isArray(t.args)||u(e,{path:a+".args",expected:"(Array<unknown> | undefined)",value:t.args}),t.kwargs===void 0||(typeof t.kwargs=="object"&&t.kwargs!==null&&Array.isArray(t.kwargs)===!1||u(e,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:t.kwargs}))&&o(t.kwargs,a+".kwargs",e)||u(e,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:t.kwargs})].every(n=>n),o=(t,a,e=!0)=>[e===!1||Object.keys(t).map(n=>(t[n]===void 0,!0)).every(n=>n)].every(n=>n),c=t=>typeof t=="object"&&t!==null&&d(t);let i,u;return K(t=>{if(c(t)===!1){i=[],u=R(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"CallParams",value:e}))&&s(e,n+"",!0)||u(!0,{path:n+"",expected:"CallParams",value:e}))(t,"$input",!0);const a=i.length===0;return a?{success:a,data:t}:{success:a,errors:i,data:t}}return{success:!0,data:t}})})(),O=(()=>{const d=t=>typeof t.tablename=="string"&&1<=t.tablename.length&&(t.args===void 0||Array.isArray(t.args))&&(t.kwargs===void 0||typeof t.kwargs=="object"&&t.kwargs!==null&&Array.isArray(t.kwargs)===!1&&r(t.kwargs)),r=t=>Object.keys(t).every(a=>(t[a]===void 0,!0)),s=(t,a,e=!0)=>[typeof t.tablename=="string"&&(1<=t.tablename.length||u(e,{path:a+".tablename",expected:"string & MinLength<1>",value:t.tablename}))||u(e,{path:a+".tablename",expected:"(string & MinLength<1>)",value:t.tablename}),t.args===void 0||Array.isArray(t.args)||u(e,{path:a+".args",expected:"(Array<unknown> | undefined)",value:t.args}),t.kwargs===void 0||(typeof t.kwargs=="object"&&t.kwargs!==null&&Array.isArray(t.kwargs)===!1||u(e,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:t.kwargs}))&&o(t.kwargs,a+".kwargs",e)||u(e,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:t.kwargs})].every(n=>n),o=(t,a,e=!0)=>[e===!1||Object.keys(t).map(n=>(t[n]===void 0,!0)).every(n=>n)].every(n=>n),c=t=>typeof t=="object"&&t!==null&&d(t);let i,u;return K(t=>{if(c(t)===!1){i=[],u=R(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"TableParams",value:e}))&&s(e,n+"",!0)||u(!0,{path:n+"",expected:"TableParams",value:e}))(t,"$input",!0);const a=i.length===0;return a?{success:a,data:t}:{success:a,errors:i,data:t}}return{success:!0,data:t}})})();function E(d){var r;return typeof process<"u"?(r=process.env)==null?void 0:r[d]:void 0}function ee(d){const r=d??E("DEVICE_SERIAL_NUMBER");if(!r)throw new Error("serialNumber option is required (or set DEVICE_SERIAL_NUMBER env var in Node.js)");return r}class C{constructor(r){this._isConfigured=!1,this._serialNumber=ee(r==null?void 0:r.serialNumber),this._deviceName=(r==null?void 0:r.deviceName)??E("DEVICE_NAME"),this._deviceKey=(r==null?void 0:r.deviceKey)??E("DEVICE_KEY"),this._appName=(r==null?void 0:r.appName)??E("APP_NAME"),this._swarmKey=(r==null?void 0:r.swarmKey)??parseInt(E("SWARM_KEY")??"0",10),this._appKey=(r==null?void 0:r.appKey)??parseInt(E("APP_KEY")??"0",10),this._env=(r==null?void 0:r.env)??E("ENV"),this._reswarmUrl=(r==null?void 0:r.reswarmUrl)??E("RESWARM_URL"),this._cburl=(r==null?void 0:r.ironFlockUrl)??(r==null?void 0:r.cburl),this._connection=new k;const s=[];this._deviceKey||s.push("DEVICE_KEY"),this._appName||s.push("APP_NAME"),this._swarmKey||s.push("SWARM_KEY"),this._appKey||s.push("APP_KEY"),s.length>0&&console.warn(`Warning: The following environment variables must be present: ${s.join(", ")}`)}get connection(){return this._connection}get isConnected(){return this._connection.is_open}configureConnection(r){if(this._isConfigured)return;const s=(this._env??"DEV").toUpperCase(),c={DEV:p.DEVELOPMENT,PROD:p.PRODUCTION}[s]??p.DEVELOPMENT,i=r??this._cburl??k.getWebSocketURI(this._reswarmUrl);this._connection.configure(this._swarmKey,this._appKey,c,this._serialNumber,i),this._isConfigured=!0}async start(r){this.configureConnection(r),await this._connection.start()}async stop(){this._connection.stop()}async publish(r,s,o){const c=D({topic:r,args:s,kwargs:o});if(!c.success)throw new Error(`Invalid publish parameters: ${c.errors.map(t=>t.path+": "+t.expected).join(", ")}`);const u={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...o??{}};return this._connection.publish(r,s,u,{acknowledge:!0})}async publishToTable(r,s,o){const c=O({tablename:r,args:s,kwargs:o});if(!c.success)throw new Error(`Invalid table parameters: ${c.errors.map(u=>u.path+": "+u.expected).join(", ")}`);if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const i=`${this._swarmKey}.${this._appKey}.${r}`;return this.publish(i,s,o)}async appendToTable(r,s,o){const c=O({tablename:r,args:s,kwargs:o});if(!c.success)throw new Error(`Invalid table parameters: ${c.errors.map(a=>a.path+": "+a.expected).join(", ")}`);if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const i=`append.${this._swarmKey}.${this._appKey}.${r}`,t={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...o??{}};return this._connection.call(i,s,t)}async subscribe(r,s,o){return this._connection.subscribe(r,s)}async subscribeToTable(r,s,o){if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const c=`${this._swarmKey}.${this._appKey}.${r}`;return this.subscribe(c,s,o)}async call(r,s,o,c){return this._connection.call(r,s,o,c)}async callDeviceFunction(r,s,o,c,i){const u=`${this._swarmKey}.${r}.${this._appKey}.${this._env}.${s}`;return this._connection.call(u,o,c,i)}async callFunction(r,s,o,c,i){return console.warn("callFunction() is deprecated and will be removed in a future version. Use callDeviceFunction() instead."),this.callDeviceFunction(r,s,o,c,i)}async registerDeviceFunction(r,s,o){const c=`${this._swarmKey}.${this._deviceKey}.${this._appKey}.${this._env}.${r}`,i=await this._connection.register(c,s,o);return console.log(`Function registered for IronFlock topic '${r}'. (Full WAMP topic: '${c}')`),i}async registerFunction(r,s,o){return console.warn("registerFunction() is deprecated and will be removed in a future version. Use registerDeviceFunction() instead."),this.registerDeviceFunction(r,s,o)}async register(r,s,o){return this.registerDeviceFunction(r,s,o)}async getHistory(r,s={limit:10}){if(!r)throw new Error("Tablename must not be empty!");s.offset==null&&(s.offset=0);const o=L(s);if(!o.success)throw new Error(`Invalid query parameters: ${o.errors.map(i=>i.path+": "+i.expected).join(", ")}`);const c=`history.transformed.app.${this._appKey}.${r}`;try{return await this._connection.call(c,[s])}catch(i){const u=String(i);return u.includes("no_such_procedure")||u.includes("no callee registered")?(console.error(`Get history failed: History service procedure '${c}' not registered`),null):(console.error(`Get history failed: ${i}`),null)}}async setDeviceLocation(r,s){const o=j({longitude:r,latitude:s});if(!o.success)throw new Error(`Invalid location parameters: ${o.errors.map(u=>u.path+": "+u.expected).join(", ")}`);const c={long:r,lat:s},i={DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName};try{return await this._connection.call("ironflock.location_service.update",[c],i)}catch(u){return console.error(`Set location failed: ${u}`),null}}getRemoteAccessUrlForPort(r){return this._deviceKey&&this._appName?`https://${this._deviceKey}-${this._appName.toLowerCase()}-${r}.app.ironflock.com`:null}static async fromServer(r){const s=await fetch(r);if(!s.ok)throw new Error(`Failed to fetch IronFlock config from ${r}: ${s.status} ${s.statusText}`);const o=await s.json();return new C(o)}}exports.CrossbarConnection=k;exports.IronFlock=C;exports.Stage=p;exports.validateCallParams=z;exports.validateLocationParams=j;exports.validatePublishParams=D;exports.validateTableParams=O;exports.validateTableQueryParams=L;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=require("autobahn");function V(d){return d&&d.__esModule&&Object.prototype.hasOwnProperty.call(d,"default")?d.default:d}var S={exports:{}},x;function Y(){return x||(x=1,(function(d){var s=Object.prototype.hasOwnProperty,t="~";function o(){}Object.create&&(o.prototype=Object.create(null),new o().__proto__||(t=!1));function l(a,r,n){this.fn=a,this.context=r,this.once=n||!1}function i(a,r,n,u,h){if(typeof n!="function")throw new TypeError("The listener must be a function");var v=new l(n,u||a,h),y=t?t+r:r;return a._events[y]?a._events[y].fn?a._events[y]=[a._events[y],v]:a._events[y].push(v):(a._events[y]=v,a._eventsCount++),a}function c(a,r){--a._eventsCount===0?a._events=new o:delete a._events[r]}function e(){this._events=new o,this._eventsCount=0}e.prototype.eventNames=function(){var r=[],n,u;if(this._eventsCount===0)return r;for(u in n=this._events)s.call(n,u)&&r.push(t?u.slice(1):u);return Object.getOwnPropertySymbols?r.concat(Object.getOwnPropertySymbols(n)):r},e.prototype.listeners=function(r){var n=t?t+r:r,u=this._events[n];if(!u)return[];if(u.fn)return[u.fn];for(var h=0,v=u.length,y=new Array(v);h<v;h++)y[h]=u[h].fn;return y},e.prototype.listenerCount=function(r){var n=t?t+r:r,u=this._events[n];return u?u.fn?1:u.length:0},e.prototype.emit=function(r,n,u,h,v,y){var w=t?t+r:r;if(!this._events[w])return!1;var f=this._events[w],b=arguments.length,A,g;if(f.fn){switch(f.once&&this.removeListener(r,f.fn,void 0,!0),b){case 1:return f.fn.call(f.context),!0;case 2:return f.fn.call(f.context,n),!0;case 3:return f.fn.call(f.context,n,u),!0;case 4:return f.fn.call(f.context,n,u,h),!0;case 5:return f.fn.call(f.context,n,u,h,v),!0;case 6:return f.fn.call(f.context,n,u,h,v,y),!0}for(g=1,A=new Array(b-1);g<b;g++)A[g-1]=arguments[g];f.fn.apply(f.context,A)}else{var W=f.length,R;for(g=0;g<W;g++)switch(f[g].once&&this.removeListener(r,f[g].fn,void 0,!0),b){case 1:f[g].fn.call(f[g].context);break;case 2:f[g].fn.call(f[g].context,n);break;case 3:f[g].fn.call(f[g].context,n,u);break;case 4:f[g].fn.call(f[g].context,n,u,h);break;default:if(!A)for(R=1,A=new Array(b-1);R<b;R++)A[R-1]=arguments[R];f[g].fn.apply(f[g].context,A)}}return!0},e.prototype.on=function(r,n,u){return i(this,r,n,u,!1)},e.prototype.once=function(r,n,u){return i(this,r,n,u,!0)},e.prototype.removeListener=function(r,n,u,h){var v=t?t+r:r;if(!this._events[v])return this;if(!n)return c(this,v),this;var y=this._events[v];if(y.fn)y.fn===n&&(!h||y.once)&&(!u||y.context===u)&&c(this,v);else{for(var w=0,f=[],b=y.length;w<b;w++)(y[w].fn!==n||h&&!y[w].once||u&&y[w].context!==u)&&f.push(y[w]);f.length?this._events[v]=f.length===1?f[0]:f:c(this,v)}return this},e.prototype.removeAllListeners=function(r){var n;return r?(n=t?t+r:r,this._events[n]&&c(this,n)):(this._events=new o,this._eventsCount=0),this},e.prototype.off=e.prototype.removeListener,e.prototype.addListener=e.prototype.on,e.prefixed=t,e.EventEmitter=e,d.exports=e})(S)),S.exports}var B=Y();const Q=V(B),J="wss://cbw.datapods.io/ws-ua-usr",j="wss://cbw.ironflock.com/ws-ua-usr",G="wss://cbw.ironflock.dev/ws-ua-usr",H="wss://cbw.record-evolution.com/ws-ua-usr",T="ws://localhost:8080/ws-ua-usr",L={"https://studio.datapods.io":J,"https://studio.ironflock.dev":G,"https://studio.ironflock.com":j,"https://studio.record-evolution.com":H,"http://localhost:8085":T,"http://localhost:8086":T,"http://host.docker.internal:8086":T},q=6e3;class K extends Q{constructor(){super(),this.subscriptions=[],this.registrations=[],this.firstResolver=()=>{},this.firstRejecter=()=>{},this.shouldReconnect=!1,this.isReconnecting=!1,this.hasOpenedOnce=!1}static getWebSocketURI(s){var l;const t=typeof process<"u"?(l=process.env)==null?void 0:l.DEVICE_ENDPOINT_URL:void 0;if(t)try{const i=new URL(t);return i.pathname="/ws-ua-usr",i.toString().replace(/\/$/,"")}catch{}if(!s)return j;const o=L[s];if(o===void 0)throw new Error(`Cannot resolve WebSocket URI for reswarmUrl=${JSON.stringify(s)}. Set DEVICE_ENDPOINT_URL to the deployment's WAMP router URL (e.g. ws://<host>:18080/ws-re-dev) or pass ironFlockUrl=… to IronFlock(). Known cloud URLs: ${JSON.stringify(Object.keys(L))}`);return o}configure(s,t,o,l,i){this.realm=`realm-${s}-${t}-${o}`,this.serial_number=l,this.socketURI=i??K.getWebSocketURI()}async start(){if(!this.realm||!this.serial_number||!this.socketURI)throw new Error("CrossbarConnection must be configured before starting. Call configure() first.");return this.shouldReconnect=!0,this.firstConnection=new Promise((s,t)=>{this.firstResolver=s,this.firstRejecter=t}),this.connection=new N.Connection({realm:this.realm,url:this.socketURI,authmethods:["wampcra"],authid:this.serial_number,max_retries:-1,max_retry_delay:2,initial_retry_delay:1,autoping_interval:2,autoping_timeout:4,onchallenge:(s,t,o)=>N.auth_cra.sign(this.serial_number,o.challenge)}),this.connection.onopen=this.onOpen.bind(this),this.connection.onclose=this.onClose.bind(this),this.connection.open(),this.firstConnection}onOpen(s){this.session=s,this.session.caller_disclose_me=!0,this.hasOpenedOnce=!0,this.resubscribeAll(),this.reregisterAll(),this.emit("connected",this.serial_number),this.firstResolver(),this.firstResolver=()=>{}}onClose(s,t){return this.session=void 0,this.emit("disconnected"),this.firstRejecter(new Error(`Connection failed: ${s} - ${JSON.stringify(t,null,2)}`)),this.firstRejecter=()=>{},console.warn("Connection closed:",{reason:s,details:t,realm:this.realm,url:this.socketURI,authid:this.serial_number}),this.shouldReconnect&&this.hasOpenedOnce&&(t==null?void 0:t.will_retry)===!1&&this.handleManualReconnect((t==null?void 0:t.reason)??s),!1}async handleManualReconnect(s){if(!(this.isReconnecting||!this.shouldReconnect)){for(this.isReconnecting=!0;this.shouldReconnect&&!this.session;)if(await new Promise(t=>setTimeout(t,1e3)),this.shouldReconnect&&this.connection&&!this.session){console.log(`Manually retrying connection after ${s}...`);try{this.connection.open(),await new Promise(t=>setTimeout(t,500))}catch(t){console.error("Error during manual reconnection attempt:",t)}}this.isReconnecting=!1}}async sessionWait(){const s=Date.now();for(;!this.session;){if(Date.now()-s>q)throw new Error("Timeout waiting for session");await new Promise(t=>setTimeout(t,200))}}async waitForConnection(){return this.firstConnection}getSession(){return this.session}get is_open(){var s;return!!((s=this.session)!=null&&s.isOpen)}isConnected(){return this.is_open}stop(){var s;this.shouldReconnect=!1,(s=this.connection)==null||s.close("wamp.close.normal","Connection closed by client")}async subscribe(s,t){var l;await this.sessionWait();const o=await((l=this.session)==null?void 0:l.subscribe(s,t));return o&&this.subscriptions.push(o),o}async unsubscribe(s){var o;await this.sessionWait();const t=this.subscriptions.indexOf(s);t!==-1&&(this.subscriptions.splice(t,1),await((o=this.session)==null?void 0:o.unsubscribe(s)))}async unsubscribeTopic(s){const t=this.subscriptions.filter(o=>o.topic===s);for(const o of t)await this.unsubscribe(o)}async resubscribeAll(){const s=[...this.subscriptions];this.subscriptions=[],await Promise.all(s.map(t=>this.subscribe(t.topic,t.handler)))}async reregisterAll(){const s=[...this.registrations];this.registrations=[],await Promise.all(s.map(t=>this.register(t.procedure,t.endpoint,t.options)))}async register(s,t,o){var c;await this.sessionWait();const l={force_reregister:!0,...o??{}},i=await((c=this.session)==null?void 0:c.register(s,t,l));return i&&this.registrations.push(i),i}async unregister(s){var o;await this.sessionWait(),await((o=this.session)==null?void 0:o.unregister(s));const t=this.registrations.indexOf(s);t!==-1&&this.registrations.splice(t,1)}async call(s,t,o,l){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.call(s,t,o,l)}async publish(s,t,o,l){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.publish(s,t,o,l)}}const M=d=>Math.floor(d)===d&&X<=d&&d<=Z,X=0,Z=2**32-1,I=d=>z.test(d),z=/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(T|\s)([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$/i,k=d=>{const s=t=>{if(d.length===0)return!0;const o=d[d.length-1].path;return t.length>o.length||o.substring(0,t.length)!==t};return(t,o)=>(t&&s(o.path)&&(o.value===void 0&&(o.description??(o.description=["The value at this path is `undefined`.","",`Please fill the \`${o.expected}\` typed value next time.`].join(`
2
+ `))),d.push(o)),!1)},_=d=>Object.assign(d,{"~standard":{version:1,vendor:"typia",validate:s=>{const t=d(s);return t.success?{value:t.data}:{issues:t.errors.map(o=>({message:`expected ${o.expected}, got ${o.value}`,path:ee(o.path)}))}}}});var m;(function(d){d[d.Start=0]="Start",d[d.Property=1]="Property",d[d.StringKey=2]="StringKey",d[d.NumberKey=3]="NumberKey"})(m||(m={}));const ee=d=>{if(!d.startsWith("$input"))throw new Error(`Invalid path: ${JSON.stringify(d)}`);const s=[];let t="",o=m.Start,l=5;for(;l<d.length-1;){l++;const i=d[l];if(o===m.Property?i==="."||i==="["?(s.push({key:t}),o=m.Start):l===d.length-1?(t+=i,s.push({key:t}),l++,o=m.Start):t+=i:o===m.StringKey?i==='"'?(s.push({key:JSON.parse(t+i)}),l+=2,o=m.Start):i==="\\"?(t+=d[l],l++,t+=d[l]):t+=i:o===m.NumberKey&&(i==="]"?(s.push({key:Number.parseInt(t)}),l++,o=m.Start):t+=i),o===m.Start&&l<d.length-1){const c=d[l];if(t="",c==="[")d[l+1]==='"'?(o=m.StringKey,l++,t='"'):o=m.NumberKey;else if(c===".")o=m.Property;else throw new Error("Unreachable: pointer points invalid character")}}if(o!==m.Start)throw new Error(`Failed to parse path: ${JSON.stringify(d)}`);return s};var p=(d=>(d.DEVELOPMENT="dev",d.PRODUCTION="prod",d))(p||{});const D=(()=>{const d=r=>typeof r.limit=="number"&&M(r.limit)&&1<=r.limit&&r.limit<=1e4&&(r.offset===void 0||typeof r.offset=="number"&&M(r.offset)&&0<=r.offset)&&(r.timeRange===void 0||typeof r.timeRange=="object"&&r.timeRange!==null&&s(r.timeRange))&&(r.filterAnd===void 0||Array.isArray(r.filterAnd)&&r.filterAnd.every(n=>typeof n=="object"&&n!==null&&t(n))),s=r=>typeof r.start=="string"&&I(r.start)&&typeof r.end=="string"&&I(r.end),t=r=>typeof r.column=="string"&&1<=r.column.length&&typeof r.operator=="string"&&1<=r.operator.length&&r.value!==null&&r.value!==void 0&&(typeof r.value=="string"||typeof r.value=="number"||typeof r.value=="boolean"||Array.isArray(r.value)&&r.value.every(n=>typeof n=="string"||typeof n=="number")),o=(r,n,u=!0)=>[typeof r.limit=="number"&&(M(r.limit)||a(u,{path:n+".limit",expected:'number & Type<"uint32">',value:r.limit}))&&(1<=r.limit||a(u,{path:n+".limit",expected:"number & Minimum<1>",value:r.limit}))&&(r.limit<=1e4||a(u,{path:n+".limit",expected:"number & Maximum<10000>",value:r.limit}))||a(u,{path:n+".limit",expected:'(number & Type<"uint32"> & Minimum<1> & Maximum<10000>)',value:r.limit}),r.offset===void 0||typeof r.offset=="number"&&(M(r.offset)||a(u,{path:n+".offset",expected:'number & Type<"uint32">',value:r.offset}))&&(0<=r.offset||a(u,{path:n+".offset",expected:"number & Minimum<0>",value:r.offset}))||a(u,{path:n+".offset",expected:'((number & Type<"uint32"> & Minimum<0>) | undefined)',value:r.offset}),r.timeRange===void 0||(typeof r.timeRange=="object"&&r.timeRange!==null||a(u,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:r.timeRange}))&&l(r.timeRange,n+".timeRange",u)||a(u,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:r.timeRange}),r.filterAnd===void 0||(Array.isArray(r.filterAnd)||a(u,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:r.filterAnd}))&&r.filterAnd.map((h,v)=>(typeof h=="object"&&h!==null||a(u,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:h}))&&i(h,n+".filterAnd["+v+"]",u)||a(u,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:h})).every(h=>h)||a(u,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:r.filterAnd})].every(h=>h),l=(r,n,u=!0)=>[typeof r.start=="string"&&(I(r.start)||a(u,{path:n+".start",expected:'string & Format<"date-time">',value:r.start}))||a(u,{path:n+".start",expected:'(string & Format<"date-time">)',value:r.start}),typeof r.end=="string"&&(I(r.end)||a(u,{path:n+".end",expected:'string & Format<"date-time">',value:r.end}))||a(u,{path:n+".end",expected:'(string & Format<"date-time">)',value:r.end})].every(h=>h),i=(r,n,u=!0)=>[typeof r.column=="string"&&(1<=r.column.length||a(u,{path:n+".column",expected:"string & MinLength<1>",value:r.column}))||a(u,{path:n+".column",expected:"(string & MinLength<1>)",value:r.column}),typeof r.operator=="string"&&(1<=r.operator.length||a(u,{path:n+".operator",expected:"string & MinLength<1>",value:r.operator}))||a(u,{path:n+".operator",expected:"(string & MinLength<1>)",value:r.operator}),(r.value!==null||a(u,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))&&(r.value!==void 0||a(u,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))&&(typeof r.value=="string"||typeof r.value=="number"||typeof r.value=="boolean"||(Array.isArray(r.value)||a(u,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))&&r.value.map((h,v)=>typeof h=="string"||typeof h=="number"||a(u,{path:n+".value["+v+"]",expected:"(number | string)",value:h})).every(h=>h)||a(u,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))].every(h=>h),c=r=>typeof r=="object"&&r!==null&&d(r);let e,a;return _(r=>{if(c(r)===!1){e=[],a=k(e),((u,h,v=!0)=>(typeof u=="object"&&u!==null||a(!0,{path:h+"",expected:"TableQueryParams",value:u}))&&o(u,h+"",!0)||a(!0,{path:h+"",expected:"TableQueryParams",value:u}))(r,"$input",!0);const n=e.length===0;return n?{success:n,data:r}:{success:n,errors:e,data:r}}return{success:!0,data:r}})})(),U=(()=>{const d=i=>typeof i.longitude=="number"&&-180<=i.longitude&&i.longitude<=180&&typeof i.latitude=="number"&&-90<=i.latitude&&i.latitude<=90,s=(i,c,e=!0)=>[typeof i.longitude=="number"&&(-180<=i.longitude||l(e,{path:c+".longitude",expected:"number & Minimum<-180>",value:i.longitude}))&&(i.longitude<=180||l(e,{path:c+".longitude",expected:"number & Maximum<180>",value:i.longitude}))||l(e,{path:c+".longitude",expected:"(number & Minimum<-180> & Maximum<180>)",value:i.longitude}),typeof i.latitude=="number"&&(-90<=i.latitude||l(e,{path:c+".latitude",expected:"number & Minimum<-90>",value:i.latitude}))&&(i.latitude<=90||l(e,{path:c+".latitude",expected:"number & Maximum<90>",value:i.latitude}))||l(e,{path:c+".latitude",expected:"(number & Minimum<-90> & Maximum<90>)",value:i.latitude})].every(a=>a),t=i=>typeof i=="object"&&i!==null&&d(i);let o,l;return _(i=>{if(t(i)===!1){o=[],l=k(o),((e,a,r=!0)=>(typeof e=="object"&&e!==null||l(!0,{path:a+"",expected:"LocationParams",value:e}))&&s(e,a+"",!0)||l(!0,{path:a+"",expected:"LocationParams",value:e}))(i,"$input",!0);const c=o.length===0;return c?{success:c,data:i}:{success:c,errors:o,data:i}}return{success:!0,data:i}})})(),F=(()=>{const d=e=>typeof e.topic=="string"&&1<=e.topic.length&&(e.args===void 0||Array.isArray(e.args))&&(e.kwargs===void 0||typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1&&s(e.kwargs)),s=e=>Object.keys(e).every(a=>(e[a]===void 0,!0)),t=(e,a,r=!0)=>[typeof e.topic=="string"&&(1<=e.topic.length||c(r,{path:a+".topic",expected:"string & MinLength<1>",value:e.topic}))||c(r,{path:a+".topic",expected:"(string & MinLength<1>)",value:e.topic}),e.args===void 0||Array.isArray(e.args)||c(r,{path:a+".args",expected:"(Array<unknown> | undefined)",value:e.args}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&o(e.kwargs,a+".kwargs",r)||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(n=>n),o=(e,a,r=!0)=>[r===!1||Object.keys(e).map(n=>(e[n]===void 0,!0)).every(n=>n)].every(n=>n),l=e=>typeof e=="object"&&e!==null&&d(e);let i,c;return _(e=>{if(l(e)===!1){i=[],c=k(i),((r,n,u=!0)=>(typeof r=="object"&&r!==null||c(!0,{path:n+"",expected:"PublishParams",value:r}))&&t(r,n+"",!0)||c(!0,{path:n+"",expected:"PublishParams",value:r}))(e,"$input",!0);const a=i.length===0;return a?{success:a,data:e}:{success:a,errors:i,data:e}}return{success:!0,data:e}})})(),re=(()=>{const d=e=>typeof e.deviceKey=="string"&&1<=e.deviceKey.length&&typeof e.topic=="string"&&1<=e.topic.length&&(e.args===void 0||Array.isArray(e.args))&&(e.kwargs===void 0||typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1&&s(e.kwargs)),s=e=>Object.keys(e).every(a=>(e[a]===void 0,!0)),t=(e,a,r=!0)=>[typeof e.deviceKey=="string"&&(1<=e.deviceKey.length||c(r,{path:a+".deviceKey",expected:"string & MinLength<1>",value:e.deviceKey}))||c(r,{path:a+".deviceKey",expected:"(string & MinLength<1>)",value:e.deviceKey}),typeof e.topic=="string"&&(1<=e.topic.length||c(r,{path:a+".topic",expected:"string & MinLength<1>",value:e.topic}))||c(r,{path:a+".topic",expected:"(string & MinLength<1>)",value:e.topic}),e.args===void 0||Array.isArray(e.args)||c(r,{path:a+".args",expected:"(Array<unknown> | undefined)",value:e.args}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&o(e.kwargs,a+".kwargs",r)||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(n=>n),o=(e,a,r=!0)=>[r===!1||Object.keys(e).map(n=>(e[n]===void 0,!0)).every(n=>n)].every(n=>n),l=e=>typeof e=="object"&&e!==null&&d(e);let i,c;return _(e=>{if(l(e)===!1){i=[],c=k(i),((r,n,u=!0)=>(typeof r=="object"&&r!==null||c(!0,{path:n+"",expected:"CallParams",value:r}))&&t(r,n+"",!0)||c(!0,{path:n+"",expected:"CallParams",value:r}))(e,"$input",!0);const a=i.length===0;return a?{success:a,data:e}:{success:a,errors:i,data:e}}return{success:!0,data:e}})})(),$=(()=>{const d=e=>typeof e.tablename=="string"&&1<=e.tablename.length&&(e.args===void 0||Array.isArray(e.args))&&(e.kwargs===void 0||typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1&&s(e.kwargs)),s=e=>Object.keys(e).every(a=>(e[a]===void 0,!0)),t=(e,a,r=!0)=>[typeof e.tablename=="string"&&(1<=e.tablename.length||c(r,{path:a+".tablename",expected:"string & MinLength<1>",value:e.tablename}))||c(r,{path:a+".tablename",expected:"(string & MinLength<1>)",value:e.tablename}),e.args===void 0||Array.isArray(e.args)||c(r,{path:a+".args",expected:"(Array<unknown> | undefined)",value:e.args}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&o(e.kwargs,a+".kwargs",r)||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(n=>n),o=(e,a,r=!0)=>[r===!1||Object.keys(e).map(n=>(e[n]===void 0,!0)).every(n=>n)].every(n=>n),l=e=>typeof e=="object"&&e!==null&&d(e);let i,c;return _(e=>{if(l(e)===!1){i=[],c=k(i),((r,n,u=!0)=>(typeof r=="object"&&r!==null||c(!0,{path:n+"",expected:"TableParams",value:r}))&&t(r,n+"",!0)||c(!0,{path:n+"",expected:"TableParams",value:r}))(e,"$input",!0);const a=i.length===0;return a?{success:a,data:e}:{success:a,errors:i,data:e}}return{success:!0,data:e}})})(),O=(()=>{const d=e=>typeof e.tablename=="string"&&1<=e.tablename.length&&Array.isArray(e.rows)&&1<=e.rows.length&&e.rows.every(a=>typeof a=="object"&&a!==null&&Array.isArray(a)===!1&&s(a))&&(e.kwargs===void 0||typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1&&s(e.kwargs)),s=e=>Object.keys(e).every(a=>(e[a]===void 0,!0)),t=(e,a,r=!0)=>[typeof e.tablename=="string"&&(1<=e.tablename.length||c(r,{path:a+".tablename",expected:"string & MinLength<1>",value:e.tablename}))||c(r,{path:a+".tablename",expected:"(string & MinLength<1>)",value:e.tablename}),(Array.isArray(e.rows)||c(r,{path:a+".rows",expected:"(Array<Record<string, unknown>> & MinItems<1>)",value:e.rows}))&&(1<=e.rows.length||c(r,{path:a+".rows",expected:"Array<> & MinItems<1>",value:e.rows}))&&e.rows.map((n,u)=>(typeof n=="object"&&n!==null&&Array.isArray(n)===!1||c(r,{path:a+".rows["+u+"]",expected:"Record<string, unknown>",value:n}))&&o(n,a+".rows["+u+"]",r)||c(r,{path:a+".rows["+u+"]",expected:"Record<string, unknown>",value:n})).every(n=>n)||c(r,{path:a+".rows",expected:"(Array<Record<string, unknown>> & MinItems<1>)",value:e.rows}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&o(e.kwargs,a+".kwargs",r)||c(r,{path:a+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(n=>n),o=(e,a,r=!0)=>[r===!1||Object.keys(e).map(n=>(e[n]===void 0,!0)).every(n=>n)].every(n=>n),l=e=>typeof e=="object"&&e!==null&&d(e);let i,c;return _(e=>{if(l(e)===!1){i=[],c=k(i),((r,n,u=!0)=>(typeof r=="object"&&r!==null||c(!0,{path:n+"",expected:"BulkTableParams",value:r}))&&t(r,n+"",!0)||c(!0,{path:n+"",expected:"BulkTableParams",value:r}))(e,"$input",!0);const a=i.length===0;return a?{success:a,data:e}:{success:a,errors:i,data:e}}return{success:!0,data:e}})})(),P="error-logs";function E(d){var s;return typeof process<"u"?(s=process.env)==null?void 0:s[d]:void 0}function te(d){const s=d??E("DEVICE_SERIAL_NUMBER");if(!s)throw new Error("serialNumber option is required (or set DEVICE_SERIAL_NUMBER env var in Node.js)");return s}class C{constructor(s){this._isConfigured=!1,this._serialNumber=te(s==null?void 0:s.serialNumber),this._deviceName=(s==null?void 0:s.deviceName)??E("DEVICE_NAME"),this._deviceKey=(s==null?void 0:s.deviceKey)??E("DEVICE_KEY"),this._appName=(s==null?void 0:s.appName)??E("APP_NAME"),this._swarmKey=(s==null?void 0:s.swarmKey)??parseInt(E("SWARM_KEY")??"0",10),this._appKey=(s==null?void 0:s.appKey)??parseInt(E("APP_KEY")??"0",10),this._env=(s==null?void 0:s.env)??E("ENV"),this._reswarmUrl=(s==null?void 0:s.reswarmUrl)??E("RESWARM_URL"),this._cburl=(s==null?void 0:s.ironFlockUrl)??(s==null?void 0:s.cburl),this._connection=new K;const t=[];this._deviceKey||t.push("DEVICE_KEY"),this._appName||t.push("APP_NAME"),this._swarmKey||t.push("SWARM_KEY"),this._appKey||t.push("APP_KEY"),t.length>0&&console.warn(`Warning: The following environment variables must be present: ${t.join(", ")}`)}get connection(){return this._connection}get isConnected(){return this._connection.is_open}configureConnection(s){if(this._isConfigured)return;const t=(this._env??"DEV").toUpperCase(),l={DEV:p.DEVELOPMENT,PROD:p.PRODUCTION}[t]??p.DEVELOPMENT,i=s??this._cburl??K.getWebSocketURI(this._reswarmUrl);this._connection.configure(this._swarmKey,this._appKey,l,this._serialNumber,i),this._isConfigured=!0}async start(s){this.configureConnection(s),await this._connection.start()}async stop(){this._connection.stop()}async publish(s,t,o){const l=F({topic:s,args:t,kwargs:o});if(!l.success)throw new Error(`Invalid publish parameters: ${l.errors.map(e=>e.path+": "+e.expected).join(", ")}`);const c={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...o??{}};return this._connection.publish(s,t,c,{acknowledge:!0})}async publishToTable(s,t,o){const l=$({tablename:s,args:t,kwargs:o});if(!l.success)throw new Error(`Invalid table parameters: ${l.errors.map(c=>c.path+": "+c.expected).join(", ")}`);if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const i=`${this._swarmKey}.${this._appKey}.${s}`;return this.publish(i,t,o)}async reportError(s,t){const o=s instanceof Error?s.stack??s.message:s,l={tsp:(t==null?void 0:t.tsp)??new Date().toISOString(),msg:o,source:"app",level:(t==null?void 0:t.level)??"error"};return t!=null&&t.append?this.appendToTable(P,[l]):this.publishToTable(P,[l])}async appendToTable(s,t,o){const l=$({tablename:s,args:t,kwargs:o});if(!l.success)throw new Error(`Invalid table parameters: ${l.errors.map(a=>a.path+": "+a.expected).join(", ")}`);if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const i=`append.${this._swarmKey}.${this._appKey}.${s}`,e={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...o??{}};return this._connection.call(i,t,e)}async publishRowsToTable(s,t,o){const l=O({tablename:s,rows:t,kwargs:o});if(!l.success)throw new Error(`Invalid bulk table parameters: ${l.errors.map(c=>c.path+": "+c.expected).join(", ")}`);if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const i=`bulk.${this._swarmKey}.${this._appKey}.${s}`;return this.publish(i,[t],o)}async appendRowsToTable(s,t,o){const l=O({tablename:s,rows:t,kwargs:o});if(!l.success)throw new Error(`Invalid bulk table parameters: ${l.errors.map(a=>a.path+": "+a.expected).join(", ")}`);if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const i=`appendBulk.${this._swarmKey}.${this._appKey}.${s}`,e={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...o??{}};return this._connection.call(i,[t],e)}async subscribe(s,t,o){return this._connection.subscribe(s,t)}async subscribeToTable(s,t,o){if(!this._swarmKey)throw new Error("SWARM_KEY not set in environment variables!");if(!this._appKey)throw new Error("APP_KEY not set in environment variables!");const l=`transformed.${s}`,i=await this.subscribe(l,t,o),c=(e,a,r)=>{const n=Array.isArray(e)?e[0]:e,u=Array.isArray(n)?n:n==null?[]:[n];for(const h of u)t([h],a,r)};return await this.subscribe(`transformed.bulk.${s}`,c,o),i}async call(s,t,o,l){return this._connection.call(s,t,o,l)}async callDeviceFunction(s,t,o,l,i){const c=`${this._swarmKey}.${s}.${this._appKey}.${this._env}.${t}`;return this._connection.call(c,o,l,i)}async callFunction(s,t,o,l,i){return console.warn("callFunction() is deprecated and will be removed in a future version. Use callDeviceFunction() instead."),this.callDeviceFunction(s,t,o,l,i)}async registerDeviceFunction(s,t,o){const l=`${this._swarmKey}.${this._deviceKey}.${this._appKey}.${this._env}.${s}`,i=await this._connection.register(l,t,o);return console.log(`Function registered for IronFlock topic '${s}'. (Full WAMP topic: '${l}')`),i}async registerFunction(s,t,o){return console.warn("registerFunction() is deprecated and will be removed in a future version. Use registerDeviceFunction() instead."),this.registerDeviceFunction(s,t,o)}async register(s,t,o){return this.registerDeviceFunction(s,t,o)}async getHistory(s,t={limit:10}){if(!s)throw new Error("Tablename must not be empty!");t.offset==null&&(t.offset=0);const o=D(t);if(!o.success)throw new Error(`Invalid query parameters: ${o.errors.map(i=>i.path+": "+i.expected).join(", ")}`);const l=`history.transformed.${s}`;try{return await this._connection.call(l,[t])}catch(i){const c=String(i);return c.includes("no_such_procedure")||c.includes("no callee registered")?(console.error(`Get history failed: History service procedure '${l}' not registered`),null):(console.error(`Get history failed: ${i}`),null)}}async setDeviceLocation(s,t){const o=U({longitude:s,latitude:t});if(!o.success)throw new Error(`Invalid location parameters: ${o.errors.map(c=>c.path+": "+c.expected).join(", ")}`);const l={long:s,lat:t},i={DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName};try{return await this._connection.call("ironflock.location_service.update",[l],i)}catch(c){return console.error(`Set location failed: ${c}`),null}}getRemoteAccessUrlForPort(s){return this._deviceKey&&this._appName?`https://${this._deviceKey}-${this._appName.toLowerCase()}-${s}.app.ironflock.com`:null}static async fromServer(s){const t=await fetch(s);if(!t.ok)throw new Error(`Failed to fetch IronFlock config from ${s}: ${t.status} ${t.statusText}`);const o=await t.json();return new C(o)}}exports.CrossbarConnection=K;exports.ERROR_LOGS_TABLE=P;exports.IronFlock=C;exports.Stage=p;exports.validateBulkTableParams=O;exports.validateCallParams=re;exports.validateLocationParams=U;exports.validatePublishParams=F;exports.validateTableParams=$;exports.validateTableQueryParams=D;
3
3
  //# sourceMappingURL=index.cjs.map