ironflock 1.3.3 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +244 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +187 -0
- package/dist/index.mjs +1019 -552
- 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
|
|
|
@@ -331,6 +331,40 @@ Supported filter operators: `=`, `!=`, `>`, `<`, `>=`, `<=`, `LIKE`, `ILIKE`, `I
|
|
|
331
331
|
|
|
332
332
|
---
|
|
333
333
|
|
|
334
|
+
### `getSeriesHistory(tablename, params)`
|
|
335
|
+
|
|
336
|
+
Retrieves **down-sampled time-series** data from a fleet table — numeric columns aggregated into time buckets (e.g. hourly averages). Ideal for charts over long time ranges. Available for tables (not transforms).
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
const series = await ironflock.getSeriesHistory("sensordata", {
|
|
340
|
+
metrics: ["temperature", "humidity"],
|
|
341
|
+
method: "AVG",
|
|
342
|
+
limit: 500,
|
|
343
|
+
timeRange: ["2026-01-01T00:00:00Z", "2026-03-01T00:00:00Z"],
|
|
344
|
+
groupBy: ["device_id"],
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
| Parameter | Type | Description |
|
|
349
|
+
|-----------|------|-------------|
|
|
350
|
+
| `tablename` | `string` | The name of the table to query |
|
|
351
|
+
| `params` | `SeriesQueryParams` | Series query parameters (see below) |
|
|
352
|
+
|
|
353
|
+
**params fields:**
|
|
354
|
+
|
|
355
|
+
| Field | Type | Description |
|
|
356
|
+
|-------|------|-------------|
|
|
357
|
+
| `metrics` | `string[]` | Numeric columns to down-sample |
|
|
358
|
+
| `method` | `DownSampleMethod` | Aggregation per bucket: `"AVG"`, `"SUM"`, `"COUNT"`, `"MIN"`, `"MAX"`, `"FIRST"` or `"LAST"` |
|
|
359
|
+
| `limit` | `number` | Maximum number of buckets (1–10000) |
|
|
360
|
+
| `timeRange` | `SeriesTimeRange` | `[start, end]` — ISO strings or epoch-ms numbers; `null` = open end (required) |
|
|
361
|
+
| `groupBy` | `string[]`, optional | Columns to group the series by |
|
|
362
|
+
| `filterAnd` | `SQLFilterAnd[]`, optional | AND filter conditions |
|
|
363
|
+
|
|
364
|
+
**Returns:** `Promise<unknown | null>` — The down-sampled series rows, or `null` if the call failed.
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
334
368
|
### `call(topic, args?, kwargs?)`
|
|
335
369
|
|
|
336
370
|
Calls a remote procedure on the IronFlock message router using a full WAMP topic URI.
|
|
@@ -460,6 +494,215 @@ const url = ironflock.getRemoteAccessUrlForPort(8080);
|
|
|
460
494
|
| `await start(cburl?)` | Configures and starts the connection to the platform |
|
|
461
495
|
| `await stop()` | Stops the connection |
|
|
462
496
|
|
|
497
|
+
## Cross-App Data Access
|
|
498
|
+
|
|
499
|
+
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.
|
|
500
|
+
|
|
501
|
+
```ts
|
|
502
|
+
import { IronFlock, CrossAppAccessError } from "ironflock";
|
|
503
|
+
|
|
504
|
+
const ironflock = new IronFlock();
|
|
505
|
+
await ironflock.start();
|
|
506
|
+
|
|
507
|
+
// Open a read-only handle on another app's data backend
|
|
508
|
+
const weather = await ironflock.connectToApp("weather-app");
|
|
509
|
+
|
|
510
|
+
// Inspect what the provider shares (non-private tables / transforms)
|
|
511
|
+
console.log(weather.tables.map((t) => t.tablename));
|
|
512
|
+
|
|
513
|
+
// Query history, just like your own tables
|
|
514
|
+
const rows = await weather.getHistory("forecasts", { limit: 100 });
|
|
515
|
+
|
|
516
|
+
// Subscribe to realtime rows
|
|
517
|
+
await weather.subscribeToTable("forecasts", (...args) => {
|
|
518
|
+
console.log("New forecast:", args);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
// Access errors carry a machine-readable code
|
|
522
|
+
try {
|
|
523
|
+
await ironflock.connectToApp("unshared-app");
|
|
524
|
+
} catch (err) {
|
|
525
|
+
if (err instanceof CrossAppAccessError) {
|
|
526
|
+
console.error(err.code); // e.g. "NO_GRANT"
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
Consumed-app connections are cached per app + stage and are closed automatically by `ironflock.stop()`.
|
|
532
|
+
|
|
533
|
+
If your app holds the **wildcard** grant (`consumes: [{ app: "*" }]`), use [`listConsumableApps`](#listconsumableapps) to discover every provider in the project and [`connectToAllApps`](#connecttoallappsopts) to open them all at once.
|
|
534
|
+
|
|
535
|
+
### `connectToApp(appName, opts?)`
|
|
536
|
+
|
|
537
|
+
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.
|
|
538
|
+
|
|
539
|
+
```ts
|
|
540
|
+
const weather = await ironflock.connectToApp("weather-app", { stage: "prod" });
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
| Parameter | Type | Description |
|
|
544
|
+
|-----------|------|-------------|
|
|
545
|
+
| `appName` | `string` | Provider app name, as declared in your `consumes:` section |
|
|
546
|
+
| `opts` | `ConnectToAppOptions`, optional | Options (see below) |
|
|
547
|
+
|
|
548
|
+
**opts fields:**
|
|
549
|
+
|
|
550
|
+
| Field | Type | Description |
|
|
551
|
+
|-------|------|-------------|
|
|
552
|
+
| `stage` | `"dev" \| "prod"`, optional | Provider stage to connect to. Defaults to this app's own stage (`ENV`) |
|
|
553
|
+
| `onError` | `(error: CrossAppAccessError) => void`, optional | Called when the connection is fatally denied *after* `connectToApp` resolved (e.g. the grant is later revoked) |
|
|
554
|
+
|
|
555
|
+
**Returns:** `Promise<ConsumedApp>` — A read-only handle on the provider's data backend.
|
|
556
|
+
|
|
557
|
+
**Throws:** `CrossAppAccessError` (`code`: `NO_GRANT`, `PROVIDER_NOT_INSTALLED`, `UNKNOWN_APP`, or `NOT_AUTHORIZED`).
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
### `listConsumableApps()`
|
|
562
|
+
|
|
563
|
+
Lists **every** non-private provider in the project — the discovery primitive for apps that hold the **wildcard** consume grant (`consumes: [{ app: "*" }]` in your data-template, granted by the project user). Performs a single `sys.appaccess.list` call and opens **no** connections: render the returned catalogs in a picker, then call [`connectToApp`](#connecttoappappname-opts) for the ones you want — or [`connectToAllApps`](#connecttoallappsopts) to open them all at once.
|
|
564
|
+
|
|
565
|
+
> **Note:** Declare the grant in your app's `data-template.yml`, and **quote the `*`** — a bare `*` is a YAML alias and won't parse:
|
|
566
|
+
>
|
|
567
|
+
> ```yaml
|
|
568
|
+
> consumes:
|
|
569
|
+
> - app: "*"
|
|
570
|
+
> ```
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
const providers = await ironflock.listConsumableApps();
|
|
574
|
+
|
|
575
|
+
for (const p of providers) {
|
|
576
|
+
console.log(p.app, Object.keys(p.stages)); // e.g. "weather-app" ["dev", "prod"]
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Returns:** `Promise<ConsumedAppInfo[]>` — one entry per non-private provider:
|
|
581
|
+
|
|
582
|
+
| Field | Type | Description |
|
|
583
|
+
|-------|------|-------------|
|
|
584
|
+
| `app` | `string` | Provider app name |
|
|
585
|
+
| `provider_app_key` | `number` | The provider's app key |
|
|
586
|
+
| `stages` | `{ dev?, prod? }` | Per-stage catalog; a stage is present only if the provider has a data backend for it. Each catalog is the non-private `{ tables, transforms }` it shares |
|
|
587
|
+
|
|
588
|
+
**Throws:** `CrossAppAccessError` (`code`: `NO_GRANT`) when your app holds no wildcard grant.
|
|
589
|
+
|
|
590
|
+
---
|
|
591
|
+
|
|
592
|
+
### `connectToAllApps(opts?)`
|
|
593
|
+
|
|
594
|
+
Opens read-only connections to **every** non-private provider in the project in one go (wildcard consumers only). Enumerates providers via [`listConsumableApps`](#listconsumableapps) and opens each one, skipping any that lack a data backend for the requested stage. Each handle is cached under the same app + stage key as [`connectToApp`](#connecttoappappname-opts), so a later `connectToApp(name)` returns the already-warmed handle instead of opening a duplicate.
|
|
595
|
+
|
|
596
|
+
```ts
|
|
597
|
+
const apps = await ironflock.connectToAllApps({
|
|
598
|
+
onError: (err) => console.warn("Provider skipped:", err),
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
for (const app of apps) {
|
|
602
|
+
const rows = await app.getHistory(app.tables[0]?.tablename, { limit: 10 });
|
|
603
|
+
console.log(app.app, rows);
|
|
604
|
+
}
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
| Parameter | Type | Description |
|
|
608
|
+
|-----------|------|-------------|
|
|
609
|
+
| `opts` | `ConnectToAllAppsOptions`, optional | Options (see below) |
|
|
610
|
+
|
|
611
|
+
**opts fields:**
|
|
612
|
+
|
|
613
|
+
| Field | Type | Description |
|
|
614
|
+
|-------|------|-------------|
|
|
615
|
+
| `stage` | `"dev" \| "prod"`, optional | Provider stage to connect to. Defaults to this app's own stage (`ENV`) |
|
|
616
|
+
| `continueOnError` | `boolean`, optional | When `true` (the default), a provider that fails to open is reported via `onError` and omitted from the result. When `false`, the first failure rejects the whole call |
|
|
617
|
+
| `onError` | `(error: unknown) => void`, optional | Called with each provider that could not be opened (while `continueOnError` is `true`), and with a `CrossAppAccessError` if an already-opened connection is later fatally denied (e.g. the grant is revoked) |
|
|
618
|
+
|
|
619
|
+
**Returns:** `Promise<ConsumedApp[]>` — the successfully-opened provider handles. Closed together by `ironflock.stop()`.
|
|
620
|
+
|
|
621
|
+
**Throws:** `CrossAppAccessError` (`code`: `NO_GRANT`) when your app holds no wildcard grant. With `continueOnError: false`, also rejects with the first provider's open failure.
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
### `ConsumedApp` handle
|
|
626
|
+
|
|
627
|
+
Returned by `connectToApp`. A read-only view of a provider app's shared tables and transforms.
|
|
628
|
+
|
|
629
|
+
**Properties:**
|
|
630
|
+
|
|
631
|
+
| Property | Type | Description |
|
|
632
|
+
|----------|------|-------------|
|
|
633
|
+
| `app` | `string` | Provider app name |
|
|
634
|
+
| `stage` | `"dev" \| "prod"` | Provider stage this handle is connected to |
|
|
635
|
+
| `tables` | `ProviderTableInfo[]` | Non-private tables the provider shares |
|
|
636
|
+
| `transforms` | `ProviderTableInfo[]` | Non-private transforms (views) the provider shares |
|
|
637
|
+
| `isConnected` | `boolean` | `true` while the connection to the provider is open |
|
|
638
|
+
| `connection` | `CrossbarConnection` | The underlying connection (advanced use) |
|
|
639
|
+
|
|
640
|
+
#### `consumedApp.getHistory(tablename, queryParams?)`
|
|
641
|
+
|
|
642
|
+
Queries history rows of a shared table or transform. Takes the same query parameters as [`getHistory`](#gethistorytablename-queryparams) (`limit`, `offset`, `timeRange`, `filterAnd`).
|
|
643
|
+
|
|
644
|
+
```ts
|
|
645
|
+
const rows = await weather.getHistory("forecasts", { limit: 100 });
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
**Returns:** `Promise<unknown>` — The query result rows.
|
|
649
|
+
|
|
650
|
+
#### `consumedApp.subscribeToTable(tablename, handler)`
|
|
651
|
+
|
|
652
|
+
Subscribes to realtime rows of a shared table or transform. Bulk-inserted rows are delivered one at a time, exactly like [`subscribeToTable`](#subscribetotabletablename-handler).
|
|
653
|
+
|
|
654
|
+
```ts
|
|
655
|
+
await weather.subscribeToTable("forecasts", (...args) => console.log(args));
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
**Returns:** `Promise<Subscription | undefined>` — The subscription object.
|
|
659
|
+
|
|
660
|
+
#### `consumedApp.getSeriesHistory(tablename, params)`
|
|
661
|
+
|
|
662
|
+
Queries down-sampled time-series history of a shared **table** (not available for transforms).
|
|
663
|
+
|
|
664
|
+
```ts
|
|
665
|
+
const series = await weather.getSeriesHistory("forecasts", {
|
|
666
|
+
metrics: ["temperature"],
|
|
667
|
+
method: "AVG",
|
|
668
|
+
limit: 500,
|
|
669
|
+
timeRange: ["2026-01-01T00:00:00Z", "2026-03-01T00:00:00Z"],
|
|
670
|
+
});
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**params fields (`SeriesQueryParams`):**
|
|
674
|
+
|
|
675
|
+
| Field | Type | Description |
|
|
676
|
+
|-------|------|-------------|
|
|
677
|
+
| `metrics` | `string[]` | Numeric columns to down-sample |
|
|
678
|
+
| `method` | `DownSampleMethod` | Aggregation per bucket: `"AVG"`, `"SUM"`, `"COUNT"`, `"MIN"`, `"MAX"`, `"FIRST"` or `"LAST"` |
|
|
679
|
+
| `limit` | `number` | Maximum number of rows (1–10000) |
|
|
680
|
+
| `timeRange` | `SeriesTimeRange` | `[start, end]` — ISO strings or epoch-ms numbers; `null` = open end (required) |
|
|
681
|
+
| `groupBy` | `string[]`, optional | Columns to group the series by |
|
|
682
|
+
| `filterAnd` | `SQLFilterAnd[]`, optional | AND filter conditions |
|
|
683
|
+
|
|
684
|
+
**Returns:** `Promise<unknown>` — The down-sampled series rows.
|
|
685
|
+
|
|
686
|
+
#### `consumedApp.close()`
|
|
687
|
+
|
|
688
|
+
Closes this handle's connection to the provider. (All consumed-app connections are also closed by `ironflock.stop()`.)
|
|
689
|
+
|
|
690
|
+
**Returns:** `Promise<void>`
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
### `CrossAppAccessError`
|
|
695
|
+
|
|
696
|
+
Thrown by `connectToApp` and the `ConsumedApp` methods when cross-app access is denied or misused. Exposes a machine-readable `code`:
|
|
697
|
+
|
|
698
|
+
| `code` | Meaning |
|
|
699
|
+
|--------|---------|
|
|
700
|
+
| `NO_GRANT` | The project user has not granted your app access to the provider |
|
|
701
|
+
| `PROVIDER_NOT_INSTALLED` | The provider app has no data backend for that stage in this project |
|
|
702
|
+
| `UNKNOWN_APP` | No app by that name |
|
|
703
|
+
| `PRIVATE_TABLE` | The requested table/transform is not in the provider's shared catalog |
|
|
704
|
+
| `NOT_AUTHORIZED` | The router/provider denied access (e.g. the grant was revoked) |
|
|
705
|
+
|
|
463
706
|
## Development
|
|
464
707
|
|
|
465
708
|
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 O={exports:{}},U;function G(){return U||(U=1,(function(h){var t=Object.prototype.hasOwnProperty,s="~";function a(){}Object.create&&(a.prototype=Object.create(null),new a().__proto__||(s=!1));function l(o,e,n){this.fn=o,this.context=e,this.once=n||!1}function i(o,e,n,c,d){if(typeof n!="function")throw new TypeError("The listener must be a function");var v=new l(n,c||o,d),f=s?s+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,c;if(this._eventsCount===0)return e;for(c in n=this._events)t.call(n,c)&&e.push(s?c.slice(1):c);return Object.getOwnPropertySymbols?e.concat(Object.getOwnPropertySymbols(n)):e},r.prototype.listeners=function(e){var n=s?s+e:e,c=this._events[n];if(!c)return[];if(c.fn)return[c.fn];for(var d=0,v=c.length,f=new Array(v);d<v;d++)f[d]=c[d].fn;return f},r.prototype.listenerCount=function(e){var n=s?s+e:e,c=this._events[n];return c?c.fn?1:c.length:0},r.prototype.emit=function(e,n,c,d,v,f){var g=s?s+e:e;if(!this._events[g])return!1;var y=this._events[g],A=arguments.length,p,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,c),!0;case 4:return y.fn.call(y.context,n,c,d),!0;case 5:return y.fn.call(y.context,n,c,d,v),!0;case 6:return y.fn.call(y.context,n,c,d,v,f),!0}for(m=1,p=new Array(A-1);m<A;m++)p[m-1]=arguments[m];y.fn.apply(y.context,p)}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,c);break;case 4:y[m].fn.call(y[m].context,n,c,d);break;default:if(!p)for(S=1,p=new Array(A-1);S<A;S++)p[S-1]=arguments[S];y[m].fn.apply(y[m].context,p)}}return!0},r.prototype.on=function(e,n,c){return i(this,e,n,c,!1)},r.prototype.once=function(e,n,c){return i(this,e,n,c,!0)},r.prototype.removeListener=function(e,n,c,d){var v=s?s+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)&&(!c||f.context===c)&&u(this,v);else{for(var g=0,y=[],A=f.length;g<A;g++)(f[g].fn!==n||d&&!f[g].once||c&&f[g].context!==c)&&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=s?s+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=s,r.EventEmitter=r,h.exports=r})(O)),O.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",C="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":C,"http://localhost:8086":C,"http://host.docker.internal:8086":C},ee=6e3,re=["wamp.error.not_authorized","wamp.error.authorization_failed","wamp.error.authentication_failed","wamp.error.no_auth_method"];class k 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(t){var l;const s=typeof process<"u"?(l=process.env)==null?void 0:l.DEVICE_ENDPOINT_URL:void 0;if(s)try{const i=new URL(s);return i.pathname="/ws-ua-usr",i.toString().replace(/\/$/,"")}catch{}if(!t)return V;const a=F[t];if(a===void 0)throw new Error(`Cannot resolve WebSocket URI for reswarmUrl=${JSON.stringify(t)}. 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(t,s,a,l,i){this.realm=`realm-${t}-${s}-${a}`,this.serial_number=l,this.socketURI=i??k.getWebSocketURI()}async start(){if(!this.realm||!this.serial_number||!this.socketURI)throw new Error("CrossbarConnection must be configured before starting. Call configure() first.");return this.shouldReconnect=!0,this.firstConnection=new Promise((t,s)=>{this.firstResolver=t,this.firstRejecter=s}),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:(t,s,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(t){this.session=t,this.session.caller_disclose_me=!0,this.hasOpenedOnce=!0,this.resubscribeAll(),this.reregisterAll(),this.emit("connected",this.serial_number),this.firstResolver(),this.firstResolver=()=>{}}onClose(t,s){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});const a=(s==null?void 0:s.reason)??t;return this.failOnAuthError&&typeof a=="string"&&re.includes(a)?(this.shouldReconnect=!1,this.emit("auth_failure",a,s),!0):(this.shouldReconnect&&this.hasOpenedOnce&&(s==null?void 0:s.will_retry)===!1&&this.handleManualReconnect((s==null?void 0:s.reason)??t),!1)}async handleManualReconnect(t){if(!(this.isReconnecting||!this.shouldReconnect)){for(this.isReconnecting=!0;this.shouldReconnect&&!this.session;)if(await new Promise(s=>setTimeout(s,1e3)),this.shouldReconnect&&this.connection&&!this.session){console.log(`Manually retrying connection after ${t}...`);try{this.connection.open(),await new Promise(s=>setTimeout(s,500))}catch(s){console.error("Error during manual reconnection attempt:",s)}}this.isReconnecting=!1}}async sessionWait(){const t=Date.now();for(;!this.session;){if(Date.now()-t>ee)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;this.shouldReconnect=!1,(t=this.connection)==null||t.close("wamp.close.normal","Connection closed by client")}async subscribe(t,s){var l;await this.sessionWait();const a=await((l=this.session)==null?void 0:l.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 reregisterAll(){const t=[...this.registrations];this.registrations=[],await Promise.all(t.map(s=>this.register(s.procedure,s.endpoint,s.options)))}async register(t,s,a){var u;await this.sessionWait();const l={force_reregister:!0,...a??{}},i=await((u=this.session)==null?void 0:u.register(t,s,l));return i&&this.registrations.push(i),i}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,l){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.call(t,s,a,l)}async publish(t,s,a,l){var i;return await this.sessionWait(),(i=this.session)==null?void 0:i.publish(t,s,a,l)}}const I=h=>Math.floor(h)===h&&te<=h&&h<=se,te=0,se=2**32-1,$=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 t=s=>{if(h.length===0)return!0;const a=h[h.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
|
+
`))),h.push(a)),!1)},T=h=>Object.assign(h,{"~standard":{version:1,vendor:"typia",validate:t=>{const s=h(t);return s.success?{value:s.data}:{issues:s.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 t=[];let s="",a=w.Start,l=5;for(;l<h.length-1;){l++;const i=h[l];if(a===w.Property?i==="."||i==="["?(t.push({key:s}),a=w.Start):l===h.length-1?(s+=i,t.push({key:s}),l++,a=w.Start):s+=i:a===w.StringKey?i==='"'?(t.push({key:JSON.parse(s+i)}),l+=2,a=w.Start):i==="\\"?(s+=h[l],l++,s+=h[l]):s+=i:a===w.NumberKey&&(i==="]"?(t.push({key:Number.parseInt(s)}),l++,a=w.Start):s+=i),a===w.Start&&l<h.length-1){const u=h[l];if(s="",u==="[")h[l+1]==='"'?(a=w.StringKey,l++,s='"'):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 t};var R=(h=>(h.DEVELOPMENT="dev",h.PRODUCTION="prod",h))(R||{});const P=(()=>{const h=e=>typeof e.limit=="number"&&I(e.limit)&&1<=e.limit&&e.limit<=1e4&&(e.offset===void 0||typeof e.offset=="number"&&I(e.offset)&&0<=e.offset)&&(e.timeRange===void 0||typeof e.timeRange=="object"&&e.timeRange!==null&&t(e.timeRange))&&(e.filterAnd===void 0||Array.isArray(e.filterAnd)&&e.filterAnd.every(n=>typeof n=="object"&&n!==null&&s(n))),t=e=>typeof e.start=="string"&&$(e.start)&&typeof e.end=="string"&&$(e.end),s=e=>typeof e.column=="string"&&1<=e.column.length&&typeof e.operator=="string"&&1<=e.operator.length&&e.value!==null&&e.value!==void 0&&(typeof e.value=="string"||typeof e.value=="number"||typeof e.value=="boolean"||Array.isArray(e.value)&&e.value.every(n=>typeof n=="string"||typeof n=="number")),a=(e,n,c=!0)=>[typeof e.limit=="number"&&(I(e.limit)||o(c,{path:n+".limit",expected:'number & Type<"uint32">',value:e.limit}))&&(1<=e.limit||o(c,{path:n+".limit",expected:"number & Minimum<1>",value:e.limit}))&&(e.limit<=1e4||o(c,{path:n+".limit",expected:"number & Maximum<10000>",value:e.limit}))||o(c,{path:n+".limit",expected:'(number & Type<"uint32"> & Minimum<1> & Maximum<10000>)',value:e.limit}),e.offset===void 0||typeof e.offset=="number"&&(I(e.offset)||o(c,{path:n+".offset",expected:'number & Type<"uint32">',value:e.offset}))&&(0<=e.offset||o(c,{path:n+".offset",expected:"number & Minimum<0>",value:e.offset}))||o(c,{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(c,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:e.timeRange}))&&l(e.timeRange,n+".timeRange",c)||o(c,{path:n+".timeRange",expected:"(ISOTimeRange | undefined)",value:e.timeRange}),e.filterAnd===void 0||(Array.isArray(e.filterAnd)||o(c,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:e.filterAnd}))&&e.filterAnd.map((d,v)=>(typeof d=="object"&&d!==null||o(c,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d}))&&i(d,n+".filterAnd["+v+"]",c)||o(c,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d})).every(d=>d)||o(c,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | undefined)",value:e.filterAnd})].every(d=>d),l=(e,n,c=!0)=>[typeof e.start=="string"&&($(e.start)||o(c,{path:n+".start",expected:'string & Format<"date-time">',value:e.start}))||o(c,{path:n+".start",expected:'(string & Format<"date-time">)',value:e.start}),typeof e.end=="string"&&($(e.end)||o(c,{path:n+".end",expected:'string & Format<"date-time">',value:e.end}))||o(c,{path:n+".end",expected:'(string & Format<"date-time">)',value:e.end})].every(d=>d),i=(e,n,c=!0)=>[typeof e.column=="string"&&(1<=e.column.length||o(c,{path:n+".column",expected:"string & MinLength<1>",value:e.column}))||o(c,{path:n+".column",expected:"(string & MinLength<1>)",value:e.column}),typeof e.operator=="string"&&(1<=e.operator.length||o(c,{path:n+".operator",expected:"string & MinLength<1>",value:e.operator}))||o(c,{path:n+".operator",expected:"(string & MinLength<1>)",value:e.operator}),(e.value!==null||o(c,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&(e.value!==void 0||o(c,{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(c,{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(c,{path:n+".value["+v+"]",expected:"(number | string)",value:d})).every(d=>d)||o(c,{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),((c,d,v=!0)=>(typeof c=="object"&&c!==null||o(!0,{path:d+"",expected:"TableQueryParams",value:c}))&&a(c,d+"",!0)||o(!0,{path:d+"",expected:"TableQueryParams",value:c}))(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}})})(),j=(()=>{const h=e=>{const n=e,c=[[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 c)if(d[0](n))return d[1](n);return!1},t=(e,n,c=!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(c,{path:n,expected:"[(null | number), (null | number)]",value:f}))&&[f[0]===null||typeof f[0]=="number"||o(c,{path:n+"[0]",expected:"(null | number)",value:f[0]}),f[1]===null||typeof f[1]=="number"||o(c,{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(c,{path:n,expected:"[(null | string), (null | string)]",value:f}))&&[f[0]===null||typeof f[0]=="string"||o(c,{path:n+"[0]",expected:"(null | string)",value:f[0]}),f[1]===null||typeof f[1]=="string"||o(c,{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(c,{path:n,expected:"([number | null, number | null] | [string | null, string | null])",value:e})},s=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"&&I(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")),l=(e,n,c=!0)=>[(Array.isArray(e.metrics)||o(c,{path:n+".metrics",expected:"Array<string>",value:e.metrics}))&&e.metrics.map((d,v)=>typeof d=="string"||o(c,{path:n+".metrics["+v+"]",expected:"string",value:d})).every(d=>d)||o(c,{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(c,{path:n+".method",expected:'("AVG" | "COUNT" | "FIRST" | "LAST" | "MAX" | "MIN" | "SUM")',value:e.method}),typeof e.limit=="number"&&(I(e.limit)||o(c,{path:n+".limit",expected:'number & Type<"uint32">',value:e.limit}))&&(1<=e.limit||o(c,{path:n+".limit",expected:"number & Minimum<1>",value:e.limit}))&&(e.limit<=1e4||o(c,{path:n+".limit",expected:"number & Maximum<10000>",value:e.limit}))||o(c,{path:n+".limit",expected:'(number & Type<"uint32"> & Minimum<1> & Maximum<10000>)',value:e.limit}),(Array.isArray(e.timeRange)||o(c,{path:n+".timeRange",expected:"([number | null, number | null] | [string | null, string | null])",value:e.timeRange}))&&(t(e.timeRange,n+".timeRange",c)||o(c,{path:n+".timeRange",expected:"[number | null, number | null] | [string | null, string | null]",value:e.timeRange}))||o(c,{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(c,{path:n+".groupBy",expected:"(Array<string> | null | undefined)",value:e.groupBy}))&&e.groupBy.map((d,v)=>typeof d=="string"||o(c,{path:n+".groupBy["+v+"]",expected:"string",value:d})).every(d=>d)||o(c,{path:n+".groupBy",expected:"(Array<string> | null | undefined)",value:e.groupBy}),e.filterAnd===null||e.filterAnd===void 0||(Array.isArray(e.filterAnd)||o(c,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | null | undefined)",value:e.filterAnd}))&&e.filterAnd.map((d,v)=>(typeof d=="object"&&d!==null||o(c,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d}))&&i(d,n+".filterAnd["+v+"]",c)||o(c,{path:n+".filterAnd["+v+"]",expected:"SQLFilterAnd",value:d})).every(d=>d)||o(c,{path:n+".filterAnd",expected:"(Array<SQLFilterAnd> | null | undefined)",value:e.filterAnd})].every(d=>d),i=(e,n,c=!0)=>[typeof e.column=="string"&&(1<=e.column.length||o(c,{path:n+".column",expected:"string & MinLength<1>",value:e.column}))||o(c,{path:n+".column",expected:"(string & MinLength<1>)",value:e.column}),typeof e.operator=="string"&&(1<=e.operator.length||o(c,{path:n+".operator",expected:"string & MinLength<1>",value:e.operator}))||o(c,{path:n+".operator",expected:"(string & MinLength<1>)",value:e.operator}),(e.value!==null||o(c,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))&&(e.value!==void 0||o(c,{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(c,{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(c,{path:n+".value["+v+"]",expected:"(number | string)",value:d})).every(d=>d)||o(c,{path:n+".value",expected:"(Array<string | number> | boolean | number | string)",value:e.value}))].every(d=>d),u=e=>typeof e=="object"&&e!==null&&s(e);let r,o;return T(e=>{if(u(e)===!1){r=[],o=_(r),((c,d,v=!0)=>(typeof c=="object"&&c!==null||o(!0,{path:d+"",expected:"SeriesQueryParams",value:c}))&&l(c,d+"",!0)||o(!0,{path:d+"",expected:"SeriesQueryParams",value:c}))(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,t=(i,u,r=!0)=>[typeof i.longitude=="number"&&(-180<=i.longitude||l(r,{path:u+".longitude",expected:"number & Minimum<-180>",value:i.longitude}))&&(i.longitude<=180||l(r,{path:u+".longitude",expected:"number & Maximum<180>",value:i.longitude}))||l(r,{path:u+".longitude",expected:"(number & Minimum<-180> & Maximum<180>)",value:i.longitude}),typeof i.latitude=="number"&&(-90<=i.latitude||l(r,{path:u+".latitude",expected:"number & Minimum<-90>",value:i.latitude}))&&(i.latitude<=90||l(r,{path:u+".latitude",expected:"number & Maximum<90>",value:i.latitude}))||l(r,{path:u+".latitude",expected:"(number & Minimum<-90> & Maximum<90>)",value:i.latitude})].every(o=>o),s=i=>typeof i=="object"&&i!==null&&h(i);let a,l;return T(i=>{if(s(i)===!1){a=[],l=_(a),((r,o,e=!0)=>(typeof r=="object"&&r!==null||l(!0,{path:o+"",expected:"LocationParams",value:r}))&&t(r,o+"",!0)||l(!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&&t(r.kwargs)),t=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),s=(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),l=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(l(r)===!1){i=[],u=_(i),((e,n,c=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"PublishParams",value:e}))&&s(e,n+"",!0)||u(!0,{path:n+"",expected:"PublishParams",value:e}))(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&&t(r.kwargs)),t=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),s=(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),l=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(l(r)===!1){i=[],u=_(i),((e,n,c=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"CallParams",value:e}))&&s(e,n+"",!0)||u(!0,{path:n+"",expected:"CallParams",value:e}))(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}})})(),N=(()=>{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&&t(r.kwargs)),t=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),s=(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),l=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(l(r)===!1){i=[],u=_(i),((e,n,c=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"TableParams",value:e}))&&s(e,n+"",!0)||u(!0,{path:n+"",expected:"TableParams",value:e}))(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&&Array.isArray(r.rows)&&1<=r.rows.length&&r.rows.every(o=>typeof o=="object"&&o!==null&&Array.isArray(o)===!1&&t(o))&&(r.kwargs===void 0||typeof r.kwargs=="object"&&r.kwargs!==null&&Array.isArray(r.kwargs)===!1&&t(r.kwargs)),t=r=>Object.keys(r).every(o=>(r[o]===void 0,!0)),s=(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,c)=>(typeof n=="object"&&n!==null&&Array.isArray(n)===!1||u(e,{path:o+".rows["+c+"]",expected:"Record<string, unknown>",value:n}))&&a(n,o+".rows["+c+"]",e)||u(e,{path:o+".rows["+c+"]",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),l=r=>typeof r=="object"&&r!==null&&h(r);let i,u;return T(r=>{if(l(r)===!1){i=[],u=_(i),((e,n,c=!0)=>(typeof e=="object"&&e!==null||u(!0,{path:n+"",expected:"BulkTableParams",value:e}))&&s(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 E extends Error{constructor(t,s){super(s??t),this.name="CrossAppAccessError",this.code=t}}function M(h){const t=h==null?void 0:h.error;if(typeof t!="string")return null;const s=ie[t];if(!s)return null;const a=h.args,l=Array.isArray(a)&&a.length>0?`: ${JSON.stringify(a[0])}`:"";return new E(s,`${t}${l}`)}class Y{constructor(t,s,a,l,i){this.app=t,this.stage=s,this.tables=a.tables??[],this.transforms=a.transforms??[],this._connection=l,this._onClosed=i}get connection(){return this._connection}get isConnected(){return this._connection.is_open}assertInCatalog(t){if(!t)throw new Error("Tablename must not be empty!");const s=[...this.tables,...this.transforms].map(a=>a.tablename);if(!s.includes(t))throw new E("PRIVATE_TABLE",`'${t}' is not shared by app '${this.app}' (${this.stage}). Available tables/transforms: ${s.length>0?s.join(", "):"none"}`)}async subscribeToTable(t,s,a){this.assertInCatalog(t);const l=await this._connection.subscribe(`transformed.${t}`,s),i=(u,r,o)=>{const e=Array.isArray(u)?u[0]:u,n=Array.isArray(e)?e:e==null?[]:[e];for(const c of n)s([c],r,o)};return await this._connection.subscribe(`transformed.bulk.${t}`,i),l}async getHistory(t,s={limit:10}){this.assertInCatalog(t),s.offset==null&&(s.offset=0);const a=P(s);if(!a.success)throw new Error(`Invalid query parameters: ${a.errors.map(l=>l.path+": "+l.expected).join(", ")}`);try{return await this._connection.call(`history.transformed.${t}`,[s])}catch(l){throw M(l)??l}}async getSeriesHistory(t,s){if(!t)throw new Error("Tablename must not be empty!");const a=this.tables.map(i=>i.tablename);if(!a.includes(t))throw this.transforms.some(i=>i.tablename===t)?new E("PRIVATE_TABLE",`'${t}' is a transform of app '${this.app}' (${this.stage}); series history is available for tables only — use getHistory() instead.`):new E("PRIVATE_TABLE",`'${t}' is not a shared table of app '${this.app}' (${this.stage}). Available tables: ${a.length>0?a.join(", "):"none"}`);const l=j(s);if(!l.success)throw new Error(`Invalid series query parameters: ${l.errors.map(i=>i.path+": "+i.expected).join(", ")}`);try{return await this._connection.call(`history.transformed.series.${t}`,[s])}catch(i){throw M(i)??i}}async close(){var t;this._connection.stop(),(t=this._onClosed)==null||t.call(this),this._onClosed=void 0}}const L="error-logs";function b(h){var t;return typeof process<"u"?(t=process.env)==null?void 0:t[h]:void 0}function ce(h){const t=h??b("DEVICE_SERIAL_NUMBER");if(!t)throw new Error("serialNumber option is required (or set DEVICE_SERIAL_NUMBER env var in Node.js)");return t}class x{constructor(t){this._isConfigured=!1,this._consumedApps=new Map,this._serialNumber=ce(t==null?void 0:t.serialNumber),this._deviceName=(t==null?void 0:t.deviceName)??b("DEVICE_NAME"),this._deviceKey=(t==null?void 0:t.deviceKey)??b("DEVICE_KEY"),this._appName=(t==null?void 0:t.appName)??b("APP_NAME"),this._swarmKey=(t==null?void 0:t.swarmKey)??parseInt(b("SWARM_KEY")??"0",10),this._appKey=(t==null?void 0:t.appKey)??parseInt(b("APP_KEY")??"0",10),this._env=(t==null?void 0:t.env)??b("ENV"),this._reswarmUrl=(t==null?void 0:t.reswarmUrl)??b("RESWARM_URL"),this._cburl=(t==null?void 0:t.ironFlockUrl)??(t==null?void 0:t.cburl),this._connection=new k;const s=[];this._deviceKey||s.push("DEVICE_KEY"),this._appName||s.push("APP_NAME"),this._swarmKey||s.push("SWARM_KEY"),this._appKey||s.push("APP_KEY"),s.length>0&&console.warn(`Warning: The following environment variables must be present: ${s.join(", ")}`)}get connection(){return this._connection}get isConnected(){return this._connection.is_open}configureConnection(t){if(this._isConfigured)return;const s=(this._env??"DEV").toUpperCase(),l={DEV:R.DEVELOPMENT,PROD:R.PRODUCTION}[s]??R.DEVELOPMENT,i=t??this._cburl??k.getWebSocketURI(this._reswarmUrl);this._connection.configure(this._swarmKey,this._appKey,l,this._serialNumber,i),this._isConfigured=!0}async start(t){this.configureConnection(t),await this._connection.start()}async stop(){const t=[...this._consumedApps.values()];this._consumedApps.clear(),await Promise.all(t.map(s=>s.then(a=>a.close()).catch(()=>{}))),this._connection.stop()}async connectToApp(t,s){if(!t)throw new Error("appName must not be empty!");const a=(this._env??"DEV").toUpperCase()==="PROD"?"prod":"dev",l=(s==null?void 0:s.stage)??a,i=`${t.toLowerCase()}:${l}`,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(t,l,o,s==null?void 0:s.onError),this._consumedApps.set(i,r),r.catch(o),r}async listConsumableApps(){try{return await this._connection.call("sys.appaccess.list",[])??[]}catch(t){throw M(t)??t}}async connectToAllApps(t){var e,n;const s=(this._env??"DEV").toUpperCase()==="PROD"?"prod":"dev",a=(t==null?void 0:t.stage)??s,l=(t==null?void 0:t.continueOnError)??!0,i=await this.listConsumableApps(),u=[];for(const c of i)(e=c.stages)!=null&&e[a]&&u.push(this.openCachedFromInfo(c,a,t==null?void 0:t.onError));const r=await Promise.allSettled(u),o=[];for(const c of r)if(c.status==="fulfilled")o.push(c.value);else if(l)(n=t==null?void 0:t.onError)==null||n.call(t,c.reason);else throw c.reason;return o}async openConsumedApp(t,s,a,l){let i;try{i=await this._connection.call("sys.appaccess.resolve",[{app:t}])}catch(u){throw M(u)??u}if(!i)throw new E("PROVIDER_NOT_INSTALLED",`App '${t}' has no ${s} data backend in this project`);return this.openFromInfo(i,s,a,l)}openCachedFromInfo(t,s,a){const l=`${t.app}:${s}`,i=this._consumedApps.get(l);if(i)return i;let u;const r=()=>{this._consumedApps.get(l)===u&&this._consumedApps.delete(l)};return u=this.openFromInfo(t,s,r,a),this._consumedApps.set(l,u),u.catch(r),u}async openFromInfo(t,s,a,l){var n;const i=t.app,u=(n=t.stages)==null?void 0:n[s];if(!u)throw new E("PROVIDER_NOT_INSTALLED",`App '${i}' has no ${s} data backend in this project`);const r=new k;r.failOnAuthError=!0,r.configure(this._swarmKey,t.provider_app_key,s==="prod"?R.PRODUCTION:R.DEVELOPMENT,this._serialNumber,this._connection.socketURI??this._cburl??k.getWebSocketURI(this._reswarmUrl));let o=!1,e;r.on("auth_failure",c=>{e=new E("NOT_AUTHORIZED",`Access to app '${i}' (${s}) denied: ${c}. The grant may have been revoked.`),a(),o&&(l==null||l(e))});try{await r.start()}catch(c){throw e??c}return o=!0,new Y(i,s,u,r,a)}async publish(t,s,a){const l=B({topic:t,args:s,kwargs:a});if(!l.success)throw new Error(`Invalid publish parameters: ${l.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(t,s,u,{acknowledge:!0})}async publishToTable(t,s,a){const l=N({tablename:t,args:s,kwargs:a});if(!l.success)throw new Error(`Invalid table parameters: ${l.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}.${t}`;return this.publish(i,s,a)}async reportError(t,s){const a=t instanceof Error?t.stack??t.message:t,l={tsp:(s==null?void 0:s.tsp)??new Date().toISOString(),msg:a,source:"app",level:(s==null?void 0:s.level)??"error"};return s!=null&&s.append?this.appendToTable(L,[l]):this.publishToTable(L,[l])}async appendToTable(t,s,a){const l=N({tablename:t,args:s,kwargs:a});if(!l.success)throw new Error(`Invalid table parameters: ${l.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}.${t}`,r={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...a??{}};return this._connection.call(i,s,r)}async publishRowsToTable(t,s,a){const l=K({tablename:t,rows:s,kwargs:a});if(!l.success)throw new Error(`Invalid bulk table parameters: ${l.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}.${t}`;return this.publish(i,[s],a)}async appendRowsToTable(t,s,a){const l=K({tablename:t,rows:s,kwargs:a});if(!l.success)throw new Error(`Invalid bulk table parameters: ${l.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}.${t}`,r={...{DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName},...a??{}};return this._connection.call(i,[s],r)}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 l=`transformed.${t}`,i=await this.subscribe(l,s,a),u=(r,o,e)=>{const n=Array.isArray(r)?r[0]:r,c=Array.isArray(n)?n:n==null?[]:[n];for(const d of c)s([d],o,e)};return await this.subscribe(`transformed.bulk.${t}`,u,a),i}async call(t,s,a,l){return this._connection.call(t,s,a,l)}async callDeviceFunction(t,s,a,l,i){const u=`${this._swarmKey}.${t}.${this._appKey}.${this._env}.${s}`;return this._connection.call(u,a,l,i)}async callFunction(t,s,a,l,i){return console.warn("callFunction() is deprecated and will be removed in a future version. Use callDeviceFunction() instead."),this.callDeviceFunction(t,s,a,l,i)}async registerDeviceFunction(t,s,a){const l=`${this._swarmKey}.${this._deviceKey}.${this._appKey}.${this._env}.${t}`,i=await this._connection.register(l,s,a);return console.log(`Function registered for IronFlock topic '${t}'. (Full WAMP topic: '${l}')`),i}async registerFunction(t,s,a){return console.warn("registerFunction() is deprecated and will be removed in a future version. Use registerDeviceFunction() instead."),this.registerDeviceFunction(t,s,a)}async register(t,s,a){return this.registerDeviceFunction(t,s,a)}async getHistory(t,s={limit:10}){if(!t)throw new Error("Tablename must not be empty!");s.offset==null&&(s.offset=0);const a=P(s);if(!a.success)throw new Error(`Invalid query parameters: ${a.errors.map(i=>i.path+": "+i.expected).join(", ")}`);const l=`history.transformed.${t}`;try{return await this._connection.call(l,[s])}catch(i){const u=String(i);return u.includes("no_such_procedure")||u.includes("no callee registered")?(console.error(`Get history failed: History service procedure '${l}' not registered`),null):(console.error(`Get history failed: ${i}`),null)}}async getSeriesHistory(t,s){if(!t)throw new Error("Tablename must not be empty!");const a=j(s);if(!a.success)throw new Error(`Invalid series query parameters: ${a.errors.map(i=>i.path+": "+i.expected).join(", ")}`);const l=`history.transformed.series.${t}`;try{return await this._connection.call(l,[s])}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 '${l}' not registered`),null):(console.error(`Get series history failed: ${i}`),null)}}async setDeviceLocation(t,s){const a=W({longitude:t,latitude:s});if(!a.success)throw new Error(`Invalid location parameters: ${a.errors.map(u=>u.path+": "+u.expected).join(", ")}`);const l={long:t,lat:s},i={DEVICE_SERIAL_NUMBER:this._serialNumber,DEVICE_KEY:this._deviceKey,DEVICE_NAME:this._deviceName};try{return await this._connection.call("ironflock.location_service.update",[l],i)}catch(u){return console.error(`Set location failed: ${u}`),null}}getRemoteAccessUrlForPort(t){return this._deviceKey&&this._appName?`https://${this._deviceKey}-${this._appName.toLowerCase()}-${t}.app.ironflock.com`:null}static async fromServer(t){const s=await fetch(t);if(!s.ok)throw new Error(`Failed to fetch IronFlock config from ${t}: ${s.status} ${s.statusText}`);const a=await s.json();return new x(a)}}exports.ConsumedApp=Y;exports.CrossAppAccessError=E;exports.CrossbarConnection=k;exports.ERROR_LOGS_TABLE=L;exports.IronFlock=x;exports.Stage=R;exports.validateBulkTableParams=K;exports.validateCallParams=ae;exports.validateLocationParams=W;exports.validatePublishParams=B;exports.validateSeriesQueryParams=j;exports.validateTableParams=N;exports.validateTableQueryParams=P;
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|