conduithub 1.0.1 → 1.1.0
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/dist/core/conduit-hub/index.d.cts +1 -1
- package/dist/core/conduit-hub/index.d.mts +1 -1
- package/dist/core/conduit-hub/index.d.ts +1 -1
- package/dist/core/config-manager/index.d.cts +1 -1
- package/dist/core/config-manager/index.d.mts +1 -1
- package/dist/core/config-manager/index.d.ts +1 -1
- package/dist/core/index.cjs +4 -2
- package/dist/core/index.d.cts +8 -184
- package/dist/core/index.d.mts +8 -184
- package/dist/core/index.d.ts +8 -184
- package/dist/core/index.mjs +3 -2
- package/dist/core/plugin/index.d.cts +1 -1
- package/dist/core/plugin/index.d.mts +1 -1
- package/dist/core/plugin/index.d.ts +1 -1
- package/dist/index.cjs +185 -14
- package/dist/index.d.cts +67 -3
- package/dist/index.d.mts +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.mjs +159 -6
- package/dist/plugins/index.cjs +32 -4
- package/dist/plugins/index.d.cts +4 -2
- package/dist/plugins/index.d.mts +4 -2
- package/dist/plugins/index.d.ts +4 -2
- package/dist/plugins/index.mjs +21 -3
- package/dist/plugins/kafka/index.cjs +34 -0
- package/dist/plugins/kafka/index.d.cts +250 -0
- package/dist/plugins/kafka/index.d.mts +250 -0
- package/dist/plugins/kafka/index.d.ts +250 -0
- package/dist/plugins/kafka/index.mjs +23 -0
- package/dist/plugins/redis/index.cjs +26 -5
- package/dist/plugins/redis/index.d.cts +59 -17
- package/dist/plugins/redis/index.d.mts +59 -17
- package/dist/plugins/redis/index.d.ts +59 -17
- package/dist/plugins/redis/index.mjs +21 -4
- package/dist/shared/conduithub.0FKJet8c.cjs +1130 -0
- package/dist/shared/conduithub.B16qn6pY.mjs +174 -0
- package/dist/shared/conduithub.BW-S7Bp_.d.cts +181 -0
- package/dist/shared/conduithub.BdX_BLza.mjs +1124 -0
- package/dist/shared/{conduithub.-bZD30_I.mjs → conduithub.BzuAKyjY.mjs} +238 -36
- package/dist/shared/conduithub.DSAmRivG.d.ts +181 -0
- package/dist/shared/{conduithub.cvEjE62V.cjs → conduithub.DhMIxMx2.cjs} +242 -36
- package/dist/shared/conduithub.GrtzQn_7.d.mts +181 -0
- package/dist/shared/conduithub.jH-df3Zd.cjs +181 -0
- package/package.json +22 -1
|
@@ -1,38 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
require('node:fs');
|
|
4
|
+
require('node:fs/promises');
|
|
5
|
+
require('node:path');
|
|
6
|
+
require('./conduithub.BNQsddJO.cjs');
|
|
7
|
+
const schema = require('./conduithub.jH-df3Zd.cjs');
|
|
8
|
+
const core_conduitHub_index = require('../core/conduit-hub/index.cjs');
|
|
9
|
+
require('process');
|
|
10
|
+
require('readline');
|
|
11
|
+
require('uuid');
|
|
3
12
|
const Redis = require('ioredis');
|
|
4
13
|
const core_plugin_index = require('../core/plugin/index.cjs');
|
|
5
|
-
const zod = require('zod');
|
|
6
14
|
|
|
7
15
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
8
16
|
|
|
9
17
|
const Redis__default = /*#__PURE__*/_interopDefaultCompat(Redis);
|
|
10
18
|
|
|
11
|
-
const redisConfigSchema = zod.z.object({
|
|
12
|
-
host: zod.z.string().default("localhost"),
|
|
13
|
-
port: zod.z.number().default(6379),
|
|
14
|
-
password: zod.z.string().optional(),
|
|
15
|
-
db: zod.z.number().default(0),
|
|
16
|
-
username: zod.z.string().optional(),
|
|
17
|
-
url: zod.z.string().url().optional(),
|
|
18
|
-
keyPrefix: zod.z.string().optional(),
|
|
19
|
-
tls: zod.z.object({
|
|
20
|
-
ca: zod.z.string().optional(),
|
|
21
|
-
cert: zod.z.string().optional(),
|
|
22
|
-
key: zod.z.string().optional(),
|
|
23
|
-
rejectUnauthorized: zod.z.boolean().default(true)
|
|
24
|
-
}).optional(),
|
|
25
|
-
connectionTimeout: zod.z.number().default(5e4),
|
|
26
|
-
commandTimeout: zod.z.number().default(5e4),
|
|
27
|
-
maxRetriesPerRequest: zod.z.number().default(3),
|
|
28
|
-
retryDelayOnFailover: zod.z.number().default(100),
|
|
29
|
-
enableReadyCheck: zod.z.boolean().default(true),
|
|
30
|
-
enableOfflineQueue: zod.z.boolean().default(true),
|
|
31
|
-
keepAlive: zod.z.boolean().default(true),
|
|
32
|
-
lazyConnect: zod.z.boolean().default(false),
|
|
33
|
-
family: zod.z.enum(["IPv4", "IPv6"]).default("IPv4")
|
|
34
|
-
});
|
|
35
|
-
|
|
36
19
|
function createNoopRedisClient() {
|
|
37
20
|
return {
|
|
38
21
|
set: async () => "OK",
|
|
@@ -106,7 +89,7 @@ class RedisPlugin extends core_plugin_index.BasePlugin {
|
|
|
106
89
|
}
|
|
107
90
|
}
|
|
108
91
|
constructor(config) {
|
|
109
|
-
const normalized = redisConfigSchema.parse(config ?? {});
|
|
92
|
+
const normalized = schema.redisConfigSchema.parse(config ?? {});
|
|
110
93
|
super({
|
|
111
94
|
name: "redis",
|
|
112
95
|
version: "1.0.0",
|
|
@@ -121,12 +104,20 @@ class RedisPlugin extends core_plugin_index.BasePlugin {
|
|
|
121
104
|
if (!options || Object.keys(options).length === 0) {
|
|
122
105
|
return redisClient.set(key, String(value));
|
|
123
106
|
}
|
|
124
|
-
const
|
|
125
|
-
if (options.EX
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (options.
|
|
129
|
-
|
|
107
|
+
const args = [];
|
|
108
|
+
if (typeof options.EX === "number") {
|
|
109
|
+
args.push("EX", options.EX);
|
|
110
|
+
}
|
|
111
|
+
if (typeof options.PX === "number") {
|
|
112
|
+
args.push("PX", options.PX);
|
|
113
|
+
}
|
|
114
|
+
if (options.NX) {
|
|
115
|
+
args.push("NX");
|
|
116
|
+
}
|
|
117
|
+
if (options.XX) {
|
|
118
|
+
args.push("XX");
|
|
119
|
+
}
|
|
120
|
+
return redisClient.set(key, String(value), ...args);
|
|
130
121
|
},
|
|
131
122
|
get: (key) => redisClient.get(key),
|
|
132
123
|
del: (key) => Array.isArray(key) ? redisClient.del(...key) : redisClient.del(key),
|
|
@@ -177,17 +168,17 @@ class RedisPlugin extends core_plugin_index.BasePlugin {
|
|
|
177
168
|
retryDelayOnFailover: config.retryDelayOnFailover,
|
|
178
169
|
maxRetriesPerRequest: config.maxRetriesPerRequest,
|
|
179
170
|
connectTimeout: config.connectionTimeout,
|
|
180
|
-
commandTimeout: config.commandTimeout
|
|
171
|
+
commandTimeout: config.commandTimeout,
|
|
172
|
+
lazyConnect: config.lazyConnect ?? (process.env.VITEST === "true" || process.env.NODE_ENV === "test")
|
|
181
173
|
};
|
|
182
174
|
if (config.password) redisOptions.password = config.password;
|
|
183
175
|
if (config.username) redisOptions.username = config.username;
|
|
184
176
|
if (config.keyPrefix) redisOptions.keyPrefix = config.keyPrefix;
|
|
185
177
|
if (config.tls) redisOptions.tls = config.tls;
|
|
186
178
|
const redisClient = new Redis__default(redisOptions);
|
|
187
|
-
await redisClient.ping();
|
|
188
179
|
this.ioredisClient = redisClient;
|
|
189
180
|
this.redis = this.createRedisWrapper(redisClient);
|
|
190
|
-
this.logger.log?.("info", "
|
|
181
|
+
this.logger.log?.("info", "Redis client initialized");
|
|
191
182
|
} catch (error) {
|
|
192
183
|
this.logger.log?.(
|
|
193
184
|
"error",
|
|
@@ -772,4 +763,219 @@ class RedisPlugin extends core_plugin_index.BasePlugin {
|
|
|
772
763
|
}
|
|
773
764
|
}
|
|
774
765
|
|
|
766
|
+
let hub = null;
|
|
767
|
+
let redisPlugin = null;
|
|
768
|
+
function readRedisConfigFromEnv() {
|
|
769
|
+
const toNumber = (v) => v !== void 0 && v !== null && v !== "" && !Number.isNaN(Number(v)) ? Number(v) : void 0;
|
|
770
|
+
const toBoolean = (v) => v === "true" ? true : v === "false" ? false : void 0;
|
|
771
|
+
const host = process.env.REDIS_HOST;
|
|
772
|
+
const port = toNumber(process.env.REDIS_PORT);
|
|
773
|
+
const password = process.env.REDIS_PASSWORD;
|
|
774
|
+
const db = toNumber(process.env.REDIS_DB);
|
|
775
|
+
const username = process.env.REDIS_USERNAME;
|
|
776
|
+
const keyPrefix = process.env.REDIS_KEY_PREFIX;
|
|
777
|
+
const connectionTimeout = toNumber(process.env.REDIS_CONNECTION_TIMEOUT);
|
|
778
|
+
const commandTimeout = toNumber(process.env.REDIS_COMMAND_TIMEOUT);
|
|
779
|
+
const maxRetriesPerRequest = toNumber(
|
|
780
|
+
process.env.REDIS_MAX_RETRIES_PER_REQUEST
|
|
781
|
+
);
|
|
782
|
+
const retryDelayOnFailover = toNumber(
|
|
783
|
+
process.env.REDIS_RETRY_DELAY_ON_FAILOVER
|
|
784
|
+
);
|
|
785
|
+
const enableReadyCheck = toBoolean(process.env.REDIS_ENABLE_READY_CHECK);
|
|
786
|
+
const enableOfflineQueue = toBoolean(process.env.REDIS_ENABLE_OFFLINE_QUEUE);
|
|
787
|
+
const keepAlive = toBoolean(process.env.REDIS_KEEP_ALIVE);
|
|
788
|
+
const lazyConnect = toBoolean(process.env.REDIS_LAZY_CONNECT);
|
|
789
|
+
const familyEnv = process.env.REDIS_FAMILY;
|
|
790
|
+
const family = familyEnv === "IPv6" ? "IPv6" : familyEnv === "IPv4" ? "IPv4" : void 0;
|
|
791
|
+
const tlsCa = process.env.REDIS_TLS_CA;
|
|
792
|
+
const tlsCert = process.env.REDIS_TLS_CERT;
|
|
793
|
+
const tlsKey = process.env.REDIS_TLS_KEY;
|
|
794
|
+
const tlsRejectUnauthorized = toBoolean(
|
|
795
|
+
process.env.REDIS_TLS_REJECT_UNAUTHORIZED
|
|
796
|
+
);
|
|
797
|
+
const cfg = {};
|
|
798
|
+
if (host) cfg.host = host;
|
|
799
|
+
if (port !== void 0) cfg.port = port;
|
|
800
|
+
if (password) cfg.password = password;
|
|
801
|
+
if (db !== void 0) cfg.db = db;
|
|
802
|
+
if (username) cfg.username = username;
|
|
803
|
+
if (keyPrefix) cfg.keyPrefix = keyPrefix;
|
|
804
|
+
if (connectionTimeout !== void 0)
|
|
805
|
+
cfg.connectionTimeout = connectionTimeout;
|
|
806
|
+
if (commandTimeout !== void 0) cfg.commandTimeout = commandTimeout;
|
|
807
|
+
if (maxRetriesPerRequest !== void 0)
|
|
808
|
+
cfg.maxRetriesPerRequest = maxRetriesPerRequest;
|
|
809
|
+
if (retryDelayOnFailover !== void 0)
|
|
810
|
+
cfg.retryDelayOnFailover = retryDelayOnFailover;
|
|
811
|
+
if (enableReadyCheck !== void 0) cfg.enableReadyCheck = enableReadyCheck;
|
|
812
|
+
if (enableOfflineQueue !== void 0)
|
|
813
|
+
cfg.enableOfflineQueue = enableOfflineQueue;
|
|
814
|
+
if (keepAlive !== void 0) cfg.keepAlive = keepAlive;
|
|
815
|
+
if (lazyConnect !== void 0) cfg.lazyConnect = lazyConnect;
|
|
816
|
+
if (family !== void 0) cfg.family = family;
|
|
817
|
+
if (tlsCa || tlsCert || tlsKey || tlsRejectUnauthorized !== void 0) {
|
|
818
|
+
const tls = {
|
|
819
|
+
rejectUnauthorized: tlsRejectUnauthorized ?? true
|
|
820
|
+
};
|
|
821
|
+
if (tlsCa) tls.ca = tlsCa;
|
|
822
|
+
if (tlsCert) tls.cert = tlsCert;
|
|
823
|
+
if (tlsKey) tls.key = tlsKey;
|
|
824
|
+
cfg.tls = tls;
|
|
825
|
+
}
|
|
826
|
+
return cfg;
|
|
827
|
+
}
|
|
828
|
+
async function initRedis(override) {
|
|
829
|
+
if (redisPlugin) return redisPlugin;
|
|
830
|
+
const cfg = {
|
|
831
|
+
...readRedisConfigFromEnv(),
|
|
832
|
+
...override ?? {}
|
|
833
|
+
};
|
|
834
|
+
if (!hub) hub = core_conduitHub_index.ConduitHub.getInstance();
|
|
835
|
+
if (!hub.isInitialized) await hub.initialize({});
|
|
836
|
+
const plugin = new RedisPlugin(cfg);
|
|
837
|
+
await hub.registerPlugin(plugin);
|
|
838
|
+
await hub.startPlugin("RedisPlugin");
|
|
839
|
+
redisPlugin = plugin;
|
|
840
|
+
return plugin;
|
|
841
|
+
}
|
|
842
|
+
function getRedis() {
|
|
843
|
+
if (!redisPlugin)
|
|
844
|
+
throw new Error("RedisPlugin is not initialized. Call initRedis() first.");
|
|
845
|
+
return redisPlugin;
|
|
846
|
+
}
|
|
847
|
+
async function shutdownRedis() {
|
|
848
|
+
if (!hub) return;
|
|
849
|
+
try {
|
|
850
|
+
if (hub.isInitialized && hub.isPluginRegistered("RedisPlugin")) {
|
|
851
|
+
if (hub.isPluginRunning("RedisPlugin"))
|
|
852
|
+
await hub.stopPlugin("RedisPlugin");
|
|
853
|
+
await hub.unregisterPlugin("RedisPlugin");
|
|
854
|
+
}
|
|
855
|
+
} finally {
|
|
856
|
+
redisPlugin = null;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
const redis = {
|
|
860
|
+
init: initRedis,
|
|
861
|
+
getPlugin: getRedis,
|
|
862
|
+
shutdown: shutdownRedis,
|
|
863
|
+
set: async (key, value, options) => {
|
|
864
|
+
const client = await initRedis();
|
|
865
|
+
return client.set(key, value, options);
|
|
866
|
+
},
|
|
867
|
+
get: async (key) => {
|
|
868
|
+
const client = await initRedis();
|
|
869
|
+
return client.get(key);
|
|
870
|
+
},
|
|
871
|
+
del: async (key) => {
|
|
872
|
+
const client = await initRedis();
|
|
873
|
+
return client.del(key);
|
|
874
|
+
},
|
|
875
|
+
exists: async (key) => {
|
|
876
|
+
const client = await initRedis();
|
|
877
|
+
return client.exists(key);
|
|
878
|
+
},
|
|
879
|
+
expire: async (key, seconds) => {
|
|
880
|
+
const client = await initRedis();
|
|
881
|
+
return client.expire(key, seconds);
|
|
882
|
+
},
|
|
883
|
+
ttl: async (key) => {
|
|
884
|
+
const client = await initRedis();
|
|
885
|
+
return client.ttl(key);
|
|
886
|
+
},
|
|
887
|
+
hset: async (key, field, value) => {
|
|
888
|
+
const client = await initRedis();
|
|
889
|
+
return client.hset(key, field, value);
|
|
890
|
+
},
|
|
891
|
+
hget: async (key, field) => {
|
|
892
|
+
const client = await initRedis();
|
|
893
|
+
return client.hget(key, field);
|
|
894
|
+
},
|
|
895
|
+
hgetall: async (key) => {
|
|
896
|
+
const client = await initRedis();
|
|
897
|
+
return client.hgetall(key);
|
|
898
|
+
},
|
|
899
|
+
hdel: async (key, field) => {
|
|
900
|
+
const client = await initRedis();
|
|
901
|
+
return client.hdel(key, field);
|
|
902
|
+
},
|
|
903
|
+
lpush: async (key, ...elements) => {
|
|
904
|
+
const client = await initRedis();
|
|
905
|
+
return client.lpush(key, ...elements);
|
|
906
|
+
},
|
|
907
|
+
rpush: async (key, ...elements) => {
|
|
908
|
+
const client = await initRedis();
|
|
909
|
+
return client.rpush(key, ...elements);
|
|
910
|
+
},
|
|
911
|
+
lpop: async (key) => {
|
|
912
|
+
const client = await initRedis();
|
|
913
|
+
return client.lpop(key);
|
|
914
|
+
},
|
|
915
|
+
rpop: async (key) => {
|
|
916
|
+
const client = await initRedis();
|
|
917
|
+
return client.rpop(key);
|
|
918
|
+
},
|
|
919
|
+
llen: async (key) => {
|
|
920
|
+
const client = await initRedis();
|
|
921
|
+
return client.llen(key);
|
|
922
|
+
},
|
|
923
|
+
lrange: async (key, start, stop) => {
|
|
924
|
+
const client = await initRedis();
|
|
925
|
+
return client.lrange(key, start, stop);
|
|
926
|
+
},
|
|
927
|
+
sadd: async (key, ...members) => {
|
|
928
|
+
const client = await initRedis();
|
|
929
|
+
return client.sadd(key, ...members);
|
|
930
|
+
},
|
|
931
|
+
srem: async (key, ...members) => {
|
|
932
|
+
const client = await initRedis();
|
|
933
|
+
return client.srem(key, ...members);
|
|
934
|
+
},
|
|
935
|
+
smembers: async (key) => {
|
|
936
|
+
const client = await initRedis();
|
|
937
|
+
return client.smembers(key);
|
|
938
|
+
},
|
|
939
|
+
sismember: async (key, member) => {
|
|
940
|
+
const client = await initRedis();
|
|
941
|
+
return client.sismember(key, member);
|
|
942
|
+
},
|
|
943
|
+
scard: async (key) => {
|
|
944
|
+
const client = await initRedis();
|
|
945
|
+
return client.scard(key);
|
|
946
|
+
},
|
|
947
|
+
zadd: async (key, score, member) => {
|
|
948
|
+
const client = await initRedis();
|
|
949
|
+
return client.zadd(key, score, member);
|
|
950
|
+
},
|
|
951
|
+
zrange: async (key, start, stop) => {
|
|
952
|
+
const client = await initRedis();
|
|
953
|
+
return client.zrange(key, start, stop);
|
|
954
|
+
},
|
|
955
|
+
ping: async () => {
|
|
956
|
+
const client = await initRedis();
|
|
957
|
+
return client.ping();
|
|
958
|
+
},
|
|
959
|
+
flushdb: async () => {
|
|
960
|
+
const client = await initRedis();
|
|
961
|
+
return client.flushdb();
|
|
962
|
+
},
|
|
963
|
+
flushall: async () => {
|
|
964
|
+
const client = await initRedis();
|
|
965
|
+
return client.flushall();
|
|
966
|
+
},
|
|
967
|
+
getConnectionInfo: async () => {
|
|
968
|
+
const client = await initRedis();
|
|
969
|
+
return client.getConnectionInfo();
|
|
970
|
+
},
|
|
971
|
+
getStats: async () => {
|
|
972
|
+
const client = await initRedis();
|
|
973
|
+
return client.getStats();
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
|
|
775
977
|
exports.RedisPlugin = RedisPlugin;
|
|
978
|
+
exports.getRedis = getRedis;
|
|
979
|
+
exports.initRedis = initRedis;
|
|
980
|
+
exports.redis = redis;
|
|
981
|
+
exports.shutdownRedis = shutdownRedis;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Hook, HookResult } from '../core/hook/index.mjs';
|
|
3
|
+
import { a as Logger } from './conduithub.B7aryjPG.mjs';
|
|
4
|
+
import { E as EventBus, a as EventData } from './conduithub.BzLwccre.mjs';
|
|
5
|
+
import { ServiceContainer } from '../core/service-container/index.mjs';
|
|
6
|
+
import { StateManager } from '../core/state-manager/index.mjs';
|
|
7
|
+
|
|
8
|
+
interface PluginStatus {
|
|
9
|
+
name: string;
|
|
10
|
+
version: string;
|
|
11
|
+
status: "registered" | "initialized" | "running" | "stopped" | "destroyed" | "error";
|
|
12
|
+
config: PluginConfig;
|
|
13
|
+
error?: string;
|
|
14
|
+
lastActivity: number;
|
|
15
|
+
}
|
|
16
|
+
declare class PluginManager {
|
|
17
|
+
private eventBus;
|
|
18
|
+
private logger;
|
|
19
|
+
private serviceContainer;
|
|
20
|
+
private stateManager;
|
|
21
|
+
private hookSystem;
|
|
22
|
+
private configManager;
|
|
23
|
+
private plugins;
|
|
24
|
+
private pluginStatuses;
|
|
25
|
+
private pluginConfigs;
|
|
26
|
+
constructor(eventBus: EventBus<Record<string, unknown>>, logger: Logger, serviceContainer: ServiceContainer, stateManager: StateManager, hookSystem: Hook<Record<string, {
|
|
27
|
+
input: unknown;
|
|
28
|
+
output: unknown;
|
|
29
|
+
}>>, configManager: ConfigManager);
|
|
30
|
+
private log;
|
|
31
|
+
registerPlugin(plugin: BasePlugin, config?: PluginConfig): Promise<void>;
|
|
32
|
+
unregisterPlugin(pluginName: string): Promise<void>;
|
|
33
|
+
initializePlugin(pluginName: string): Promise<void>;
|
|
34
|
+
startPlugin(pluginName: string): Promise<void>;
|
|
35
|
+
stopPlugin(pluginName: string): Promise<void>;
|
|
36
|
+
shutdownAll(): Promise<void>;
|
|
37
|
+
isPluginRegistered(pluginName: string): boolean;
|
|
38
|
+
isPluginRunning(pluginName: string): boolean;
|
|
39
|
+
getPluginStatus(pluginName: string): PluginStatus | undefined;
|
|
40
|
+
listPlugins(): string[];
|
|
41
|
+
getAllPluginStatuses(): PluginStatus[];
|
|
42
|
+
getPlugin(pluginName: string): BasePlugin | undefined;
|
|
43
|
+
getPluginConfig(pluginName: string): PluginConfig | undefined;
|
|
44
|
+
updatePluginConfig(pluginName: string, config: Partial<PluginConfig>): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface PluginConfig {
|
|
48
|
+
name: string;
|
|
49
|
+
version: string;
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
dependencies?: string[];
|
|
52
|
+
config?: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
interface PluginContext<EM extends Record<string, unknown> = Record<string, unknown>, HM extends Record<string, {
|
|
55
|
+
input: unknown;
|
|
56
|
+
output: unknown;
|
|
57
|
+
}> = Record<string, {
|
|
58
|
+
input: unknown;
|
|
59
|
+
output: unknown;
|
|
60
|
+
}>> {
|
|
61
|
+
eventBus: EventBus<EM>;
|
|
62
|
+
logger: Logger;
|
|
63
|
+
config: PluginConfig;
|
|
64
|
+
serviceContainer: ServiceContainer;
|
|
65
|
+
hookSystem: Hook<HM>;
|
|
66
|
+
stateManager: StateManager;
|
|
67
|
+
}
|
|
68
|
+
interface PluginMetadata {
|
|
69
|
+
name: string;
|
|
70
|
+
version: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
author?: string;
|
|
73
|
+
dependencies?: string[];
|
|
74
|
+
hooks: string[];
|
|
75
|
+
events: string[];
|
|
76
|
+
}
|
|
77
|
+
type PluginLifecycle = "beforeInit" | "afterInit" | "beforeStart" | "afterStart" | "beforeStop" | "afterStop" | "beforeDestroy" | "afterDestroy";
|
|
78
|
+
declare abstract class BasePlugin<T extends Record<string, unknown> = Record<string, unknown>, EM extends Record<string, unknown> = Record<string, unknown>, HM extends Record<string, {
|
|
79
|
+
input: unknown;
|
|
80
|
+
output: unknown;
|
|
81
|
+
}> = Record<string, {
|
|
82
|
+
input: unknown;
|
|
83
|
+
output: unknown;
|
|
84
|
+
}>> {
|
|
85
|
+
protected config: PluginConfig & {
|
|
86
|
+
config: T;
|
|
87
|
+
};
|
|
88
|
+
protected context: PluginContext<EM, HM>;
|
|
89
|
+
protected metadata: PluginMetadata;
|
|
90
|
+
protected isInitialized: boolean;
|
|
91
|
+
protected isRunning: boolean;
|
|
92
|
+
private managedEventHandlers;
|
|
93
|
+
private managedHookHandlers;
|
|
94
|
+
private lock;
|
|
95
|
+
constructor(config: PluginConfig & {
|
|
96
|
+
config: T;
|
|
97
|
+
});
|
|
98
|
+
abstract getMetadata(): PluginMetadata;
|
|
99
|
+
initialize(context: PluginContext<EM, HM>): Promise<void>;
|
|
100
|
+
start(): Promise<void>;
|
|
101
|
+
stop(): Promise<void>;
|
|
102
|
+
destroy(): Promise<void>;
|
|
103
|
+
protected abstract onInitialize(): Promise<void>;
|
|
104
|
+
protected abstract onStart(): Promise<void>;
|
|
105
|
+
protected abstract onStop(): Promise<void>;
|
|
106
|
+
protected abstract onDestroy(): Promise<void>;
|
|
107
|
+
private executeLifecycleHook;
|
|
108
|
+
getConfig(): PluginConfig & {
|
|
109
|
+
config: T;
|
|
110
|
+
};
|
|
111
|
+
getContext(): PluginContext<EM, HM>;
|
|
112
|
+
isPluginInitialized(): boolean;
|
|
113
|
+
isPluginRunning(): boolean;
|
|
114
|
+
protected emit<K extends keyof EM>(event: K, data: EM[K]): Promise<void>;
|
|
115
|
+
protected on<K extends keyof EM>(event: K, listener: (payload: EM[K], event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
116
|
+
protected once<K extends keyof EM>(event: K, listener: (payload: EM[K], event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
117
|
+
protected onManaged<K extends keyof EM>(event: K, listener: (payload: EM[K], event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
118
|
+
protected onceManaged<K extends keyof EM>(event: K, listener: (payload: EM[K], event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
119
|
+
protected off<K extends keyof EM>(event: K, handlerId: string): void;
|
|
120
|
+
protected executeHook<K extends keyof HM>(hook: K, input: HM[K]["input"]): Promise<HM[K]["output"]>;
|
|
121
|
+
protected executeHookSeries<K extends keyof HM>(hook: K, input: HM[K]["input"]): Promise<HookResult<HM[K]["output"]>[]>;
|
|
122
|
+
protected executeHookSeriesWithContext<K extends keyof HM>(hook: K, input: HM[K]["input"], context: Record<string, unknown>): Promise<HookResult<HM[K]["output"]>[]>;
|
|
123
|
+
protected registerHook<K extends keyof HM>(hook: K, handler: (data: HM[K]["input"], context?: Record<string, unknown>) => HM[K]["output"] | Promise<HM[K]["output"]> | HookResult<HM[K]["output"]> | Promise<HookResult<HM[K]["output"]>>, priority?: number, customId?: string): Promise<string>;
|
|
124
|
+
protected registerHookManaged<K extends keyof HM>(hook: K, handler: (data: HM[K]["input"], context?: Record<string, unknown>) => HM[K]["output"] | Promise<HM[K]["output"]> | HookResult<HM[K]["output"]> | Promise<HookResult<HM[K]["output"]>>, priority?: number, customId?: string): Promise<string>;
|
|
125
|
+
protected unregisterHook<K extends keyof HM>(hook: K, handlerId: string): Promise<boolean>;
|
|
126
|
+
protected getStatus(): {
|
|
127
|
+
initialized: boolean;
|
|
128
|
+
running: boolean;
|
|
129
|
+
};
|
|
130
|
+
protected getName(): string;
|
|
131
|
+
protected getVersion(): string;
|
|
132
|
+
protected isEnabled(): boolean;
|
|
133
|
+
protected getState(key: string): unknown;
|
|
134
|
+
protected setState(key: string, value: unknown): void;
|
|
135
|
+
protected deleteState(key: string): void;
|
|
136
|
+
protected get logger(): Logger;
|
|
137
|
+
updateConfig(update: Partial<PluginConfig & {
|
|
138
|
+
config: T;
|
|
139
|
+
}>): void;
|
|
140
|
+
private cleanupManagedHandlers;
|
|
141
|
+
private cleanupManagedHooks;
|
|
142
|
+
private withLock;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
declare class ConfigManager {
|
|
146
|
+
private config;
|
|
147
|
+
private pluginConfigs;
|
|
148
|
+
private isInitialized;
|
|
149
|
+
initialize(config: Record<string, unknown>): Promise<void>;
|
|
150
|
+
shutdown(): Promise<void>;
|
|
151
|
+
get<T>(key: string, defaultValue?: T): T | undefined;
|
|
152
|
+
set<T>(key: string, value: T): void;
|
|
153
|
+
has(key: string): boolean;
|
|
154
|
+
delete(key: string): boolean;
|
|
155
|
+
loadConfig(config: Record<string, unknown>): void;
|
|
156
|
+
clearConfig(): void;
|
|
157
|
+
getPluginConfig(pluginName: string): PluginConfig | undefined;
|
|
158
|
+
setPluginConfig(pluginName: string, config: PluginConfig): void;
|
|
159
|
+
updatePluginConfig(pluginName: string, updates: Partial<PluginConfig>): void;
|
|
160
|
+
hasPluginConfig(pluginName: string): boolean;
|
|
161
|
+
deletePluginConfig(pluginName: string): boolean;
|
|
162
|
+
getAllPluginConfigs(): Record<string, PluginConfig>;
|
|
163
|
+
loadPluginConfigs(configs: Record<string, PluginConfig>): void;
|
|
164
|
+
validateConfig(schema: z.ZodTypeAny, config: unknown): {
|
|
165
|
+
valid: boolean;
|
|
166
|
+
errors: string[];
|
|
167
|
+
};
|
|
168
|
+
exportConfig(format?: "json"): string;
|
|
169
|
+
importConfig(configJson: string): void;
|
|
170
|
+
getPluginConfigNames(): string[];
|
|
171
|
+
getStats(): {
|
|
172
|
+
totalConfigKeys: number;
|
|
173
|
+
totalPluginConfigs: number;
|
|
174
|
+
configKeys: string[];
|
|
175
|
+
pluginConfigNames: string[];
|
|
176
|
+
};
|
|
177
|
+
watchConfig(key: string, callback: (value: unknown) => void): () => void;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export { BasePlugin as B, ConfigManager as C, PluginManager as e };
|
|
181
|
+
export type { PluginConfig as P, PluginContext as a, PluginMetadata as b, PluginLifecycle as c, PluginStatus as d };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const zod = require('zod');
|
|
4
|
+
|
|
5
|
+
const redisConfigSchema = zod.z.object({
|
|
6
|
+
host: zod.z.string().default("localhost"),
|
|
7
|
+
port: zod.z.number().default(6379),
|
|
8
|
+
password: zod.z.string().optional(),
|
|
9
|
+
db: zod.z.number().default(0),
|
|
10
|
+
username: zod.z.string().optional(),
|
|
11
|
+
url: zod.z.string().url().optional(),
|
|
12
|
+
keyPrefix: zod.z.string().optional(),
|
|
13
|
+
tls: zod.z.object({
|
|
14
|
+
ca: zod.z.string().optional(),
|
|
15
|
+
cert: zod.z.string().optional(),
|
|
16
|
+
key: zod.z.string().optional(),
|
|
17
|
+
rejectUnauthorized: zod.z.boolean().default(true)
|
|
18
|
+
}).optional(),
|
|
19
|
+
connectionTimeout: zod.z.number().default(5e4),
|
|
20
|
+
commandTimeout: zod.z.number().default(5e4),
|
|
21
|
+
maxRetriesPerRequest: zod.z.number().default(3),
|
|
22
|
+
retryDelayOnFailover: zod.z.number().default(100),
|
|
23
|
+
enableReadyCheck: zod.z.boolean().default(true),
|
|
24
|
+
enableOfflineQueue: zod.z.boolean().default(true),
|
|
25
|
+
keepAlive: zod.z.boolean().default(true),
|
|
26
|
+
lazyConnect: zod.z.boolean().default(false),
|
|
27
|
+
family: zod.z.enum(["IPv4", "IPv6"]).default("IPv4")
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const conduithubConfigSchema = zod.z.object({
|
|
31
|
+
logLevel: zod.z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
32
|
+
autoEnable: zod.z.boolean().default(true),
|
|
33
|
+
strictMode: zod.z.boolean().default(true),
|
|
34
|
+
enableHotReload: zod.z.boolean().default(false),
|
|
35
|
+
plugins: zod.z.record(zod.z.string(), zod.z.any()).optional(),
|
|
36
|
+
redis: redisConfigSchema.optional()
|
|
37
|
+
});
|
|
38
|
+
function createConfigSchema(shape) {
|
|
39
|
+
return zod.z.object(shape);
|
|
40
|
+
}
|
|
41
|
+
function extendConfigSchema(baseSchema, extensions) {
|
|
42
|
+
return baseSchema.extend(extensions);
|
|
43
|
+
}
|
|
44
|
+
function mergeConfigSchemas(...schemas) {
|
|
45
|
+
return schemas.reduce(
|
|
46
|
+
(merged, schema) => merged.extend(schema.shape),
|
|
47
|
+
zod.z.object({})
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const KafkaPluginConfigSchema = zod.z.object({
|
|
52
|
+
clientId: zod.z.string().default("conduithub-kafka-client"),
|
|
53
|
+
brokers: zod.z.array(zod.z.string()).default(["localhost:9092"]),
|
|
54
|
+
ssl: zod.z.boolean().default(false),
|
|
55
|
+
sasl: zod.z.object({
|
|
56
|
+
mechanism: zod.z.enum([
|
|
57
|
+
"plain",
|
|
58
|
+
"scram-sha-256",
|
|
59
|
+
"scram-sha-512",
|
|
60
|
+
"aws",
|
|
61
|
+
"oauthbearer"
|
|
62
|
+
]),
|
|
63
|
+
username: zod.z.string().optional(),
|
|
64
|
+
password: zod.z.string().optional()
|
|
65
|
+
}).optional(),
|
|
66
|
+
connectionTimeout: zod.z.number().default(3e3),
|
|
67
|
+
requestTimeout: zod.z.number().default(3e4),
|
|
68
|
+
authenticationTimeout: zod.z.number().default(1e3),
|
|
69
|
+
reauthenticationThreshold: zod.z.number().default(1e4),
|
|
70
|
+
enforceRequestTimeout: zod.z.boolean().default(true),
|
|
71
|
+
retry: zod.z.object({
|
|
72
|
+
initialRetryTime: zod.z.number().default(300),
|
|
73
|
+
retries: zod.z.number().default(5),
|
|
74
|
+
maxRetryTime: zod.z.number().default(3e4),
|
|
75
|
+
factor: zod.z.number().default(2),
|
|
76
|
+
multiplier: zod.z.number().default(2)
|
|
77
|
+
}).default(() => ({
|
|
78
|
+
initialRetryTime: 300,
|
|
79
|
+
retries: 5,
|
|
80
|
+
maxRetryTime: 3e4,
|
|
81
|
+
factor: 2,
|
|
82
|
+
multiplier: 2
|
|
83
|
+
})),
|
|
84
|
+
producer: zod.z.object({
|
|
85
|
+
allowAutoTopicCreation: zod.z.boolean().default(true),
|
|
86
|
+
idempotent: zod.z.boolean().default(false),
|
|
87
|
+
maxInFlightRequests: zod.z.number().default(5),
|
|
88
|
+
acks: zod.z.union([zod.z.literal(-1), zod.z.literal(0), zod.z.literal(1)]).default(1),
|
|
89
|
+
compression: zod.z.enum(["none", "gzip", "snappy", "lz4", "zstd"]).default("none"),
|
|
90
|
+
maxBatchSize: zod.z.number().default(1048576),
|
|
91
|
+
linger: zod.z.number().default(0),
|
|
92
|
+
partitioner: zod.z.enum(["random", "murmur2", "murmur2_random", "consistent"]).default("murmur2")
|
|
93
|
+
}).default({
|
|
94
|
+
allowAutoTopicCreation: true,
|
|
95
|
+
idempotent: false,
|
|
96
|
+
maxInFlightRequests: 5,
|
|
97
|
+
acks: 1,
|
|
98
|
+
compression: "none",
|
|
99
|
+
maxBatchSize: 1048576,
|
|
100
|
+
linger: 0,
|
|
101
|
+
partitioner: "murmur2"
|
|
102
|
+
}),
|
|
103
|
+
consumer: zod.z.object({
|
|
104
|
+
groupId: zod.z.string().default("conduithub-kafka-group"),
|
|
105
|
+
groupInstanceId: zod.z.string().optional(),
|
|
106
|
+
sessionTimeout: zod.z.number().default(3e4),
|
|
107
|
+
rebalanceTimeout: zod.z.number().default(6e4),
|
|
108
|
+
heartbeatInterval: zod.z.number().default(3e3),
|
|
109
|
+
maxBytesPerPartition: zod.z.number().default(1048576),
|
|
110
|
+
minBytes: zod.z.number().default(1),
|
|
111
|
+
maxBytes: zod.z.number().default(10485760),
|
|
112
|
+
maxWaitTimeInMs: zod.z.number().default(5e3),
|
|
113
|
+
retryBackoffMs: zod.z.number().default(100),
|
|
114
|
+
autoCommit: zod.z.boolean().default(true),
|
|
115
|
+
autoCommitInterval: zod.z.number().default(5e3),
|
|
116
|
+
autoOffsetReset: zod.z.enum(["earliest", "latest", "none"]).default("latest"),
|
|
117
|
+
allowAutoTopicCreation: zod.z.boolean().default(true),
|
|
118
|
+
maxPollRecords: zod.z.number().default(500),
|
|
119
|
+
maxPollIntervalMs: zod.z.number().default(3e5),
|
|
120
|
+
readUncommitted: zod.z.boolean().default(false)
|
|
121
|
+
}).default({
|
|
122
|
+
groupId: "conduithub-kafka-group",
|
|
123
|
+
sessionTimeout: 3e4,
|
|
124
|
+
rebalanceTimeout: 6e4,
|
|
125
|
+
heartbeatInterval: 3e3,
|
|
126
|
+
maxBytesPerPartition: 1048576,
|
|
127
|
+
minBytes: 1,
|
|
128
|
+
maxBytes: 10485760,
|
|
129
|
+
maxWaitTimeInMs: 5e3,
|
|
130
|
+
retryBackoffMs: 100,
|
|
131
|
+
autoCommit: true,
|
|
132
|
+
autoCommitInterval: 5e3,
|
|
133
|
+
autoOffsetReset: "latest",
|
|
134
|
+
allowAutoTopicCreation: true,
|
|
135
|
+
maxPollRecords: 500,
|
|
136
|
+
maxPollIntervalMs: 3e5,
|
|
137
|
+
readUncommitted: false
|
|
138
|
+
}),
|
|
139
|
+
admin: zod.z.object({
|
|
140
|
+
clientTimeout: zod.z.number().default(3e4),
|
|
141
|
+
requestTimeout: zod.z.number().default(3e4),
|
|
142
|
+
retry: zod.z.object({
|
|
143
|
+
initialRetryTime: zod.z.number().default(300),
|
|
144
|
+
retries: zod.z.number().default(5),
|
|
145
|
+
maxRetryTime: zod.z.number().default(3e4),
|
|
146
|
+
factor: zod.z.number().default(2),
|
|
147
|
+
multiplier: zod.z.number().default(2)
|
|
148
|
+
}).default(() => ({
|
|
149
|
+
initialRetryTime: 300,
|
|
150
|
+
retries: 5,
|
|
151
|
+
maxRetryTime: 3e4,
|
|
152
|
+
factor: 2,
|
|
153
|
+
multiplier: 2
|
|
154
|
+
}))
|
|
155
|
+
}).default(() => ({
|
|
156
|
+
clientTimeout: 3e4,
|
|
157
|
+
requestTimeout: 3e4,
|
|
158
|
+
retry: {
|
|
159
|
+
initialRetryTime: 300,
|
|
160
|
+
retries: 5,
|
|
161
|
+
maxRetryTime: 3e4,
|
|
162
|
+
factor: 2,
|
|
163
|
+
multiplier: 2
|
|
164
|
+
}
|
|
165
|
+
})),
|
|
166
|
+
// Logging controls
|
|
167
|
+
kafkaLogLevel: zod.z.enum(["NOTHING", "ERROR", "WARN", "INFO", "DEBUG"]).default("INFO"),
|
|
168
|
+
verboseLogging: zod.z.boolean().default(false),
|
|
169
|
+
redactSensitiveLogs: zod.z.boolean().default(true),
|
|
170
|
+
topics: zod.z.array(zod.z.string()).default([]),
|
|
171
|
+
autoCreateTopics: zod.z.boolean().default(true),
|
|
172
|
+
defaultTopicPartitions: zod.z.number().default(1),
|
|
173
|
+
defaultTopicReplicationFactor: zod.z.number().default(1)
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
exports.KafkaPluginConfigSchema = KafkaPluginConfigSchema;
|
|
177
|
+
exports.conduithubConfigSchema = conduithubConfigSchema;
|
|
178
|
+
exports.createConfigSchema = createConfigSchema;
|
|
179
|
+
exports.extendConfigSchema = extendConfigSchema;
|
|
180
|
+
exports.mergeConfigSchemas = mergeConfigSchemas;
|
|
181
|
+
exports.redisConfigSchema = redisConfigSchema;
|