@walkeros/server-destination-redis 3.4.0-next-1776749829492
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 +67 -0
- package/dist/dev.d.mts +196 -0
- package/dist/dev.d.ts +196 -0
- package/dist/dev.js +1 -0
- package/dist/dev.js.map +1 -0
- package/dist/dev.mjs +1 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/examples/index.d.mts +144 -0
- package/dist/examples/index.d.ts +144 -0
- package/dist/examples/index.js +146 -0
- package/dist/examples/index.mjs +124 -0
- package/dist/index.d.mts +133 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -0
- package/dist/walkerOS.json +611 -0
- package/package.json +76 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { DestinationServer } from '@walkeros/server-core';
|
|
2
|
+
import { Flow } from '@walkeros/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).
|
|
6
|
+
*/
|
|
7
|
+
type XaddArg = string | number;
|
|
8
|
+
/**
|
|
9
|
+
* Mock-friendly Redis pipeline interface. Accumulates commands and
|
|
10
|
+
* executes them with a single round-trip via exec().
|
|
11
|
+
*/
|
|
12
|
+
interface RedisPipelineMock {
|
|
13
|
+
xadd: (...args: XaddArg[]) => RedisPipelineMock;
|
|
14
|
+
exec: () => Promise<Array<[Error | null, unknown]> | null>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Mock-friendly Redis client interface used by the destination.
|
|
18
|
+
* Tests provide this via env.Redis; production creates a real ioredis
|
|
19
|
+
* client and uses it directly.
|
|
20
|
+
*/
|
|
21
|
+
interface RedisClientMock {
|
|
22
|
+
xadd: (...args: XaddArg[]) => Promise<string | null>;
|
|
23
|
+
pipeline: () => RedisPipelineMock;
|
|
24
|
+
quit: () => Promise<string>;
|
|
25
|
+
on?: (event: string, listener: (...args: unknown[]) => void) => unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Constructor signature for the Redis client. Accepts either a URL
|
|
29
|
+
* string or an options object, matching ioredis's dual signature.
|
|
30
|
+
*/
|
|
31
|
+
interface RedisClientConstructor {
|
|
32
|
+
new (url: string): RedisClientMock;
|
|
33
|
+
new (options: RedisClientOptions): RedisClientMock;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Minimal ioredis options subset the destination passes through.
|
|
37
|
+
* Unknown options are preserved for the SDK to handle.
|
|
38
|
+
*/
|
|
39
|
+
interface RedisClientOptions {
|
|
40
|
+
host?: string;
|
|
41
|
+
port?: number;
|
|
42
|
+
username?: string;
|
|
43
|
+
password?: string;
|
|
44
|
+
db?: number;
|
|
45
|
+
tls?: boolean | Record<string, unknown>;
|
|
46
|
+
connectTimeout?: number;
|
|
47
|
+
commandTimeout?: number;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
type SerializationMode = 'json' | 'flat';
|
|
51
|
+
interface RedisSettings {
|
|
52
|
+
/** Redis stream key name (e.g. 'walkeros:events'). */
|
|
53
|
+
streamKey: string;
|
|
54
|
+
/** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */
|
|
55
|
+
url?: string;
|
|
56
|
+
/** ioredis connection options (used if no url provided). */
|
|
57
|
+
options?: RedisClientOptions;
|
|
58
|
+
/**
|
|
59
|
+
* Maximum stream length. Enables MAXLEN trimming on every XADD.
|
|
60
|
+
* Uses approximate (~) trimming by default for performance.
|
|
61
|
+
* Omit for unlimited stream length.
|
|
62
|
+
*/
|
|
63
|
+
maxLen?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Use exact MAXLEN instead of approximate (~).
|
|
66
|
+
* Not recommended for production -- significantly slower.
|
|
67
|
+
* Default: false (approximate trimming).
|
|
68
|
+
*/
|
|
69
|
+
exactTrimming?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Serialization mode for the event payload.
|
|
72
|
+
* - 'json': Single 'event' field with JSON string (default)
|
|
73
|
+
* - 'flat': Top-level event fields as separate stream fields
|
|
74
|
+
*/
|
|
75
|
+
serialization?: SerializationMode;
|
|
76
|
+
_client?: RedisClientMock;
|
|
77
|
+
_ownedClient?: boolean;
|
|
78
|
+
}
|
|
79
|
+
interface Settings {
|
|
80
|
+
redis: RedisSettings;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Env -- optional Redis SDK override. Production leaves this undefined
|
|
84
|
+
* and the destination creates real ioredis client instances. Tests provide
|
|
85
|
+
* mocks via env.Redis.
|
|
86
|
+
*/
|
|
87
|
+
interface Env extends DestinationServer.Env {
|
|
88
|
+
Redis?: {
|
|
89
|
+
Client: RedisClientConstructor;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
declare const push: Env;
|
|
94
|
+
declare const simulation: string[];
|
|
95
|
+
|
|
96
|
+
declare const env_push: typeof push;
|
|
97
|
+
declare const env_simulation: typeof simulation;
|
|
98
|
+
declare namespace env {
|
|
99
|
+
export { env_push as push, env_simulation as simulation };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Extended step example that may carry destination-level settings overrides.
|
|
104
|
+
*/
|
|
105
|
+
type RedisStepExample = Flow.StepExample & {
|
|
106
|
+
settings?: Partial<Settings>;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Default JSON serialization -- single 'event' field with full event JSON.
|
|
110
|
+
*/
|
|
111
|
+
declare const jsonDefault: RedisStepExample;
|
|
112
|
+
/**
|
|
113
|
+
* Order event -- verifies different event types pass through correctly.
|
|
114
|
+
*/
|
|
115
|
+
declare const orderComplete: RedisStepExample;
|
|
116
|
+
/**
|
|
117
|
+
* With MAXLEN approximate trimming -- trimming args inserted before '*'.
|
|
118
|
+
*/
|
|
119
|
+
declare const withMaxLen: RedisStepExample;
|
|
120
|
+
/**
|
|
121
|
+
* Exact MAXLEN trimming -- no '~' between MAXLEN and the count.
|
|
122
|
+
*/
|
|
123
|
+
declare const withExactTrim: RedisStepExample;
|
|
124
|
+
/**
|
|
125
|
+
* Stream key override per rule -- routes this event to a dedicated stream.
|
|
126
|
+
*/
|
|
127
|
+
declare const streamKeyOverride: RedisStepExample;
|
|
128
|
+
/**
|
|
129
|
+
* Ignored event -- mapping.ignore: true produces no xadd call.
|
|
130
|
+
*/
|
|
131
|
+
declare const ignoredEvent: RedisStepExample;
|
|
132
|
+
|
|
133
|
+
type step_RedisStepExample = RedisStepExample;
|
|
134
|
+
declare const step_ignoredEvent: typeof ignoredEvent;
|
|
135
|
+
declare const step_jsonDefault: typeof jsonDefault;
|
|
136
|
+
declare const step_orderComplete: typeof orderComplete;
|
|
137
|
+
declare const step_streamKeyOverride: typeof streamKeyOverride;
|
|
138
|
+
declare const step_withExactTrim: typeof withExactTrim;
|
|
139
|
+
declare const step_withMaxLen: typeof withMaxLen;
|
|
140
|
+
declare namespace step {
|
|
141
|
+
export { type step_RedisStepExample as RedisStepExample, step_ignoredEvent as ignoredEvent, step_jsonDefault as jsonDefault, step_orderComplete as orderComplete, step_streamKeyOverride as streamKeyOverride, step_withExactTrim as withExactTrim, step_withMaxLen as withMaxLen };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export { env, step };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/examples/index.ts
|
|
21
|
+
var examples_exports = {};
|
|
22
|
+
__export(examples_exports, {
|
|
23
|
+
env: () => env_exports,
|
|
24
|
+
step: () => step_exports
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(examples_exports);
|
|
27
|
+
|
|
28
|
+
// src/examples/env.ts
|
|
29
|
+
var env_exports = {};
|
|
30
|
+
__export(env_exports, {
|
|
31
|
+
push: () => push,
|
|
32
|
+
simulation: () => simulation
|
|
33
|
+
});
|
|
34
|
+
var asyncXadd = () => Promise.resolve("1700000100000-0");
|
|
35
|
+
var asyncQuit = () => Promise.resolve("OK");
|
|
36
|
+
function createMockPipeline() {
|
|
37
|
+
const pipeline = {
|
|
38
|
+
xadd: () => pipeline,
|
|
39
|
+
exec: () => Promise.resolve([])
|
|
40
|
+
};
|
|
41
|
+
return pipeline;
|
|
42
|
+
}
|
|
43
|
+
var MockRedisClient = class {
|
|
44
|
+
constructor(_urlOrOptions) {
|
|
45
|
+
this.xadd = asyncXadd;
|
|
46
|
+
this.quit = asyncQuit;
|
|
47
|
+
}
|
|
48
|
+
pipeline() {
|
|
49
|
+
return createMockPipeline();
|
|
50
|
+
}
|
|
51
|
+
on() {
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var MockRedisConstructor = MockRedisClient;
|
|
56
|
+
var push = {
|
|
57
|
+
Redis: {
|
|
58
|
+
Client: MockRedisConstructor
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var simulation = ["call:client.xadd"];
|
|
62
|
+
|
|
63
|
+
// src/examples/step.ts
|
|
64
|
+
var step_exports = {};
|
|
65
|
+
__export(step_exports, {
|
|
66
|
+
ignoredEvent: () => ignoredEvent,
|
|
67
|
+
jsonDefault: () => jsonDefault,
|
|
68
|
+
orderComplete: () => orderComplete,
|
|
69
|
+
streamKeyOverride: () => streamKeyOverride,
|
|
70
|
+
withExactTrim: () => withExactTrim,
|
|
71
|
+
withMaxLen: () => withMaxLen
|
|
72
|
+
});
|
|
73
|
+
var import_core = require("@walkeros/core");
|
|
74
|
+
var jsonDefault = {
|
|
75
|
+
in: (0, import_core.getEvent)("page view", {
|
|
76
|
+
timestamp: 1700000100
|
|
77
|
+
}),
|
|
78
|
+
out: [["client.xadd", ["walkeros:events", "*", "event", "json:event"]]]
|
|
79
|
+
};
|
|
80
|
+
var orderComplete = {
|
|
81
|
+
in: (0, import_core.getEvent)("order complete", {
|
|
82
|
+
timestamp: 1700000101,
|
|
83
|
+
data: { id: "ORD-400", total: 99.99, currency: "EUR" }
|
|
84
|
+
}),
|
|
85
|
+
out: [["client.xadd", ["walkeros:events", "*", "event", "json:event"]]]
|
|
86
|
+
};
|
|
87
|
+
var withMaxLen = {
|
|
88
|
+
in: (0, import_core.getEvent)("product view", {
|
|
89
|
+
timestamp: 1700000102,
|
|
90
|
+
data: { id: "SKU-123", name: "Widget" }
|
|
91
|
+
}),
|
|
92
|
+
settings: {
|
|
93
|
+
redis: {
|
|
94
|
+
streamKey: "walkeros:events",
|
|
95
|
+
maxLen: 5e4
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
out: [
|
|
99
|
+
[
|
|
100
|
+
"client.xadd",
|
|
101
|
+
["walkeros:events", "MAXLEN", "~", 5e4, "*", "event", "json:event"]
|
|
102
|
+
]
|
|
103
|
+
]
|
|
104
|
+
};
|
|
105
|
+
var withExactTrim = {
|
|
106
|
+
in: (0, import_core.getEvent)("page view", {
|
|
107
|
+
timestamp: 1700000103
|
|
108
|
+
}),
|
|
109
|
+
settings: {
|
|
110
|
+
redis: {
|
|
111
|
+
streamKey: "walkeros:events",
|
|
112
|
+
maxLen: 5e3,
|
|
113
|
+
exactTrimming: true
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
out: [
|
|
117
|
+
[
|
|
118
|
+
"client.xadd",
|
|
119
|
+
["walkeros:events", "MAXLEN", 5e3, "*", "event", "json:event"]
|
|
120
|
+
]
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
var streamKeyOverride = {
|
|
124
|
+
in: (0, import_core.getEvent)("order complete", {
|
|
125
|
+
timestamp: 1700000104,
|
|
126
|
+
data: { id: "ORD-500", total: 42 }
|
|
127
|
+
}),
|
|
128
|
+
mapping: {
|
|
129
|
+
settings: {
|
|
130
|
+
streamKey: "walkeros:orders"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
out: [["client.xadd", ["walkeros:orders", "*", "event", "json:event"]]]
|
|
134
|
+
};
|
|
135
|
+
var ignoredEvent = {
|
|
136
|
+
in: (0, import_core.getEvent)("debug noise", {
|
|
137
|
+
timestamp: 1700000105
|
|
138
|
+
}),
|
|
139
|
+
mapping: { ignore: true },
|
|
140
|
+
out: []
|
|
141
|
+
};
|
|
142
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
143
|
+
0 && (module.exports = {
|
|
144
|
+
env,
|
|
145
|
+
step
|
|
146
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/examples/env.ts
|
|
8
|
+
var env_exports = {};
|
|
9
|
+
__export(env_exports, {
|
|
10
|
+
push: () => push,
|
|
11
|
+
simulation: () => simulation
|
|
12
|
+
});
|
|
13
|
+
var asyncXadd = () => Promise.resolve("1700000100000-0");
|
|
14
|
+
var asyncQuit = () => Promise.resolve("OK");
|
|
15
|
+
function createMockPipeline() {
|
|
16
|
+
const pipeline = {
|
|
17
|
+
xadd: () => pipeline,
|
|
18
|
+
exec: () => Promise.resolve([])
|
|
19
|
+
};
|
|
20
|
+
return pipeline;
|
|
21
|
+
}
|
|
22
|
+
var MockRedisClient = class {
|
|
23
|
+
constructor(_urlOrOptions) {
|
|
24
|
+
this.xadd = asyncXadd;
|
|
25
|
+
this.quit = asyncQuit;
|
|
26
|
+
}
|
|
27
|
+
pipeline() {
|
|
28
|
+
return createMockPipeline();
|
|
29
|
+
}
|
|
30
|
+
on() {
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var MockRedisConstructor = MockRedisClient;
|
|
35
|
+
var push = {
|
|
36
|
+
Redis: {
|
|
37
|
+
Client: MockRedisConstructor
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var simulation = ["call:client.xadd"];
|
|
41
|
+
|
|
42
|
+
// src/examples/step.ts
|
|
43
|
+
var step_exports = {};
|
|
44
|
+
__export(step_exports, {
|
|
45
|
+
ignoredEvent: () => ignoredEvent,
|
|
46
|
+
jsonDefault: () => jsonDefault,
|
|
47
|
+
orderComplete: () => orderComplete,
|
|
48
|
+
streamKeyOverride: () => streamKeyOverride,
|
|
49
|
+
withExactTrim: () => withExactTrim,
|
|
50
|
+
withMaxLen: () => withMaxLen
|
|
51
|
+
});
|
|
52
|
+
import { getEvent } from "@walkeros/core";
|
|
53
|
+
var jsonDefault = {
|
|
54
|
+
in: getEvent("page view", {
|
|
55
|
+
timestamp: 1700000100
|
|
56
|
+
}),
|
|
57
|
+
out: [["client.xadd", ["walkeros:events", "*", "event", "json:event"]]]
|
|
58
|
+
};
|
|
59
|
+
var orderComplete = {
|
|
60
|
+
in: getEvent("order complete", {
|
|
61
|
+
timestamp: 1700000101,
|
|
62
|
+
data: { id: "ORD-400", total: 99.99, currency: "EUR" }
|
|
63
|
+
}),
|
|
64
|
+
out: [["client.xadd", ["walkeros:events", "*", "event", "json:event"]]]
|
|
65
|
+
};
|
|
66
|
+
var withMaxLen = {
|
|
67
|
+
in: getEvent("product view", {
|
|
68
|
+
timestamp: 1700000102,
|
|
69
|
+
data: { id: "SKU-123", name: "Widget" }
|
|
70
|
+
}),
|
|
71
|
+
settings: {
|
|
72
|
+
redis: {
|
|
73
|
+
streamKey: "walkeros:events",
|
|
74
|
+
maxLen: 5e4
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
out: [
|
|
78
|
+
[
|
|
79
|
+
"client.xadd",
|
|
80
|
+
["walkeros:events", "MAXLEN", "~", 5e4, "*", "event", "json:event"]
|
|
81
|
+
]
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
var withExactTrim = {
|
|
85
|
+
in: getEvent("page view", {
|
|
86
|
+
timestamp: 1700000103
|
|
87
|
+
}),
|
|
88
|
+
settings: {
|
|
89
|
+
redis: {
|
|
90
|
+
streamKey: "walkeros:events",
|
|
91
|
+
maxLen: 5e3,
|
|
92
|
+
exactTrimming: true
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
out: [
|
|
96
|
+
[
|
|
97
|
+
"client.xadd",
|
|
98
|
+
["walkeros:events", "MAXLEN", 5e3, "*", "event", "json:event"]
|
|
99
|
+
]
|
|
100
|
+
]
|
|
101
|
+
};
|
|
102
|
+
var streamKeyOverride = {
|
|
103
|
+
in: getEvent("order complete", {
|
|
104
|
+
timestamp: 1700000104,
|
|
105
|
+
data: { id: "ORD-500", total: 42 }
|
|
106
|
+
}),
|
|
107
|
+
mapping: {
|
|
108
|
+
settings: {
|
|
109
|
+
streamKey: "walkeros:orders"
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
out: [["client.xadd", ["walkeros:orders", "*", "event", "json:event"]]]
|
|
113
|
+
};
|
|
114
|
+
var ignoredEvent = {
|
|
115
|
+
in: getEvent("debug noise", {
|
|
116
|
+
timestamp: 1700000105
|
|
117
|
+
}),
|
|
118
|
+
mapping: { ignore: true },
|
|
119
|
+
out: []
|
|
120
|
+
};
|
|
121
|
+
export {
|
|
122
|
+
env_exports as env,
|
|
123
|
+
step_exports as step
|
|
124
|
+
};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Destination as Destination$1 } from '@walkeros/core';
|
|
2
|
+
import { DestinationServer } from '@walkeros/server-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).
|
|
6
|
+
*/
|
|
7
|
+
type XaddArg = string | number;
|
|
8
|
+
/**
|
|
9
|
+
* Mock-friendly Redis pipeline interface. Accumulates commands and
|
|
10
|
+
* executes them with a single round-trip via exec().
|
|
11
|
+
*/
|
|
12
|
+
interface RedisPipelineMock {
|
|
13
|
+
xadd: (...args: XaddArg[]) => RedisPipelineMock;
|
|
14
|
+
exec: () => Promise<Array<[Error | null, unknown]> | null>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Mock-friendly Redis client interface used by the destination.
|
|
18
|
+
* Tests provide this via env.Redis; production creates a real ioredis
|
|
19
|
+
* client and uses it directly.
|
|
20
|
+
*/
|
|
21
|
+
interface RedisClientMock {
|
|
22
|
+
xadd: (...args: XaddArg[]) => Promise<string | null>;
|
|
23
|
+
pipeline: () => RedisPipelineMock;
|
|
24
|
+
quit: () => Promise<string>;
|
|
25
|
+
on?: (event: string, listener: (...args: unknown[]) => void) => unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Constructor signature for the Redis client. Accepts either a URL
|
|
29
|
+
* string or an options object, matching ioredis's dual signature.
|
|
30
|
+
*/
|
|
31
|
+
interface RedisClientConstructor {
|
|
32
|
+
new (url: string): RedisClientMock;
|
|
33
|
+
new (options: RedisClientOptions): RedisClientMock;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Minimal ioredis options subset the destination passes through.
|
|
37
|
+
* Unknown options are preserved for the SDK to handle.
|
|
38
|
+
*/
|
|
39
|
+
interface RedisClientOptions {
|
|
40
|
+
host?: string;
|
|
41
|
+
port?: number;
|
|
42
|
+
username?: string;
|
|
43
|
+
password?: string;
|
|
44
|
+
db?: number;
|
|
45
|
+
tls?: boolean | Record<string, unknown>;
|
|
46
|
+
connectTimeout?: number;
|
|
47
|
+
commandTimeout?: number;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
type SerializationMode = 'json' | 'flat';
|
|
51
|
+
interface RedisSettings {
|
|
52
|
+
/** Redis stream key name (e.g. 'walkeros:events'). */
|
|
53
|
+
streamKey: string;
|
|
54
|
+
/** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */
|
|
55
|
+
url?: string;
|
|
56
|
+
/** ioredis connection options (used if no url provided). */
|
|
57
|
+
options?: RedisClientOptions;
|
|
58
|
+
/**
|
|
59
|
+
* Maximum stream length. Enables MAXLEN trimming on every XADD.
|
|
60
|
+
* Uses approximate (~) trimming by default for performance.
|
|
61
|
+
* Omit for unlimited stream length.
|
|
62
|
+
*/
|
|
63
|
+
maxLen?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Use exact MAXLEN instead of approximate (~).
|
|
66
|
+
* Not recommended for production -- significantly slower.
|
|
67
|
+
* Default: false (approximate trimming).
|
|
68
|
+
*/
|
|
69
|
+
exactTrimming?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Serialization mode for the event payload.
|
|
72
|
+
* - 'json': Single 'event' field with JSON string (default)
|
|
73
|
+
* - 'flat': Top-level event fields as separate stream fields
|
|
74
|
+
*/
|
|
75
|
+
serialization?: SerializationMode;
|
|
76
|
+
_client?: RedisClientMock;
|
|
77
|
+
_ownedClient?: boolean;
|
|
78
|
+
}
|
|
79
|
+
interface Settings {
|
|
80
|
+
redis: RedisSettings;
|
|
81
|
+
}
|
|
82
|
+
type InitSettings = Partial<Settings>;
|
|
83
|
+
interface Mapping {
|
|
84
|
+
/** Override stream key for this rule. */
|
|
85
|
+
streamKey?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Env -- optional Redis SDK override. Production leaves this undefined
|
|
89
|
+
* and the destination creates real ioredis client instances. Tests provide
|
|
90
|
+
* mocks via env.Redis.
|
|
91
|
+
*/
|
|
92
|
+
interface Env extends DestinationServer.Env {
|
|
93
|
+
Redis?: {
|
|
94
|
+
Client: RedisClientConstructor;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
|
|
98
|
+
interface Destination extends DestinationServer.Destination<Types> {
|
|
99
|
+
init: DestinationServer.InitFn<Types>;
|
|
100
|
+
}
|
|
101
|
+
type Config = {
|
|
102
|
+
settings: Settings;
|
|
103
|
+
} & DestinationServer.Config<Types>;
|
|
104
|
+
type InitFn = DestinationServer.InitFn<Types>;
|
|
105
|
+
type PushFn = DestinationServer.PushFn<Types>;
|
|
106
|
+
type PartialConfig = DestinationServer.PartialConfig<Types>;
|
|
107
|
+
type PushEvents = DestinationServer.PushEvents<Mapping>;
|
|
108
|
+
|
|
109
|
+
type index_Config = Config;
|
|
110
|
+
type index_Destination = Destination;
|
|
111
|
+
type index_Env = Env;
|
|
112
|
+
type index_InitFn = InitFn;
|
|
113
|
+
type index_InitSettings = InitSettings;
|
|
114
|
+
type index_Mapping = Mapping;
|
|
115
|
+
type index_PartialConfig = PartialConfig;
|
|
116
|
+
type index_PushEvents = PushEvents;
|
|
117
|
+
type index_PushFn = PushFn;
|
|
118
|
+
type index_RedisClientConstructor = RedisClientConstructor;
|
|
119
|
+
type index_RedisClientMock = RedisClientMock;
|
|
120
|
+
type index_RedisClientOptions = RedisClientOptions;
|
|
121
|
+
type index_RedisPipelineMock = RedisPipelineMock;
|
|
122
|
+
type index_RedisSettings = RedisSettings;
|
|
123
|
+
type index_SerializationMode = SerializationMode;
|
|
124
|
+
type index_Settings = Settings;
|
|
125
|
+
type index_Types = Types;
|
|
126
|
+
type index_XaddArg = XaddArg;
|
|
127
|
+
declare namespace index {
|
|
128
|
+
export type { index_Config as Config, index_Destination as Destination, index_Env as Env, index_InitFn as InitFn, index_InitSettings as InitSettings, index_Mapping as Mapping, index_PartialConfig as PartialConfig, index_PushEvents as PushEvents, index_PushFn as PushFn, index_RedisClientConstructor as RedisClientConstructor, index_RedisClientMock as RedisClientMock, index_RedisClientOptions as RedisClientOptions, index_RedisPipelineMock as RedisPipelineMock, index_RedisSettings as RedisSettings, index_SerializationMode as SerializationMode, index_Settings as Settings, index_Types as Types, index_XaddArg as XaddArg };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
declare const destinationRedis: Destination;
|
|
132
|
+
|
|
133
|
+
export { index as DestinationRedis, destinationRedis as default, destinationRedis };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Destination as Destination$1 } from '@walkeros/core';
|
|
2
|
+
import { DestinationServer } from '@walkeros/server-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).
|
|
6
|
+
*/
|
|
7
|
+
type XaddArg = string | number;
|
|
8
|
+
/**
|
|
9
|
+
* Mock-friendly Redis pipeline interface. Accumulates commands and
|
|
10
|
+
* executes them with a single round-trip via exec().
|
|
11
|
+
*/
|
|
12
|
+
interface RedisPipelineMock {
|
|
13
|
+
xadd: (...args: XaddArg[]) => RedisPipelineMock;
|
|
14
|
+
exec: () => Promise<Array<[Error | null, unknown]> | null>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Mock-friendly Redis client interface used by the destination.
|
|
18
|
+
* Tests provide this via env.Redis; production creates a real ioredis
|
|
19
|
+
* client and uses it directly.
|
|
20
|
+
*/
|
|
21
|
+
interface RedisClientMock {
|
|
22
|
+
xadd: (...args: XaddArg[]) => Promise<string | null>;
|
|
23
|
+
pipeline: () => RedisPipelineMock;
|
|
24
|
+
quit: () => Promise<string>;
|
|
25
|
+
on?: (event: string, listener: (...args: unknown[]) => void) => unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Constructor signature for the Redis client. Accepts either a URL
|
|
29
|
+
* string or an options object, matching ioredis's dual signature.
|
|
30
|
+
*/
|
|
31
|
+
interface RedisClientConstructor {
|
|
32
|
+
new (url: string): RedisClientMock;
|
|
33
|
+
new (options: RedisClientOptions): RedisClientMock;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Minimal ioredis options subset the destination passes through.
|
|
37
|
+
* Unknown options are preserved for the SDK to handle.
|
|
38
|
+
*/
|
|
39
|
+
interface RedisClientOptions {
|
|
40
|
+
host?: string;
|
|
41
|
+
port?: number;
|
|
42
|
+
username?: string;
|
|
43
|
+
password?: string;
|
|
44
|
+
db?: number;
|
|
45
|
+
tls?: boolean | Record<string, unknown>;
|
|
46
|
+
connectTimeout?: number;
|
|
47
|
+
commandTimeout?: number;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
type SerializationMode = 'json' | 'flat';
|
|
51
|
+
interface RedisSettings {
|
|
52
|
+
/** Redis stream key name (e.g. 'walkeros:events'). */
|
|
53
|
+
streamKey: string;
|
|
54
|
+
/** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */
|
|
55
|
+
url?: string;
|
|
56
|
+
/** ioredis connection options (used if no url provided). */
|
|
57
|
+
options?: RedisClientOptions;
|
|
58
|
+
/**
|
|
59
|
+
* Maximum stream length. Enables MAXLEN trimming on every XADD.
|
|
60
|
+
* Uses approximate (~) trimming by default for performance.
|
|
61
|
+
* Omit for unlimited stream length.
|
|
62
|
+
*/
|
|
63
|
+
maxLen?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Use exact MAXLEN instead of approximate (~).
|
|
66
|
+
* Not recommended for production -- significantly slower.
|
|
67
|
+
* Default: false (approximate trimming).
|
|
68
|
+
*/
|
|
69
|
+
exactTrimming?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Serialization mode for the event payload.
|
|
72
|
+
* - 'json': Single 'event' field with JSON string (default)
|
|
73
|
+
* - 'flat': Top-level event fields as separate stream fields
|
|
74
|
+
*/
|
|
75
|
+
serialization?: SerializationMode;
|
|
76
|
+
_client?: RedisClientMock;
|
|
77
|
+
_ownedClient?: boolean;
|
|
78
|
+
}
|
|
79
|
+
interface Settings {
|
|
80
|
+
redis: RedisSettings;
|
|
81
|
+
}
|
|
82
|
+
type InitSettings = Partial<Settings>;
|
|
83
|
+
interface Mapping {
|
|
84
|
+
/** Override stream key for this rule. */
|
|
85
|
+
streamKey?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Env -- optional Redis SDK override. Production leaves this undefined
|
|
89
|
+
* and the destination creates real ioredis client instances. Tests provide
|
|
90
|
+
* mocks via env.Redis.
|
|
91
|
+
*/
|
|
92
|
+
interface Env extends DestinationServer.Env {
|
|
93
|
+
Redis?: {
|
|
94
|
+
Client: RedisClientConstructor;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
|
|
98
|
+
interface Destination extends DestinationServer.Destination<Types> {
|
|
99
|
+
init: DestinationServer.InitFn<Types>;
|
|
100
|
+
}
|
|
101
|
+
type Config = {
|
|
102
|
+
settings: Settings;
|
|
103
|
+
} & DestinationServer.Config<Types>;
|
|
104
|
+
type InitFn = DestinationServer.InitFn<Types>;
|
|
105
|
+
type PushFn = DestinationServer.PushFn<Types>;
|
|
106
|
+
type PartialConfig = DestinationServer.PartialConfig<Types>;
|
|
107
|
+
type PushEvents = DestinationServer.PushEvents<Mapping>;
|
|
108
|
+
|
|
109
|
+
type index_Config = Config;
|
|
110
|
+
type index_Destination = Destination;
|
|
111
|
+
type index_Env = Env;
|
|
112
|
+
type index_InitFn = InitFn;
|
|
113
|
+
type index_InitSettings = InitSettings;
|
|
114
|
+
type index_Mapping = Mapping;
|
|
115
|
+
type index_PartialConfig = PartialConfig;
|
|
116
|
+
type index_PushEvents = PushEvents;
|
|
117
|
+
type index_PushFn = PushFn;
|
|
118
|
+
type index_RedisClientConstructor = RedisClientConstructor;
|
|
119
|
+
type index_RedisClientMock = RedisClientMock;
|
|
120
|
+
type index_RedisClientOptions = RedisClientOptions;
|
|
121
|
+
type index_RedisPipelineMock = RedisPipelineMock;
|
|
122
|
+
type index_RedisSettings = RedisSettings;
|
|
123
|
+
type index_SerializationMode = SerializationMode;
|
|
124
|
+
type index_Settings = Settings;
|
|
125
|
+
type index_Types = Types;
|
|
126
|
+
type index_XaddArg = XaddArg;
|
|
127
|
+
declare namespace index {
|
|
128
|
+
export type { index_Config as Config, index_Destination as Destination, index_Env as Env, index_InitFn as InitFn, index_InitSettings as InitSettings, index_Mapping as Mapping, index_PartialConfig as PartialConfig, index_PushEvents as PushEvents, index_PushFn as PushFn, index_RedisClientConstructor as RedisClientConstructor, index_RedisClientMock as RedisClientMock, index_RedisClientOptions as RedisClientOptions, index_RedisPipelineMock as RedisPipelineMock, index_RedisSettings as RedisSettings, index_SerializationMode as SerializationMode, index_Settings as Settings, index_Types as Types, index_XaddArg as XaddArg };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
declare const destinationRedis: Destination;
|
|
132
|
+
|
|
133
|
+
export { index as DestinationRedis, destinationRedis as default, destinationRedis };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,s={};((e,n)=>{for(var i in n)t(e,i,{get:n[i],enumerable:!0})})(s,{DestinationRedis:()=>u,default:()=>d,destinationRedis:()=>c}),module.exports=(e=s,((e,s,o,l)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let a of i(s))r.call(e,a)||a===o||t(e,a,{get:()=>s[a],enumerable:!(l=n(s,a))||l.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o=require("@walkeros/core");var l=require("@walkeros/core"),a=async function(e,{config:t,rule:n,logger:i}){var r,s;const o=t.settings,a=null==o?void 0:o.redis;if(!a)return void i.warn("Redis settings missing");const u=a._client;if(!u)return void i.warn("Redis client not initialized");const c=null!=(r=null==n?void 0:n.settings)?r:{},d=(0,l.isString)(c.streamKey)?c.streamKey:a.streamKey,f="flat"===(null!=(s=a.serialization)?s:"json")?function(e){const t=[];for(const[n,i]of Object.entries(e))t.push(n,"object"==typeof i&&null!==i?JSON.stringify(i):String(i));return t}(e):["event",JSON.stringify(e)],g=[d];a.maxLen&&(g.push("MAXLEN"),a.exactTrimming||g.push("~"),g.push(a.maxLen)),g.push("*"),g.push(...f),i.debug("Redis XADD",{stream:d});try{const e=await u.xadd(...g);i.debug("Redis XADD complete",{stream:d,entryId:e})}catch(e){i.error("Redis XADD failed",{stream:d,error:e instanceof Error?e.message:String(e)})}};var u={},c={type:"redis",config:{},async init({config:e,logger:t,env:n}){var i,r,s;const l=function(e={},t){var n,i,r;const s=null!=(i=(null!=(n=e.settings)?n:{}).redis)?i:{};s.streamKey||t.throw("Config settings redis.streamKey missing");const o={redis:{...s,streamKey:s.streamKey,serialization:null!=(r=s.serialization)?r:"json"}};return{...e,settings:o}}(e,t),a=l.settings.redis;if(a._client)return l;let u,c;if(function(e){var t;return!!(0,o.isObject)(e)&&"function"==typeof(null==(t=e.Redis)?void 0:t.Client)}(n)){u=null==(i=n.Redis)?void 0:i.Client}if(!u)try{const e=require("ioredis");u=null!=(r=e.default)?r:e.Redis}catch(e){return t.throw(`Failed to load ioredis: ${String(e)}`),l}return u?(c=a.url?new u(a.url):new u(null!=(s=a.options)?s:{}),a._client=c,a._ownedClient=!0,l):(t.throw("ioredis constructor not found"),l)},push:async(e,t)=>await a(e,t),async destroy({config:e}){const t=null==e?void 0:e.settings,n=null==t?void 0:t.redis;if(!n)return;const i=n._client;if(i&&n._ownedClient)try{await i.quit()}finally{n._client=void 0,n._ownedClient=void 0}}},d=c;//# sourceMappingURL=index.js.map
|