@uns-kit/core 0.0.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/LICENSE +21 -0
- package/README.md +44 -0
- package/dist/app-config.d.ts +177 -0
- package/dist/app-config.js +1 -0
- package/dist/base-path.d.ts +1 -0
- package/dist/base-path.js +5 -0
- package/dist/config/project.config.extension.d.ts +3 -0
- package/dist/config/project.config.extension.js +3 -0
- package/dist/config-file.d.ts +12 -0
- package/dist/config-file.js +44 -0
- package/dist/examples/data-example.d.ts +1 -0
- package/dist/examples/data-example.js +44 -0
- package/dist/examples/load-test-data.d.ts +1 -0
- package/dist/examples/load-test-data.js +72 -0
- package/dist/examples/table-example.d.ts +4 -0
- package/dist/examples/table-example.js +52 -0
- package/dist/examples/uns-gateway.d.ts +1 -0
- package/dist/examples/uns-gateway.js +5 -0
- package/dist/graphql/schema.d.ts +377 -0
- package/dist/graphql/schema.js +13 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +18 -0
- package/dist/tools/auth/auth-client.d.ts +23 -0
- package/dist/tools/auth/auth-client.js +172 -0
- package/dist/tools/auth/index.d.ts +1 -0
- package/dist/tools/auth/index.js +1 -0
- package/dist/tools/auth/secure-store.d.ts +17 -0
- package/dist/tools/auth/secure-store.js +110 -0
- package/dist/tools/base-path.d.ts +1 -0
- package/dist/tools/base-path.js +5 -0
- package/dist/tools/generate-config-schema.d.ts +1 -0
- package/dist/tools/generate-config-schema.js +23 -0
- package/dist/tools/initialize.d.ts +1 -0
- package/dist/tools/initialize.js +103 -0
- package/dist/tools/make.d.ts +1 -0
- package/dist/tools/make.js +27 -0
- package/dist/tools/pull-request.d.ts +1 -0
- package/dist/tools/pull-request.js +157 -0
- package/dist/tools/refresh-uns.d.ts +1 -0
- package/dist/tools/refresh-uns.js +109 -0
- package/dist/tools/schema.d.ts +208 -0
- package/dist/tools/schema.js +1 -0
- package/dist/tools/update-rtt.d.ts +1 -0
- package/dist/tools/update-rtt.js +169 -0
- package/dist/tools/update-tools.d.ts +1 -0
- package/dist/tools/update-tools.js +72 -0
- package/dist/uns/handover-manager-event-emitter.d.ts +6 -0
- package/dist/uns/handover-manager-event-emitter.js +19 -0
- package/dist/uns/handover-manager.d.ts +34 -0
- package/dist/uns/handover-manager.js +227 -0
- package/dist/uns/process-config.d.ts +10 -0
- package/dist/uns/process-config.js +12 -0
- package/dist/uns/process-name-service.d.ts +7 -0
- package/dist/uns/process-name-service.js +28 -0
- package/dist/uns/status-monitor.d.ts +35 -0
- package/dist/uns/status-monitor.js +82 -0
- package/dist/uns/uns-event-emitter.d.ts +6 -0
- package/dist/uns/uns-event-emitter.js +19 -0
- package/dist/uns/uns-interfaces.d.ts +156 -0
- package/dist/uns/uns-interfaces.js +5 -0
- package/dist/uns/uns-measurements.d.ts +95 -0
- package/dist/uns/uns-measurements.js +146 -0
- package/dist/uns/uns-packet.d.ts +28 -0
- package/dist/uns/uns-packet.js +223 -0
- package/dist/uns/uns-proxy-process.d.ts +56 -0
- package/dist/uns/uns-proxy-process.js +179 -0
- package/dist/uns/uns-proxy.d.ts +31 -0
- package/dist/uns/uns-proxy.js +120 -0
- package/dist/uns/uns-tags.d.ts +1 -0
- package/dist/uns/uns-tags.js +1 -0
- package/dist/uns/uns-topic-matcher.d.ts +9 -0
- package/dist/uns/uns-topic-matcher.js +34 -0
- package/dist/uns/uns-topics.d.ts +1 -0
- package/dist/uns/uns-topics.js +1 -0
- package/dist/uns-config/config-schema.d.ts +7 -0
- package/dist/uns-config/config-schema.js +5 -0
- package/dist/uns-config/host-placeholders.d.ts +139 -0
- package/dist/uns-config/host-placeholders.js +70 -0
- package/dist/uns-config/schema-tolls.d.ts +2 -0
- package/dist/uns-config/schema-tolls.js +4 -0
- package/dist/uns-config/schema-tools.d.ts +2 -0
- package/dist/uns-config/schema-tools.js +18 -0
- package/dist/uns-config/secret-placeholders.d.ts +128 -0
- package/dist/uns-config/secret-placeholders.js +64 -0
- package/dist/uns-config/secret-resolver.d.ts +77 -0
- package/dist/uns-config/secret-resolver.js +285 -0
- package/dist/uns-config/uns-core-schema.d.ts +705 -0
- package/dist/uns-config/uns-core-schema.js +25 -0
- package/dist/uns-grpc/uns-gateway-cli.d.ts +2 -0
- package/dist/uns-grpc/uns-gateway-cli.js +32 -0
- package/dist/uns-grpc/uns-gateway-server.d.ts +47 -0
- package/dist/uns-grpc/uns-gateway-server.js +424 -0
- package/dist/uns-mqtt/mqtt-interfaces.d.ts +22 -0
- package/dist/uns-mqtt/mqtt-interfaces.js +1 -0
- package/dist/uns-mqtt/mqtt-proxy.d.ts +34 -0
- package/dist/uns-mqtt/mqtt-proxy.js +245 -0
- package/dist/uns-mqtt/mqtt-topic-builder.d.ts +51 -0
- package/dist/uns-mqtt/mqtt-topic-builder.js +70 -0
- package/dist/uns-mqtt/mqtt-worker-init.d.ts +1 -0
- package/dist/uns-mqtt/mqtt-worker-init.js +5 -0
- package/dist/uns-mqtt/mqtt-worker.d.ts +20 -0
- package/dist/uns-mqtt/mqtt-worker.js +120 -0
- package/dist/uns-mqtt/throttled-queue.d.ts +166 -0
- package/dist/uns-mqtt/throttled-queue.js +388 -0
- package/dist/uns-mqtt/uns-mqtt-proxy.d.ts +107 -0
- package/dist/uns-mqtt/uns-mqtt-proxy.js +349 -0
- package/dist/uns-mqtt/ws-proxy.d.ts +38 -0
- package/dist/uns-mqtt/ws-proxy.js +86 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Aljoša Vister
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @uns-kit/core
|
|
2
|
+
|
|
3
|
+
Core utilities and runtime building blocks for building Unified Namespace (UNS) realtime transformers. The package bundles the process lifecycle manager, MQTT integrations, gRPC gateway helpers, configuration tooling, and shared type definitions that power the UNS ecosystem.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @uns-kit/core
|
|
9
|
+
# or
|
|
10
|
+
npm install @uns-kit/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Key Features
|
|
14
|
+
|
|
15
|
+
- **UnsProxyProcess** – plugin-ready runtime for managing UNS proxy instances and MQTT wiring.
|
|
16
|
+
- **MQTT helpers** – resilient publishers, topic builders, throttled queues, and handover support.
|
|
17
|
+
- **Configuration utilities** – Zod-powered config schema generation and secret resolution helpers.
|
|
18
|
+
- **gRPC gateway helpers** – infrastructure to bridge Python workers into the UNS message fabric.
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
Most projects start by creating an `UnsProxyProcess` and registering plugins:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import UnsProxyProcess from "@uns-kit/core/uns/uns-proxy-process";
|
|
26
|
+
|
|
27
|
+
const process = new UnsProxyProcess("mqtt-broker.svc:1883", { processName: "my-rtt" });
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
See the individual plugin packages (`@uns-kit/cron`, `@uns-kit/api`, `@uns-kit/temporal`) for examples on extending the process with runtime capabilities.
|
|
31
|
+
|
|
32
|
+
## Development
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Lint and type-check the sources
|
|
36
|
+
pnpm run typecheck
|
|
37
|
+
|
|
38
|
+
# Emit JavaScript and declaration files to dist/
|
|
39
|
+
pnpm run build
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
MIT © Aljoša Vister
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
export type AppConfig = {
|
|
2
|
+
uns: {
|
|
3
|
+
graphql: string;
|
|
4
|
+
rest: string;
|
|
5
|
+
instanceMode?: "wait" | "force" | "handover";
|
|
6
|
+
processName?: string | undefined;
|
|
7
|
+
handover?: boolean;
|
|
8
|
+
jwksWellKnownUrl?: string | undefined;
|
|
9
|
+
kidWellKnownUrl?: string | undefined;
|
|
10
|
+
env?: "dev" | "staging" | "test" | "prod";
|
|
11
|
+
};
|
|
12
|
+
input?: {
|
|
13
|
+
host: string | ({
|
|
14
|
+
/** Use the supplied host or IP address. */
|
|
15
|
+
provider: "inline";
|
|
16
|
+
/** Host or IP address that should be used directly. */
|
|
17
|
+
value: string;
|
|
18
|
+
} | {
|
|
19
|
+
/** Resolve the host from an external mapping. */
|
|
20
|
+
provider: "external";
|
|
21
|
+
/** Identifier used when resolving the host from HostResolverOptions. */
|
|
22
|
+
key: string;
|
|
23
|
+
/** Allow the external host to be missing without throwing during resolution. */
|
|
24
|
+
optional?: boolean | undefined;
|
|
25
|
+
/** Fallback host when optional is true and the external entry is missing. */
|
|
26
|
+
default?: string | undefined;
|
|
27
|
+
} | {
|
|
28
|
+
/** Resolve the host from local network interfaces. */
|
|
29
|
+
provider: "system";
|
|
30
|
+
/** Address family to return when scanning interfaces. */
|
|
31
|
+
family?: "IPv4" | "IPv6";
|
|
32
|
+
/** Specific interface to read (falls back to the first match when omitted). */
|
|
33
|
+
interfaceName?: string | undefined;
|
|
34
|
+
/** Allow the interface lookup to fail without throwing during resolution. */
|
|
35
|
+
optional?: boolean | undefined;
|
|
36
|
+
/** Fallback host/IP when optional is true and no interface matches. */
|
|
37
|
+
default?: string | undefined;
|
|
38
|
+
});
|
|
39
|
+
username?: string | undefined;
|
|
40
|
+
password?: (string | ({
|
|
41
|
+
/** Load the secret from an environment variable. */
|
|
42
|
+
provider: "env";
|
|
43
|
+
/** Name of the environment variable to read. */
|
|
44
|
+
key: string;
|
|
45
|
+
/** Allow the variable to be absent without throwing during resolution. */
|
|
46
|
+
optional?: boolean | undefined;
|
|
47
|
+
/** Fallback value when optional is true and the variable is missing. */
|
|
48
|
+
default?: string | undefined;
|
|
49
|
+
} | {
|
|
50
|
+
/** Load the secret from Infisical. */
|
|
51
|
+
provider: "infisical";
|
|
52
|
+
/** Secret folder path in Infisical, e.g. '/app/database'. */
|
|
53
|
+
path: string;
|
|
54
|
+
/** Secret key/name inside the given path. */
|
|
55
|
+
key: string;
|
|
56
|
+
/** Allow the secret to be absent without throwing during resolution. */
|
|
57
|
+
optional?: boolean | undefined;
|
|
58
|
+
/** Infisical environment override (defaults to current mode if omitted). */
|
|
59
|
+
environment?: string | undefined;
|
|
60
|
+
/** Optional Infisical project identifier when not using the default. */
|
|
61
|
+
projectId?: string | undefined;
|
|
62
|
+
/** Fallback value when the secret is missing and optional resolution is allowed. */
|
|
63
|
+
default?: string | undefined;
|
|
64
|
+
})) | undefined;
|
|
65
|
+
clientId?: string | undefined;
|
|
66
|
+
} | undefined;
|
|
67
|
+
output?: {
|
|
68
|
+
host: string | ({
|
|
69
|
+
/** Use the supplied host or IP address. */
|
|
70
|
+
provider: "inline";
|
|
71
|
+
/** Host or IP address that should be used directly. */
|
|
72
|
+
value: string;
|
|
73
|
+
} | {
|
|
74
|
+
/** Resolve the host from an external mapping. */
|
|
75
|
+
provider: "external";
|
|
76
|
+
/** Identifier used when resolving the host from HostResolverOptions. */
|
|
77
|
+
key: string;
|
|
78
|
+
/** Allow the external host to be missing without throwing during resolution. */
|
|
79
|
+
optional?: boolean | undefined;
|
|
80
|
+
/** Fallback host when optional is true and the external entry is missing. */
|
|
81
|
+
default?: string | undefined;
|
|
82
|
+
} | {
|
|
83
|
+
/** Resolve the host from local network interfaces. */
|
|
84
|
+
provider: "system";
|
|
85
|
+
/** Address family to return when scanning interfaces. */
|
|
86
|
+
family?: "IPv4" | "IPv6";
|
|
87
|
+
/** Specific interface to read (falls back to the first match when omitted). */
|
|
88
|
+
interfaceName?: string | undefined;
|
|
89
|
+
/** Allow the interface lookup to fail without throwing during resolution. */
|
|
90
|
+
optional?: boolean | undefined;
|
|
91
|
+
/** Fallback host/IP when optional is true and no interface matches. */
|
|
92
|
+
default?: string | undefined;
|
|
93
|
+
});
|
|
94
|
+
username?: string | undefined;
|
|
95
|
+
password?: (string | ({
|
|
96
|
+
/** Load the secret from an environment variable. */
|
|
97
|
+
provider: "env";
|
|
98
|
+
/** Name of the environment variable to read. */
|
|
99
|
+
key: string;
|
|
100
|
+
/** Allow the variable to be absent without throwing during resolution. */
|
|
101
|
+
optional?: boolean | undefined;
|
|
102
|
+
/** Fallback value when optional is true and the variable is missing. */
|
|
103
|
+
default?: string | undefined;
|
|
104
|
+
} | {
|
|
105
|
+
/** Load the secret from Infisical. */
|
|
106
|
+
provider: "infisical";
|
|
107
|
+
/** Secret folder path in Infisical, e.g. '/app/database'. */
|
|
108
|
+
path: string;
|
|
109
|
+
/** Secret key/name inside the given path. */
|
|
110
|
+
key: string;
|
|
111
|
+
/** Allow the secret to be absent without throwing during resolution. */
|
|
112
|
+
optional?: boolean | undefined;
|
|
113
|
+
/** Infisical environment override (defaults to current mode if omitted). */
|
|
114
|
+
environment?: string | undefined;
|
|
115
|
+
/** Optional Infisical project identifier when not using the default. */
|
|
116
|
+
projectId?: string | undefined;
|
|
117
|
+
/** Fallback value when the secret is missing and optional resolution is allowed. */
|
|
118
|
+
default?: string | undefined;
|
|
119
|
+
})) | undefined;
|
|
120
|
+
clientId?: string | undefined;
|
|
121
|
+
} | undefined;
|
|
122
|
+
infra: {
|
|
123
|
+
host: string | ({
|
|
124
|
+
/** Use the supplied host or IP address. */
|
|
125
|
+
provider: "inline";
|
|
126
|
+
/** Host or IP address that should be used directly. */
|
|
127
|
+
value: string;
|
|
128
|
+
} | {
|
|
129
|
+
/** Resolve the host from an external mapping. */
|
|
130
|
+
provider: "external";
|
|
131
|
+
/** Identifier used when resolving the host from HostResolverOptions. */
|
|
132
|
+
key: string;
|
|
133
|
+
/** Allow the external host to be missing without throwing during resolution. */
|
|
134
|
+
optional?: boolean | undefined;
|
|
135
|
+
/** Fallback host when optional is true and the external entry is missing. */
|
|
136
|
+
default?: string | undefined;
|
|
137
|
+
} | {
|
|
138
|
+
/** Resolve the host from local network interfaces. */
|
|
139
|
+
provider: "system";
|
|
140
|
+
/** Address family to return when scanning interfaces. */
|
|
141
|
+
family?: "IPv4" | "IPv6";
|
|
142
|
+
/** Specific interface to read (falls back to the first match when omitted). */
|
|
143
|
+
interfaceName?: string | undefined;
|
|
144
|
+
/** Allow the interface lookup to fail without throwing during resolution. */
|
|
145
|
+
optional?: boolean | undefined;
|
|
146
|
+
/** Fallback host/IP when optional is true and no interface matches. */
|
|
147
|
+
default?: string | undefined;
|
|
148
|
+
});
|
|
149
|
+
username?: string | undefined;
|
|
150
|
+
password?: (string | ({
|
|
151
|
+
/** Load the secret from an environment variable. */
|
|
152
|
+
provider: "env";
|
|
153
|
+
/** Name of the environment variable to read. */
|
|
154
|
+
key: string;
|
|
155
|
+
/** Allow the variable to be absent without throwing during resolution. */
|
|
156
|
+
optional?: boolean | undefined;
|
|
157
|
+
/** Fallback value when optional is true and the variable is missing. */
|
|
158
|
+
default?: string | undefined;
|
|
159
|
+
} | {
|
|
160
|
+
/** Load the secret from Infisical. */
|
|
161
|
+
provider: "infisical";
|
|
162
|
+
/** Secret folder path in Infisical, e.g. '/app/database'. */
|
|
163
|
+
path: string;
|
|
164
|
+
/** Secret key/name inside the given path. */
|
|
165
|
+
key: string;
|
|
166
|
+
/** Allow the secret to be absent without throwing during resolution. */
|
|
167
|
+
optional?: boolean | undefined;
|
|
168
|
+
/** Infisical environment override (defaults to current mode if omitted). */
|
|
169
|
+
environment?: string | undefined;
|
|
170
|
+
/** Optional Infisical project identifier when not using the default. */
|
|
171
|
+
projectId?: string | undefined;
|
|
172
|
+
/** Fallback value when the secret is missing and optional resolution is allowed. */
|
|
173
|
+
default?: string | undefined;
|
|
174
|
+
})) | undefined;
|
|
175
|
+
clientId?: string | undefined;
|
|
176
|
+
};
|
|
177
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const basePath: string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AppConfig } from "./app-config";
|
|
2
|
+
import { type ResolvedAppConfig, type SecretResolverOptions } from "./uns-config/secret-resolver.js";
|
|
3
|
+
export declare class ConfigFile {
|
|
4
|
+
private static rawCache?;
|
|
5
|
+
private static rawPath?;
|
|
6
|
+
private static resolvedCache?;
|
|
7
|
+
static loadRawConfig(configPath?: string): AppConfig;
|
|
8
|
+
static get(): AppConfig;
|
|
9
|
+
static loadConfig(configPath?: string, options?: SecretResolverOptions): Promise<ResolvedAppConfig>;
|
|
10
|
+
static loadResolvedConfig(options?: SecretResolverOptions): Promise<ResolvedAppConfig>;
|
|
11
|
+
static clearCache(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { clearSecretResolverCaches, resolveConfigSecrets, } from "./uns-config/secret-resolver.js";
|
|
4
|
+
const hasOptions = (options) => !!options && Object.values(options).some(value => value !== undefined);
|
|
5
|
+
export class ConfigFile {
|
|
6
|
+
static rawCache;
|
|
7
|
+
static rawPath;
|
|
8
|
+
static resolvedCache;
|
|
9
|
+
static loadRawConfig(configPath) {
|
|
10
|
+
const p = configPath ?? path.resolve(process.cwd(), "config.json");
|
|
11
|
+
if (!this.rawCache || this.rawPath !== p) {
|
|
12
|
+
const raw = fs.readFileSync(p, "utf8");
|
|
13
|
+
this.rawCache = JSON.parse(raw); // no runtime validation
|
|
14
|
+
this.rawPath = p;
|
|
15
|
+
this.resolvedCache = undefined;
|
|
16
|
+
}
|
|
17
|
+
return this.rawCache;
|
|
18
|
+
}
|
|
19
|
+
static get() {
|
|
20
|
+
if (!this.rawCache) {
|
|
21
|
+
throw new Error("Config not loaded. Call ConfigFile.loadConfig() first.");
|
|
22
|
+
}
|
|
23
|
+
return this.rawCache;
|
|
24
|
+
}
|
|
25
|
+
static async loadConfig(configPath, options) {
|
|
26
|
+
const raw = this.loadRawConfig(configPath);
|
|
27
|
+
if (hasOptions(options)) {
|
|
28
|
+
return resolveConfigSecrets(raw, options);
|
|
29
|
+
}
|
|
30
|
+
if (!this.resolvedCache) {
|
|
31
|
+
this.resolvedCache = await resolveConfigSecrets(raw);
|
|
32
|
+
}
|
|
33
|
+
return this.resolvedCache;
|
|
34
|
+
}
|
|
35
|
+
static async loadResolvedConfig(options) {
|
|
36
|
+
return this.loadConfig(undefined, options);
|
|
37
|
+
}
|
|
38
|
+
static clearCache() {
|
|
39
|
+
this.rawCache = undefined;
|
|
40
|
+
this.resolvedCache = undefined;
|
|
41
|
+
this.rawPath = undefined;
|
|
42
|
+
clearSecretResolverCaches();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change this file according to your specifications and rename it to index.ts
|
|
3
|
+
*/
|
|
4
|
+
import UnsProxyProcess from "../uns/uns-proxy-process.js";
|
|
5
|
+
import { ConfigFile } from "../config-file.js";
|
|
6
|
+
import logger from "../logger.js";
|
|
7
|
+
import { PhysicalMeasurements } from "../uns/uns-measurements.js";
|
|
8
|
+
import { UnsPacket } from "../uns/uns-packet.js";
|
|
9
|
+
/**
|
|
10
|
+
* Load the configuration from a file.
|
|
11
|
+
* On the server, this file is provided by the `uns-datahub-controller`.
|
|
12
|
+
* In the development environment, you are responsible for creating and maintaining this file and its contents.
|
|
13
|
+
*/
|
|
14
|
+
const config = await ConfigFile.loadConfig();
|
|
15
|
+
/**
|
|
16
|
+
* Connect to input and output brokers
|
|
17
|
+
*/
|
|
18
|
+
const unsProxyProcess = new UnsProxyProcess(config.infra.host, { processName: config.uns.processName });
|
|
19
|
+
const mqttInput = await unsProxyProcess.createUnsMqttProxy(config.input.host, "templateUnsRttInput", config.uns.instanceMode, config.uns.handover, {
|
|
20
|
+
mqttSubToTopics: ["raw/#"],
|
|
21
|
+
});
|
|
22
|
+
const mqttOutput = await unsProxyProcess.createUnsMqttProxy(config.output.host, "templateUnsRttOutput", config.uns.instanceMode, config.uns.handover, { publishThrottlingDelay: 1000 });
|
|
23
|
+
/**
|
|
24
|
+
* Event listener for input events.
|
|
25
|
+
* Transform an input message and publish it with publishMqttMessage function.
|
|
26
|
+
*/
|
|
27
|
+
mqttInput.event.on("input", async (event) => {
|
|
28
|
+
try {
|
|
29
|
+
if (event.topic === "raw/data") {
|
|
30
|
+
const time = UnsPacket.formatToISO8601(new Date());
|
|
31
|
+
const values = event.message.split(",");
|
|
32
|
+
const numberValue = parseFloat(values[0]);
|
|
33
|
+
const message = { data: { dataGroup: "electricity", time, value: numberValue, uom: PhysicalMeasurements.MiliVolt } };
|
|
34
|
+
const topic = "sij/";
|
|
35
|
+
const tags = [];
|
|
36
|
+
const packet = await UnsPacket.unsPacketFromUnsMessage(message);
|
|
37
|
+
mqttOutput.publishMqttMessage({ topic, attribute: "data-number", packet, description: "Number value", tags });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error(`Error publishing message to MQTT: ${error.message}`);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load the configuration from a file.
|
|
3
|
+
* On the server, this file is provided by the `uns-datahub-controller`.
|
|
4
|
+
* In the development environment, you are responsible for creating and maintaining this file and its contents.
|
|
5
|
+
*/
|
|
6
|
+
import readline from "readline";
|
|
7
|
+
import { ConfigFile } from "../config-file.js";
|
|
8
|
+
import UnsMqttProxy from "../uns-mqtt/uns-mqtt-proxy.js";
|
|
9
|
+
import logger from "../logger.js";
|
|
10
|
+
/**
|
|
11
|
+
* This script initializes an MQTT output proxy for load testing purposes.
|
|
12
|
+
* It sets up a connection to the specified MQTT broker and configures
|
|
13
|
+
* a proxy instance. The load test is designed to evaluate the performance
|
|
14
|
+
* and reliability of the MQTT broker under simulated load conditions.
|
|
15
|
+
*/
|
|
16
|
+
async function main() {
|
|
17
|
+
try {
|
|
18
|
+
const config = await ConfigFile.loadConfig();
|
|
19
|
+
const mqttOutput = new UnsMqttProxy(config.output.host, "loadTest", "templateUnsRttLoadTest", { publishThrottlingDelay: 0 }, true);
|
|
20
|
+
const rl = readline.createInterface({
|
|
21
|
+
input: process.stdin,
|
|
22
|
+
output: process.stdout,
|
|
23
|
+
});
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
25
|
+
rl.question(`Would you like to continue with load-test on ${config.output.host}? (Y/n) `, async (answer) => {
|
|
26
|
+
if (answer.toLowerCase() === "y" || answer.trim() === "") {
|
|
27
|
+
rl.question("How many iterations should be run? (default is 100) ", async (iterations) => {
|
|
28
|
+
const maxIntervals = parseInt(iterations) || 100;
|
|
29
|
+
rl.question("What should be the delay between intervals in milliseconds? (default is 0 ms) ", async (intervalDelay) => {
|
|
30
|
+
const delay = parseInt(intervalDelay) || 0;
|
|
31
|
+
logger.info(`Starting load test with ${maxIntervals} messages and ${delay} ms delay...`);
|
|
32
|
+
let count = 0;
|
|
33
|
+
const startTime = Date.now();
|
|
34
|
+
while (count < maxIntervals) {
|
|
35
|
+
try {
|
|
36
|
+
const currentDate = new Date();
|
|
37
|
+
const rawData = `${count},${currentDate.getTime()}`;
|
|
38
|
+
await mqttOutput.publishMessage("raw/data", rawData);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error("Error publishing message:", error.message);
|
|
42
|
+
}
|
|
43
|
+
count++;
|
|
44
|
+
if (delay > 0) {
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
logger.info(`Sleeping for 50ms.`);
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
50
|
+
const endTime = Date.now();
|
|
51
|
+
const duration = (endTime - startTime) / 1000;
|
|
52
|
+
const messagesPerSecond = maxIntervals / duration;
|
|
53
|
+
logger.info(`Load test completed in ${duration.toFixed(2)} seconds.`);
|
|
54
|
+
logger.info(`Message rate: ${messagesPerSecond.toFixed(2)} msg/s.`);
|
|
55
|
+
rl.close();
|
|
56
|
+
process.exit(0);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
logger.info("Load test aborted.");
|
|
62
|
+
rl.close();
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
logger.error("Error initializing load test:", error.message);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
main();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change this file according to your specifications and rename it to index.ts
|
|
3
|
+
*/
|
|
4
|
+
import UnsProxyProcess from "../uns/uns-proxy-process.js";
|
|
5
|
+
import { ConfigFile } from "../config-file.js";
|
|
6
|
+
import logger from "../logger.js";
|
|
7
|
+
import { UnsPacket } from "../uns/uns-packet.js";
|
|
8
|
+
/**
|
|
9
|
+
* Load the configuration from a file.
|
|
10
|
+
* On the server, this file is provided by the `uns-datahub-controller`.
|
|
11
|
+
* In the development environment, you are responsible for creating and maintaining this file and its contents.
|
|
12
|
+
*/
|
|
13
|
+
const config = await ConfigFile.loadConfig();
|
|
14
|
+
/**
|
|
15
|
+
* Load and configure input and output brokers from config.json
|
|
16
|
+
*/
|
|
17
|
+
if (!config.infra?.host || !config.input?.host || !config.output?.host) {
|
|
18
|
+
throw new Error("Missing required configuration in config.json");
|
|
19
|
+
}
|
|
20
|
+
const unsProxyProcess = new UnsProxyProcess(config.infra.host, { processName: config.uns.processName });
|
|
21
|
+
const mqttInput = await unsProxyProcess.createUnsMqttProxy(config.input.host, "templateUnsRttInput", config.uns.instanceMode, config.uns.handover, {
|
|
22
|
+
mqttSubToTopics: ["iba/zrm"],
|
|
23
|
+
publishThrottlingDelay: 0,
|
|
24
|
+
subscribeThrottlingDelay: 0
|
|
25
|
+
});
|
|
26
|
+
const mqttOutput = await unsProxyProcess.createUnsMqttProxy(config.output.host, "templateUnsRttOutput", config.uns.instanceMode, config.uns.handover, {
|
|
27
|
+
publishThrottlingDelay: 0,
|
|
28
|
+
subscribeThrottlingDelay: 0
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* The input worker connects to the IBA broker and listens for incoming messages.
|
|
32
|
+
* It processes the messages and transforms them into a table-type IUnsMessage.
|
|
33
|
+
* The resulting message is published to the output broker.
|
|
34
|
+
*/
|
|
35
|
+
mqttInput.event.on("input", async (event) => {
|
|
36
|
+
try {
|
|
37
|
+
if (event.topic === "iba/zrm") {
|
|
38
|
+
const jsonObject = JSON.parse(event.message);
|
|
39
|
+
const timestamp = jsonObject.Timestamp;
|
|
40
|
+
delete (jsonObject.Timestamp);
|
|
41
|
+
const time = UnsPacket.formatToISO8601(new Date(timestamp));
|
|
42
|
+
const message = { table: { dataGroup: "iba_test", values: jsonObject, time } };
|
|
43
|
+
const topic = "sij/acroni/hv/";
|
|
44
|
+
const tags = [];
|
|
45
|
+
const packet = await UnsPacket.unsPacketFromUnsMessage(message);
|
|
46
|
+
mqttOutput.publishMqttMessage({ topic, attribute: "zrm", packet, description: "Table", tags });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
logger.error(`Error publishing message to MQTT: ${error.message}`);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|