ironflock 1.0.2 → 1.1.1

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
@@ -8,59 +8,293 @@ of the device's fleet and the data is collected in the respective fleet database
8
8
 
9
9
  So if you use the library in your app, the data collection will always be private to the app user's fleet.
10
10
 
11
- For more information on the IronFlock IoT Devops Platform for engineers and developers visit our [home page](https://www.ironflock.com).
11
+ For more information on the IronFlock IoT Devops Platform for engineers and developers visit our [IronFlock](https://www.ironflock.com) home page.
12
12
 
13
- ## Usage
13
+ ## Requirements
14
+
15
+ - Node.js 18 or higher
14
16
 
15
- ### Install
17
+ ## Installation
16
18
 
17
19
  ```shell
18
- npm install --save ironflock
20
+ npm install ironflock
19
21
  ```
20
22
 
21
- **CommonJS**
22
-
23
- ```js
24
- const IronFlock = require("ironflock")
25
- const ironflock = new IronFlock()
23
+ ## Usage
26
24
 
27
- ironflock.publish("re.example.rpc", [{ example_data: "test" }]) // any type of data is publishable
28
- ```
25
+ ```ts
26
+ import { IronFlock } from "ironflock";
29
27
 
30
- **ES6**
28
+ // Create an IronFlock instance to connect to the IronFlock platform data infrastructure.
29
+ // The IronFlock instance handles authentication when run on a device registered in IronFlock.
30
+ const ironflock = new IronFlock();
31
31
 
32
- For ES6 modules `"type": "module"` is required in your package.json
32
+ // Start the connection to the platform
33
+ await ironflock.start();
33
34
 
34
- ```js
35
- import IronFlock from "ironflock"
36
- const ironflock = new IronFlock()
35
+ // Publish an event
36
+ await ironflock.publish("test.publish.example", [{ temperature: 20 }]);
37
37
 
38
- ironflock.publish("re.example.rpc", [{ example_data: "test" }]) // any type of data is publishable
38
+ // Stop the connection when done
39
+ await ironflock.stop();
39
40
  ```
40
41
 
41
- ### Options
42
+ ## Options
42
43
 
43
44
  The `IronFlock` constructor can be configured with the following options:
44
45
 
45
46
  ```ts
46
47
  {
47
- quiet?: boolean;
48
- serialNumber?: string;
48
+ serialNumber?: string;
49
49
  }
50
50
  ```
51
51
 
52
- **quiet**: Toggles autobahn.js debug information
52
+ **serialNumber**: Used to set the serial number of the device if the `DEVICE_SERIAL_NUMBER` environment variable does not exist. It can also be used if the user wishes to authenticate as another device.
53
+
54
+ ## API Reference
55
+
56
+ ### `publish(topic, args?, kwargs?)`
57
+
58
+ Publishes an event to a topic on the IronFlock message router.
59
+
60
+ ```ts
61
+ const publication = await ironflock.publish("com.myapp.mytopic", [{ temperature: 20 }]);
62
+ ```
63
+
64
+ | Parameter | Type | Description |
65
+ |-----------|------|-------------|
66
+ | `topic` | `string` | The URI of the topic to publish to |
67
+ | `args` | `unknown[]`, optional | Payload arguments |
68
+ | `kwargs` | `Record<string, unknown>`, optional | Payload keyword arguments |
69
+
70
+ **Returns:** `Promise<unknown>` — The publication object (an acknowledged publish receipt).
71
+
72
+ ---
73
+
74
+ ### `publishToTable(tablename, args?, kwargs?)`
75
+
76
+ Convenience function to publish data to a fleet table in the IronFlock platform. Automatically constructs the correct topic using the `SWARM_KEY` and `APP_KEY` environment variables.
77
+
78
+ ```ts
79
+ await ironflock.publishToTable("sensordata", [{ temperature: 22.5, humidity: 60 }]);
80
+ ```
81
+
82
+ | Parameter | Type | Description |
83
+ |-----------|------|-------------|
84
+ | `tablename` | `string` | The name of the table, e.g. `"sensordata"` |
85
+ | `args` | `unknown[]`, optional | Row data to publish |
86
+ | `kwargs` | `Record<string, unknown>`, optional | Row data as keyword arguments |
87
+
88
+ **Returns:** `Promise<unknown>` — The publication object (an acknowledged publish receipt).
89
+
90
+ ---
91
+
92
+ ### `subscribe(topic, handler)`
93
+
94
+ Subscribes to a topic on the IronFlock message router.
95
+
96
+ ```ts
97
+ function onMessage(...args: any[]) {
98
+ console.log("Received:", args);
99
+ }
100
+
101
+ const subscription = await ironflock.subscribe("com.myapp.mytopic", onMessage);
102
+ ```
103
+
104
+ | Parameter | Type | Description |
105
+ |-----------|------|-------------|
106
+ | `topic` | `string` | The URI of the topic to subscribe to |
107
+ | `handler` | `(...args: any[]) => void` | Function called when a message is received |
108
+
109
+ **Returns:** `Promise<Subscription | undefined>` — The subscription object.
110
+
111
+ ---
112
+
113
+ ### `subscribeToTable(tablename, handler)`
114
+
115
+ Convenience function to subscribe to a fleet table. Automatically constructs the correct topic using the `SWARM_KEY` and `APP_KEY` environment variables.
116
+
117
+ ```ts
118
+ function onTableData(...args: any[]) {
119
+ console.log("New row:", args);
120
+ }
121
+
122
+ await ironflock.subscribeToTable("sensordata", onTableData);
123
+ ```
124
+
125
+ | Parameter | Type | Description |
126
+ |-----------|------|-------------|
127
+ | `tablename` | `string` | The name of the table to subscribe to |
128
+ | `handler` | `(...args: any[]) => void` | Function called when new data arrives |
129
+
130
+ **Returns:** `Promise<Subscription | undefined>` — The subscription object.
131
+
132
+ ---
133
+
134
+ ### `getHistory(tablename, queryParams?)`
135
+
136
+ Retrieves historical data from a fleet table.
137
+
138
+ ```ts
139
+ // Simple query with limit
140
+ const data = await ironflock.getHistory("sensordata", { limit: 100 });
141
+
142
+ // Query with time range and filters
143
+ const data = await ironflock.getHistory("sensordata", {
144
+ limit: 500,
145
+ offset: 0,
146
+ timeRange: {
147
+ start: "2026-01-01T00:00:00Z",
148
+ end: "2026-03-01T00:00:00Z",
149
+ },
150
+ filterAnd: [
151
+ { column: "temperature", operator: ">", value: 20 },
152
+ { column: "humidity", operator: "<=", value: 80 },
153
+ ],
154
+ });
155
+ ```
156
+
157
+ | Parameter | Type | Description |
158
+ |-----------|------|-------------|
159
+ | `tablename` | `string` | The name of the table to query |
160
+ | `queryParams` | `TableQueryParams` | Query parameters (see below) |
161
+
162
+ **queryParams fields:**
163
+
164
+ | Field | Type | Description |
165
+ |-------|------|-------------|
166
+ | `limit` | `number` | Maximum number of rows to return (1–10000, required) |
167
+ | `offset` | `number`, optional | Offset for pagination |
168
+ | `timeRange` | `ISOTimeRange`, optional | `{ start: "<ISO datetime>", end: "<ISO datetime>" }` |
169
+ | `filterAnd` | `SQLFilterAnd[]`, optional | List of AND filter conditions: `{ column: string, operator: string, value: ... }` |
170
+
171
+ Supported filter operators: `=`, `!=`, `>`, `<`, `>=`, `<=`, `LIKE`, `ILIKE`, `IN`, `NOT IN`, `IS`, `IS NOT`.
172
+
173
+ **Returns:** `Promise<unknown | null>` — The query result data (typically an array of row objects), or `null` if the call failed.
174
+
175
+ ---
53
176
 
54
- **serialNumber**: Used to set the serial_number of the device if the `DEVICE_SERIAL_NUMBER` environment variable does not exist. It can also be used if the user wishes to authenticate as another device.
177
+ ### `call(deviceKey, topic, args?, kwargs?)`
55
178
 
179
+ Calls a remote procedure registered by another IronFlock device.
180
+
181
+ ```ts
182
+ const result = await ironflock.call("other-device-key", "com.myapp.myprocedure", [42]);
183
+ ```
184
+
185
+ | Parameter | Type | Description |
186
+ |-----------|------|-------------|
187
+ | `deviceKey` | `string` | The device key of the target device |
188
+ | `topic` | `string` | The URI of the procedure to call |
189
+ | `args` | `unknown[]`, optional | Positional arguments |
190
+ | `kwargs` | `Record<string, unknown>`, optional | Keyword arguments |
191
+
192
+ **Returns:** `Promise<unknown>` — The result of the remote procedure call.
193
+
194
+ ---
195
+
196
+ ### `registerFunction(topic, endpoint)`
197
+
198
+ Registers a procedure that can be called by other devices in the fleet.
199
+
200
+ ```ts
201
+ function add(args: any[]) {
202
+ return args[0] + args[1];
203
+ }
204
+
205
+ await ironflock.registerFunction("com.myapp.add", add);
206
+ ```
207
+
208
+ | Parameter | Type | Description |
209
+ |-----------|------|-------------|
210
+ | `topic` | `string` | The URI of the procedure to register |
211
+ | `endpoint` | `(...args: any[]) => any` | The function to register |
212
+
213
+ **Returns:** `Promise<Registration | undefined>` — The registration object.
214
+
215
+ > `register()` is an alias for `registerFunction()`.
216
+
217
+ ---
218
+
219
+ ### `setDeviceLocation(long, lat)`
220
+
221
+ Updates the device's location in the platform master data. The maps in device or group overviews will reflect the new location in realtime.
222
+
223
+ ```ts
224
+ await ironflock.setDeviceLocation(8.6821, 50.1109);
225
+ ```
226
+
227
+ | Parameter | Type | Description |
228
+ |-----------|------|-------------|
229
+ | `long` | `number` | Longitude (-180 to 180) |
230
+ | `lat` | `number` | Latitude (-90 to 90) |
231
+
232
+ **Returns:** `Promise<unknown | null>` — The result of the location update call, or `null` if the call failed.
233
+
234
+ > **Note:** Location history is not stored. If you need location history, create a dedicated table and use `publishToTable`.
235
+
236
+ ---
237
+
238
+ ### `getRemoteAccessUrlForPort(port)`
239
+
240
+ Returns the remote access URL for a given port on the device.
241
+
242
+ ```ts
243
+ const url = ironflock.getRemoteAccessUrlForPort(8080);
244
+ // e.g. "https://<device_key>-<app_name>-8080.app.ironflock.com"
245
+ ```
246
+
247
+ | Parameter | Type | Description |
248
+ |-----------|------|-------------|
249
+ | `port` | `number` | The port number |
250
+
251
+ **Returns:** `string | null` — The remote access URL string, or `null` if the device key or app name is not available.
252
+
253
+ ---
254
+
255
+ ### Properties
256
+
257
+ | Property | Type | Description |
258
+ |----------|------|-------------|
259
+ | `isConnected` | `boolean` | `true` if the connection to the platform is established |
260
+ | `connection` | `CrossbarConnection` | The underlying connection instance (for advanced use) |
261
+
262
+ ### Lifecycle Methods
263
+
264
+ | Method | Description |
265
+ |--------|-------------|
266
+ | `await start(cburl?)` | Configures and starts the connection to the platform |
267
+ | `await stop()` | Stops the connection |
56
268
 
57
269
  ## Development
58
270
 
59
- To publish a new release
271
+ Install dependencies:
272
+
273
+ ```shell
274
+ npm install
275
+ ```
276
+
277
+ Run tests:
278
+
279
+ ```shell
280
+ npm test
281
+ ```
282
+
283
+ Type check:
284
+
285
+ ```shell
286
+ npm run typecheck
287
+ ```
288
+
289
+ Build:
60
290
 
61
291
  ```shell
62
292
  npm run build
293
+ ```
294
+
295
+ Publish a new release:
296
+
297
+ ```shell
63
298
  npm run release
64
- npm run publish
65
299
  ```
66
300
 
package/dist/index.cjs ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("autobahn"),K=require("events"),T="wss://cbw.datapods.io/ws-ua-usr",k="wss://cbw.ironflock.com/ws-ua-usr",$="wss://cbw.ironflock.dev/ws-ua-usr",P="wss://cbw.record-evolution.com/ws-ua-usr",E="ws://localhost:8080/ws-ua-usr",C={"https://studio.datapods.io":T,"https://studio.ironflock.dev":$,"https://studio.ironflock.com":k,"https://studio.record-evolution.com":P,"http://localhost:8085":E,"http://localhost:8086":E,"http://host.docker.internal:8086":E},N=6e3;class A extends K.EventEmitter{constructor(){super(),this.subscriptions=[],this.registrations=[],this.firstResolver=()=>{},this.firstRejecter=()=>{}}static getWebSocketURI(){const t=process.env.RESWARM_URL;return t?C[t]??k:k}configure(t,s,a,c,n){this.realm=`realm-${t}-${s}-${a}`,this.serial_number=c,this.socketURI=n??A.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.firstConnection=new Promise((t,s)=>{this.firstResolver=t,this.firstRejecter=s}),this.connection=new R.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:(t,s,a)=>R.auth_cra.sign(this.serial_number,a.challenge)}),this.connection.onopen=this.onOpen.bind(this),this.connection.onclose=this.onClose.bind(this),this.connection.open(),this.firstConnection}onOpen(t){this.session=t,this.session.caller_disclose_me=!0,this.resubscribeAll(),this.emit("connected",this.serial_number),this.firstResolver(),this.firstResolver=()=>{}}onClose(t,s){return this.session=void 0,this.emit("disconnected"),this.firstRejecter(new Error(`Connection failed: ${t} - ${JSON.stringify(s,null,2)}`)),this.firstRejecter=()=>{},console.warn("Connection closed:",{reason:t,details:s,realm:this.realm,url:this.socketURI,authid:this.serial_number}),!1}async sessionWait(){const t=Date.now();for(;!this.session;){if(Date.now()-t>N)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 t;return!!((t=this.session)!=null&&t.isOpen)}isConnected(){return this.is_open}stop(){var t;(t=this.connection)==null||t.close("wamp.close.normal","Connection closed by client")}async subscribe(t,s){var c;await this.sessionWait();const a=await((c=this.session)==null?void 0:c.subscribe(t,s));return a&&this.subscriptions.push(a),a}async unsubscribe(t){var a;await this.sessionWait();const s=this.subscriptions.indexOf(t);s!==-1&&(this.subscriptions.splice(s,1),await((a=this.session)==null?void 0:a.unsubscribe(t)))}async unsubscribeTopic(t){const s=this.subscriptions.filter(a=>a.topic===t);for(const a of s)await this.unsubscribe(a)}async resubscribeAll(){const t=[...this.subscriptions];this.subscriptions=[],await Promise.all(t.map(s=>this.subscribe(s.topic,s.handler)))}async register(t,s){var c;await this.sessionWait();const a=await((c=this.session)==null?void 0:c.register(t,s));return a&&this.registrations.push(a),a}async unregister(t){var a;await this.sessionWait(),await((a=this.session)==null?void 0:a.unregister(t));const s=this.registrations.indexOf(t);s!==-1&&this.registrations.splice(s,1)}async call(t,s,a,c){var n;return await this.sessionWait(),(n=this.session)==null?void 0:n.call(t,s,a,c)}async publish(t,s,a,c){var n;return await this.sessionWait(),(n=this.session)==null?void 0:n.publish(t,s,a,c)}}const w=d=>Math.floor(d)===d&&j<=d&&d<=x,j=0,x=2**32-1,b=d=>O.test(d),O=/^[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,m=d=>{const t=s=>{if(d.length===0)return!0;const a=d[d.length-1].path;return s.length>a.length||a.substring(0,s.length)!==s};return(s,a)=>(s&&t(a.path)&&(a.value===void 0&&(a.description??(a.description=["The value at this path is `undefined`.","",`Please fill the \`${a.expected}\` typed value next time.`].join(`
2
+ `))),d.push(a)),!1)},y=d=>Object.assign(d,{"~standard":{version:1,vendor:"typia",validate:t=>{const s=d(t);return s.success?{value:s.data}:{issues:s.errors.map(a=>({message:`expected ${a.expected}, got ${a.value}`,path:L(a.path)}))}}}});var v;(function(d){d[d.Start=0]="Start",d[d.Property=1]="Property",d[d.StringKey=2]="StringKey",d[d.NumberKey=3]="NumberKey"})(v||(v={}));const L=d=>{if(!d.startsWith("$input"))throw new Error(`Invalid path: ${JSON.stringify(d)}`);const t=[];let s="",a=v.Start,c=5;for(;c<d.length-1;){c++;const n=d[c];if(a===v.Property?n==="."||n==="["?(t.push({key:s}),a=v.Start):c===d.length-1?(s+=n,t.push({key:s}),c++,a=v.Start):s+=n:a===v.StringKey?n==='"'?(t.push({key:JSON.parse(s+n)}),c+=2,a=v.Start):n==="\\"?(s+=d[c],c++,s+=d[c]):s+=n:a===v.NumberKey&&(n==="]"?(t.push({key:Number.parseInt(s)}),c++,a=v.Start):s+=n),a===v.Start&&c<d.length-1){const l=d[c];if(s="",l==="[")d[c+1]==='"'?(a=v.StringKey,c++,s='"'):a=v.NumberKey;else if(l===".")a=v.Property;else throw new Error("Unreachable: pointer points invalid character")}}if(a!==v.Start)throw new Error(`Failed to parse path: ${JSON.stringify(d)}`);return t};var f=(d=>(d.DEVELOPMENT="dev",d.PRODUCTION="prod",d))(f||{});const M=(()=>{const d=r=>typeof r.limit=="number"&&w(r.limit)&&1<=r.limit&&r.limit<=1e4&&(r.offset===void 0||typeof r.offset=="number"&&w(r.offset)&&0<=r.offset)&&(r.timeRange===void 0||typeof r.timeRange=="object"&&r.timeRange!==null&&t(r.timeRange))&&(r.filterAnd===void 0||Array.isArray(r.filterAnd)&&r.filterAnd.every(i=>typeof i=="object"&&i!==null&&s(i))),t=r=>typeof r.start=="string"&&b(r.start)&&typeof r.end=="string"&&b(r.end),s=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(i=>typeof i=="string"||typeof i=="number")),a=(r,i,u=!0)=>[typeof r.limit=="number"&&(w(r.limit)||o(u,{path:i+".limit",expected:'number & Type<"uint32">',value:r.limit}))&&(1<=r.limit||o(u,{path:i+".limit",expected:"number & Minimum<1>",value:r.limit}))&&(r.limit<=1e4||o(u,{path:i+".limit",expected:"number & Maximum<10000>",value:r.limit}))||o(u,{path:i+".limit",expected:'(number & Type<"uint32"> & Minimum<1> & Maximum<10000>)',value:r.limit}),r.offset===void 0||typeof r.offset=="number"&&(w(r.offset)||o(u,{path:i+".offset",expected:'number & Type<"uint32">',value:r.offset}))&&(0<=r.offset||o(u,{path:i+".offset",expected:"number & Minimum<0>",value:r.offset}))||o(u,{path:i+".offset",expected:'((number & Type<"uint32"> & Minimum<0>) | undefined)',value:r.offset}),r.timeRange===void 0||(typeof r.timeRange=="object"&&r.timeRange!==null||o(u,{path:i+".timeRange",expected:"(ISOTimeRange | undefined)",value:r.timeRange}))&&c(r.timeRange,i+".timeRange",u)||o(u,{path:i+".timeRange",expected:"(ISOTimeRange | undefined)",value:r.timeRange}),r.filterAnd===void 0||(Array.isArray(r.filterAnd)||o(u,{path:i+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:r.filterAnd}))&&r.filterAnd.map((h,g)=>(typeof h=="object"&&h!==null||o(u,{path:i+".filterAnd["+g+"]",expected:"SQLFilterAnd",value:h}))&&n(h,i+".filterAnd["+g+"]",u)||o(u,{path:i+".filterAnd["+g+"]",expected:"SQLFilterAnd",value:h})).every(h=>h)||o(u,{path:i+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:r.filterAnd})].every(h=>h),c=(r,i,u=!0)=>[typeof r.start=="string"&&(b(r.start)||o(u,{path:i+".start",expected:'string & Format<"date-time">',value:r.start}))||o(u,{path:i+".start",expected:'(string & Format<"date-time">)',value:r.start}),typeof r.end=="string"&&(b(r.end)||o(u,{path:i+".end",expected:'string & Format<"date-time">',value:r.end}))||o(u,{path:i+".end",expected:'(string & Format<"date-time">)',value:r.end})].every(h=>h),n=(r,i,u=!0)=>[typeof r.column=="string"&&(1<=r.column.length||o(u,{path:i+".column",expected:"string & MinLength<1>",value:r.column}))||o(u,{path:i+".column",expected:"(string & MinLength<1>)",value:r.column}),typeof r.operator=="string"&&(1<=r.operator.length||o(u,{path:i+".operator",expected:"string & MinLength<1>",value:r.operator}))||o(u,{path:i+".operator",expected:"(string & MinLength<1>)",value:r.operator}),(r.value!==null||o(u,{path:i+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))&&(r.value!==void 0||o(u,{path:i+".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)||o(u,{path:i+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))&&r.value.map((h,g)=>typeof h=="string"||typeof h=="number"||o(u,{path:i+".value["+g+"]",expected:"(number | string)",value:h})).every(h=>h)||o(u,{path:i+".value",expected:"(Array<string | number> | boolean | number | string)",value:r.value}))].every(h=>h),l=r=>typeof r=="object"&&r!==null&&d(r);let e,o;return y(r=>{if(l(r)===!1){e=[],o=m(e),((u,h,g=!0)=>(typeof u=="object"&&u!==null||o(!0,{path:h+"",expected:"TableQueryParams",value:u}))&&a(u,h+"",!0)||o(!0,{path:h+"",expected:"TableQueryParams",value:u}))(r,"$input",!0);const i=e.length===0;return i?{success:i,data:r}:{success:i,errors:e,data:r}}return{success:!0,data:r}})})(),_=(()=>{const d=n=>typeof n.longitude=="number"&&-180<=n.longitude&&n.longitude<=180&&typeof n.latitude=="number"&&-90<=n.latitude&&n.latitude<=90,t=(n,l,e=!0)=>[typeof n.longitude=="number"&&(-180<=n.longitude||c(e,{path:l+".longitude",expected:"number & Minimum<-180>",value:n.longitude}))&&(n.longitude<=180||c(e,{path:l+".longitude",expected:"number & Maximum<180>",value:n.longitude}))||c(e,{path:l+".longitude",expected:"(number & Minimum<-180> & Maximum<180>)",value:n.longitude}),typeof n.latitude=="number"&&(-90<=n.latitude||c(e,{path:l+".latitude",expected:"number & Minimum<-90>",value:n.latitude}))&&(n.latitude<=90||c(e,{path:l+".latitude",expected:"number & Maximum<90>",value:n.latitude}))||c(e,{path:l+".latitude",expected:"(number & Minimum<-90> & Maximum<90>)",value:n.latitude})].every(o=>o),s=n=>typeof n=="object"&&n!==null&&d(n);let a,c;return y(n=>{if(s(n)===!1){a=[],c=m(a),((e,o,r=!0)=>(typeof e=="object"&&e!==null||c(!0,{path:o+"",expected:"LocationParams",value:e}))&&t(e,o+"",!0)||c(!0,{path:o+"",expected:"LocationParams",value:e}))(n,"$input",!0);const l=a.length===0;return l?{success:l,data:n}:{success:l,errors:a,data:n}}return{success:!0,data:n}})})(),S=(()=>{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&&t(e.kwargs)),t=e=>Object.keys(e).every(o=>(e[o]===void 0,!0)),s=(e,o,r=!0)=>[typeof e.topic=="string"&&(1<=e.topic.length||l(r,{path:o+".topic",expected:"string & MinLength<1>",value:e.topic}))||l(r,{path:o+".topic",expected:"(string & MinLength<1>)",value:e.topic}),e.args===void 0||Array.isArray(e.args)||l(r,{path:o+".args",expected:"(Array<unknown> | undefined)",value:e.args}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||l(r,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&a(e.kwargs,o+".kwargs",r)||l(r,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(i=>i),a=(e,o,r=!0)=>[r===!1||Object.keys(e).map(i=>(e[i]===void 0,!0)).every(i=>i)].every(i=>i),c=e=>typeof e=="object"&&e!==null&&d(e);let n,l;return y(e=>{if(c(e)===!1){n=[],l=m(n),((r,i,u=!0)=>(typeof r=="object"&&r!==null||l(!0,{path:i+"",expected:"PublishParams",value:r}))&&s(r,i+"",!0)||l(!0,{path:i+"",expected:"PublishParams",value:r}))(e,"$input",!0);const o=n.length===0;return o?{success:o,data:e}:{success:o,errors:n,data:e}}return{success:!0,data:e}})})(),p=(()=>{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&&t(e.kwargs)),t=e=>Object.keys(e).every(o=>(e[o]===void 0,!0)),s=(e,o,r=!0)=>[typeof e.deviceKey=="string"&&(1<=e.deviceKey.length||l(r,{path:o+".deviceKey",expected:"string & MinLength<1>",value:e.deviceKey}))||l(r,{path:o+".deviceKey",expected:"(string & MinLength<1>)",value:e.deviceKey}),typeof e.topic=="string"&&(1<=e.topic.length||l(r,{path:o+".topic",expected:"string & MinLength<1>",value:e.topic}))||l(r,{path:o+".topic",expected:"(string & MinLength<1>)",value:e.topic}),e.args===void 0||Array.isArray(e.args)||l(r,{path:o+".args",expected:"(Array<unknown> | undefined)",value:e.args}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||l(r,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&a(e.kwargs,o+".kwargs",r)||l(r,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(i=>i),a=(e,o,r=!0)=>[r===!1||Object.keys(e).map(i=>(e[i]===void 0,!0)).every(i=>i)].every(i=>i),c=e=>typeof e=="object"&&e!==null&&d(e);let n,l;return y(e=>{if(c(e)===!1){n=[],l=m(n),((r,i,u=!0)=>(typeof r=="object"&&r!==null||l(!0,{path:i+"",expected:"CallParams",value:r}))&&s(r,i+"",!0)||l(!0,{path:i+"",expected:"CallParams",value:r}))(e,"$input",!0);const o=n.length===0;return o?{success:o,data:e}:{success:o,errors:n,data:e}}return{success:!0,data:e}})})(),I=(()=>{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&&t(e.kwargs)),t=e=>Object.keys(e).every(o=>(e[o]===void 0,!0)),s=(e,o,r=!0)=>[typeof e.tablename=="string"&&(1<=e.tablename.length||l(r,{path:o+".tablename",expected:"string & MinLength<1>",value:e.tablename}))||l(r,{path:o+".tablename",expected:"(string & MinLength<1>)",value:e.tablename}),e.args===void 0||Array.isArray(e.args)||l(r,{path:o+".args",expected:"(Array<unknown> | undefined)",value:e.args}),e.kwargs===void 0||(typeof e.kwargs=="object"&&e.kwargs!==null&&Array.isArray(e.kwargs)===!1||l(r,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs}))&&a(e.kwargs,o+".kwargs",r)||l(r,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:e.kwargs})].every(i=>i),a=(e,o,r=!0)=>[r===!1||Object.keys(e).map(i=>(e[i]===void 0,!0)).every(i=>i)].every(i=>i),c=e=>typeof e=="object"&&e!==null&&d(e);let n,l;return y(e=>{if(c(e)===!1){n=[],l=m(n),((r,i,u=!0)=>(typeof r=="object"&&r!==null||l(!0,{path:i+"",expected:"TableParams",value:r}))&&s(r,i+"",!0)||l(!0,{path:i+"",expected:"TableParams",value:r}))(e,"$input",!0);const o=n.length===0;return o?{success:o,data:e}:{success:o,errors:n,data:e}}return{success:!0,data:e}})})();function D(d){const t=d??process.env.DEVICE_SERIAL_NUMBER;if(!t)throw new Error("DEVICE_SERIAL_NUMBER environment variable is not set and no serialNumber was provided");return t}class U{constructor(t){this._isConfigured=!1,this._serialNumber=D(t==null?void 0:t.serialNumber),this._deviceName=process.env.DEVICE_NAME,this._deviceKey=process.env.DEVICE_KEY,this._appName=process.env.APP_NAME,this._swarmKey=parseInt(process.env.SWARM_KEY??"0",10),this._appKey=parseInt(process.env.APP_KEY??"0",10),this._env=process.env.ENV,this._connection=new A;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(t){if(this._isConfigured)return;const s=(this._env??"DEV").toUpperCase(),c={DEV:f.DEVELOPMENT,PROD:f.PRODUCTION}[s]??f.DEVELOPMENT;this._connection.configure(this._swarmKey,this._appKey,c,this._serialNumber,t),this._isConfigured=!0}async start(t){this.configureConnection(t),await this._connection.start()}async stop(){this._connection.stop()}async publish(t,s,a){const c=S({topic:t,args:s,kwargs:a});if(!c.success)throw new Error(`Invalid publish parameters: ${c.errors.map(e=>e.path+": "+e.expected).join(", ")}`);const l={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...a??{}};return this._connection.publish(t,s,l,{acknowledge:!0})}async publishToTable(t,s,a){const c=I({tablename:t,args:s,kwargs:a});if(!c.success)throw new Error(`Invalid table parameters: ${c.errors.map(l=>l.path+": "+l.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 n=`${this._swarmKey}.${this._appKey}.${t}`;return this.publish(n,s,a)}async subscribe(t,s,a){return this._connection.subscribe(t,s)}async subscribeToTable(t,s,a){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}.${t}`;return this.subscribe(c,s,a)}async call(t,s,a,c,n){const l=p({deviceKey:t,topic:s,args:a,kwargs:c});if(!l.success)throw new Error(`Invalid call parameters: ${l.errors.map(o=>o.path+": "+o.expected).join(", ")}`);const e=`${t}.${s}`;return this._connection.call(e,a,c,n)}async registerFunction(t,s,a){const c=`${this._swarmKey}.${this._deviceKey}.${this._appKey}.${this._env}.${t}`,n=await this._connection.register(c,s);return console.log(`Function registered for IronFlock topic '${t}'. (Full WAMP topic: '${c}')`),n}async register(t,s,a){return this.registerFunction(t,s,a)}async getHistory(t,s={limit:10}){if(!t)throw new Error("Tablename must not be empty!");const a=M(s);if(!a.success)throw new Error(`Invalid query parameters: ${a.errors.map(n=>n.path+": "+n.expected).join(", ")}`);const c=`history.transformed.app.${this._appKey}.${t}`;try{return await this._connection.call(c,[s])}catch(n){const l=String(n);return l.includes("no_such_procedure")||l.includes("no callee registered")?(console.error(`Get history failed: History service procedure '${c}' not registered`),null):(console.error(`Get history failed: ${n}`),null)}}async setDeviceLocation(t,s){const a=_({longitude:t,latitude:s});if(!a.success)throw new Error(`Invalid location parameters: ${a.errors.map(l=>l.path+": "+l.expected).join(", ")}`);const c={long:t,lat:s},n={DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName};try{return await this._connection.call("ironflock.location_service.update",[c],n)}catch(l){return console.error(`Set location failed: ${l}`),null}}getRemoteAccessUrlForPort(t){return this._deviceKey&&this._appName?`https://${this._deviceKey}-${this._appName.toLowerCase()}-${t}.app.ironflock.com`:null}}exports.CrossbarConnection=A;exports.IronFlock=U;exports.Stage=f;exports.validateCallParams=p;exports.validateLocationParams=_;exports.validatePublishParams=S;exports.validateTableParams=I;exports.validateTableQueryParams=M;
3
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/crossbar/index.ts","../node_modules/typia/lib/internal/_isTypeUint32.mjs","../node_modules/typia/lib/internal/_isFormatDateTime.mjs","../node_modules/typia/lib/internal/_validateReport.mjs","../node_modules/typia/lib/internal/_createStandardSchema.mjs","../src/types.ts","../src/ironflock.ts"],"sourcesContent":["import autobahn from \"autobahn\";\nimport { EventEmitter } from \"events\";\nimport { Stage } from \"../types\";\n\nexport type Details = { caller_authid: string; caller_authrole: string };\n\nexport type AuthPayload = {\n success: boolean;\n role: string;\n realm: string;\n authid: string;\n extra: {\n username: string;\n };\n};\n\nconst DATAPODS_WS_URI = \"wss://cbw.datapods.io/ws-ua-usr\";\nconst STUDIO_WS_URI = \"wss://cbw.ironflock.com/ws-ua-usr\";\nconst STUDIO_DEV_WS_URI = \"wss://cbw.ironflock.dev/ws-ua-usr\";\nconst STUDIO_WS_URI_OLD = \"wss://cbw.record-evolution.com/ws-ua-usr\";\nconst LOCALHOST_WS_URI = \"ws://localhost:8080/ws-ua-usr\";\n\nconst socketURIMap: Record<string, string> = {\n \"https://studio.datapods.io\": DATAPODS_WS_URI,\n \"https://studio.ironflock.dev\": STUDIO_DEV_WS_URI,\n \"https://studio.ironflock.com\": STUDIO_WS_URI,\n \"https://studio.record-evolution.com\": STUDIO_WS_URI_OLD,\n \"http://localhost:8085\": LOCALHOST_WS_URI,\n \"http://localhost:8086\": LOCALHOST_WS_URI,\n \"http://host.docker.internal:8086\": LOCALHOST_WS_URI,\n};\n\nconst SESSION_WAIT_TIMEOUT = 6000;\n\nexport class CrossbarConnection extends EventEmitter {\n session?: autobahn.Session;\n connection?: autobahn.Connection;\n serial_number?: string;\n socketURI?: string;\n realm?: string;\n\n private subscriptions: autobahn.Subscription[] = [];\n private registrations: autobahn.Registration[] = [];\n private firstConnection?: Promise<void>;\n private firstResolver: () => void = () => undefined;\n private firstRejecter: (reason?: any) => void = () => undefined;\n\n constructor() {\n super();\n }\n\n static getWebSocketURI(): string {\n const reswarmUrl = process.env.RESWARM_URL;\n if (!reswarmUrl) return STUDIO_WS_URI;\n return socketURIMap[reswarmUrl] ?? STUDIO_WS_URI;\n }\n\n configure(\n swarmKey: number,\n appKey: number,\n stage: Stage,\n serialNumber: string,\n cburl?: string\n ) {\n this.realm = `realm-${swarmKey}-${appKey}-${stage}`;\n this.serial_number = serialNumber;\n this.socketURI = cburl ?? CrossbarConnection.getWebSocketURI();\n }\n\n async start(): Promise<void> {\n if (!this.realm || !this.serial_number || !this.socketURI) {\n throw new Error(\"CrossbarConnection must be configured before starting. Call configure() first.\");\n }\n\n this.firstConnection = new Promise((resolve, reject) => {\n this.firstResolver = resolve;\n this.firstRejecter = reject;\n });\n\n this.connection = new autobahn.Connection({\n realm: this.realm,\n url: this.socketURI,\n authmethods: [\"wampcra\"],\n authid: this.serial_number,\n max_retries: -1,\n max_retry_delay: 2,\n initial_retry_delay: 1,\n // @ts-ignore\n autoping_interval: 2,\n autoping_timeout: 4,\n onchallenge: (_session, _method, extra) => {\n return autobahn.auth_cra.sign(this.serial_number!, extra.challenge);\n },\n });\n\n this.connection.onopen = this.onOpen.bind(this);\n this.connection.onclose = this.onClose.bind(this);\n this.connection.open();\n\n return this.firstConnection;\n }\n\n private onOpen(session: autobahn.Session) {\n this.session = session;\n this.session.caller_disclose_me = true;\n\n this.resubscribeAll();\n this.emit(\"connected\", this.serial_number);\n\n this.firstResolver();\n this.firstResolver = () => undefined;\n }\n\n private onClose(reason: string, details: any): boolean {\n this.session = undefined;\n this.emit(\"disconnected\");\n\n this.firstRejecter(\n new Error(\n `Connection failed: ${reason} - ${JSON.stringify(details, null, 2)}`\n )\n );\n this.firstRejecter = () => undefined;\n\n console.warn(\"Connection closed:\", {\n reason,\n details,\n realm: this.realm,\n url: this.socketURI,\n authid: this.serial_number,\n });\n\n // return false to let autobahn handle auto-reconnect\n return false;\n }\n\n private async sessionWait() {\n const startTime = Date.now();\n while (!this.session) {\n if (Date.now() - startTime > SESSION_WAIT_TIMEOUT) {\n throw new Error(\"Timeout waiting for session\");\n }\n await new Promise((resolve) => setTimeout(resolve, 200));\n }\n }\n\n async waitForConnection() {\n return this.firstConnection;\n }\n\n getSession() {\n return this.session;\n }\n\n get is_open(): boolean {\n return !!this.session?.isOpen;\n }\n\n isConnected() {\n return this.is_open;\n }\n\n stop() {\n this.connection?.close(\"wamp.close.normal\", \"Connection closed by client\");\n }\n\n async subscribe(\n topic: string,\n handler: autobahn.SubscribeHandler\n ): Promise<autobahn.Subscription | undefined> {\n await this.sessionWait();\n const sub = await this.session?.subscribe(topic, handler);\n if (sub) {\n this.subscriptions.push(sub);\n }\n return sub;\n }\n\n async unsubscribe(sub: autobahn.Subscription) {\n await this.sessionWait();\n const idx = this.subscriptions.indexOf(sub);\n if (idx !== -1) {\n this.subscriptions.splice(idx, 1);\n await this.session?.unsubscribe(sub);\n }\n }\n\n async unsubscribeTopic(topic: string) {\n const matching = this.subscriptions.filter((sub) => sub.topic === topic);\n for (const sub of matching) {\n await this.unsubscribe(sub);\n }\n }\n\n private async resubscribeAll() {\n const previous = [...this.subscriptions];\n this.subscriptions = [];\n await Promise.all(\n previous.map((sub) => this.subscribe(sub.topic, sub.handler))\n );\n }\n\n async register(\n topic: string,\n endpoint: autobahn.RegisterEndpoint\n ): Promise<autobahn.IRegistration | undefined> {\n await this.sessionWait();\n const registration = await this.session?.register(topic, endpoint);\n if (registration) {\n this.registrations.push(registration);\n }\n return registration;\n }\n\n async unregister(registration: autobahn.Registration) {\n await this.sessionWait();\n await this.session?.unregister(registration);\n const idx = this.registrations.indexOf(registration);\n if (idx !== -1) {\n this.registrations.splice(idx, 1);\n }\n }\n\n async call<T>(\n procedure: string,\n args?: any[],\n kwargs?: object,\n options?: any\n ) {\n await this.sessionWait();\n return this.session?.call<T>(procedure, args, kwargs, options);\n }\n\n async publish(\n topic: string,\n args?: any[],\n kwargs?: object,\n options?: any\n ) {\n await this.sessionWait();\n return this.session?.publish(topic, args, kwargs, options);\n }\n}\n","const _isTypeUint32 = (value) => Math.floor(value) === value && MINIMUM <= value && value <= MAXIMUM;\nconst MINIMUM = 0;\nconst MAXIMUM = 2 ** 32 - 1;\n\nexport { _isTypeUint32 };\n//# sourceMappingURL=_isTypeUint32.mjs.map\n","const _isFormatDateTime = (str) => PATTERN.test(str);\nconst PATTERN = /^[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;\n\nexport { _isFormatDateTime };\n//# sourceMappingURL=_isFormatDateTime.mjs.map\n","const _validateReport = (array) => {\n const reportable = (path) => {\n if (array.length === 0)\n return true;\n const last = array[array.length - 1].path;\n return path.length > last.length || last.substring(0, path.length) !== path;\n };\n return (exceptable, error) => {\n if (exceptable && reportable(error.path)) {\n if (error.value === undefined)\n error.description ??= [\n \"The value at this path is `undefined`.\",\n \"\",\n `Please fill the \\`${error.expected}\\` typed value next time.`,\n ].join(\"\\n\");\n array.push(error);\n }\n return false;\n };\n};\n\nexport { _validateReport };\n//# sourceMappingURL=_validateReport.mjs.map\n","const _createStandardSchema = (fn) => Object.assign(fn, {\n \"~standard\": {\n version: 1,\n vendor: \"typia\",\n validate: (input) => {\n const result = fn(input);\n if (result.success) {\n return {\n value: result.data,\n };\n }\n else {\n return {\n issues: result.errors.map((error) => ({\n message: `expected ${error.expected}, got ${error.value}`,\n path: typiaPathToStandardSchemaPath(error.path),\n })),\n };\n }\n },\n },\n});\nvar PathParserState;\n(function (PathParserState) {\n // Start of a new segment\n // When the parser is in this state,\n // the pointer must point `.` or `[` or equal to length of the path\n PathParserState[PathParserState[\"Start\"] = 0] = \"Start\";\n // Parsing a property key (`.hoge`)\n PathParserState[PathParserState[\"Property\"] = 1] = \"Property\";\n // Parsing a string key (`[\"fuga\"]`)\n PathParserState[PathParserState[\"StringKey\"] = 2] = \"StringKey\";\n // Parsing a number key (`[42]`)\n PathParserState[PathParserState[\"NumberKey\"] = 3] = \"NumberKey\";\n})(PathParserState || (PathParserState = {}));\nconst typiaPathToStandardSchemaPath = (path) => {\n if (!path.startsWith(\"$input\")) {\n throw new Error(`Invalid path: ${JSON.stringify(path)}`);\n }\n const segments = [];\n let currentSegment = \"\";\n let state = PathParserState.Start;\n let index = \"$input\".length - 1;\n while (index < path.length - 1) {\n index++;\n const char = path[index];\n if (state === PathParserState.Property) {\n if (char === \".\" || char === \"[\") {\n // End of property\n segments.push({\n key: currentSegment,\n });\n state = PathParserState.Start;\n }\n else if (index === path.length - 1) {\n // End of path\n currentSegment += char;\n segments.push({\n key: currentSegment,\n });\n index++;\n state = PathParserState.Start;\n }\n else {\n currentSegment += char;\n }\n }\n else if (state === PathParserState.StringKey) {\n if (char === '\"') {\n // End of string key\n segments.push({\n key: JSON.parse(currentSegment + char),\n });\n // Skip `\"` and `]`\n index += 2;\n state = PathParserState.Start;\n }\n else if (char === \"\\\\\") {\n // Skip the next character from parsing\n currentSegment += path[index];\n index++;\n currentSegment += path[index];\n }\n else {\n currentSegment += char;\n }\n }\n else if (state === PathParserState.NumberKey) {\n if (char === \"]\") {\n // End of number key\n segments.push({\n key: Number.parseInt(currentSegment),\n });\n index++;\n state = PathParserState.Start;\n }\n else {\n currentSegment += char;\n }\n }\n if (state === PathParserState.Start && index < path.length - 1) {\n const newChar = path[index];\n currentSegment = \"\";\n if (newChar === \"[\") {\n if (path[index + 1] === '\"') {\n // Start of string key\n // NOTE: Typia uses JSON.stringify for this kind of keys, so `'` will not used as a string delimiter\n state = PathParserState.StringKey;\n index++;\n currentSegment = '\"';\n }\n else {\n // Start of number key\n state = PathParserState.NumberKey;\n }\n }\n else if (newChar === \".\") {\n // Start of property\n state = PathParserState.Property;\n }\n else {\n throw new Error(\"Unreachable: pointer points invalid character\");\n }\n }\n }\n if (state !== PathParserState.Start) {\n throw new Error(`Failed to parse path: ${JSON.stringify(path)}`);\n }\n return segments;\n};\n\nexport { _createStandardSchema };\n//# sourceMappingURL=_createStandardSchema.mjs.map\n","import typia, { tags } from \"typia\";\n\nexport enum Stage {\n DEVELOPMENT = \"dev\",\n PRODUCTION = \"prod\",\n}\n\nexport interface ISOTimeRange {\n start: string & tags.Format<\"date-time\">;\n end: string & tags.Format<\"date-time\">;\n}\n\nexport interface SQLFilterAnd {\n column: string & tags.MinLength<1>;\n operator: string & tags.MinLength<1>;\n value: string | number | boolean | Array<string | number>;\n}\n\nexport interface TableQueryParams {\n limit: number & tags.Type<\"uint32\"> & tags.Minimum<1> & tags.Maximum<10000>;\n offset?: number & tags.Type<\"uint32\"> & tags.Minimum<0>;\n timeRange?: ISOTimeRange;\n filterAnd?: SQLFilterAnd[];\n}\n\nexport interface LocationParams {\n longitude: number & tags.Minimum<-180> & tags.Maximum<180>;\n latitude: number & tags.Minimum<-90> & tags.Maximum<90>;\n}\n\nexport interface PublishParams {\n topic: string & tags.MinLength<1>;\n args?: unknown[];\n kwargs?: Record<string, unknown>;\n}\n\nexport interface CallParams {\n deviceKey: string & tags.MinLength<1>;\n topic: string & tags.MinLength<1>;\n args?: unknown[];\n kwargs?: Record<string, unknown>;\n}\n\nexport interface TableParams {\n tablename: string & tags.MinLength<1>;\n args?: unknown[];\n kwargs?: Record<string, unknown>;\n}\n\nexport const validateTableQueryParams = typia.createValidate<TableQueryParams>();\nexport const validateLocationParams = typia.createValidate<LocationParams>();\nexport const validatePublishParams = typia.createValidate<PublishParams>();\nexport const validateCallParams = typia.createValidate<CallParams>();\nexport const validateTableParams = typia.createValidate<TableParams>();\n","import { CrossbarConnection } from \"./crossbar\";\nimport {\n Stage,\n validatePublishParams,\n validateCallParams,\n validateTableParams,\n validateLocationParams,\n validateTableQueryParams,\n type TableQueryParams,\n} from \"./types\";\n\nfunction getSerialNumber(serialNumber?: string): string {\n const sn = serialNumber ?? process.env.DEVICE_SERIAL_NUMBER;\n if (!sn) {\n throw new Error(\"DEVICE_SERIAL_NUMBER environment variable is not set and no serialNumber was provided\");\n }\n return sn;\n}\n\nexport interface IronFlockOptions {\n serialNumber?: string;\n}\n\nexport class IronFlock {\n private _connection: CrossbarConnection;\n private _serialNumber: string;\n private _deviceName?: string;\n private _deviceKey?: string;\n private _appName?: string;\n private _swarmKey: number;\n private _appKey: number;\n private _env?: string;\n private _isConfigured = false;\n\n constructor(options?: IronFlockOptions) {\n this._serialNumber = getSerialNumber(options?.serialNumber);\n this._deviceName = process.env.DEVICE_NAME;\n this._deviceKey = process.env.DEVICE_KEY;\n this._appName = process.env.APP_NAME;\n this._swarmKey = parseInt(process.env.SWARM_KEY ?? \"0\", 10);\n this._appKey = parseInt(process.env.APP_KEY ?? \"0\", 10);\n this._env = process.env.ENV;\n this._connection = new CrossbarConnection();\n\n const missing: string[] = [];\n if (!this._deviceKey) missing.push(\"DEVICE_KEY\");\n if (!this._appName) missing.push(\"APP_NAME\");\n if (!this._swarmKey) missing.push(\"SWARM_KEY\");\n if (!this._appKey) missing.push(\"APP_KEY\");\n if (missing.length > 0) {\n console.warn(\n `Warning: The following environment variables must be present: ${missing.join(\", \")}`\n );\n }\n }\n\n get connection(): CrossbarConnection {\n return this._connection;\n }\n\n get isConnected(): boolean {\n return this._connection.is_open;\n }\n\n private configureConnection(cburl?: string) {\n if (this._isConfigured) return;\n\n const envValue = (this._env ?? \"DEV\").toUpperCase();\n const stageMap: Record<string, Stage> = {\n DEV: Stage.DEVELOPMENT,\n PROD: Stage.PRODUCTION,\n };\n const stage = stageMap[envValue] ?? Stage.DEVELOPMENT;\n\n this._connection.configure(\n this._swarmKey,\n this._appKey,\n stage,\n this._serialNumber,\n cburl\n );\n this._isConfigured = true;\n }\n\n async start(cburl?: string): Promise<void> {\n this.configureConnection(cburl);\n await this._connection.start();\n }\n\n async stop(): Promise<void> {\n this._connection.stop();\n }\n\n async publish(\n topic: string,\n args?: unknown[],\n kwargs?: Record<string, unknown>\n ): Promise<unknown> {\n const validation = validatePublishParams({ topic, args, kwargs });\n if (!validation.success) {\n throw new Error(`Invalid publish parameters: ${validation.errors.map(e => e.path + \": \" + e.expected).join(\", \")}`);\n }\n\n const deviceMetadata: Record<string, unknown> = {\n DEVICE_SERIAL_NUMBER: this._serialNumber,\n DEVICE_KEY: this._deviceKey,\n DEVICE_NAME: this._deviceName,\n };\n const combinedKwargs = { ...deviceMetadata, ...(kwargs ?? {}) };\n\n return this._connection.publish(topic, args, combinedKwargs, {\n acknowledge: true,\n });\n }\n\n async publishToTable(\n tablename: string,\n args?: unknown[],\n kwargs?: Record<string, unknown>\n ): Promise<unknown> {\n const validation = validateTableParams({ tablename, args, kwargs });\n if (!validation.success) {\n throw new Error(`Invalid table parameters: ${validation.errors.map(e => e.path + \": \" + e.expected).join(\", \")}`);\n }\n\n if (!this._swarmKey) throw new Error(\"SWARM_KEY not set in environment variables!\");\n if (!this._appKey) throw new Error(\"APP_KEY not set in environment variables!\");\n\n const topic = `${this._swarmKey}.${this._appKey}.${tablename}`;\n return this.publish(topic, args, kwargs);\n }\n\n async subscribe(\n topic: string,\n handler: (...args: any[]) => void,\n options?: object\n ) {\n return this._connection.subscribe(topic, handler);\n }\n\n async subscribeToTable(\n tablename: string,\n handler: (...args: any[]) => void,\n options?: object\n ) {\n if (!this._swarmKey) throw new Error(\"SWARM_KEY not set in environment variables!\");\n if (!this._appKey) throw new Error(\"APP_KEY not set in environment variables!\");\n\n const topic = `${this._swarmKey}.${this._appKey}.${tablename}`;\n return this.subscribe(topic, handler, options);\n }\n\n async call(\n deviceKey: string,\n topic: string,\n args?: unknown[],\n kwargs?: Record<string, unknown>,\n options?: object\n ) {\n const validation = validateCallParams({ deviceKey, topic, args, kwargs });\n if (!validation.success) {\n throw new Error(`Invalid call parameters: ${validation.errors.map(e => e.path + \": \" + e.expected).join(\", \")}`);\n }\n\n const callTopic = `${deviceKey}.${topic}`;\n return this._connection.call(callTopic, args as any[], kwargs, options);\n }\n\n async registerFunction(\n topic: string,\n endpoint: (...args: any[]) => any,\n options?: object\n ) {\n const fullTopic = `${this._swarmKey}.${this._deviceKey}.${this._appKey}.${this._env}.${topic}`;\n\n const reg = await this._connection.register(fullTopic, endpoint);\n console.log(`Function registered for IronFlock topic '${topic}'. (Full WAMP topic: '${fullTopic}')`);\n return reg;\n }\n\n async register(\n topic: string,\n endpoint: (...args: any[]) => any,\n options?: object\n ) {\n return this.registerFunction(topic, endpoint, options);\n }\n\n async getHistory(\n tablename: string,\n queryParams: TableQueryParams = { limit: 10 }\n ) {\n if (!tablename) throw new Error(\"Tablename must not be empty!\");\n\n const validation = validateTableQueryParams(queryParams);\n if (!validation.success) {\n throw new Error(`Invalid query parameters: ${validation.errors.map(e => e.path + \": \" + e.expected).join(\", \")}`);\n }\n\n const topic = `history.transformed.app.${this._appKey}.${tablename}`;\n try {\n return await this._connection.call(topic, [queryParams]);\n } catch (e: any) {\n const errorStr = String(e);\n if (\n errorStr.includes(\"no_such_procedure\") ||\n errorStr.includes(\"no callee registered\")\n ) {\n console.error(`Get history failed: History service procedure '${topic}' not registered`);\n return null;\n }\n console.error(`Get history failed: ${e}`);\n return null;\n }\n }\n\n async setDeviceLocation(long: number, lat: number) {\n const validation = validateLocationParams({ longitude: long, latitude: lat });\n if (!validation.success) {\n throw new Error(`Invalid location parameters: ${validation.errors.map(e => e.path + \": \" + e.expected).join(\", \")}`);\n }\n\n const payload = { long, lat };\n const extra: Record<string, unknown> = {\n DEVICE_SERIAL_NUMBER: this._serialNumber,\n DEVICE_KEY: this._deviceKey,\n DEVICE_NAME: this._deviceName,\n };\n\n try {\n return await this._connection.call(\n \"ironflock.location_service.update\",\n [payload],\n extra\n );\n } catch (e) {\n console.error(`Set location failed: ${e}`);\n return null;\n }\n }\n\n getRemoteAccessUrlForPort(port: number): string | null {\n if (this._deviceKey && this._appName) {\n return `https://${this._deviceKey}-${this._appName.toLowerCase()}-${port}.app.ironflock.com`;\n }\n return null;\n }\n}\n"],"names":["DATAPODS_WS_URI","STUDIO_WS_URI","STUDIO_DEV_WS_URI","STUDIO_WS_URI_OLD","LOCALHOST_WS_URI","socketURIMap","SESSION_WAIT_TIMEOUT","CrossbarConnection","EventEmitter","reswarmUrl","swarmKey","appKey","stage","serialNumber","cburl","resolve","reject","autobahn","_session","_method","extra","session","reason","details","startTime","_a","topic","handler","sub","idx","matching","previous","endpoint","registration","procedure","args","kwargs","options","_isTypeUint32","value","MINIMUM","MAXIMUM","_isFormatDateTime","str","PATTERN","_validateReport","array","reportable","path","last","exceptable","error","_createStandardSchema","fn","input","result","typiaPathToStandardSchemaPath","PathParserState","segments","currentSegment","state","index","char","newChar","Stage","validateTableQueryParams","_io0","__typia_transform__isTypeUint32._isTypeUint32","_io1","elem","_io2","__typia_transform__isFormatDateTime._isFormatDateTime","_vo0","_path","_exceptionable","_report","_vo1","_index3","_vo2","flag","_index4","__is","errors","__typia_transform__createStandardSchema._createStandardSchema","__typia_transform__validateReport._validateReport","success","validateLocationParams","validatePublishParams","key","validateCallParams","validateTableParams","getSerialNumber","sn","IronFlock","missing","envValue","validation","combinedKwargs","tablename","e","deviceKey","callTopic","fullTopic","reg","queryParams","errorStr","long","lat","payload","port"],"mappings":"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","x_google_ignoreList":[1,2,3,4]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,146 @@
1
- import { IronFlock } from "./ironflock";
2
- export = IronFlock;
1
+ import { default as default_2 } from 'autobahn';
2
+ import { default as default_3 } from 'typia';
3
+ import { EventEmitter } from 'events';
4
+ import { IRegistration } from 'autobahn';
5
+ import { StandardSchemaV1 } from '@standard-schema/spec';
6
+ import { Subscription } from 'autobahn';
7
+ import { tags } from 'typia';
8
+
9
+ export declare type AuthPayload = {
10
+ success: boolean;
11
+ role: string;
12
+ realm: string;
13
+ authid: string;
14
+ extra: {
15
+ username: string;
16
+ };
17
+ };
18
+
19
+ export declare interface CallParams {
20
+ deviceKey: string & tags.MinLength<1>;
21
+ topic: string & tags.MinLength<1>;
22
+ args?: unknown[];
23
+ kwargs?: Record<string, unknown>;
24
+ }
25
+
26
+ export declare class CrossbarConnection extends EventEmitter {
27
+ session?: default_2.Session;
28
+ connection?: default_2.Connection;
29
+ serial_number?: string;
30
+ socketURI?: string;
31
+ realm?: string;
32
+ private subscriptions;
33
+ private registrations;
34
+ private firstConnection?;
35
+ private firstResolver;
36
+ private firstRejecter;
37
+ constructor();
38
+ static getWebSocketURI(): string;
39
+ configure(swarmKey: number, appKey: number, stage: Stage, serialNumber: string, cburl?: string): void;
40
+ start(): Promise<void>;
41
+ private onOpen;
42
+ private onClose;
43
+ private sessionWait;
44
+ waitForConnection(): Promise<void | undefined>;
45
+ getSession(): default_2.Session | undefined;
46
+ get is_open(): boolean;
47
+ isConnected(): boolean;
48
+ stop(): void;
49
+ subscribe(topic: string, handler: default_2.SubscribeHandler): Promise<default_2.Subscription | undefined>;
50
+ unsubscribe(sub: default_2.Subscription): Promise<void>;
51
+ unsubscribeTopic(topic: string): Promise<void>;
52
+ private resubscribeAll;
53
+ register(topic: string, endpoint: default_2.RegisterEndpoint): Promise<default_2.IRegistration | undefined>;
54
+ unregister(registration: default_2.Registration): Promise<void>;
55
+ call<T>(procedure: string, args?: any[], kwargs?: object, options?: any): Promise<T | undefined>;
56
+ publish(topic: string, args?: any[], kwargs?: object, options?: any): Promise<default_2.IPublication | undefined>;
57
+ }
58
+
59
+ export declare type Details = {
60
+ caller_authid: string;
61
+ caller_authrole: string;
62
+ };
63
+
64
+ export declare class IronFlock {
65
+ private _connection;
66
+ private _serialNumber;
67
+ private _deviceName?;
68
+ private _deviceKey?;
69
+ private _appName?;
70
+ private _swarmKey;
71
+ private _appKey;
72
+ private _env?;
73
+ private _isConfigured;
74
+ constructor(options?: IronFlockOptions);
75
+ get connection(): CrossbarConnection;
76
+ get isConnected(): boolean;
77
+ private configureConnection;
78
+ start(cburl?: string): Promise<void>;
79
+ stop(): Promise<void>;
80
+ publish(topic: string, args?: unknown[], kwargs?: Record<string, unknown>): Promise<unknown>;
81
+ publishToTable(tablename: string, args?: unknown[], kwargs?: Record<string, unknown>): Promise<unknown>;
82
+ subscribe(topic: string, handler: (...args: any[]) => void, options?: object): Promise<Subscription<any[], any, string> | undefined>;
83
+ subscribeToTable(tablename: string, handler: (...args: any[]) => void, options?: object): Promise<Subscription<any[], any, string> | undefined>;
84
+ call(deviceKey: string, topic: string, args?: unknown[], kwargs?: Record<string, unknown>, options?: object): Promise<unknown>;
85
+ registerFunction(topic: string, endpoint: (...args: any[]) => any, options?: object): Promise<IRegistration<any, any[], any, string> | undefined>;
86
+ register(topic: string, endpoint: (...args: any[]) => any, options?: object): Promise<IRegistration<any, any[], any, string> | undefined>;
87
+ getHistory(tablename: string, queryParams?: TableQueryParams): Promise<unknown>;
88
+ setDeviceLocation(long: number, lat: number): Promise<unknown>;
89
+ getRemoteAccessUrlForPort(port: number): string | null;
90
+ }
91
+
92
+ export declare interface IronFlockOptions {
93
+ serialNumber?: string;
94
+ }
95
+
96
+ export declare interface ISOTimeRange {
97
+ start: string & tags.Format<"date-time">;
98
+ end: string & tags.Format<"date-time">;
99
+ }
100
+
101
+ export declare interface LocationParams {
102
+ longitude: number & tags.Minimum<-180> & tags.Maximum<180>;
103
+ latitude: number & tags.Minimum<-90> & tags.Maximum<90>;
104
+ }
105
+
106
+ export declare interface PublishParams {
107
+ topic: string & tags.MinLength<1>;
108
+ args?: unknown[];
109
+ kwargs?: Record<string, unknown>;
110
+ }
111
+
112
+ export declare interface SQLFilterAnd {
113
+ column: string & tags.MinLength<1>;
114
+ operator: string & tags.MinLength<1>;
115
+ value: string | number | boolean | Array<string | number>;
116
+ }
117
+
118
+ export declare enum Stage {
119
+ DEVELOPMENT = "dev",
120
+ PRODUCTION = "prod"
121
+ }
122
+
123
+ export declare interface TableParams {
124
+ tablename: string & tags.MinLength<1>;
125
+ args?: unknown[];
126
+ kwargs?: Record<string, unknown>;
127
+ }
128
+
129
+ export declare interface TableQueryParams {
130
+ limit: number & tags.Type<"uint32"> & tags.Minimum<1> & tags.Maximum<10000>;
131
+ offset?: number & tags.Type<"uint32"> & tags.Minimum<0>;
132
+ timeRange?: ISOTimeRange;
133
+ filterAnd?: SQLFilterAnd[];
134
+ }
135
+
136
+ export declare const validateCallParams: ((input: unknown) => default_3.IValidation<CallParams>) & StandardSchemaV1<CallParams, CallParams>;
137
+
138
+ export declare const validateLocationParams: ((input: unknown) => default_3.IValidation<LocationParams>) & StandardSchemaV1<LocationParams, LocationParams>;
139
+
140
+ export declare const validatePublishParams: ((input: unknown) => default_3.IValidation<PublishParams>) & StandardSchemaV1<PublishParams, PublishParams>;
141
+
142
+ export declare const validateTableParams: ((input: unknown) => default_3.IValidation<TableParams>) & StandardSchemaV1<TableParams, TableParams>;
143
+
144
+ export declare const validateTableQueryParams: ((input: unknown) => default_3.IValidation<TableQueryParams>) & StandardSchemaV1<TableQueryParams, TableQueryParams>;
145
+
146
+ export { }