@walkeros/server-destination-redis 3.4.2 → 4.0.0-next-1777882869103
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/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/examples/index.js +2 -2
- package/dist/examples/index.mjs +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +20 -83
- package/package.json +4 -4
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,r=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,o=(e,r)=>{for(var s in r)t(e,s,{get:r[s],enumerable:!0})},n={};o(n,{examples:()=>f,schemas:()=>a}),module.exports=(e=n,((e,o,n,a)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let d of s(o))i.call(e,d)||d===n||t(e,d,{get:()=>o[d],enumerable:!(a=r(o,d))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var a={};o(a,{MappingSchema:()=>v,RedisSettingsSchema:()=>m,SettingsSchema:()=>c,mapping:()=>g,settings:()=>u});var d=require("@walkeros/core/dev"),l=require("@walkeros/core/dev"),m=l.z.object({streamKey:l.z.string().min(1).describe("Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD."),url:l.z.string().describe("Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.").optional(),options:l.z.record(l.z.string(),l.z.unknown()).describe("ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.").optional(),maxLen:l.z.number().int().positive().describe("Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).").optional(),exactTrimming:l.z.boolean().describe("Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.").optional(),serialization:l.z.enum(["json","flat"]).describe("Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.").optional()}),c=l.z.object({redis:m.describe("Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })")}),p=require("@walkeros/core/dev"),v=p.z.object({streamKey:p.z.string().optional().describe("Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.")}),u=(0,d.zodToSchema)(c),g=(0,d.zodToSchema)(v),f={};o(f,{env:()=>h,step:()=>y});var h={};o(h,{push:()=>x,simulation:()=>k});var w=()=>Promise.resolve("1700000100000-0"),b=()=>Promise.resolve("OK");var x={Redis:{Client:class{constructor(e){
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,r=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,o=(e,r)=>{for(var s in r)t(e,s,{get:r[s],enumerable:!0})},n={};o(n,{examples:()=>f,schemas:()=>a}),module.exports=(e=n,((e,o,n,a)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let d of s(o))i.call(e,d)||d===n||t(e,d,{get:()=>o[d],enumerable:!(a=r(o,d))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var a={};o(a,{MappingSchema:()=>v,RedisSettingsSchema:()=>m,SettingsSchema:()=>c,mapping:()=>g,settings:()=>u});var d=require("@walkeros/core/dev"),l=require("@walkeros/core/dev"),m=l.z.object({streamKey:l.z.string().min(1).describe("Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD."),url:l.z.string().describe("Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.").optional(),options:l.z.record(l.z.string(),l.z.unknown()).describe("ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.").optional(),maxLen:l.z.number().int().positive().describe("Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).").optional(),exactTrimming:l.z.boolean().describe("Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.").optional(),serialization:l.z.enum(["json","flat"]).describe("Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.").optional()}),c=l.z.object({redis:m.describe("Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })")}),p=require("@walkeros/core/dev"),v=p.z.object({streamKey:p.z.string().optional().describe("Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.")}),u=(0,d.zodToSchema)(c),g=(0,d.zodToSchema)(v),f={};o(f,{env:()=>h,step:()=>y});var h={};o(h,{push:()=>x,simulation:()=>k});var w=()=>Promise.resolve("1700000100000-0"),b=()=>Promise.resolve("OK");var x={Redis:{Client:class{constructor(e){}xadd=w;pipeline(){return function(){const e={xadd:()=>e,exec:()=>Promise.resolve([])};return e}()}quit=b;on(){return this}}}},k=["call:client.xadd"],y={};o(y,{ignoredEvent:()=>S,jsonDefault:()=>j,orderComplete:()=>z,streamKeyOverride:()=>R,withExactTrim:()=>D,withMaxLen:()=>A});var E=require("@walkeros/core"),j={title:"Default stream",description:"An event is appended to the configured Redis stream via XADD with the full event JSON as a single field.",in:(0,E.getEvent)("page view",{timestamp:1700000100}),out:[["client.xadd",["walkeros:events","*","event","json:event"]]]},z={title:"Order event",description:"An order complete event is appended to the Redis stream alongside other event types for downstream consumers.",in:(0,E.getEvent)("order complete",{timestamp:1700000101,data:{id:"ORD-400",total:99.99,currency:"EUR"}}),out:[["client.xadd",["walkeros:events","*","event","json:event"]]]},A={title:"MAXLEN trim",description:"XADD uses approximate MAXLEN trimming to cap the Redis stream length, discarding older entries efficiently.",in:(0,E.getEvent)("product view",{timestamp:1700000102,data:{id:"SKU-123",name:"Widget"}}),settings:{redis:{streamKey:"walkeros:events",maxLen:5e4}},out:[["client.xadd",["walkeros:events","MAXLEN","~",5e4,"*","event","json:event"]]]},D={title:"Exact trim",description:"XADD uses exact MAXLEN trimming to enforce a precise Redis stream length at the cost of extra work.",in:(0,E.getEvent)("page view",{timestamp:1700000103}),settings:{redis:{streamKey:"walkeros:events",maxLen:5e3,exactTrimming:!0}},out:[["client.xadd",["walkeros:events","MAXLEN",5e3,"*","event","json:event"]]]},R={title:"Stream key override",description:"A mapping rule routes the event to a dedicated Redis stream instead of the destination default.",in:(0,E.getEvent)("order complete",{timestamp:1700000104,data:{id:"ORD-500",total:42}}),mapping:{settings:{streamKey:"walkeros:orders"}},out:[["client.xadd",["walkeros:orders","*","event","json:event"]]]},S={public:!1,in:(0,E.getEvent)("debug noise",{timestamp:1700000105}),mapping:{ignore:!0},out:[]};//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, RedisSettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const RedisSettingsSchema = z.object({\n streamKey: z\n .string()\n .min(1)\n .describe(\n \"Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD.\",\n ),\n url: z\n .string()\n .describe(\n \"Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.\",\n )\n .optional(),\n options: z\n .record(z.string(), z.unknown())\n .describe(\n 'ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.',\n )\n .optional(),\n maxLen: z\n .number()\n .int()\n .positive()\n .describe(\n 'Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).',\n )\n .optional(),\n exactTrimming: z\n .boolean()\n .describe(\n 'Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.',\n )\n .optional(),\n serialization: z\n .enum(['json', 'flat'])\n .describe(\n \"Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.\",\n )\n .optional(),\n});\n\nexport const SettingsSchema = z.object({\n redis: RedisSettingsSchema.describe(\n \"Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })\",\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n streamKey: z\n .string()\n .optional()\n .describe(\n 'Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.',\n ),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n RedisClientConstructor,\n RedisClientMock,\n RedisPipelineMock,\n XaddArg,\n} from '../types';\n\n// Narrow helper type aliases so the mock SDK is typed explicitly without `any`.\ntype XaddFn = (...args: XaddArg[]) => Promise<string | null>;\ntype QuitFn = () => Promise<string>;\n\nconst asyncXadd: XaddFn = () => Promise.resolve('1700000100000-0');\nconst asyncQuit: QuitFn = () => Promise.resolve('OK');\n\nfunction createMockPipeline(): RedisPipelineMock {\n const pipeline: RedisPipelineMock = {\n xadd: () => pipeline,\n exec: () => Promise.resolve([]),\n };\n return pipeline;\n}\n\nclass MockRedisClient implements RedisClientMock {\n constructor(_urlOrOptions: string | Record<string, unknown>) {}\n xadd: XaddFn = asyncXadd;\n pipeline(): RedisPipelineMock {\n return createMockPipeline();\n }\n quit: QuitFn = asyncQuit;\n on(): unknown {\n return this;\n }\n}\n\nconst MockRedisConstructor: RedisClientConstructor = MockRedisClient;\n\nexport const push: Env = {\n Redis: {\n Client: MockRedisConstructor,\n },\n};\n\nexport const simulation = ['call:client.xadd'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type RedisStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default JSON serialization -- single 'event' field with full event JSON.\n */\nexport const jsonDefault: RedisStepExample = {\n title: 'Default stream',\n description:\n 'An event is appended to the configured Redis stream via XADD with the full event JSON as a single field.',\n in: getEvent('page view', {\n timestamp: 1700000100,\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * Order event -- verifies different event types pass through correctly.\n */\nexport const orderComplete: RedisStepExample = {\n title: 'Order event',\n description:\n 'An order complete event is appended to the Redis stream alongside other event types for downstream consumers.',\n in: getEvent('order complete', {\n timestamp: 1700000101,\n data: { id: 'ORD-400', total: 99.99, currency: 'EUR' },\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * With MAXLEN approximate trimming -- trimming args inserted before '*'.\n */\nexport const withMaxLen: RedisStepExample = {\n title: 'MAXLEN trim',\n description:\n 'XADD uses approximate MAXLEN trimming to cap the Redis stream length, discarding older entries efficiently.',\n in: getEvent('product view', {\n timestamp: 1700000102,\n data: { id: 'SKU-123', name: 'Widget' },\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 50000,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', '~', 50000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Exact MAXLEN trimming -- no '~' between MAXLEN and the count.\n */\nexport const withExactTrim: RedisStepExample = {\n title: 'Exact trim',\n description:\n 'XADD uses exact MAXLEN trimming to enforce a precise Redis stream length at the cost of extra work.',\n in: getEvent('page view', {\n timestamp: 1700000103,\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 5000,\n exactTrimming: true,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', 5000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Stream key override per rule -- routes this event to a dedicated stream.\n */\nexport const streamKeyOverride: RedisStepExample = {\n title: 'Stream key override',\n description:\n 'A mapping rule routes the event to a dedicated Redis stream instead of the destination default.',\n in: getEvent('order complete', {\n timestamp: 1700000104,\n data: { id: 'ORD-500', total: 42 },\n }),\n mapping: {\n settings: {\n streamKey: 'walkeros:orders',\n },\n },\n out: [['client.xadd', ['walkeros:orders', '*', 'event', 'json:event']]],\n};\n\n/**\n * Ignored event -- mapping.ignore: true produces no xadd call.\n */\nexport const ignoredEvent: RedisStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000105,\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["import_dev","import_dev"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, RedisSettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const RedisSettingsSchema = z.object({\n streamKey: z\n .string()\n .min(1)\n .describe(\n \"Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD.\",\n ),\n url: z\n .string()\n .describe(\n \"Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.\",\n )\n .optional(),\n options: z\n .record(z.string(), z.unknown())\n .describe(\n 'ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.',\n )\n .optional(),\n maxLen: z\n .number()\n .int()\n .positive()\n .describe(\n 'Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).',\n )\n .optional(),\n exactTrimming: z\n .boolean()\n .describe(\n 'Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.',\n )\n .optional(),\n serialization: z\n .enum(['json', 'flat'])\n .describe(\n \"Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.\",\n )\n .optional(),\n});\n\nexport const SettingsSchema = z.object({\n redis: RedisSettingsSchema.describe(\n \"Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })\",\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n streamKey: z\n .string()\n .optional()\n .describe(\n 'Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.',\n ),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n RedisClientConstructor,\n RedisClientMock,\n RedisPipelineMock,\n XaddArg,\n} from '../types';\n\n// Narrow helper type aliases so the mock SDK is typed explicitly without `any`.\ntype XaddFn = (...args: XaddArg[]) => Promise<string | null>;\ntype QuitFn = () => Promise<string>;\n\nconst asyncXadd: XaddFn = () => Promise.resolve('1700000100000-0');\nconst asyncQuit: QuitFn = () => Promise.resolve('OK');\n\nfunction createMockPipeline(): RedisPipelineMock {\n const pipeline: RedisPipelineMock = {\n xadd: () => pipeline,\n exec: () => Promise.resolve([]),\n };\n return pipeline;\n}\n\nclass MockRedisClient implements RedisClientMock {\n constructor(_urlOrOptions: string | Record<string, unknown>) {}\n xadd: XaddFn = asyncXadd;\n pipeline(): RedisPipelineMock {\n return createMockPipeline();\n }\n quit: QuitFn = asyncQuit;\n on(): unknown {\n return this;\n }\n}\n\nconst MockRedisConstructor: RedisClientConstructor = MockRedisClient;\n\nexport const push: Env = {\n Redis: {\n Client: MockRedisConstructor,\n },\n};\n\nexport const simulation = ['call:client.xadd'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type RedisStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default JSON serialization -- single 'event' field with full event JSON.\n */\nexport const jsonDefault: RedisStepExample = {\n title: 'Default stream',\n description:\n 'An event is appended to the configured Redis stream via XADD with the full event JSON as a single field.',\n in: getEvent('page view', {\n timestamp: 1700000100,\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * Order event -- verifies different event types pass through correctly.\n */\nexport const orderComplete: RedisStepExample = {\n title: 'Order event',\n description:\n 'An order complete event is appended to the Redis stream alongside other event types for downstream consumers.',\n in: getEvent('order complete', {\n timestamp: 1700000101,\n data: { id: 'ORD-400', total: 99.99, currency: 'EUR' },\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * With MAXLEN approximate trimming -- trimming args inserted before '*'.\n */\nexport const withMaxLen: RedisStepExample = {\n title: 'MAXLEN trim',\n description:\n 'XADD uses approximate MAXLEN trimming to cap the Redis stream length, discarding older entries efficiently.',\n in: getEvent('product view', {\n timestamp: 1700000102,\n data: { id: 'SKU-123', name: 'Widget' },\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 50000,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', '~', 50000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Exact MAXLEN trimming -- no '~' between MAXLEN and the count.\n */\nexport const withExactTrim: RedisStepExample = {\n title: 'Exact trim',\n description:\n 'XADD uses exact MAXLEN trimming to enforce a precise Redis stream length at the cost of extra work.',\n in: getEvent('page view', {\n timestamp: 1700000103,\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 5000,\n exactTrimming: true,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', 5000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Stream key override per rule -- routes this event to a dedicated stream.\n */\nexport const streamKeyOverride: RedisStepExample = {\n title: 'Stream key override',\n description:\n 'A mapping rule routes the event to a dedicated Redis stream instead of the destination default.',\n in: getEvent('order complete', {\n timestamp: 1700000104,\n data: { id: 'ORD-500', total: 42 },\n }),\n mapping: {\n settings: {\n streamKey: 'walkeros:orders',\n },\n },\n out: [['client.xadd', ['walkeros:orders', '*', 'event', 'json:event']]],\n};\n\n/**\n * Ignored event -- mapping.ignore: true produces no xadd call.\n */\nexport const ignoredEvent: RedisStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000105,\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["import_dev","import_dev"]}
|
package/dist/dev.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,t=(t,s)=>{for(var i in s)e(t,i,{get:s[i],enumerable:!0})},s={};t(s,{MappingSchema:()=>d,RedisSettingsSchema:()=>o,SettingsSchema:()=>n,mapping:()=>m,settings:()=>l});import{zodToSchema as i}from"@walkeros/core/dev";import{z as r}from"@walkeros/core/dev";var o=r.object({streamKey:r.string().min(1).describe("Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD."),url:r.string().describe("Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.").optional(),options:r.record(r.string(),r.unknown()).describe("ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.").optional(),maxLen:r.number().int().positive().describe("Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).").optional(),exactTrimming:r.boolean().describe("Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.").optional(),serialization:r.enum(["json","flat"]).describe("Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.").optional()}),n=r.object({redis:o.describe("Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })")});import{z as a}from"@walkeros/core/dev";var d=a.object({streamKey:a.string().optional().describe("Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.")}),l=i(n),m=i(d),p={};t(p,{env:()=>c,step:()=>h});var c={};t(c,{push:()=>g,simulation:()=>f});var v=()=>Promise.resolve("1700000100000-0"),u=()=>Promise.resolve("OK");var g={Redis:{Client:class{constructor(e){
|
|
1
|
+
var e=Object.defineProperty,t=(t,s)=>{for(var i in s)e(t,i,{get:s[i],enumerable:!0})},s={};t(s,{MappingSchema:()=>d,RedisSettingsSchema:()=>o,SettingsSchema:()=>n,mapping:()=>m,settings:()=>l});import{zodToSchema as i}from"@walkeros/core/dev";import{z as r}from"@walkeros/core/dev";var o=r.object({streamKey:r.string().min(1).describe("Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD."),url:r.string().describe("Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.").optional(),options:r.record(r.string(),r.unknown()).describe("ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.").optional(),maxLen:r.number().int().positive().describe("Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).").optional(),exactTrimming:r.boolean().describe("Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.").optional(),serialization:r.enum(["json","flat"]).describe("Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.").optional()}),n=r.object({redis:o.describe("Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })")});import{z as a}from"@walkeros/core/dev";var d=a.object({streamKey:a.string().optional().describe("Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.")}),l=i(n),m=i(d),p={};t(p,{env:()=>c,step:()=>h});var c={};t(c,{push:()=>g,simulation:()=>f});var v=()=>Promise.resolve("1700000100000-0"),u=()=>Promise.resolve("OK");var g={Redis:{Client:class{constructor(e){}xadd=v;pipeline(){return function(){const e={xadd:()=>e,exec:()=>Promise.resolve([])};return e}()}quit=u;on(){return this}}}},f=["call:client.xadd"],h={};t(h,{ignoredEvent:()=>D,jsonDefault:()=>x,orderComplete:()=>k,streamKeyOverride:()=>A,withExactTrim:()=>y,withMaxLen:()=>b});import{getEvent as w}from"@walkeros/core";var x={title:"Default stream",description:"An event is appended to the configured Redis stream via XADD with the full event JSON as a single field.",in:w("page view",{timestamp:1700000100}),out:[["client.xadd",["walkeros:events","*","event","json:event"]]]},k={title:"Order event",description:"An order complete event is appended to the Redis stream alongside other event types for downstream consumers.",in:w("order complete",{timestamp:1700000101,data:{id:"ORD-400",total:99.99,currency:"EUR"}}),out:[["client.xadd",["walkeros:events","*","event","json:event"]]]},b={title:"MAXLEN trim",description:"XADD uses approximate MAXLEN trimming to cap the Redis stream length, discarding older entries efficiently.",in:w("product view",{timestamp:1700000102,data:{id:"SKU-123",name:"Widget"}}),settings:{redis:{streamKey:"walkeros:events",maxLen:5e4}},out:[["client.xadd",["walkeros:events","MAXLEN","~",5e4,"*","event","json:event"]]]},y={title:"Exact trim",description:"XADD uses exact MAXLEN trimming to enforce a precise Redis stream length at the cost of extra work.",in:w("page view",{timestamp:1700000103}),settings:{redis:{streamKey:"walkeros:events",maxLen:5e3,exactTrimming:!0}},out:[["client.xadd",["walkeros:events","MAXLEN",5e3,"*","event","json:event"]]]},A={title:"Stream key override",description:"A mapping rule routes the event to a dedicated Redis stream instead of the destination default.",in:w("order complete",{timestamp:1700000104,data:{id:"ORD-500",total:42}}),mapping:{settings:{streamKey:"walkeros:orders"}},out:[["client.xadd",["walkeros:orders","*","event","json:event"]]]},D={public:!1,in:w("debug noise",{timestamp:1700000105}),mapping:{ignore:!0},out:[]};export{p as examples,s as schemas};//# sourceMappingURL=dev.mjs.map
|
package/dist/dev.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, RedisSettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const RedisSettingsSchema = z.object({\n streamKey: z\n .string()\n .min(1)\n .describe(\n \"Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD.\",\n ),\n url: z\n .string()\n .describe(\n \"Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.\",\n )\n .optional(),\n options: z\n .record(z.string(), z.unknown())\n .describe(\n 'ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.',\n )\n .optional(),\n maxLen: z\n .number()\n .int()\n .positive()\n .describe(\n 'Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).',\n )\n .optional(),\n exactTrimming: z\n .boolean()\n .describe(\n 'Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.',\n )\n .optional(),\n serialization: z\n .enum(['json', 'flat'])\n .describe(\n \"Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.\",\n )\n .optional(),\n});\n\nexport const SettingsSchema = z.object({\n redis: RedisSettingsSchema.describe(\n \"Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })\",\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n streamKey: z\n .string()\n .optional()\n .describe(\n 'Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.',\n ),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n RedisClientConstructor,\n RedisClientMock,\n RedisPipelineMock,\n XaddArg,\n} from '../types';\n\n// Narrow helper type aliases so the mock SDK is typed explicitly without `any`.\ntype XaddFn = (...args: XaddArg[]) => Promise<string | null>;\ntype QuitFn = () => Promise<string>;\n\nconst asyncXadd: XaddFn = () => Promise.resolve('1700000100000-0');\nconst asyncQuit: QuitFn = () => Promise.resolve('OK');\n\nfunction createMockPipeline(): RedisPipelineMock {\n const pipeline: RedisPipelineMock = {\n xadd: () => pipeline,\n exec: () => Promise.resolve([]),\n };\n return pipeline;\n}\n\nclass MockRedisClient implements RedisClientMock {\n constructor(_urlOrOptions: string | Record<string, unknown>) {}\n xadd: XaddFn = asyncXadd;\n pipeline(): RedisPipelineMock {\n return createMockPipeline();\n }\n quit: QuitFn = asyncQuit;\n on(): unknown {\n return this;\n }\n}\n\nconst MockRedisConstructor: RedisClientConstructor = MockRedisClient;\n\nexport const push: Env = {\n Redis: {\n Client: MockRedisConstructor,\n },\n};\n\nexport const simulation = ['call:client.xadd'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type RedisStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default JSON serialization -- single 'event' field with full event JSON.\n */\nexport const jsonDefault: RedisStepExample = {\n title: 'Default stream',\n description:\n 'An event is appended to the configured Redis stream via XADD with the full event JSON as a single field.',\n in: getEvent('page view', {\n timestamp: 1700000100,\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * Order event -- verifies different event types pass through correctly.\n */\nexport const orderComplete: RedisStepExample = {\n title: 'Order event',\n description:\n 'An order complete event is appended to the Redis stream alongside other event types for downstream consumers.',\n in: getEvent('order complete', {\n timestamp: 1700000101,\n data: { id: 'ORD-400', total: 99.99, currency: 'EUR' },\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * With MAXLEN approximate trimming -- trimming args inserted before '*'.\n */\nexport const withMaxLen: RedisStepExample = {\n title: 'MAXLEN trim',\n description:\n 'XADD uses approximate MAXLEN trimming to cap the Redis stream length, discarding older entries efficiently.',\n in: getEvent('product view', {\n timestamp: 1700000102,\n data: { id: 'SKU-123', name: 'Widget' },\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 50000,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', '~', 50000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Exact MAXLEN trimming -- no '~' between MAXLEN and the count.\n */\nexport const withExactTrim: RedisStepExample = {\n title: 'Exact trim',\n description:\n 'XADD uses exact MAXLEN trimming to enforce a precise Redis stream length at the cost of extra work.',\n in: getEvent('page view', {\n timestamp: 1700000103,\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 5000,\n exactTrimming: true,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', 5000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Stream key override per rule -- routes this event to a dedicated stream.\n */\nexport const streamKeyOverride: RedisStepExample = {\n title: 'Stream key override',\n description:\n 'A mapping rule routes the event to a dedicated Redis stream instead of the destination default.',\n in: getEvent('order complete', {\n timestamp: 1700000104,\n data: { id: 'ORD-500', total: 42 },\n }),\n mapping: {\n settings: {\n streamKey: 'walkeros:orders',\n },\n },\n out: [['client.xadd', ['walkeros:orders', '*', 'event', 'json:event']]],\n};\n\n/**\n * Ignored event -- mapping.ignore: true produces no xadd call.\n */\nexport const ignoredEvent: RedisStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000105,\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["z"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, RedisSettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const RedisSettingsSchema = z.object({\n streamKey: z\n .string()\n .min(1)\n .describe(\n \"Redis stream key name (like 'walkeros:events'). All events are appended to this stream via XADD.\",\n ),\n url: z\n .string()\n .describe(\n \"Redis connection URL (like 'redis://localhost:6379' or 'rediss://:password@host:6380'). Supports redis:// and rediss:// (TLS) protocols.\",\n )\n .optional(),\n options: z\n .record(z.string(), z.unknown())\n .describe(\n 'ioredis connection options. Used when url is not provided. Supports host, port, password, db, tls, and all other ioredis options.',\n )\n .optional(),\n maxLen: z\n .number()\n .int()\n .positive()\n .describe(\n 'Maximum stream length. Enables approximate MAXLEN trimming on every XADD to bound memory usage (like 50000).',\n )\n .optional(),\n exactTrimming: z\n .boolean()\n .describe(\n 'Use exact MAXLEN instead of approximate (~). Not recommended for production. Default: false.',\n )\n .optional(),\n serialization: z\n .enum(['json', 'flat'])\n .describe(\n \"Serialization mode. 'json' stores the full event as a single 'event' field (default). 'flat' stores top-level event fields as separate stream entry fields.\",\n )\n .optional(),\n});\n\nexport const SettingsSchema = z.object({\n redis: RedisSettingsSchema.describe(\n \"Redis Streams configuration (like { streamKey: 'walkeros:events', url: 'redis://localhost:6379' })\",\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n streamKey: z\n .string()\n .optional()\n .describe(\n 'Override Redis stream key for this rule. Takes precedence over settings.redis.streamKey.',\n ),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n RedisClientConstructor,\n RedisClientMock,\n RedisPipelineMock,\n XaddArg,\n} from '../types';\n\n// Narrow helper type aliases so the mock SDK is typed explicitly without `any`.\ntype XaddFn = (...args: XaddArg[]) => Promise<string | null>;\ntype QuitFn = () => Promise<string>;\n\nconst asyncXadd: XaddFn = () => Promise.resolve('1700000100000-0');\nconst asyncQuit: QuitFn = () => Promise.resolve('OK');\n\nfunction createMockPipeline(): RedisPipelineMock {\n const pipeline: RedisPipelineMock = {\n xadd: () => pipeline,\n exec: () => Promise.resolve([]),\n };\n return pipeline;\n}\n\nclass MockRedisClient implements RedisClientMock {\n constructor(_urlOrOptions: string | Record<string, unknown>) {}\n xadd: XaddFn = asyncXadd;\n pipeline(): RedisPipelineMock {\n return createMockPipeline();\n }\n quit: QuitFn = asyncQuit;\n on(): unknown {\n return this;\n }\n}\n\nconst MockRedisConstructor: RedisClientConstructor = MockRedisClient;\n\nexport const push: Env = {\n Redis: {\n Client: MockRedisConstructor,\n },\n};\n\nexport const simulation = ['call:client.xadd'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type RedisStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default JSON serialization -- single 'event' field with full event JSON.\n */\nexport const jsonDefault: RedisStepExample = {\n title: 'Default stream',\n description:\n 'An event is appended to the configured Redis stream via XADD with the full event JSON as a single field.',\n in: getEvent('page view', {\n timestamp: 1700000100,\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * Order event -- verifies different event types pass through correctly.\n */\nexport const orderComplete: RedisStepExample = {\n title: 'Order event',\n description:\n 'An order complete event is appended to the Redis stream alongside other event types for downstream consumers.',\n in: getEvent('order complete', {\n timestamp: 1700000101,\n data: { id: 'ORD-400', total: 99.99, currency: 'EUR' },\n }),\n out: [['client.xadd', ['walkeros:events', '*', 'event', 'json:event']]],\n};\n\n/**\n * With MAXLEN approximate trimming -- trimming args inserted before '*'.\n */\nexport const withMaxLen: RedisStepExample = {\n title: 'MAXLEN trim',\n description:\n 'XADD uses approximate MAXLEN trimming to cap the Redis stream length, discarding older entries efficiently.',\n in: getEvent('product view', {\n timestamp: 1700000102,\n data: { id: 'SKU-123', name: 'Widget' },\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 50000,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', '~', 50000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Exact MAXLEN trimming -- no '~' between MAXLEN and the count.\n */\nexport const withExactTrim: RedisStepExample = {\n title: 'Exact trim',\n description:\n 'XADD uses exact MAXLEN trimming to enforce a precise Redis stream length at the cost of extra work.',\n in: getEvent('page view', {\n timestamp: 1700000103,\n }),\n settings: {\n redis: {\n streamKey: 'walkeros:events',\n maxLen: 5000,\n exactTrimming: true,\n },\n },\n out: [\n [\n 'client.xadd',\n ['walkeros:events', 'MAXLEN', 5000, '*', 'event', 'json:event'],\n ],\n ],\n};\n\n/**\n * Stream key override per rule -- routes this event to a dedicated stream.\n */\nexport const streamKeyOverride: RedisStepExample = {\n title: 'Stream key override',\n description:\n 'A mapping rule routes the event to a dedicated Redis stream instead of the destination default.',\n in: getEvent('order complete', {\n timestamp: 1700000104,\n data: { id: 'ORD-500', total: 42 },\n }),\n mapping: {\n settings: {\n streamKey: 'walkeros:orders',\n },\n },\n out: [['client.xadd', ['walkeros:orders', '*', 'event', 'json:event']]],\n};\n\n/**\n * Ignored event -- mapping.ignore: true produces no xadd call.\n */\nexport const ignoredEvent: RedisStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000105,\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,SAAS;AAEX,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,WAAW,EACR,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,KAAK,EACF,OAAO,EACP;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,SAAS,EACN,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAC9B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,QAAQ,EACL,OAAO,EACP,IAAI,EACJ,SAAS,EACT;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAe,EACZ,QAAQ,EACR;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAe,EACZ,KAAK,CAAC,QAAQ,MAAM,CAAC,EACrB;AAAA,IACC;AAAA,EACF,EACC,SAAS;AACd,CAAC;AAEM,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,OAAO,oBAAoB;AAAA,IACzB;AAAA,EACF;AACF,CAAC;;;AC/CD,SAAS,KAAAA,UAAS;AAEX,IAAM,gBAAgBA,GAAE,OAAO;AAAA,EACpC,WAAWA,GACR,OAAO,EACP,SAAS,EACT;AAAA,IACC;AAAA,EACF;AACJ,CAAC;;;AFDM,IAAM,WAAW,YAAY,cAAc;AAC3C,IAAM,UAAU,YAAY,aAAa;;;AGThD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAYA,IAAM,YAAoB,MAAM,QAAQ,QAAQ,iBAAiB;AACjE,IAAM,YAAoB,MAAM,QAAQ,QAAQ,IAAI;AAEpD,SAAS,qBAAwC;AAC/C,QAAM,WAA8B;AAAA,IAClC,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAChC;AACA,SAAO;AACT;AAEA,IAAM,kBAAN,MAAiD;AAAA,EAC/C,YAAY,eAAiD;AAAA,EAAC;AAAA,EAC9D,OAAe;AAAA,EACf,WAA8B;AAC5B,WAAO,mBAAmB;AAAA,EAC5B;AAAA,EACA,OAAe;AAAA,EACf,KAAc;AACZ,WAAO;AAAA,EACT;AACF;AAEA,IAAM,uBAA+C;AAE9C,IAAM,OAAY;AAAA,EACvB,OAAO;AAAA,IACL,QAAQ;AAAA,EACV;AACF;AAEO,IAAM,aAAa,CAAC,kBAAkB;;;AC3C7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,SAAS,gBAAgB;AAalB,IAAM,cAAgC;AAAA,EAC3C,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,aAAa;AAAA,IACxB,WAAW;AAAA,EACb,CAAC;AAAA,EACD,KAAK,CAAC,CAAC,eAAe,CAAC,mBAAmB,KAAK,SAAS,YAAY,CAAC,CAAC;AACxE;AAKO,IAAM,gBAAkC;AAAA,EAC7C,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,kBAAkB;AAAA,IAC7B,WAAW;AAAA,IACX,MAAM,EAAE,IAAI,WAAW,OAAO,OAAO,UAAU,MAAM;AAAA,EACvD,CAAC;AAAA,EACD,KAAK,CAAC,CAAC,eAAe,CAAC,mBAAmB,KAAK,SAAS,YAAY,CAAC,CAAC;AACxE;AAKO,IAAM,aAA+B;AAAA,EAC1C,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,gBAAgB;AAAA,IAC3B,WAAW;AAAA,IACX,MAAM,EAAE,IAAI,WAAW,MAAM,SAAS;AAAA,EACxC,CAAC;AAAA,EACD,UAAU;AAAA,IACR,OAAO;AAAA,MACL,WAAW;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA,CAAC,mBAAmB,UAAU,KAAK,KAAO,KAAK,SAAS,YAAY;AAAA,IACtE;AAAA,EACF;AACF;AAKO,IAAM,gBAAkC;AAAA,EAC7C,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,aAAa;AAAA,IACxB,WAAW;AAAA,EACb,CAAC;AAAA,EACD,UAAU;AAAA,IACR,OAAO;AAAA,MACL,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA,CAAC,mBAAmB,UAAU,KAAM,KAAK,SAAS,YAAY;AAAA,IAChE;AAAA,EACF;AACF;AAKO,IAAM,oBAAsC;AAAA,EACjD,OAAO;AAAA,EACP,aACE;AAAA,EACF,IAAI,SAAS,kBAAkB;AAAA,IAC7B,WAAW;AAAA,IACX,MAAM,EAAE,IAAI,WAAW,OAAO,GAAG;AAAA,EACnC,CAAC;AAAA,EACD,SAAS;AAAA,IACP,UAAU;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,KAAK,CAAC,CAAC,eAAe,CAAC,mBAAmB,KAAK,SAAS,YAAY,CAAC,CAAC;AACxE;AAKO,IAAM,eAAiC;AAAA,EAC5C,QAAQ;AAAA,EACR,IAAI,SAAS,eAAe;AAAA,IAC1B,WAAW;AAAA,EACb,CAAC;AAAA,EACD,SAAS,EAAE,QAAQ,KAAK;AAAA,EACxB,KAAK,CAAC;AACR;","names":["z"]}
|
package/dist/examples/index.js
CHANGED
|
@@ -42,12 +42,12 @@ function createMockPipeline() {
|
|
|
42
42
|
}
|
|
43
43
|
var MockRedisClient = class {
|
|
44
44
|
constructor(_urlOrOptions) {
|
|
45
|
-
this.xadd = asyncXadd;
|
|
46
|
-
this.quit = asyncQuit;
|
|
47
45
|
}
|
|
46
|
+
xadd = asyncXadd;
|
|
48
47
|
pipeline() {
|
|
49
48
|
return createMockPipeline();
|
|
50
49
|
}
|
|
50
|
+
quit = asyncQuit;
|
|
51
51
|
on() {
|
|
52
52
|
return this;
|
|
53
53
|
}
|
package/dist/examples/index.mjs
CHANGED
|
@@ -21,12 +21,12 @@ function createMockPipeline() {
|
|
|
21
21
|
}
|
|
22
22
|
var MockRedisClient = class {
|
|
23
23
|
constructor(_urlOrOptions) {
|
|
24
|
-
this.xadd = asyncXadd;
|
|
25
|
-
this.quit = asyncQuit;
|
|
26
24
|
}
|
|
25
|
+
xadd = asyncXadd;
|
|
27
26
|
pipeline() {
|
|
28
27
|
return createMockPipeline();
|
|
29
28
|
}
|
|
29
|
+
quit = asyncQuit;
|
|
30
30
|
on() {
|
|
31
31
|
return this;
|
|
32
32
|
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,s={};((e,i)=>{for(var n in i)t(e,n,{get:i[n],enumerable:!0})})(s,{DestinationRedis:()=>u,default:()=>l,destinationRedis:()=>d}),module.exports=(e=s,((e,s,o,a)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let c of n(s))r.call(e,c)||c===o||t(e,c,{get:()=>s[c],enumerable:!(a=i(s,c))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o=require("@walkeros/core");var a=require("@walkeros/core"),c=async function(e,{config:t,rule:i,logger:n}){const r=t.settings,s=r?.redis;if(!s)return void n.warn("Redis settings missing");const o=s._client;if(!o)return void n.warn("Redis client not initialized");const c=i?.settings??{},u=(0,a.isString)(c.streamKey)?c.streamKey:s.streamKey,d="flat"===(s.serialization??"json")?function(e){const t=[];for(const[i,n]of Object.entries(e))t.push(i,"object"==typeof n&&null!==n?JSON.stringify(n):String(n));return t}(e):["event",JSON.stringify(e)],l=[u];s.maxLen&&(l.push("MAXLEN"),s.exactTrimming||l.push("~"),l.push(s.maxLen)),l.push("*"),l.push(...d),n.debug("Redis XADD",{stream:u});try{const e=await o.xadd(...l);n.debug("Redis XADD complete",{stream:u,entryId:e})}catch(e){n.error("Redis XADD failed",{stream:u,error:e instanceof Error?e.message:String(e)})}};var u={},d={type:"redis",config:{},async init({config:e,logger:t,env:i}){const n=function(e={},t){const i=(e.settings??{}).redis??{};i.streamKey||t.throw("Config settings redis.streamKey missing");const n={redis:{...i,streamKey:i.streamKey,serialization:i.serialization??"json"}};return{...e,settings:n}}(e,t),r=n.settings.redis;if(r._client)return n;let s,a;if(function(e){if(!(0,o.isObject)(e))return!1;const t=e;return"function"==typeof t.Redis?.Client}(i)){const e=i;s=e.Redis?.Client}if(!s)try{const e=require("ioredis");s=e.default??e.Redis}catch(e){return t.throw(`Failed to load ioredis: ${String(e)}`),n}return s?(a=r.url?new s(r.url):new s(r.options??{}),r._client=a,r._ownedClient=!0,n):(t.throw("ioredis constructor not found"),n)},push:async(e,t)=>await c(e,t),async destroy({config:e}){const t=e?.settings,i=t?.redis;if(!i)return;const n=i._client;if(n&&i._ownedClient)try{await n.quit()}finally{i._client=void 0,i._ownedClient=void 0}}},l=d;//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Destination,\n Settings,\n Env,\n RedisClientMock,\n RedisClientConstructor,\n RedisClientOptions,\n} from './types';\nimport { getConfig, isRedisEnv } from './config';\nimport { push } from './push';\n\n// Types re-export\nexport * as DestinationRedis from './types';\n\nexport const destinationRedis: Destination = {\n type: 'redis',\n\n config: {},\n\n async init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n const redis = settings.redis;\n\n // Skip creation if a client has already been wired in (testing).\n if (redis._client) return config;\n\n let Constructor: RedisClientConstructor | undefined;\n\n // Prefer env-injected constructor (testing, dependency injection).\n if (isRedisEnv(env)) {\n const envTyped = env as Env;\n Constructor = envTyped.Redis?.Client;\n }\n\n // Production path: load real ioredis SDK.\n if (!Constructor) {\n try {\n // Use dynamic require to allow tests to mock via jest.mock('ioredis').\n const ioredis = require('ioredis') as {\n default?: RedisClientConstructor;\n Redis?: RedisClientConstructor;\n };\n // ioredis exports the class as default (ESM) and as named Redis export.\n Constructor = ioredis.default ?? ioredis.Redis;\n } catch (err) {\n logger.throw(`Failed to load ioredis: ${String(err)}`);\n return config;\n }\n }\n\n if (!Constructor) {\n logger.throw('ioredis constructor not found');\n return config;\n }\n\n let client: RedisClientMock;\n if (redis.url) {\n client = new Constructor(redis.url);\n } else {\n client = new Constructor(redis.options ?? ({} as RedisClientOptions));\n }\n\n redis._client = client;\n redis._ownedClient = true;\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const settings = config?.settings as Settings | undefined;\n const redis = settings?.redis;\n if (!redis) return;\n\n const client = redis._client;\n // Only close clients the destination created (not user-provided)\n if (client && redis._ownedClient) {\n try {\n await client.quit();\n } finally {\n redis._client = undefined;\n redis._ownedClient = undefined;\n }\n }\n },\n};\n\nexport default destinationRedis;\n","import type {\n Config,\n Settings,\n RedisSettings,\n PartialConfig,\n Env,\n} from './types';\nimport type { Logger } from '@walkeros/core';\nimport { isObject } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const raw = (partialConfig.settings ?? {}) as Partial<Settings>;\n const redis: Partial<RedisSettings> =\n raw.redis ?? ({} as Partial<RedisSettings>);\n\n if (!redis.streamKey) {\n logger.throw('Config settings redis.streamKey missing');\n }\n\n const redisSettings: RedisSettings = {\n ...redis,\n streamKey: redis.streamKey as string,\n serialization: redis.serialization ?? 'json',\n };\n\n const settings: Settings = { redis: redisSettings };\n\n return { ...partialConfig, settings };\n}\n\nexport function isRedisEnv(env: unknown): env is Env {\n if (!isObject(env)) return false;\n const maybe = env as { Redis?: { Client?: unknown } };\n return typeof maybe.Redis?.Client === 'function';\n}\n","import type {\n PushFn,\n RedisSettings,\n RedisClientMock,\n XaddArg,\n SerializationMode,\n} from './types';\nimport { isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (event, { config, rule, logger }) {\n const settings = config.settings as { redis?: RedisSettings } | undefined;\n const redis: RedisSettings | undefined = settings?.redis;\n\n if (!redis) {\n logger.warn('Redis settings missing');\n return;\n }\n\n const client = redis._client;\n if (!client) {\n logger.warn('Redis client not initialized');\n return;\n }\n\n // Derive stream key: rule override -> destination default\n const ruleSettings = rule?.settings ?? {};\n const streamKey = isString(ruleSettings.streamKey)\n ? ruleSettings.streamKey\n : redis.streamKey;\n\n const serialization: SerializationMode = redis.serialization ?? 'json';\n\n // Serialize event\n const fields: string[] =\n serialization === 'flat'\n ? flattenEvent(event as unknown as Record<string, unknown>)\n : ['event', JSON.stringify(event)];\n\n // Build XADD arguments\n const args: XaddArg[] = [streamKey];\n\n // Optional MAXLEN trimming\n if (redis.maxLen) {\n args.push('MAXLEN');\n if (!redis.exactTrimming) args.push('~');\n args.push(redis.maxLen);\n }\n\n args.push('*'); // Auto-generate entry ID\n args.push(...fields); // Field-value pairs\n\n logger.debug('Redis XADD', { stream: streamKey });\n\n try {\n const entryId = await (client as RedisClientMock).xadd(...args);\n logger.debug('Redis XADD complete', { stream: streamKey, entryId });\n } catch (error) {\n logger.error('Redis XADD failed', {\n stream: streamKey,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n};\n\nfunction flattenEvent(event: Record<string, unknown>): string[] {\n const fields: string[] = [];\n for (const [key, value] of Object.entries(event)) {\n fields.push(\n key,\n typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value),\n );\n }\n return fields;\n}\n","import type { Destination as CoreDestination } from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\n/**\n * Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).\n */\nexport type XaddArg = string | number;\n\n/**\n * Mock-friendly Redis pipeline interface. Accumulates commands and\n * executes them with a single round-trip via exec().\n */\nexport interface RedisPipelineMock {\n xadd: (...args: XaddArg[]) => RedisPipelineMock;\n exec: () => Promise<Array<[Error | null, unknown]> | null>;\n}\n\n/**\n * Mock-friendly Redis client interface used by the destination.\n * Tests provide this via env.Redis; production creates a real ioredis\n * client and uses it directly.\n */\nexport interface RedisClientMock {\n xadd: (...args: XaddArg[]) => Promise<string | null>;\n pipeline: () => RedisPipelineMock;\n quit: () => Promise<string>;\n on?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n}\n\n/**\n * Constructor signature for the Redis client. Accepts either a URL\n * string or an options object, matching ioredis's dual signature.\n */\nexport interface RedisClientConstructor {\n new (url: string): RedisClientMock;\n new (options: RedisClientOptions): RedisClientMock;\n}\n\n/**\n * Minimal ioredis options subset the destination passes through.\n * Unknown options are preserved for the SDK to handle.\n */\nexport interface RedisClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n db?: number;\n tls?: boolean | Record<string, unknown>;\n connectTimeout?: number;\n commandTimeout?: number;\n [key: string]: unknown;\n}\n\nexport type SerializationMode = 'json' | 'flat';\n\nexport interface RedisSettings {\n /** Redis stream key name (e.g. 'walkeros:events'). */\n streamKey: string;\n /** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */\n url?: string;\n /** ioredis connection options (used if no url provided). */\n options?: RedisClientOptions;\n /**\n * Maximum stream length. Enables MAXLEN trimming on every XADD.\n * Uses approximate (~) trimming by default for performance.\n * Omit for unlimited stream length.\n */\n maxLen?: number;\n /**\n * Use exact MAXLEN instead of approximate (~).\n * Not recommended for production -- significantly slower.\n * Default: false (approximate trimming).\n */\n exactTrimming?: boolean;\n /**\n * Serialization mode for the event payload.\n * - 'json': Single 'event' field with JSON string (default)\n * - 'flat': Top-level event fields as separate stream fields\n */\n serialization?: SerializationMode;\n\n // Runtime -- set during init, not user-facing\n _client?: RedisClientMock;\n _ownedClient?: boolean;\n}\n\nexport interface Settings {\n redis: RedisSettings;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n /** Override stream key for this rule. */\n streamKey?: string;\n}\n\n/**\n * Env -- optional Redis SDK override. Production leaves this undefined\n * and the destination creates real ioredis client instances. Tests provide\n * mocks via env.Redis.\n */\nexport interface Env extends DestinationServer.Env {\n Redis?: {\n Client: RedisClientConstructor;\n };\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n"],"mappings":"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","names":["import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Destination,\n Settings,\n Env,\n RedisClientMock,\n RedisClientConstructor,\n RedisClientOptions,\n} from './types';\nimport { getConfig, isRedisEnv } from './config';\nimport { push } from './push';\n\n// Types re-export\nexport * as DestinationRedis from './types';\n\nexport const destinationRedis: Destination = {\n type: 'redis',\n\n config: {},\n\n async init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n const redis = settings.redis;\n\n // Skip creation if a client has already been wired in (testing).\n if (redis._client) return config;\n\n let Constructor: RedisClientConstructor | undefined;\n\n // Prefer env-injected constructor (testing, dependency injection).\n if (isRedisEnv(env)) {\n const envTyped = env as Env;\n Constructor = envTyped.Redis?.Client;\n }\n\n // Production path: load real ioredis SDK.\n if (!Constructor) {\n try {\n // Use dynamic require to allow tests to mock via jest.mock('ioredis').\n const ioredis = require('ioredis') as {\n default?: RedisClientConstructor;\n Redis?: RedisClientConstructor;\n };\n // ioredis exports the class as default (ESM) and as named Redis export.\n Constructor = ioredis.default ?? ioredis.Redis;\n } catch (err) {\n logger.throw(`Failed to load ioredis: ${String(err)}`);\n return config;\n }\n }\n\n if (!Constructor) {\n logger.throw('ioredis constructor not found');\n return config;\n }\n\n let client: RedisClientMock;\n if (redis.url) {\n client = new Constructor(redis.url);\n } else {\n client = new Constructor(redis.options ?? ({} as RedisClientOptions));\n }\n\n redis._client = client;\n redis._ownedClient = true;\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const settings = config?.settings as Settings | undefined;\n const redis = settings?.redis;\n if (!redis) return;\n\n const client = redis._client;\n // Only close clients the destination created (not user-provided)\n if (client && redis._ownedClient) {\n try {\n await client.quit();\n } finally {\n redis._client = undefined;\n redis._ownedClient = undefined;\n }\n }\n },\n};\n\nexport default destinationRedis;\n","import type {\n Config,\n Settings,\n RedisSettings,\n PartialConfig,\n Env,\n} from './types';\nimport type { Logger } from '@walkeros/core';\nimport { isObject } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const raw = (partialConfig.settings ?? {}) as Partial<Settings>;\n const redis: Partial<RedisSettings> =\n raw.redis ?? ({} as Partial<RedisSettings>);\n\n if (!redis.streamKey) {\n logger.throw('Config settings redis.streamKey missing');\n }\n\n const redisSettings: RedisSettings = {\n ...redis,\n streamKey: redis.streamKey as string,\n serialization: redis.serialization ?? 'json',\n };\n\n const settings: Settings = { redis: redisSettings };\n\n return { ...partialConfig, settings };\n}\n\nexport function isRedisEnv(env: unknown): env is Env {\n if (!isObject(env)) return false;\n const maybe = env as { Redis?: { Client?: unknown } };\n return typeof maybe.Redis?.Client === 'function';\n}\n","import type {\n PushFn,\n RedisSettings,\n RedisClientMock,\n XaddArg,\n SerializationMode,\n} from './types';\nimport { isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (event, { config, rule, logger }) {\n const settings = config.settings as { redis?: RedisSettings } | undefined;\n const redis: RedisSettings | undefined = settings?.redis;\n\n if (!redis) {\n logger.warn('Redis settings missing');\n return;\n }\n\n const client = redis._client;\n if (!client) {\n logger.warn('Redis client not initialized');\n return;\n }\n\n // Derive stream key: rule override -> destination default\n const ruleSettings = rule?.settings ?? {};\n const streamKey = isString(ruleSettings.streamKey)\n ? ruleSettings.streamKey\n : redis.streamKey;\n\n const serialization: SerializationMode = redis.serialization ?? 'json';\n\n // Serialize event\n const fields: string[] =\n serialization === 'flat'\n ? flattenEvent(event as unknown as Record<string, unknown>)\n : ['event', JSON.stringify(event)];\n\n // Build XADD arguments\n const args: XaddArg[] = [streamKey];\n\n // Optional MAXLEN trimming\n if (redis.maxLen) {\n args.push('MAXLEN');\n if (!redis.exactTrimming) args.push('~');\n args.push(redis.maxLen);\n }\n\n args.push('*'); // Auto-generate entry ID\n args.push(...fields); // Field-value pairs\n\n logger.debug('Redis XADD', { stream: streamKey });\n\n try {\n const entryId = await (client as RedisClientMock).xadd(...args);\n logger.debug('Redis XADD complete', { stream: streamKey, entryId });\n } catch (error) {\n logger.error('Redis XADD failed', {\n stream: streamKey,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n};\n\nfunction flattenEvent(event: Record<string, unknown>): string[] {\n const fields: string[] = [];\n for (const [key, value] of Object.entries(event)) {\n fields.push(\n key,\n typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value),\n );\n }\n return fields;\n}\n","import type { Destination as CoreDestination } from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\n/**\n * Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).\n */\nexport type XaddArg = string | number;\n\n/**\n * Mock-friendly Redis pipeline interface. Accumulates commands and\n * executes them with a single round-trip via exec().\n */\nexport interface RedisPipelineMock {\n xadd: (...args: XaddArg[]) => RedisPipelineMock;\n exec: () => Promise<Array<[Error | null, unknown]> | null>;\n}\n\n/**\n * Mock-friendly Redis client interface used by the destination.\n * Tests provide this via env.Redis; production creates a real ioredis\n * client and uses it directly.\n */\nexport interface RedisClientMock {\n xadd: (...args: XaddArg[]) => Promise<string | null>;\n pipeline: () => RedisPipelineMock;\n quit: () => Promise<string>;\n on?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n}\n\n/**\n * Constructor signature for the Redis client. Accepts either a URL\n * string or an options object, matching ioredis's dual signature.\n */\nexport interface RedisClientConstructor {\n new (url: string): RedisClientMock;\n new (options: RedisClientOptions): RedisClientMock;\n}\n\n/**\n * Minimal ioredis options subset the destination passes through.\n * Unknown options are preserved for the SDK to handle.\n */\nexport interface RedisClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n db?: number;\n tls?: boolean | Record<string, unknown>;\n connectTimeout?: number;\n commandTimeout?: number;\n [key: string]: unknown;\n}\n\nexport type SerializationMode = 'json' | 'flat';\n\nexport interface RedisSettings {\n /** Redis stream key name (e.g. 'walkeros:events'). */\n streamKey: string;\n /** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */\n url?: string;\n /** ioredis connection options (used if no url provided). */\n options?: RedisClientOptions;\n /**\n * Maximum stream length. Enables MAXLEN trimming on every XADD.\n * Uses approximate (~) trimming by default for performance.\n * Omit for unlimited stream length.\n */\n maxLen?: number;\n /**\n * Use exact MAXLEN instead of approximate (~).\n * Not recommended for production -- significantly slower.\n * Default: false (approximate trimming).\n */\n exactTrimming?: boolean;\n /**\n * Serialization mode for the event payload.\n * - 'json': Single 'event' field with JSON string (default)\n * - 'flat': Top-level event fields as separate stream fields\n */\n serialization?: SerializationMode;\n\n // Runtime -- set during init, not user-facing\n _client?: RedisClientMock;\n _ownedClient?: boolean;\n}\n\nexport interface Settings {\n redis: RedisSettings;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n /** Override stream key for this rule. */\n streamKey?: string;\n}\n\n/**\n * Env -- optional Redis SDK override. Production leaves this undefined\n * and the destination creates real ioredis client instances. Tests provide\n * mocks via env.Redis.\n */\nexport interface Env extends DestinationServer.Env {\n Redis?: {\n Client: RedisClientConstructor;\n };\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQA,kBAAyB;AAElB,SAAS,UACd,gBAA+B,CAAC,GAChC,QACQ;AACR,QAAM,MAAO,cAAc,YAAY,CAAC;AACxC,QAAM,QACJ,IAAI,SAAU,CAAC;AAEjB,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO,MAAM,yCAAyC;AAAA,EACxD;AAEA,QAAM,gBAA+B;AAAA,IACnC,GAAG;AAAA,IACH,WAAW,MAAM;AAAA,IACjB,eAAe,MAAM,iBAAiB;AAAA,EACxC;AAEA,QAAM,WAAqB,EAAE,OAAO,cAAc;AAElD,SAAO,EAAE,GAAG,eAAe,SAAS;AACtC;AAEO,SAAS,WAAW,KAA0B;AACnD,MAAI,KAAC,sBAAS,GAAG,EAAG,QAAO;AAC3B,QAAM,QAAQ;AACd,SAAO,OAAO,MAAM,OAAO,WAAW;AACxC;;;AC9BA,IAAAA,eAAyB;AAElB,IAAM,OAAe,eAAgB,OAAO,EAAE,QAAQ,MAAM,OAAO,GAAG;AAC3E,QAAM,WAAW,OAAO;AACxB,QAAM,QAAmC,UAAU;AAEnD,MAAI,CAAC,OAAO;AACV,WAAO,KAAK,wBAAwB;AACpC;AAAA,EACF;AAEA,QAAM,SAAS,MAAM;AACrB,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,8BAA8B;AAC1C;AAAA,EACF;AAGA,QAAM,eAAe,MAAM,YAAY,CAAC;AACxC,QAAM,gBAAY,uBAAS,aAAa,SAAS,IAC7C,aAAa,YACb,MAAM;AAEV,QAAM,gBAAmC,MAAM,iBAAiB;AAGhE,QAAM,SACJ,kBAAkB,SACd,aAAa,KAA2C,IACxD,CAAC,SAAS,KAAK,UAAU,KAAK,CAAC;AAGrC,QAAM,OAAkB,CAAC,SAAS;AAGlC,MAAI,MAAM,QAAQ;AAChB,SAAK,KAAK,QAAQ;AAClB,QAAI,CAAC,MAAM,cAAe,MAAK,KAAK,GAAG;AACvC,SAAK,KAAK,MAAM,MAAM;AAAA,EACxB;AAEA,OAAK,KAAK,GAAG;AACb,OAAK,KAAK,GAAG,MAAM;AAEnB,SAAO,MAAM,cAAc,EAAE,QAAQ,UAAU,CAAC;AAEhD,MAAI;AACF,UAAM,UAAU,MAAO,OAA2B,KAAK,GAAG,IAAI;AAC9D,WAAO,MAAM,uBAAuB,EAAE,QAAQ,WAAW,QAAQ,CAAC;AAAA,EACpE,SAAS,OAAO;AACd,WAAO,MAAM,qBAAqB;AAAA,MAChC,QAAQ;AAAA,MACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC;AAAA,EACH;AACF;AAEA,SAAS,aAAa,OAA0C;AAC9D,QAAM,SAAmB,CAAC;AAC1B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,WAAO;AAAA,MACL;AAAA,MACA,OAAO,UAAU,YAAY,UAAU,OACnC,KAAK,UAAU,KAAK,IACpB,OAAO,KAAK;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;;;AC3EA;;;AHcO,IAAM,mBAAgC;AAAA,EAC3C,MAAM;AAAA,EAEN,QAAQ,CAAC;AAAA,EAET,MAAM,KAAK,EAAE,QAAQ,eAAe,QAAQ,IAAI,GAAG;AACjD,UAAM,SAAS,UAAU,eAAe,MAAM;AAC9C,UAAM,WAAW,OAAO;AACxB,UAAM,QAAQ,SAAS;AAGvB,QAAI,MAAM,QAAS,QAAO;AAE1B,QAAI;AAGJ,QAAI,WAAW,GAAG,GAAG;AACnB,YAAM,WAAW;AACjB,oBAAc,SAAS,OAAO;AAAA,IAChC;AAGA,QAAI,CAAC,aAAa;AAChB,UAAI;AAEF,cAAM,UAAU,QAAQ,SAAS;AAKjC,sBAAc,QAAQ,WAAW,QAAQ;AAAA,MAC3C,SAAS,KAAK;AACZ,eAAO,MAAM,2BAA2B,OAAO,GAAG,CAAC,EAAE;AACrD,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QAAI,CAAC,aAAa;AAChB,aAAO,MAAM,+BAA+B;AAC5C,aAAO;AAAA,IACT;AAEA,QAAI;AACJ,QAAI,MAAM,KAAK;AACb,eAAS,IAAI,YAAY,MAAM,GAAG;AAAA,IACpC,OAAO;AACL,eAAS,IAAI,YAAY,MAAM,WAAY,CAAC,CAAwB;AAAA,IACtE;AAEA,UAAM,UAAU;AAChB,UAAM,eAAe;AAErB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAO,SAAS;AACzB,WAAO,MAAM,KAAK,OAAO,OAAO;AAAA,EAClC;AAAA,EAEA,MAAM,QAAQ,EAAE,OAAO,GAAG;AACxB,UAAM,WAAW,QAAQ;AACzB,UAAM,QAAQ,UAAU;AACxB,QAAI,CAAC,MAAO;AAEZ,UAAM,SAAS,MAAM;AAErB,QAAI,UAAU,MAAM,cAAc;AAChC,UAAI;AACF,cAAM,OAAO,KAAK;AAAA,MACpB,UAAE;AACA,cAAM,UAAU;AAChB,cAAM,eAAe;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":["import_core"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,
|
|
1
|
+
var e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});import{isObject as t}from"@walkeros/core";import{isString as i}from"@walkeros/core";var n=async function(e,{config:t,rule:n,logger:r}){const s=t.settings,o=s?.redis;if(!o)return void r.warn("Redis settings missing");const a=o._client;if(!a)return void r.warn("Redis client not initialized");const c=n?.settings??{},d=i(c.streamKey)?c.streamKey:o.streamKey,u="flat"===(o.serialization??"json")?function(e){const t=[];for(const[i,n]of Object.entries(e))t.push(i,"object"==typeof n&&null!==n?JSON.stringify(n):String(n));return t}(e):["event",JSON.stringify(e)],f=[d];o.maxLen&&(f.push("MAXLEN"),o.exactTrimming||f.push("~"),f.push(o.maxLen)),f.push("*"),f.push(...u),r.debug("Redis XADD",{stream:d});try{const e=await a.xadd(...f);r.debug("Redis XADD complete",{stream:d,entryId:e})}catch(e){r.error("Redis XADD failed",{stream:d,error:e instanceof Error?e.message:String(e)})}};var r={},s={type:"redis",config:{},async init({config:i,logger:n,env:r}){const s=function(e={},t){const i=(e.settings??{}).redis??{};i.streamKey||t.throw("Config settings redis.streamKey missing");const n={redis:{...i,streamKey:i.streamKey,serialization:i.serialization??"json"}};return{...e,settings:n}}(i,n),o=s.settings.redis;if(o._client)return s;let a,c;if(function(e){if(!t(e))return!1;const i=e;return"function"==typeof i.Redis?.Client}(r)){const e=r;a=e.Redis?.Client}if(!a)try{const t=e("ioredis");a=t.default??t.Redis}catch(e){return n.throw(`Failed to load ioredis: ${String(e)}`),s}return a?(c=o.url?new a(o.url):new a(o.options??{}),o._client=c,o._ownedClient=!0,s):(n.throw("ioredis constructor not found"),s)},push:async(e,t)=>await n(e,t),async destroy({config:e}){const t=e?.settings,i=t?.redis;if(!i)return;const n=i._client;if(n&&i._ownedClient)try{await n.quit()}finally{i._client=void 0,i._ownedClient=void 0}}},o=s;export{r as DestinationRedis,o as default,s as destinationRedis};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type {\n Config,\n Settings,\n RedisSettings,\n PartialConfig,\n Env,\n} from './types';\nimport type { Logger } from '@walkeros/core';\nimport { isObject } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const raw = (partialConfig.settings ?? {}) as Partial<Settings>;\n const redis: Partial<RedisSettings> =\n raw.redis ?? ({} as Partial<RedisSettings>);\n\n if (!redis.streamKey) {\n logger.throw('Config settings redis.streamKey missing');\n }\n\n const redisSettings: RedisSettings = {\n ...redis,\n streamKey: redis.streamKey as string,\n serialization: redis.serialization ?? 'json',\n };\n\n const settings: Settings = { redis: redisSettings };\n\n return { ...partialConfig, settings };\n}\n\nexport function isRedisEnv(env: unknown): env is Env {\n if (!isObject(env)) return false;\n const maybe = env as { Redis?: { Client?: unknown } };\n return typeof maybe.Redis?.Client === 'function';\n}\n","import type {\n PushFn,\n RedisSettings,\n RedisClientMock,\n XaddArg,\n SerializationMode,\n} from './types';\nimport { isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (event, { config, rule, logger }) {\n const settings = config.settings as { redis?: RedisSettings } | undefined;\n const redis: RedisSettings | undefined = settings?.redis;\n\n if (!redis) {\n logger.warn('Redis settings missing');\n return;\n }\n\n const client = redis._client;\n if (!client) {\n logger.warn('Redis client not initialized');\n return;\n }\n\n // Derive stream key: rule override -> destination default\n const ruleSettings = rule?.settings ?? {};\n const streamKey = isString(ruleSettings.streamKey)\n ? ruleSettings.streamKey\n : redis.streamKey;\n\n const serialization: SerializationMode = redis.serialization ?? 'json';\n\n // Serialize event\n const fields: string[] =\n serialization === 'flat'\n ? flattenEvent(event as unknown as Record<string, unknown>)\n : ['event', JSON.stringify(event)];\n\n // Build XADD arguments\n const args: XaddArg[] = [streamKey];\n\n // Optional MAXLEN trimming\n if (redis.maxLen) {\n args.push('MAXLEN');\n if (!redis.exactTrimming) args.push('~');\n args.push(redis.maxLen);\n }\n\n args.push('*'); // Auto-generate entry ID\n args.push(...fields); // Field-value pairs\n\n logger.debug('Redis XADD', { stream: streamKey });\n\n try {\n const entryId = await (client as RedisClientMock).xadd(...args);\n logger.debug('Redis XADD complete', { stream: streamKey, entryId });\n } catch (error) {\n logger.error('Redis XADD failed', {\n stream: streamKey,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n};\n\nfunction flattenEvent(event: Record<string, unknown>): string[] {\n const fields: string[] = [];\n for (const [key, value] of Object.entries(event)) {\n fields.push(\n key,\n typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value),\n );\n }\n return fields;\n}\n","import type { Destination as CoreDestination } from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\n/**\n * Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).\n */\nexport type XaddArg = string | number;\n\n/**\n * Mock-friendly Redis pipeline interface. Accumulates commands and\n * executes them with a single round-trip via exec().\n */\nexport interface RedisPipelineMock {\n xadd: (...args: XaddArg[]) => RedisPipelineMock;\n exec: () => Promise<Array<[Error | null, unknown]> | null>;\n}\n\n/**\n * Mock-friendly Redis client interface used by the destination.\n * Tests provide this via env.Redis; production creates a real ioredis\n * client and uses it directly.\n */\nexport interface RedisClientMock {\n xadd: (...args: XaddArg[]) => Promise<string | null>;\n pipeline: () => RedisPipelineMock;\n quit: () => Promise<string>;\n on?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n}\n\n/**\n * Constructor signature for the Redis client. Accepts either a URL\n * string or an options object, matching ioredis's dual signature.\n */\nexport interface RedisClientConstructor {\n new (url: string): RedisClientMock;\n new (options: RedisClientOptions): RedisClientMock;\n}\n\n/**\n * Minimal ioredis options subset the destination passes through.\n * Unknown options are preserved for the SDK to handle.\n */\nexport interface RedisClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n db?: number;\n tls?: boolean | Record<string, unknown>;\n connectTimeout?: number;\n commandTimeout?: number;\n [key: string]: unknown;\n}\n\nexport type SerializationMode = 'json' | 'flat';\n\nexport interface RedisSettings {\n /** Redis stream key name (e.g. 'walkeros:events'). */\n streamKey: string;\n /** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */\n url?: string;\n /** ioredis connection options (used if no url provided). */\n options?: RedisClientOptions;\n /**\n * Maximum stream length. Enables MAXLEN trimming on every XADD.\n * Uses approximate (~) trimming by default for performance.\n * Omit for unlimited stream length.\n */\n maxLen?: number;\n /**\n * Use exact MAXLEN instead of approximate (~).\n * Not recommended for production -- significantly slower.\n * Default: false (approximate trimming).\n */\n exactTrimming?: boolean;\n /**\n * Serialization mode for the event payload.\n * - 'json': Single 'event' field with JSON string (default)\n * - 'flat': Top-level event fields as separate stream fields\n */\n serialization?: SerializationMode;\n\n // Runtime -- set during init, not user-facing\n _client?: RedisClientMock;\n _ownedClient?: boolean;\n}\n\nexport interface Settings {\n redis: RedisSettings;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n /** Override stream key for this rule. */\n streamKey?: string;\n}\n\n/**\n * Env -- optional Redis SDK override. Production leaves this undefined\n * and the destination creates real ioredis client instances. Tests provide\n * mocks via env.Redis.\n */\nexport interface Env extends DestinationServer.Env {\n Redis?: {\n Client: RedisClientConstructor;\n };\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n","import type {\n Destination,\n Settings,\n Env,\n RedisClientMock,\n RedisClientConstructor,\n RedisClientOptions,\n} from './types';\nimport { getConfig, isRedisEnv } from './config';\nimport { push } from './push';\n\n// Types re-export\nexport * as DestinationRedis from './types';\n\nexport const destinationRedis: Destination = {\n type: 'redis',\n\n config: {},\n\n async init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n const redis = settings.redis;\n\n // Skip creation if a client has already been wired in (testing).\n if (redis._client) return config;\n\n let Constructor: RedisClientConstructor | undefined;\n\n // Prefer env-injected constructor (testing, dependency injection).\n if (isRedisEnv(env)) {\n const envTyped = env as Env;\n Constructor = envTyped.Redis?.Client;\n }\n\n // Production path: load real ioredis SDK.\n if (!Constructor) {\n try {\n // Use dynamic require to allow tests to mock via jest.mock('ioredis').\n const ioredis = require('ioredis') as {\n default?: RedisClientConstructor;\n Redis?: RedisClientConstructor;\n };\n // ioredis exports the class as default (ESM) and as named Redis export.\n Constructor = ioredis.default ?? ioredis.Redis;\n } catch (err) {\n logger.throw(`Failed to load ioredis: ${String(err)}`);\n return config;\n }\n }\n\n if (!Constructor) {\n logger.throw('ioredis constructor not found');\n return config;\n }\n\n let client: RedisClientMock;\n if (redis.url) {\n client = new Constructor(redis.url);\n } else {\n client = new Constructor(redis.options ?? ({} as RedisClientOptions));\n }\n\n redis._client = client;\n redis._ownedClient = true;\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const settings = config?.settings as Settings | undefined;\n const redis = settings?.redis;\n if (!redis) return;\n\n const client = redis._client;\n // Only close clients the destination created (not user-provided)\n if (client && redis._ownedClient) {\n try {\n await client.quit();\n } finally {\n redis._client = undefined;\n redis._ownedClient = undefined;\n }\n }\n },\n};\n\nexport default destinationRedis;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type {\n Config,\n Settings,\n RedisSettings,\n PartialConfig,\n Env,\n} from './types';\nimport type { Logger } from '@walkeros/core';\nimport { isObject } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const raw = (partialConfig.settings ?? {}) as Partial<Settings>;\n const redis: Partial<RedisSettings> =\n raw.redis ?? ({} as Partial<RedisSettings>);\n\n if (!redis.streamKey) {\n logger.throw('Config settings redis.streamKey missing');\n }\n\n const redisSettings: RedisSettings = {\n ...redis,\n streamKey: redis.streamKey as string,\n serialization: redis.serialization ?? 'json',\n };\n\n const settings: Settings = { redis: redisSettings };\n\n return { ...partialConfig, settings };\n}\n\nexport function isRedisEnv(env: unknown): env is Env {\n if (!isObject(env)) return false;\n const maybe = env as { Redis?: { Client?: unknown } };\n return typeof maybe.Redis?.Client === 'function';\n}\n","import type {\n PushFn,\n RedisSettings,\n RedisClientMock,\n XaddArg,\n SerializationMode,\n} from './types';\nimport { isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (event, { config, rule, logger }) {\n const settings = config.settings as { redis?: RedisSettings } | undefined;\n const redis: RedisSettings | undefined = settings?.redis;\n\n if (!redis) {\n logger.warn('Redis settings missing');\n return;\n }\n\n const client = redis._client;\n if (!client) {\n logger.warn('Redis client not initialized');\n return;\n }\n\n // Derive stream key: rule override -> destination default\n const ruleSettings = rule?.settings ?? {};\n const streamKey = isString(ruleSettings.streamKey)\n ? ruleSettings.streamKey\n : redis.streamKey;\n\n const serialization: SerializationMode = redis.serialization ?? 'json';\n\n // Serialize event\n const fields: string[] =\n serialization === 'flat'\n ? flattenEvent(event as unknown as Record<string, unknown>)\n : ['event', JSON.stringify(event)];\n\n // Build XADD arguments\n const args: XaddArg[] = [streamKey];\n\n // Optional MAXLEN trimming\n if (redis.maxLen) {\n args.push('MAXLEN');\n if (!redis.exactTrimming) args.push('~');\n args.push(redis.maxLen);\n }\n\n args.push('*'); // Auto-generate entry ID\n args.push(...fields); // Field-value pairs\n\n logger.debug('Redis XADD', { stream: streamKey });\n\n try {\n const entryId = await (client as RedisClientMock).xadd(...args);\n logger.debug('Redis XADD complete', { stream: streamKey, entryId });\n } catch (error) {\n logger.error('Redis XADD failed', {\n stream: streamKey,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n};\n\nfunction flattenEvent(event: Record<string, unknown>): string[] {\n const fields: string[] = [];\n for (const [key, value] of Object.entries(event)) {\n fields.push(\n key,\n typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value),\n );\n }\n return fields;\n}\n","import type { Destination as CoreDestination } from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\n/**\n * Arguments passed to Redis XADD. Strings or numbers (for MAXLEN counts).\n */\nexport type XaddArg = string | number;\n\n/**\n * Mock-friendly Redis pipeline interface. Accumulates commands and\n * executes them with a single round-trip via exec().\n */\nexport interface RedisPipelineMock {\n xadd: (...args: XaddArg[]) => RedisPipelineMock;\n exec: () => Promise<Array<[Error | null, unknown]> | null>;\n}\n\n/**\n * Mock-friendly Redis client interface used by the destination.\n * Tests provide this via env.Redis; production creates a real ioredis\n * client and uses it directly.\n */\nexport interface RedisClientMock {\n xadd: (...args: XaddArg[]) => Promise<string | null>;\n pipeline: () => RedisPipelineMock;\n quit: () => Promise<string>;\n on?: (event: string, listener: (...args: unknown[]) => void) => unknown;\n}\n\n/**\n * Constructor signature for the Redis client. Accepts either a URL\n * string or an options object, matching ioredis's dual signature.\n */\nexport interface RedisClientConstructor {\n new (url: string): RedisClientMock;\n new (options: RedisClientOptions): RedisClientMock;\n}\n\n/**\n * Minimal ioredis options subset the destination passes through.\n * Unknown options are preserved for the SDK to handle.\n */\nexport interface RedisClientOptions {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n db?: number;\n tls?: boolean | Record<string, unknown>;\n connectTimeout?: number;\n commandTimeout?: number;\n [key: string]: unknown;\n}\n\nexport type SerializationMode = 'json' | 'flat';\n\nexport interface RedisSettings {\n /** Redis stream key name (e.g. 'walkeros:events'). */\n streamKey: string;\n /** Redis connection URL (e.g. 'redis://localhost:6379' or 'rediss://...'). */\n url?: string;\n /** ioredis connection options (used if no url provided). */\n options?: RedisClientOptions;\n /**\n * Maximum stream length. Enables MAXLEN trimming on every XADD.\n * Uses approximate (~) trimming by default for performance.\n * Omit for unlimited stream length.\n */\n maxLen?: number;\n /**\n * Use exact MAXLEN instead of approximate (~).\n * Not recommended for production -- significantly slower.\n * Default: false (approximate trimming).\n */\n exactTrimming?: boolean;\n /**\n * Serialization mode for the event payload.\n * - 'json': Single 'event' field with JSON string (default)\n * - 'flat': Top-level event fields as separate stream fields\n */\n serialization?: SerializationMode;\n\n // Runtime -- set during init, not user-facing\n _client?: RedisClientMock;\n _ownedClient?: boolean;\n}\n\nexport interface Settings {\n redis: RedisSettings;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n /** Override stream key for this rule. */\n streamKey?: string;\n}\n\n/**\n * Env -- optional Redis SDK override. Production leaves this undefined\n * and the destination creates real ioredis client instances. Tests provide\n * mocks via env.Redis.\n */\nexport interface Env extends DestinationServer.Env {\n Redis?: {\n Client: RedisClientConstructor;\n };\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n","import type {\n Destination,\n Settings,\n Env,\n RedisClientMock,\n RedisClientConstructor,\n RedisClientOptions,\n} from './types';\nimport { getConfig, isRedisEnv } from './config';\nimport { push } from './push';\n\n// Types re-export\nexport * as DestinationRedis from './types';\n\nexport const destinationRedis: Destination = {\n type: 'redis',\n\n config: {},\n\n async init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n const redis = settings.redis;\n\n // Skip creation if a client has already been wired in (testing).\n if (redis._client) return config;\n\n let Constructor: RedisClientConstructor | undefined;\n\n // Prefer env-injected constructor (testing, dependency injection).\n if (isRedisEnv(env)) {\n const envTyped = env as Env;\n Constructor = envTyped.Redis?.Client;\n }\n\n // Production path: load real ioredis SDK.\n if (!Constructor) {\n try {\n // Use dynamic require to allow tests to mock via jest.mock('ioredis').\n const ioredis = require('ioredis') as {\n default?: RedisClientConstructor;\n Redis?: RedisClientConstructor;\n };\n // ioredis exports the class as default (ESM) and as named Redis export.\n Constructor = ioredis.default ?? ioredis.Redis;\n } catch (err) {\n logger.throw(`Failed to load ioredis: ${String(err)}`);\n return config;\n }\n }\n\n if (!Constructor) {\n logger.throw('ioredis constructor not found');\n return config;\n }\n\n let client: RedisClientMock;\n if (redis.url) {\n client = new Constructor(redis.url);\n } else {\n client = new Constructor(redis.options ?? ({} as RedisClientOptions));\n }\n\n redis._client = client;\n redis._ownedClient = true;\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const settings = config?.settings as Settings | undefined;\n const redis = settings?.redis;\n if (!redis) return;\n\n const client = redis._client;\n // Only close clients the destination created (not user-provided)\n if (client && redis._ownedClient) {\n try {\n await client.quit();\n } finally {\n redis._client = undefined;\n redis._ownedClient = undefined;\n }\n }\n },\n};\n\nexport default destinationRedis;\n"],"mappings":"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","names":[]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/server-destination-redis",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0-next-1777882869103",
|
|
5
5
|
"type": "destination",
|
|
6
6
|
"platform": [
|
|
7
7
|
"server"
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"push": {
|
|
83
83
|
"Redis": {
|
|
84
84
|
"Client": {
|
|
85
|
-
"$code": "class{constructor(e){
|
|
85
|
+
"$code": "class{constructor(e){}xadd=v;pipeline(){return function(){const e={xadd:()=>e,exec:()=>Promise.resolve([])};return e}()}quit=u;on(){return this}}"
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
},
|
|
@@ -127,35 +127,21 @@
|
|
|
127
127
|
"entity": "child",
|
|
128
128
|
"data": {
|
|
129
129
|
"is": "subordinated"
|
|
130
|
-
},
|
|
131
|
-
"nested": [],
|
|
132
|
-
"context": {
|
|
133
|
-
"element": [
|
|
134
|
-
"child",
|
|
135
|
-
0
|
|
136
|
-
]
|
|
137
130
|
}
|
|
138
131
|
}
|
|
139
132
|
],
|
|
140
133
|
"consent": {
|
|
141
134
|
"functional": true
|
|
142
135
|
},
|
|
143
|
-
"id": "
|
|
136
|
+
"id": "208acef44523fc34",
|
|
144
137
|
"trigger": "test",
|
|
145
138
|
"entity": "debug",
|
|
146
139
|
"action": "noise",
|
|
147
140
|
"timestamp": 1700000105,
|
|
148
141
|
"timing": 3.14,
|
|
149
|
-
"group": "gr0up",
|
|
150
|
-
"count": 1,
|
|
151
|
-
"version": {
|
|
152
|
-
"source": "3.4.2",
|
|
153
|
-
"tagging": 1
|
|
154
|
-
},
|
|
155
142
|
"source": {
|
|
156
|
-
"type": "
|
|
157
|
-
"
|
|
158
|
-
"previous_id": "http://remotehost:9001"
|
|
143
|
+
"type": "collector",
|
|
144
|
+
"schema": "4"
|
|
159
145
|
}
|
|
160
146
|
},
|
|
161
147
|
"mapping": {
|
|
@@ -198,35 +184,21 @@
|
|
|
198
184
|
"entity": "child",
|
|
199
185
|
"data": {
|
|
200
186
|
"is": "subordinated"
|
|
201
|
-
},
|
|
202
|
-
"nested": [],
|
|
203
|
-
"context": {
|
|
204
|
-
"element": [
|
|
205
|
-
"child",
|
|
206
|
-
0
|
|
207
|
-
]
|
|
208
187
|
}
|
|
209
188
|
}
|
|
210
189
|
],
|
|
211
190
|
"consent": {
|
|
212
191
|
"functional": true
|
|
213
192
|
},
|
|
214
|
-
"id": "
|
|
193
|
+
"id": "d6754c821e1d8088",
|
|
215
194
|
"trigger": "load",
|
|
216
195
|
"entity": "page",
|
|
217
196
|
"action": "view",
|
|
218
197
|
"timestamp": 1700000100,
|
|
219
198
|
"timing": 3.14,
|
|
220
|
-
"group": "gr0up",
|
|
221
|
-
"count": 1,
|
|
222
|
-
"version": {
|
|
223
|
-
"source": "3.4.2",
|
|
224
|
-
"tagging": 1
|
|
225
|
-
},
|
|
226
199
|
"source": {
|
|
227
|
-
"type": "
|
|
228
|
-
"
|
|
229
|
-
"previous_id": "http://remotehost:9001"
|
|
200
|
+
"type": "collector",
|
|
201
|
+
"schema": "4"
|
|
230
202
|
}
|
|
231
203
|
},
|
|
232
204
|
"out": [
|
|
@@ -319,22 +291,15 @@
|
|
|
319
291
|
"consent": {
|
|
320
292
|
"functional": true
|
|
321
293
|
},
|
|
322
|
-
"id": "
|
|
294
|
+
"id": "04af8f4958c95ccb",
|
|
323
295
|
"trigger": "load",
|
|
324
296
|
"entity": "order",
|
|
325
297
|
"action": "complete",
|
|
326
298
|
"timestamp": 1700000101,
|
|
327
299
|
"timing": 3.14,
|
|
328
|
-
"group": "gr0up",
|
|
329
|
-
"count": 1,
|
|
330
|
-
"version": {
|
|
331
|
-
"source": "3.4.2",
|
|
332
|
-
"tagging": 1
|
|
333
|
-
},
|
|
334
300
|
"source": {
|
|
335
|
-
"type": "
|
|
336
|
-
"
|
|
337
|
-
"previous_id": "http://remotehost:9001"
|
|
301
|
+
"type": "collector",
|
|
302
|
+
"schema": "4"
|
|
338
303
|
}
|
|
339
304
|
},
|
|
340
305
|
"out": [
|
|
@@ -426,22 +391,15 @@
|
|
|
426
391
|
"consent": {
|
|
427
392
|
"functional": true
|
|
428
393
|
},
|
|
429
|
-
"id": "
|
|
394
|
+
"id": "5df56794aac846c4",
|
|
430
395
|
"trigger": "load",
|
|
431
396
|
"entity": "order",
|
|
432
397
|
"action": "complete",
|
|
433
398
|
"timestamp": 1700000104,
|
|
434
399
|
"timing": 3.14,
|
|
435
|
-
"group": "gr0up",
|
|
436
|
-
"count": 1,
|
|
437
|
-
"version": {
|
|
438
|
-
"source": "3.4.2",
|
|
439
|
-
"tagging": 1
|
|
440
|
-
},
|
|
441
400
|
"source": {
|
|
442
|
-
"type": "
|
|
443
|
-
"
|
|
444
|
-
"previous_id": "http://remotehost:9001"
|
|
401
|
+
"type": "collector",
|
|
402
|
+
"schema": "4"
|
|
445
403
|
}
|
|
446
404
|
},
|
|
447
405
|
"mapping": {
|
|
@@ -496,35 +454,21 @@
|
|
|
496
454
|
"entity": "child",
|
|
497
455
|
"data": {
|
|
498
456
|
"is": "subordinated"
|
|
499
|
-
},
|
|
500
|
-
"nested": [],
|
|
501
|
-
"context": {
|
|
502
|
-
"element": [
|
|
503
|
-
"child",
|
|
504
|
-
0
|
|
505
|
-
]
|
|
506
457
|
}
|
|
507
458
|
}
|
|
508
459
|
],
|
|
509
460
|
"consent": {
|
|
510
461
|
"functional": true
|
|
511
462
|
},
|
|
512
|
-
"id": "
|
|
463
|
+
"id": "5b8c8d733aff63eb",
|
|
513
464
|
"trigger": "load",
|
|
514
465
|
"entity": "page",
|
|
515
466
|
"action": "view",
|
|
516
467
|
"timestamp": 1700000103,
|
|
517
468
|
"timing": 3.14,
|
|
518
|
-
"group": "gr0up",
|
|
519
|
-
"count": 1,
|
|
520
|
-
"version": {
|
|
521
|
-
"source": "3.4.2",
|
|
522
|
-
"tagging": 1
|
|
523
|
-
},
|
|
524
469
|
"source": {
|
|
525
|
-
"type": "
|
|
526
|
-
"
|
|
527
|
-
"previous_id": "http://remotehost:9001"
|
|
470
|
+
"type": "collector",
|
|
471
|
+
"schema": "4"
|
|
528
472
|
}
|
|
529
473
|
},
|
|
530
474
|
"settings": {
|
|
@@ -578,22 +522,15 @@
|
|
|
578
522
|
"consent": {
|
|
579
523
|
"functional": true
|
|
580
524
|
},
|
|
581
|
-
"id": "
|
|
525
|
+
"id": "a393ac7d8b501118",
|
|
582
526
|
"trigger": "load",
|
|
583
527
|
"entity": "product",
|
|
584
528
|
"action": "view",
|
|
585
529
|
"timestamp": 1700000102,
|
|
586
530
|
"timing": 3.14,
|
|
587
|
-
"group": "gr0up",
|
|
588
|
-
"count": 1,
|
|
589
|
-
"version": {
|
|
590
|
-
"source": "3.4.2",
|
|
591
|
-
"tagging": 1
|
|
592
|
-
},
|
|
593
531
|
"source": {
|
|
594
|
-
"type": "
|
|
595
|
-
"
|
|
596
|
-
"previous_id": "http://remotehost:9001"
|
|
532
|
+
"type": "collector",
|
|
533
|
+
"schema": "4"
|
|
597
534
|
}
|
|
598
535
|
},
|
|
599
536
|
"settings": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/server-destination-redis",
|
|
3
3
|
"description": "Redis Streams server destination for walkerOS (ioredis, XADD, pipeline batching)",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0-next-1777882869103",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"ioredis": "^5.10.0",
|
|
38
|
-
"@walkeros/core": "
|
|
39
|
-
"@walkeros/server-core": "
|
|
38
|
+
"@walkeros/core": "4.0.0-next-1777882869103",
|
|
39
|
+
"@walkeros/server-core": "4.0.0-next-1777882869103"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@walkeros/collector": "
|
|
42
|
+
"@walkeros/collector": "4.0.0-next-1777882869103"
|
|
43
43
|
},
|
|
44
44
|
"repository": {
|
|
45
45
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|