ironflock 1.3.3 → 1.5.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 +144 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +137 -0
- package/dist/index.mjs +883 -486
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ironflock
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
|
|
5
5
|
## About
|
|
6
6
|
|
|
@@ -460,6 +460,149 @@ const url = ironflock.getRemoteAccessUrlForPort(8080);
|
|
|
460
460
|
| `await start(cburl?)` | Configures and starts the connection to the platform |
|
|
461
461
|
| `await stop()` | Stops the connection |
|
|
462
462
|
|
|
463
|
+
## Cross-App Data Access
|
|
464
|
+
|
|
465
|
+
Read another app's fleet data from within your app, in the same project and fleet. The provider app must list your app in its data-template `consumes:` section, and the project user must grant access. Access is **read-only**: you can query history and subscribe to realtime rows of the tables and transforms (views) the provider shares — you cannot write to them.
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
import { IronFlock, CrossAppAccessError } from "ironflock";
|
|
469
|
+
|
|
470
|
+
const ironflock = new IronFlock();
|
|
471
|
+
await ironflock.start();
|
|
472
|
+
|
|
473
|
+
// Open a read-only handle on another app's data backend
|
|
474
|
+
const weather = await ironflock.connectToApp("weather-app");
|
|
475
|
+
|
|
476
|
+
// Inspect what the provider shares (non-private tables / transforms)
|
|
477
|
+
console.log(weather.tables.map((t) => t.tablename));
|
|
478
|
+
|
|
479
|
+
// Query history, just like your own tables
|
|
480
|
+
const rows = await weather.getHistory("forecasts", { limit: 100 });
|
|
481
|
+
|
|
482
|
+
// Subscribe to realtime rows
|
|
483
|
+
await weather.subscribeToTable("forecasts", (...args) => {
|
|
484
|
+
console.log("New forecast:", args);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// Access errors carry a machine-readable code
|
|
488
|
+
try {
|
|
489
|
+
await ironflock.connectToApp("unshared-app");
|
|
490
|
+
} catch (err) {
|
|
491
|
+
if (err instanceof CrossAppAccessError) {
|
|
492
|
+
console.error(err.code); // e.g. "NO_GRANT"
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Consumed-app connections are cached per app + stage and are closed automatically by `ironflock.stop()`.
|
|
498
|
+
|
|
499
|
+
### `connectToApp(appName, opts?)`
|
|
500
|
+
|
|
501
|
+
Opens a read-only connection to another app's data backend in the same project and returns a `ConsumedApp` handle. Resolves the provider and connects to its realm using this device's credentials.
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
const weather = await ironflock.connectToApp("weather-app", { stage: "prod" });
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
| Parameter | Type | Description |
|
|
508
|
+
|-----------|------|-------------|
|
|
509
|
+
| `appName` | `string` | Provider app name, as declared in your `consumes:` section |
|
|
510
|
+
| `opts` | `ConnectToAppOptions`, optional | Options (see below) |
|
|
511
|
+
|
|
512
|
+
**opts fields:**
|
|
513
|
+
|
|
514
|
+
| Field | Type | Description |
|
|
515
|
+
|-------|------|-------------|
|
|
516
|
+
| `stage` | `"dev" \| "prod"`, optional | Provider stage to connect to. Defaults to this app's own stage (`ENV`) |
|
|
517
|
+
| `onError` | `(error: CrossAppAccessError) => void`, optional | Called when the connection is fatally denied *after* `connectToApp` resolved (e.g. the grant is later revoked) |
|
|
518
|
+
|
|
519
|
+
**Returns:** `Promise<ConsumedApp>` — A read-only handle on the provider's data backend.
|
|
520
|
+
|
|
521
|
+
**Throws:** `CrossAppAccessError` (`code`: `NO_GRANT`, `PROVIDER_NOT_INSTALLED`, `UNKNOWN_APP`, or `NOT_AUTHORIZED`).
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
### `ConsumedApp` handle
|
|
526
|
+
|
|
527
|
+
Returned by `connectToApp`. A read-only view of a provider app's shared tables and transforms.
|
|
528
|
+
|
|
529
|
+
**Properties:**
|
|
530
|
+
|
|
531
|
+
| Property | Type | Description |
|
|
532
|
+
|----------|------|-------------|
|
|
533
|
+
| `app` | `string` | Provider app name |
|
|
534
|
+
| `stage` | `"dev" \| "prod"` | Provider stage this handle is connected to |
|
|
535
|
+
| `tables` | `ProviderTableInfo[]` | Non-private tables the provider shares |
|
|
536
|
+
| `transforms` | `ProviderTableInfo[]` | Non-private transforms (views) the provider shares |
|
|
537
|
+
| `isConnected` | `boolean` | `true` while the connection to the provider is open |
|
|
538
|
+
| `connection` | `CrossbarConnection` | The underlying connection (advanced use) |
|
|
539
|
+
|
|
540
|
+
#### `consumedApp.getHistory(tablename, queryParams?)`
|
|
541
|
+
|
|
542
|
+
Queries history rows of a shared table or transform. Takes the same query parameters as [`getHistory`](#gethistorytablename-queryparams) (`limit`, `offset`, `timeRange`, `filterAnd`).
|
|
543
|
+
|
|
544
|
+
```ts
|
|
545
|
+
const rows = await weather.getHistory("forecasts", { limit: 100 });
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Returns:** `Promise<unknown>` — The query result rows.
|
|
549
|
+
|
|
550
|
+
#### `consumedApp.subscribeToTable(tablename, handler)`
|
|
551
|
+
|
|
552
|
+
Subscribes to realtime rows of a shared table or transform. Bulk-inserted rows are delivered one at a time, exactly like [`subscribeToTable`](#subscribetotabletablename-handler).
|
|
553
|
+
|
|
554
|
+
```ts
|
|
555
|
+
await weather.subscribeToTable("forecasts", (...args) => console.log(args));
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**Returns:** `Promise<Subscription | undefined>` — The subscription object.
|
|
559
|
+
|
|
560
|
+
#### `consumedApp.getSeriesHistory(tablename, params)`
|
|
561
|
+
|
|
562
|
+
Queries down-sampled time-series history of a shared **table** (not available for transforms).
|
|
563
|
+
|
|
564
|
+
```ts
|
|
565
|
+
const series = await weather.getSeriesHistory("forecasts", {
|
|
566
|
+
metrics: ["temperature"],
|
|
567
|
+
method: "AVG",
|
|
568
|
+
limit: 500,
|
|
569
|
+
timeRange: ["2026-01-01T00:00:00Z", "2026-03-01T00:00:00Z"],
|
|
570
|
+
});
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
**params fields (`SeriesQueryParams`):**
|
|
574
|
+
|
|
575
|
+
| Field | Type | Description |
|
|
576
|
+
|-------|------|-------------|
|
|
577
|
+
| `metrics` | `string[]` | Numeric columns to down-sample |
|
|
578
|
+
| `method` | `DownSampleMethod` | Aggregation per bucket: `"AVG"`, `"SUM"`, `"COUNT"`, `"MIN"`, `"MAX"`, `"FIRST"` or `"LAST"` |
|
|
579
|
+
| `limit` | `number` | Maximum number of rows (1–10000) |
|
|
580
|
+
| `timeRange` | `SeriesTimeRange` | `[start, end]` — ISO strings or epoch-ms numbers; `null` = open end (required) |
|
|
581
|
+
| `groupBy` | `string[]`, optional | Columns to group the series by |
|
|
582
|
+
| `filterAnd` | `SQLFilterAnd[]`, optional | AND filter conditions |
|
|
583
|
+
|
|
584
|
+
**Returns:** `Promise<unknown>` — The down-sampled series rows.
|
|
585
|
+
|
|
586
|
+
#### `consumedApp.close()`
|
|
587
|
+
|
|
588
|
+
Closes this handle's connection to the provider. (All consumed-app connections are also closed by `ironflock.stop()`.)
|
|
589
|
+
|
|
590
|
+
**Returns:** `Promise<void>`
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
### `CrossAppAccessError`
|
|
595
|
+
|
|
596
|
+
Thrown by `connectToApp` and the `ConsumedApp` methods when cross-app access is denied or misused. Exposes a machine-readable `code`:
|
|
597
|
+
|
|
598
|
+
| `code` | Meaning |
|
|
599
|
+
|--------|---------|
|
|
600
|
+
| `NO_GRANT` | The project user has not granted your app access to the provider |
|
|
601
|
+
| `PROVIDER_NOT_INSTALLED` | The provider app has no data backend for that stage in this project |
|
|
602
|
+
| `UNKNOWN_APP` | No app by that name |
|
|
603
|
+
| `PRIVATE_TABLE` | The requested table/transform is not in the provider's shared catalog |
|
|
604
|
+
| `NOT_AUTHORIZED` | The router/provider denied access (e.g. the grant was revoked) |
|
|
605
|
+
|
|
463
606
|
## Development
|
|
464
607
|
|
|
465
608
|
Install dependencies:
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
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;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("autobahn");function H(h){return h&&h.__esModule&&Object.prototype.hasOwnProperty.call(h,"default")?h.default:h}var $={exports:{}},U;function G(){return U||(U=1,(function(h){var s=Object.prototype.hasOwnProperty,t="~";function a(){}Object.create&&(a.prototype=Object.create(null),new a().__proto__||(t=!1));function c(o,e,n){this.fn=o,this.context=e,this.once=n||!1}function i(o,e,n,l,d){if(typeof n!="function")throw new TypeError("The listener must be a function");var v=new c(n,l||o,d),f=t?t+e:e;return o._events[f]?o._events[f].fn?o._events[f]=[o._events[f],v]:o._events[f].push(v):(o._events[f]=v,o._eventsCount++),o}function u(o,e){--o._eventsCount===0?o._events=new a:delete o._events[e]}function r(){this._events=new a,this._eventsCount=0}r.prototype.eventNames=function(){var e=[],n,l;if(this._eventsCount===0)return e;for(l in n=this._events)s.call(n,l)&&e.push(t?l.slice(1):l);return Object.getOwnPropertySymbols?e.concat(Object.getOwnPropertySymbols(n)):e},r.prototype.listeners=function(e){var n=t?t+e:e,l=this._events[n];if(!l)return[];if(l.fn)return[l.fn];for(var d=0,v=l.length,f=new Array(v);d<v;d++)f[d]=l[d].fn;return f},r.prototype.listenerCount=function(e){var n=t?t+e:e,l=this._events[n];return l?l.fn?1:l.length:0},r.prototype.emit=function(e,n,l,d,v,f){var g=t?t+e:e;if(!this._events[g])return!1;var y=this._events[g],A=arguments.length,E,m;if(y.fn){switch(y.once&&this.removeListener(e,y.fn,void 0,!0),A){case 1:return y.fn.call(y.context),!0;case 2:return y.fn.call(y.context,n),!0;case 3:return y.fn.call(y.context,n,l),!0;case 4:return y.fn.call(y.context,n,l,d),!0;case 5:return y.fn.call(y.context,n,l,d,v),!0;case 6:return y.fn.call(y.context,n,l,d,v,f),!0}for(m=1,E=new Array(A-1);m<A;m++)E[m-1]=arguments[m];y.fn.apply(y.context,E)}else{var Q=y.length,S;for(m=0;m<Q;m++)switch(y[m].once&&this.removeListener(e,y[m].fn,void 0,!0),A){case 1:y[m].fn.call(y[m].context);break;case 2:y[m].fn.call(y[m].context,n);break;case 3:y[m].fn.call(y[m].context,n,l);break;case 4:y[m].fn.call(y[m].context,n,l,d);break;default:if(!E)for(S=1,E=new Array(A-1);S<A;S++)E[S-1]=arguments[S];y[m].fn.apply(y[m].context,E)}}return!0},r.prototype.on=function(e,n,l){return i(this,e,n,l,!1)},r.prototype.once=function(e,n,l){return i(this,e,n,l,!0)},r.prototype.removeListener=function(e,n,l,d){var v=t?t+e:e;if(!this._events[v])return this;if(!n)return u(this,v),this;var f=this._events[v];if(f.fn)f.fn===n&&(!d||f.once)&&(!l||f.context===l)&&u(this,v);else{for(var g=0,y=[],A=f.length;g<A;g++)(f[g].fn!==n||d&&!f[g].once||l&&f[g].context!==l)&&y.push(f[g]);y.length?this._events[v]=y.length===1?y[0]:y:u(this,v)}return this},r.prototype.removeAllListeners=function(e){var n;return e?(n=t?t+e:e,this._events[n]&&u(this,n)):(this._events=new a,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prefixed=t,r.EventEmitter=r,h.exports=r})($)),$.exports}var J=G();const Z=H(J),z="wss://cbw.datapods.io/ws-ua-usr",V="wss://cbw.ironflock.com/ws-ua-usr",X="wss://cbw.ironflock.dev/ws-ua-usr",q="wss://cbw.record-evolution.com/ws-ua-usr",O="ws://localhost:8080/ws-ua-usr",F={"https://studio.datapods.io":z,"https://studio.ironflock.dev":X,"https://studio.ironflock.com":V,"https://studio.record-evolution.com":q,"http://localhost:8085":O,"http://localhost:8086":O,"http://host.docker.internal:8086":O},ee=6e3,re=["wamp.error.not_authorized","wamp.error.authorization_failed","wamp.error.authentication_failed","wamp.error.no_auth_method"];class R extends Z{constructor(){super(),this.failOnAuthError=!1,this.subscriptions=[],this.registrations=[],this.firstResolver=()=>{},this.firstRejecter=()=>{},this.shouldReconnect=!1,this.isReconnecting=!1,this.hasOpenedOnce=!1}static getWebSocketURI(s){var c;const t=typeof process<"u"?(c=process.env)==null?void 0:c.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 V;const a=F[s];if(a===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(F))}`);return a}configure(s,t,a,c,i){this.realm=`realm-${s}-${t}-${a}`,this.serial_number=c,this.socketURI=i??R.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 D.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,a)=>D.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(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){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});const a=(t==null?void 0:t.reason)??s;return this.failOnAuthError&&typeof a=="string"&&re.includes(a)?(this.shouldReconnect=!1,this.emit("auth_failure",a,t),!0):(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>ee)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 c;await this.sessionWait();const a=await((c=this.session)==null?void 0:c.subscribe(s,t));return a&&this.subscriptions.push(a),a}async unsubscribe(s){var a;await this.sessionWait();const t=this.subscriptions.indexOf(s);t!==-1&&(this.subscriptions.splice(t,1),await((a=this.session)==null?void 0:a.unsubscribe(s)))}async unsubscribeTopic(s){const t=this.subscriptions.filter(a=>a.topic===s);for(const a of t)await this.unsubscribe(a)}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,a){var u;await this.sessionWait();const c={force_reregister:!0,...a??{}},i=await((u=this.session)==null?void 0:u.register(s,t,c));return i&&this.registrations.push(i),i}async unregister(s){var a;await this.sessionWait(),await((a=this.session)==null?void 0:a.unregister(s));const t=this.registrations.indexOf(s);t!==-1&&this.registrations.splice(t,1)}async call(s,t,a,c){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.call(s,t,a,c)}async publish(s,t,a,c){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.publish(s,t,a,c)}}const M=h=>Math.floor(h)===h&&te<=h&&h<=se,te=0,se=2**32-1,I=h=>ne.test(h),ne=/^[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,_=h=>{const s=t=>{if(h.length===0)return!0;const a=h[h.length-1].path;return t.length>a.length||a.substring(0,t.length)!==t};return(t,a)=>(t&&s(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
|
+
`))),h.push(a)),!1)},T=h=>Object.assign(h,{"~standard":{version:1,vendor:"typia",validate:s=>{const t=h(s);return t.success?{value:t.data}:{issues:t.errors.map(a=>({message:`expected ${a.expected}, got ${a.value}`,path:oe(a.path)}))}}}});var w;(function(h){h[h.Start=0]="Start",h[h.Property=1]="Property",h[h.StringKey=2]="StringKey",h[h.NumberKey=3]="NumberKey"})(w||(w={}));const oe=h=>{if(!h.startsWith("$input"))throw new Error(`Invalid path: ${JSON.stringify(h)}`);const s=[];let t="",a=w.Start,c=5;for(;c<h.length-1;){c++;const i=h[c];if(a===w.Property?i==="."||i==="["?(s.push({key:t}),a=w.Start):c===h.length-1?(t+=i,s.push({key:t}),c++,a=w.Start):t+=i:a===w.StringKey?i==='"'?(s.push({key:JSON.parse(t+i)}),c+=2,a=w.Start):i==="\\"?(t+=h[c],c++,t+=h[c]):t+=i:a===w.NumberKey&&(i==="]"?(s.push({key:Number.parseInt(t)}),c++,a=w.Start):t+=i),a===w.Start&&c<h.length-1){const u=h[c];if(t="",u==="[")h[c+1]==='"'?(a=w.StringKey,c++,t='"'):a=w.NumberKey;else if(u===".")a=w.Property;else throw new Error("Unreachable: pointer points invalid character")}}if(a!==w.Start)throw new Error(`Failed to parse path: ${JSON.stringify(h)}`);return s};var p=(h=>(h.DEVELOPMENT="dev",h.PRODUCTION="prod",h))(p||{});const P=(()=>{const h=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&&s(e.timeRange))&&(e.filterAnd===void 0||Array.isArray(e.filterAnd)&&e.filterAnd.every(n=>typeof n=="object"&&n!==null&&t(n))),s=e=>typeof e.start=="string"&&I(e.start)&&typeof e.end=="string"&&I(e.end),t=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")),a=(e,n,l=!0)=>[typeof e.limit=="number"&&(M(e.limit)||o(l,{path:n+".limit",expected:'number & Type<"uint32">',value:e.limit}))&&(1<=e.limit||o(l,{path:n+".limit",expected:"number & Minimum<1>",value:e.limit}))&&(e.limit<=1e4||o(l,{path:n+".limit",expected:"number & Maximum<10000>",value:e.limit}))||o(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)||o(l,{path:n+".offset",expected:'number & Type<"uint32">',value:e.offset}))&&(0<=e.offset||o(l,{path:n+".offset",expected:"number & Minimum<0>",value:e.offset}))||o(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||o(l,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:e.timeRange}))&&c(e.timeRange,n+".timeRange",l)||o(l,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:e.timeRange}),e.filterAnd===void 0||(Array.isArray(e.filterAnd)||o(l,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:e.filterAnd}))&&e.filterAnd.map((d,v)=>(typeof d=="object"&&d!==null||o(l,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d}))&&i(d,n+".filterAnd["+v+"]",l)||o(l,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d})).every(d=>d)||o(l,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:e.filterAnd})].every(d=>d),c=(e,n,l=!0)=>[typeof e.start=="string"&&(I(e.start)||o(l,{path:n+".start",expected:'string & Format<"date-time">',value:e.start}))||o(l,{path:n+".start",expected:'(string & Format<"date-time">)',value:e.start}),typeof e.end=="string"&&(I(e.end)||o(l,{path:n+".end",expected:'string & Format<"date-time">',value:e.end}))||o(l,{path:n+".end",expected:'(string & Format<"date-time">)',value:e.end})].every(d=>d),i=(e,n,l=!0)=>[typeof e.column=="string"&&(1<=e.column.length||o(l,{path:n+".column",expected:"string & MinLength<1>",value:e.column}))||o(l,{path:n+".column",expected:"(string & MinLength<1>)",value:e.column}),typeof e.operator=="string"&&(1<=e.operator.length||o(l,{path:n+".operator",expected:"string & MinLength<1>",value:e.operator}))||o(l,{path:n+".operator",expected:"(string & MinLength<1>)",value:e.operator}),(e.value!==null||o(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&(e.value!==void 0||o(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)||o(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&e.value.map((d,v)=>typeof d=="string"||typeof d=="number"||o(l,{path:n+".value["+v+"]",expected:"(number | string)",value:d})).every(d=>d)||o(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))].every(d=>d),u=e=>typeof e=="object"&&e!==null&&h(e);let r,o;return T(e=>{if(u(e)===!1){r=[],o=_(r),((l,d,v=!0)=>(typeof l=="object"&&l!==null||o(!0,{path:d+"",expected:"TableQueryParams",value:l}))&&a(l,d+"",!0)||o(!0,{path:d+"",expected:"TableQueryParams",value:l}))(e,"$input",!0);const n=r.length===0;return n?{success:n,data:e}:{success:n,errors:r,data:e}}return{success:!0,data:e}})})(),x=(()=>{const h=e=>{const n=e,l=[[d=>d.length===2&&(d[0]===null||typeof d[0]=="number")&&(d[1]===null||typeof d[1]=="number"),d=>d.length===2&&(d[0]===null||typeof d[0]=="number")&&(d[1]===null||typeof d[1]=="number")],[d=>d.length===2&&(d[0]===null||typeof d[0]=="string")&&(d[1]===null||typeof d[1]=="string"),d=>d.length===2&&(d[0]===null||typeof d[0]=="string")&&(d[1]===null||typeof d[1]=="string")]];for(const d of l)if(d[0](n))return d[1](n);return!1},s=(e,n,l=!0)=>{const d=e,v=[[f=>f.length===2&&[f[0]===null||typeof f[0]=="number",f[1]===null||typeof f[1]=="number"].every(g=>g),f=>(f.length===2||o(l,{path:n,expected:"[(null | number), (null | number)]",value:f}))&&[f[0]===null||typeof f[0]=="number"||o(l,{path:n+"[0]",expected:"(null | number)",value:f[0]}),f[1]===null||typeof f[1]=="number"||o(l,{path:n+"[1]",expected:"(null | number)",value:f[1]})].every(g=>g)],[f=>f.length===2&&[f[0]===null||typeof f[0]=="string",f[1]===null||typeof f[1]=="string"].every(g=>g),f=>(f.length===2||o(l,{path:n,expected:"[(null | string), (null | string)]",value:f}))&&[f[0]===null||typeof f[0]=="string"||o(l,{path:n+"[0]",expected:"(null | string)",value:f[0]}),f[1]===null||typeof f[1]=="string"||o(l,{path:n+"[1]",expected:"(null | string)",value:f[1]})].every(g=>g)]];for(const f of v)if(f[0](d))return f[1](d);return o(l,{path:n,expected:"([number | null, number | null] | [string | null, string | null])",value:e})},t=e=>Array.isArray(e.metrics)&&e.metrics.every(n=>typeof n=="string")&&(e.method==="AVG"||e.method==="SUM"||e.method==="COUNT"||e.method==="MIN"||e.method==="MAX"||e.method==="FIRST"||e.method==="LAST")&&typeof e.limit=="number"&&M(e.limit)&&1<=e.limit&&e.limit<=1e4&&Array.isArray(e.timeRange)&&(h(e.timeRange)||!1)&&(e.groupBy===null||e.groupBy===void 0||Array.isArray(e.groupBy)&&e.groupBy.every(n=>typeof n=="string"))&&(e.filterAnd===null||e.filterAnd===void 0||Array.isArray(e.filterAnd)&&e.filterAnd.every(n=>typeof n=="object"&&n!==null&&a(n))),a=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")),c=(e,n,l=!0)=>[(Array.isArray(e.metrics)||o(l,{path:n+".metrics",expected:"Array<string>",value:e.metrics}))&&e.metrics.map((d,v)=>typeof d=="string"||o(l,{path:n+".metrics["+v+"]",expected:"string",value:d})).every(d=>d)||o(l,{path:n+".metrics",expected:"Array<string>",value:e.metrics}),e.method==="AVG"||e.method==="SUM"||e.method==="COUNT"||e.method==="MIN"||e.method==="MAX"||e.method==="FIRST"||e.method==="LAST"||o(l,{path:n+".method",expected:'("AVG" | "COUNT" | "FIRST" | "LAST" | "MAX" | "MIN" | "SUM")',value:e.method}),typeof e.limit=="number"&&(M(e.limit)||o(l,{path:n+".limit",expected:'number & Type<"uint32">',value:e.limit}))&&(1<=e.limit||o(l,{path:n+".limit",expected:"number & Minimum<1>",value:e.limit}))&&(e.limit<=1e4||o(l,{path:n+".limit",expected:"number & Maximum<10000>",value:e.limit}))||o(l,{path:n+".limit",expected:'(number & Type<"uint32"> & Minimum<1> & Maximum<10000>)',value:e.limit}),(Array.isArray(e.timeRange)||o(l,{path:n+".timeRange",expected:"([number | null, number | null] | [string | null, string | null])",value:e.timeRange}))&&(s(e.timeRange,n+".timeRange",l)||o(l,{path:n+".timeRange",expected:"[number | null, number | null] | [string | null, string | null]",value:e.timeRange}))||o(l,{path:n+".timeRange",expected:"([number | null, number | null] | [string | null, string | null])",value:e.timeRange}),e.groupBy===null||e.groupBy===void 0||(Array.isArray(e.groupBy)||o(l,{path:n+".groupBy",expected:"(Array<string> | null | undefined)",value:e.groupBy}))&&e.groupBy.map((d,v)=>typeof d=="string"||o(l,{path:n+".groupBy["+v+"]",expected:"string",value:d})).every(d=>d)||o(l,{path:n+".groupBy",expected:"(Array<string> | null | undefined)",value:e.groupBy}),e.filterAnd===null||e.filterAnd===void 0||(Array.isArray(e.filterAnd)||o(l,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | null | undefined)",value:e.filterAnd}))&&e.filterAnd.map((d,v)=>(typeof d=="object"&&d!==null||o(l,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d}))&&i(d,n+".filterAnd["+v+"]",l)||o(l,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d})).every(d=>d)||o(l,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | null | undefined)",value:e.filterAnd})].every(d=>d),i=(e,n,l=!0)=>[typeof e.column=="string"&&(1<=e.column.length||o(l,{path:n+".column",expected:"string & MinLength<1>",value:e.column}))||o(l,{path:n+".column",expected:"(string & MinLength<1>)",value:e.column}),typeof e.operator=="string"&&(1<=e.operator.length||o(l,{path:n+".operator",expected:"string & MinLength<1>",value:e.operator}))||o(l,{path:n+".operator",expected:"(string & MinLength<1>)",value:e.operator}),(e.value!==null||o(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&(e.value!==void 0||o(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)||o(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&e.value.map((d,v)=>typeof d=="string"||typeof d=="number"||o(l,{path:n+".value["+v+"]",expected:"(number | string)",value:d})).every(d=>d)||o(l,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))].every(d=>d),u=e=>typeof e=="object"&&e!==null&&t(e);let r,o;return T(e=>{if(u(e)===!1){r=[],o=_(r),((l,d,v=!0)=>(typeof l=="object"&&l!==null||o(!0,{path:d+"",expected:"SeriesQueryParams",value:l}))&&c(l,d+"",!0)||o(!0,{path:d+"",expected:"SeriesQueryParams",value:l}))(e,"$input",!0);const n=r.length===0;return n?{success:n,data:e}:{success:n,errors:r,data:e}}return{success:!0,data:e}})})(),W=(()=>{const h=i=>typeof i.longitude=="number"&&-180<=i.longitude&&i.longitude<=180&&typeof i.latitude=="number"&&-90<=i.latitude&&i.latitude<=90,s=(i,u,r=!0)=>[typeof i.longitude=="number"&&(-180<=i.longitude||c(r,{path:u+".longitude",expected:"number & Minimum<-180>",value:i.longitude}))&&(i.longitude<=180||c(r,{path:u+".longitude",expected:"number & Maximum<180>",value:i.longitude}))||c(r,{path:u+".longitude",expected:"(number & Minimum<-180> & Maximum<180>)",value:i.longitude}),typeof i.latitude=="number"&&(-90<=i.latitude||c(r,{path:u+".latitude",expected:"number & Minimum<-90>",value:i.latitude}))&&(i.latitude<=90||c(r,{path:u+".latitude",expected:"number & Maximum<90>",value:i.latitude}))||c(r,{path:u+".latitude",expected:"(number & Minimum<-90> & Maximum<90>)",value:i.latitude})].every(o=>o),t=i=>typeof i=="object"&&i!==null&&h(i);let a,c;return T(i=>{if(t(i)===!1){a=[],c=_(a),((r,o,e=!0)=>(typeof r=="object"&&r!==null||c(!0,{path:o+"",expected:"LocationParams",value:r}))&&s(r,o+"",!0)||c(!0,{path:o+"",expected:"LocationParams",value:r}))(i,"$input",!0);const u=a.length===0;return u?{success:u,data:i}:{success:u,errors:a,data:i}}return{success:!0,data:i}})})(),B=(()=>{const h=r=>typeof r.topic=="string"&&1<=r.topic.length&&(r.args===void 0||Array.isArray(r.args))&&(r.kwargs===void 0||typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1&&s(r.kwargs)),s=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),t=(r,o,e=!0)=>[typeof r.topic=="string"&&(1<=r.topic.length||u(e,{path:o+".topic",expected:"string & MinLength<1>",value:r.topic}))||u(e,{path:o+".topic",expected:"(string & MinLength<1>)",value:r.topic}),r.args===void 0||Array.isArray(r.args)||u(e,{path:o+".args",expected:"(Array<unknown> | undefined)",value:r.args}),r.kwargs===void 0||(typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs}))&&a(r.kwargs,o+".kwargs",e)||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs})].every(n=>n),a=(r,o,e=!0)=>[e===!1||Object.keys(r).map(n=>(r[n]===void 0,!0)).every(n=>n)].every(n=>n),c=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(c(r)===!1){i=[],u=_(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"PublishParams",value:e}))&&t(e,n+"",!0)||u(!0,{path:n+"",expected:"PublishParams",value:e}))(r,"$input",!0);const o=i.length===0;return o?{success:o,data:r}:{success:o,errors:i,data:r}}return{success:!0,data:r}})})(),ae=(()=>{const h=r=>typeof r.deviceKey=="string"&&1<=r.deviceKey.length&&typeof r.topic=="string"&&1<=r.topic.length&&(r.args===void 0||Array.isArray(r.args))&&(r.kwargs===void 0||typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1&&s(r.kwargs)),s=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),t=(r,o,e=!0)=>[typeof r.deviceKey=="string"&&(1<=r.deviceKey.length||u(e,{path:o+".deviceKey",expected:"string & MinLength<1>",value:r.deviceKey}))||u(e,{path:o+".deviceKey",expected:"(string & MinLength<1>)",value:r.deviceKey}),typeof r.topic=="string"&&(1<=r.topic.length||u(e,{path:o+".topic",expected:"string & MinLength<1>",value:r.topic}))||u(e,{path:o+".topic",expected:"(string & MinLength<1>)",value:r.topic}),r.args===void 0||Array.isArray(r.args)||u(e,{path:o+".args",expected:"(Array<unknown> | undefined)",value:r.args}),r.kwargs===void 0||(typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs}))&&a(r.kwargs,o+".kwargs",e)||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs})].every(n=>n),a=(r,o,e=!0)=>[e===!1||Object.keys(r).map(n=>(r[n]===void 0,!0)).every(n=>n)].every(n=>n),c=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(c(r)===!1){i=[],u=_(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"CallParams",value:e}))&&t(e,n+"",!0)||u(!0,{path:n+"",expected:"CallParams",value:e}))(r,"$input",!0);const o=i.length===0;return o?{success:o,data:r}:{success:o,errors:i,data:r}}return{success:!0,data:r}})})(),K=(()=>{const h=r=>typeof r.tablename=="string"&&1<=r.tablename.length&&(r.args===void 0||Array.isArray(r.args))&&(r.kwargs===void 0||typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1&&s(r.kwargs)),s=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),t=(r,o,e=!0)=>[typeof r.tablename=="string"&&(1<=r.tablename.length||u(e,{path:o+".tablename",expected:"string & MinLength<1>",value:r.tablename}))||u(e,{path:o+".tablename",expected:"(string & MinLength<1>)",value:r.tablename}),r.args===void 0||Array.isArray(r.args)||u(e,{path:o+".args",expected:"(Array<unknown> | undefined)",value:r.args}),r.kwargs===void 0||(typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs}))&&a(r.kwargs,o+".kwargs",e)||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs})].every(n=>n),a=(r,o,e=!0)=>[e===!1||Object.keys(r).map(n=>(r[n]===void 0,!0)).every(n=>n)].every(n=>n),c=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(c(r)===!1){i=[],u=_(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"TableParams",value:e}))&&t(e,n+"",!0)||u(!0,{path:n+"",expected:"TableParams",value:e}))(r,"$input",!0);const o=i.length===0;return o?{success:o,data:r}:{success:o,errors:i,data:r}}return{success:!0,data:r}})})(),C=(()=>{const h=r=>typeof r.tablename=="string"&&1<=r.tablename.length&&Array.isArray(r.rows)&&1<=r.rows.length&&r.rows.every(o=>typeof o=="object"&&o!==null&&Array.isArray(o)===!1&&s(o))&&(r.kwargs===void 0||typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1&&s(r.kwargs)),s=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),t=(r,o,e=!0)=>[typeof r.tablename=="string"&&(1<=r.tablename.length||u(e,{path:o+".tablename",expected:"string & MinLength<1>",value:r.tablename}))||u(e,{path:o+".tablename",expected:"(string & MinLength<1>)",value:r.tablename}),(Array.isArray(r.rows)||u(e,{path:o+".rows",expected:"(Array<Record<string, unknown>> & MinItems<1>)",value:r.rows}))&&(1<=r.rows.length||u(e,{path:o+".rows",expected:"Array<> & MinItems<1>",value:r.rows}))&&r.rows.map((n,l)=>(typeof n=="object"&&n!==null&&Array.isArray(n)===!1||u(e,{path:o+".rows["+l+"]",expected:"Record<string, unknown>",value:n}))&&a(n,o+".rows["+l+"]",e)||u(e,{path:o+".rows["+l+"]",expected:"Record<string, unknown>",value:n})).every(n=>n)||u(e,{path:o+".rows",expected:"(Array<Record<string, unknown>> & MinItems<1>)",value:r.rows}),r.kwargs===void 0||(typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs}))&&a(r.kwargs,o+".kwargs",e)||u(e,{path:o+".kwargs",expected:"(Record<string, unknown> | undefined)",value:r.kwargs})].every(n=>n),a=(r,o,e=!0)=>[e===!1||Object.keys(r).map(n=>(r[n]===void 0,!0)).every(n=>n)].every(n=>n),c=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(c(r)===!1){i=[],u=_(i),((e,n,l=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"BulkTableParams",value:e}))&&t(e,n+"",!0)||u(!0,{path:n+"",expected:"BulkTableParams",value:e}))(r,"$input",!0);const o=i.length===0;return o?{success:o,data:r}:{success:o,errors:i,data:r}}return{success:!0,data:r}})})(),ie={"sys.appaccess.error.no_grant":"NO_GRANT","sys.appaccess.error.provider_not_installed":"PROVIDER_NOT_INSTALLED","sys.appaccess.error.unknown_app":"UNKNOWN_APP","wamp.error.not_authorized":"NOT_AUTHORIZED","wamp.error.authorization_failed":"NOT_AUTHORIZED","wamp.error.authentication_failed":"NOT_AUTHORIZED"};class k extends Error{constructor(s,t){super(t??s),this.name="CrossAppAccessError",this.code=s}}function N(h){const s=h==null?void 0:h.error;if(typeof s!="string")return null;const t=ie[s];if(!t)return null;const a=h.args,c=Array.isArray(a)&&a.length>0?`: ${JSON.stringify(a[0])}`:"";return new k(t,`${s}${c}`)}class Y{constructor(s,t,a,c,i){this.app=s,this.stage=t,this.tables=a.tables??[],this.transforms=a.transforms??[],this._connection=c,this._onClosed=i}get connection(){return this._connection}get isConnected(){return this._connection.is_open}assertInCatalog(s){if(!s)throw new Error("Tablename must not be empty!");const t=[...this.tables,...this.transforms].map(a=>a.tablename);if(!t.includes(s))throw new k("PRIVATE_TABLE",`'${s}' is not shared by app '${this.app}' (${this.stage}). Available tables/transforms: ${t.length>0?t.join(", "):"none"}`)}async subscribeToTable(s,t,a){this.assertInCatalog(s);const c=await this._connection.subscribe(`transformed.${s}`,t),i=(u,r,o)=>{const e=Array.isArray(u)?u[0]:u,n=Array.isArray(e)?e:e==null?[]:[e];for(const l of n)t([l],r,o)};return await this._connection.subscribe(`transformed.bulk.${s}`,i),c}async getHistory(s,t={limit:10}){this.assertInCatalog(s),t.offset==null&&(t.offset=0);const a=P(t);if(!a.success)throw new Error(`Invalid query parameters: ${a.errors.map(c=>c.path+": "+c.expected).join(", ")}`);try{return await this._connection.call(`history.transformed.${s}`,[t])}catch(c){throw N(c)??c}}async getSeriesHistory(s,t){if(!s)throw new Error("Tablename must not be empty!");const a=this.tables.map(i=>i.tablename);if(!a.includes(s))throw this.transforms.some(i=>i.tablename===s)?new k("PRIVATE_TABLE",`'${s}' is a transform of app '${this.app}' (${this.stage}); series history is available for tables only — use getHistory() instead.`):new k("PRIVATE_TABLE",`'${s}' is not a shared table of app '${this.app}' (${this.stage}). Available tables: ${a.length>0?a.join(", "):"none"}`);const c=x(t);if(!c.success)throw new Error(`Invalid series query parameters: ${c.errors.map(i=>i.path+": "+i.expected).join(", ")}`);try{return await this._connection.call(`history.transformed.series.${s}`,[t])}catch(i){throw N(i)??i}}async close(){var s;this._connection.stop(),(s=this._onClosed)==null||s.call(this),this._onClosed=void 0}}const L="error-logs";function b(h){var s;return typeof process<"u"?(s=process.env)==null?void 0:s[h]:void 0}function le(h){const s=h??b("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 j{constructor(s){this._isConfigured=!1,this._consumedApps=new Map,this._serialNumber=le(s==null?void 0:s.serialNumber),this._deviceName=(s==null?void 0:s.deviceName)??b("DEVICE_NAME"),this._deviceKey=(s==null?void 0:s.deviceKey)??b("DEVICE_KEY"),this._appName=(s==null?void 0:s.appName)??b("APP_NAME"),this._swarmKey=(s==null?void 0:s.swarmKey)??parseInt(b("SWARM_KEY")??"0",10),this._appKey=(s==null?void 0:s.appKey)??parseInt(b("APP_KEY")??"0",10),this._env=(s==null?void 0:s.env)??b("ENV"),this._reswarmUrl=(s==null?void 0:s.reswarmUrl)??b("RESWARM_URL"),this._cburl=(s==null?void 0:s.ironFlockUrl)??(s==null?void 0:s.cburl),this._connection=new R;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(),c={DEV:p.DEVELOPMENT,PROD:p.PRODUCTION}[t]??p.DEVELOPMENT,i=s??this._cburl??R.getWebSocketURI(this._reswarmUrl);this._connection.configure(this._swarmKey,this._appKey,c,this._serialNumber,i),this._isConfigured=!0}async start(s){this.configureConnection(s),await this._connection.start()}async stop(){const s=[...this._consumedApps.values()];this._consumedApps.clear(),await Promise.all(s.map(t=>t.then(a=>a.close()).catch(()=>{}))),this._connection.stop()}async connectToApp(s,t){if(!s)throw new Error("appName must not be empty!");const a=(this._env??"DEV").toUpperCase()==="PROD"?"prod":"dev",c=(t==null?void 0:t.stage)??a,i=`${s}:${c}`,u=this._consumedApps.get(i);if(u)return u;let r;const o=()=>{this._consumedApps.get(i)===r&&this._consumedApps.delete(i)};return r=this.openConsumedApp(s,c,o,t==null?void 0:t.onError),this._consumedApps.set(i,r),r.catch(o),r}async openConsumedApp(s,t,a,c){var n;let i;try{i=await this._connection.call("sys.appaccess.resolve",[{app:s}])}catch(l){throw N(l)??l}const u=(n=i==null?void 0:i.stages)==null?void 0:n[t];if(!i||!u)throw new k("PROVIDER_NOT_INSTALLED",`App '${s}' has no ${t} data backend in this project`);const r=new R;r.failOnAuthError=!0,r.configure(this._swarmKey,i.provider_app_key,t==="prod"?p.PRODUCTION:p.DEVELOPMENT,this._serialNumber,this._connection.socketURI??this._cburl??R.getWebSocketURI(this._reswarmUrl));let o=!1,e;r.on("auth_failure",l=>{e=new k("NOT_AUTHORIZED",`Access to app '${s}' (${t}) denied: ${l}. The grant may have been revoked.`),a(),o&&(c==null||c(e))});try{await r.start()}catch(l){throw e??l}return o=!0,new Y(s,t,u,r,a)}async publish(s,t,a){const c=B({topic:s,args:t,kwargs:a});if(!c.success)throw new Error(`Invalid publish parameters: ${c.errors.map(r=>r.path+": "+r.expected).join(", ")}`);const u={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...a??{}};return this._connection.publish(s,t,u,{acknowledge:!0})}async publishToTable(s,t,a){const c=K({tablename:s,args:t,kwargs:a});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}.${s}`;return this.publish(i,t,a)}async reportError(s,t){const a=s instanceof Error?s.stack??s.message:s,c={tsp:(t==null?void 0:t.tsp)??new Date().toISOString(),msg:a,source:"app",level:(t==null?void 0:t.level)??"error"};return t!=null&&t.append?this.appendToTable(L,[c]):this.publishToTable(L,[c])}async appendToTable(s,t,a){const c=K({tablename:s,args:t,kwargs:a});if(!c.success)throw new Error(`Invalid table parameters: ${c.errors.map(o=>o.path+": "+o.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}`,r={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...a??{}};return this._connection.call(i,t,r)}async publishRowsToTable(s,t,a){const c=C({tablename:s,rows:t,kwargs:a});if(!c.success)throw new Error(`Invalid bulk 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=`bulk.${this._swarmKey}.${this._appKey}.${s}`;return this.publish(i,[t],a)}async appendRowsToTable(s,t,a){const c=C({tablename:s,rows:t,kwargs:a});if(!c.success)throw new Error(`Invalid bulk table parameters: ${c.errors.map(o=>o.path+": "+o.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}`,r={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...a??{}};return this._connection.call(i,[t],r)}async subscribe(s,t,a){return this._connection.subscribe(s,t)}async subscribeToTable(s,t,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=`transformed.${s}`,i=await this.subscribe(c,t,a),u=(r,o,e)=>{const n=Array.isArray(r)?r[0]:r,l=Array.isArray(n)?n:n==null?[]:[n];for(const d of l)t([d],o,e)};return await this.subscribe(`transformed.bulk.${s}`,u,a),i}async call(s,t,a,c){return this._connection.call(s,t,a,c)}async callDeviceFunction(s,t,a,c,i){const u=`${this._swarmKey}.${s}.${this._appKey}.${this._env}.${t}`;return this._connection.call(u,a,c,i)}async callFunction(s,t,a,c,i){return console.warn("callFunction() is deprecated and will be removed in a future version. Use callDeviceFunction() instead."),this.callDeviceFunction(s,t,a,c,i)}async registerDeviceFunction(s,t,a){const c=`${this._swarmKey}.${this._deviceKey}.${this._appKey}.${this._env}.${s}`,i=await this._connection.register(c,t,a);return console.log(`Function registered for IronFlock topic '${s}'. (Full WAMP topic: '${c}')`),i}async registerFunction(s,t,a){return console.warn("registerFunction() is deprecated and will be removed in a future version. Use registerDeviceFunction() instead."),this.registerDeviceFunction(s,t,a)}async register(s,t,a){return this.registerDeviceFunction(s,t,a)}async getHistory(s,t={limit:10}){if(!s)throw new Error("Tablename must not be empty!");t.offset==null&&(t.offset=0);const a=P(t);if(!a.success)throw new Error(`Invalid query parameters: ${a.errors.map(i=>i.path+": "+i.expected).join(", ")}`);const c=`history.transformed.${s}`;try{return await this._connection.call(c,[t])}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 getSeriesHistory(s,t){if(!s)throw new Error("Tablename must not be empty!");const a=x(t);if(!a.success)throw new Error(`Invalid series query parameters: ${a.errors.map(i=>i.path+": "+i.expected).join(", ")}`);const c=`history.transformed.series.${s}`;try{return await this._connection.call(c,[t])}catch(i){const u=String(i);return u.includes("no_such_procedure")||u.includes("no callee registered")?(console.error(`Get series history failed: History service procedure '${c}' not registered`),null):(console.error(`Get series history failed: ${i}`),null)}}async setDeviceLocation(s,t){const a=W({longitude:s,latitude:t});if(!a.success)throw new Error(`Invalid location parameters: ${a.errors.map(u=>u.path+": "+u.expected).join(", ")}`);const c={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",[c],i)}catch(u){return console.error(`Set location failed: ${u}`),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 a=await t.json();return new j(a)}}exports.ConsumedApp=Y;exports.CrossAppAccessError=k;exports.CrossbarConnection=R;exports.ERROR_LOGS_TABLE=L;exports.IronFlock=j;exports.Stage=p;exports.validateBulkTableParams=C;exports.validateCallParams=ae;exports.validateLocationParams=W;exports.validatePublishParams=B;exports.validateSeriesQueryParams=x;exports.validateTableParams=K;exports.validateTableQueryParams=P;
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|