zod-sockets
Version:
Socket.IO solution with I/O validation and the ability to generate AsyncAPI specification and a contract for consumers
17 lines (14 loc) • 22.7 kB
JavaScript
import{z as q}from"zod/v4";import*as L from"ramda";var oe=L.tryCatch((e,t)=>typeof q.parse(e,t),L.always(void 0)),Ye=e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),Z=e=>e.charAt(0).toLowerCase()+e.slice(1),y=(...e)=>e.flatMap(t=>t.split(/[^A-Z0-9]/gi)).flatMap(t=>t.replaceAll(/[A-Z]+/g,o=>`/${o}`).split("/")).map(Ye).join(""),Ae=e=>e instanceof Error?e:e instanceof q.ZodError?new q.ZodRealError(e.issues):new Error(String(e)),ye=e=>e instanceof q.ZodError?e.issues.map(({path:t,message:o})=>`${t.length?`${q.core.toDotPath(t)}: `:""}${o}`).join("; "):e.message,k=(e,t)=>qe(e)&&"_zod"in e&&(t?L.path(["_zod","def","type"],e)===t:!0),qe=e=>typeof e=="object"&&e!==null;var ne=e=>({join:async t=>e.join(t),leave:async t=>typeof t=="string"?e.leave(t):Promise.all(t.map(o=>e.leave(o))).then(()=>{})});import Ge from"node:assert/strict";var re=({sockets:e,...t})=>e.map(o=>({id:o.id,handshake:o.handshake,rooms:Array.from(o.rooms),getData:()=>o.data||{},emit:P({subject:o,...t}),...ne(o)}));function P({subject:e,emission:t,timeout:o}){return async(r,...n)=>{let i="id"in e;Ge(r in t,new Error(`Unsupported event ${r}`));let{schema:s,ack:a}=t[r],p=s.parse(n);if(!a)return e.emit(String(r),...p)||!0;let f=await e.timeout(o).emitWithAck(String(r),...p);return(i?a:a.array()).parse(f)}}var he=({subject:e,...t})=>o=>({getClients:async()=>re({sockets:await e.in(o).fetchSockets(),...t}),broadcast:P({...t,subject:e.to(o)})});var je={onConnection:({client:{id:e,getData:t},logger:o})=>o.debug("Client connected",{...t(),id:e}),onDisconnect:({client:{id:e,getData:t},logger:o})=>o.debug("Client disconnected",{...t(),id:e}),onAnyIncoming:({event:e,client:{id:t,getData:o},logger:r})=>r.debug(`${e} from ${t}`,o()),onAnyOutgoing:({event:e,logger:t,payload:o})=>t.debug(`Sending ${e}`,o),onStartup:({logger:e})=>e.debug("Ready"),onError:({logger:e,event:t,error:o})=>e.error(t?`${t} handling error`:"Error",o)};var ie="/",F=e=>{let t=e.trim();return t.startsWith("/")?t:`/${t}`};import{hex as se,italic as Qe}from"ansis";import*as b from"ramda";var Xe=Qe("for Sheila".padEnd(40)),et="Proudly supports non-binary community.".padStart(57),tt=`
,,
MMM"""AMV \u1FEF7MM .M"""bgd \u1FEF7MM mm
M\u2019 AMV MM ,MI "Y MM MM
\u1FEF AMV ,pW"Wq. ,M""bMM \u1FEFMMb. ,pW"Wq. ,p6"bo MM ,MP\u2019 .gP"Ya mmMMmm ,pP"Ybd
AMV 6W\u2019 \u1FEFWb ,AP MM \u1FEFYMMNq. 6W\u2019 \u1FEFWb 6M\u2019 OO MM ;Y ,M\u2019 Yb MM 8I \u1FEF"
AMV , 8M M8 8MI MM . \u1FEFMM 8M M8 8M MM;Mm 8M"""""" MM \u1FEFYMMMa.
AMV ,M YA. ,A9 \u1FEFMb MM Mb dM YA. ,A9 YM. , MM \u1FEFMb. YM. , MM L. I8
AMVmmmmMM \u1FEFYbmd9\u2019 \u1FEFWbmd"MML. P"Ybmmd" \u1FEFYbmd9\u2019 YMbmd\u2019 .JMML. YA. \u1FEFMbmmd\u2019 \u1FEFMbmo M9mmmP\u2019
${Xe}${et}
`,ot=b.cond([[b.gt(4),b.always(se("#FCF434"))],[b.gt(5),b.always(se("#FFF"))],[b.gt(8),b.always(se("#9C59D1"))],[b.T,b.always(se("#383838"))]]),ve=()=>tt.split(`
`).map((e,t)=>ot(t)(e)).join(`
`);var nt=async({io:e,actions:t,target:o,config:{namespaces:r,timeout:n,startupLogo:i=!0},logger:s=console})=>{for(let a in r){let p=e.of(F(a)),{emission:f,hooks:S,metadata:x}=r[a],{onConnection:J,onDisconnect:C,onAnyIncoming:$,onAnyOutgoing:v,onStartup:I,onError:T}={...je,...S},N={emission:f,timeout:n},Y={logger:s,withRooms:he({subject:e,metadata:x,...N}),all:{getClients:async()=>re({sockets:await p.fetchSockets(),metadata:x,...N}),getRooms:()=>Array.from(p.adapter.rooms.keys()),broadcast:P({subject:e,...N})}};p.on("connection",async m=>{let E=P({subject:m,...N}),R=P({subject:m.broadcast,...N}),K={emit:E,broadcast:R,id:m.id,handshake:m.handshake,getRequest:()=>m.request,isConnected:()=>m.connected,getRooms:()=>Array.from(m.rooms),getData:()=>m.data||{},setData:g=>{x.parse(g),m.data=g},...ne(m)},O={...Y,client:K,withRooms:he({subject:m,metadata:x,...N})};await J(O),m.onAny((g,...z)=>$({event:g,payload:z,...O})),m.onAnyOutgoing((g,...z)=>v({event:g,payload:z,...O}));for(let g of t)if(g.namespace===a){let{event:z}=g;m.on(z,async(...we)=>{try{return await g.execute({params:we,...O})}catch(Je){return T({...O,event:z,payload:we,error:Ae(Je)})}})}m.on("disconnect",()=>C(O))}),await I(Y)}return(i?console.log:()=>{})(ve()),s.debug("Running","v4.0.0 (ESM)"),s.info("Listening",o.address()),e.attach(o)};import{z as rt}from"zod/v4";var ae=class e{timeout;startupLogo;security;namespaces;constructor({timeout:t=2e3,startupLogo:o=!0,namespaces:r={},security:n=[]}={}){this.timeout=t,this.startupLogo=o,this.namespaces=r,this.security=n}addNamespace({path:t=ie,emission:o={},metadata:r=rt.object({}),hooks:n={},security:i=[]}){let{namespaces:s,...a}=this,p={emission:o,hooks:n,metadata:r,security:i};return new e({...a,namespaces:{...s,[t]:p}})}},it=({startupLogo:e,timeout:t,security:o,emission:r,hooks:n,metadata:i}={})=>new ae({startupLogo:e,timeout:t,security:o}).addNamespace({emission:r,metadata:i,hooks:n});import*as le from"ramda";import{z as de}from"zod/v4";import{z as st}from"zod/v4";var ce=class extends Error{name="IOSchemaError"},_=class extends ce{constructor(o){super(ye(o),{cause:o});this.cause=o}name="InputValidationError"},G=class extends ce{constructor(o){let r=new st.ZodError(o.issues.map(({path:n,...i})=>({...i,path:["output",...n]})));super(ye(r),{cause:o});this.cause=o}name="OutputValidationError"};import{z as ge}from"zod/v4";var U=(e,t,o)=>{let r=ge.function({input:e,output:t}),n=ge.custom().transform((i,s)=>typeof i!="function"?(s.addIssue({...o,message:`Expected function, received ${typeof s.value}`}),ge.NEVER):r.implement(i));return Object.assign(n._zod.bag,{brand:"function",input:e,output:t}),n},pe=e=>e._zod.bag.brand==="function"&&k(e._zod.bag.input,"tuple")&&k(e._zod.bag.output);var me=class{},ue=class extends me{#o;#t;#e;#n;#r;constructor(t){super(),this.#o=t.event,this.#t=t.ns||ie,this.#e=t.input,this.#n="output"in t?t.output:void 0,this.#r=t.handler}get event(){return this.#o}get namespace(){return this.#t}get inputSchema(){return this.#e}get outputSchema(){return this.#n}#i(t){let o=this.#n?le.init(t):t;try{return this.#e.parse(o)}catch(r){throw r instanceof de.ZodError?new _(r):r}}#s(t){if(this.#n)try{return U(this.#n,de.void(),{path:[Math.max(0,t.length-1)]}).parse(le.last(t))}catch(o){throw o instanceof de.ZodError?new _(o):o}}#a(t){if(this.#n)try{return this.#n.parse(t)}catch(o){throw o instanceof de.ZodError?new G(o):o}}async execute({params:t,logger:o,...r}){let n=this.#i(t);o.debug(`${this.#o}: parsed input (${this.#n?"excl.":"no"} ack)`,n);let i=this.#s(t),s=await this.#r({input:n,logger:o,...r}),a=this.#a(s);i&&a&&(o.debug(`${this.#o}: parsed output`,a),i(...a))}};var Se=class{constructor(t){this.config=t}build(t){return new ue(t)}};import He from"typescript";import*as A from"ramda";import{globalRegistry as Ie,z as w}from"zod/v4";var De=(...e)=>e,be=(e,t,o=3)=>{if(!t)return U(e,w.void());let r=U(t,w.void()),n=e._zod.def.rest;if(!n||o<=0)return U(w.tuple(De(...e._zod.def.items,r)),w.void());let i=Ie.get(n)?.description,s=A.range(0,o).map(a=>{let p=[...e._zod.def.items].concat(A.range(1,a+1).map(f=>{let S=w.clone(n);return Ie.add(S,{description:`${i||"rest"}${f}`}),S})).concat(r);return U(w.tuple(De(...p)),w.void())});return w.union(s)},Pe=(e,{io:t})=>{let r=[w.toJSONSchema(e,{io:t,unrepresentable:"any",override:({jsonSchema:n})=>{typeof n.default=="bigint"&&delete n.default}})];for(;r.length;){let n=r.shift();if(A.is(Object,n)){if(n.$ref==="#")return!0;r.push(...A.values(n))}A.is(Array,n)&&r.push(...A.values(n))}return!1};import d from"typescript";import{globalRegistry as Oe,z as dt}from"zod/v4";var xe=(e,{onEach:t,rules:o,onMissing:r,ctx:n={}})=>{let i=o[pe(e)?"function":e._zod.def.type],a=i?i(e,{...n,next:f=>xe(f,{ctx:n,onEach:t,rules:o,onMissing:r})}):r(e,n),p=t&&t(e,{prev:a,...n});return p?{...a,...p}:a};import*as h from"ramda";import*as B from"ramda";import u from"typescript";var c=u.factory,H=[c.createModifier(u.SyntaxKind.ExportKeyword)],Q=(e,t)=>u.addSyntheticLeadingComment(e,u.SyntaxKind.MultiLineCommentTrivia,`* ${t} `,!0),Ue=(e,t)=>{let o=u.createSourceFile("print.ts","",u.ScriptTarget.Latest,!1,u.ScriptKind.TS);return u.createPrinter(t).printNode(u.EmitHint.Unspecified,e,o)},at=/^[A-Za-z_$][A-Za-z0-9_$]*$/,ct=e=>typeof e=="string"&&at.test(e)?c.createIdentifier(e):Fe(e),M=(e,t)=>typeof e=="number"?c.createKeywordTypeNode(e):typeof e=="string"||u.isIdentifier(e)?c.createTypeReferenceNode(e,t&&B.map(M,t)):e,Le=(e,t,{isOptional:o,isDeprecated:r,comment:n}={})=>{let i=M(t),s=c.createPropertySignature(void 0,ct(e),o?c.createToken(u.SyntaxKind.QuestionToken):void 0,o?c.createUnionTypeNode([i,M(u.SyntaxKind.UndefinedKeyword)]):i),a=B.reject(B.isNil,[r?"@deprecated":void 0,n]);return a.length?Q(s,a.join(" ")):s},Te=(e,t,{expose:o,comment:r}={})=>{let n=c.createTypeAliasDeclaration(o?H:void 0,e,void 0,t);return r?Q(n,r):n},Fe=e=>typeof e=="number"?c.createNumericLiteral(e):typeof e=="bigint"?c.createBigIntLiteral(e.toString()):typeof e=="boolean"?e?c.createTrue():c.createFalse():e===null?c.createNull():c.createStringLiteral(e),V=e=>c.createLiteralTypeNode(Fe(e)),pt=[u.SyntaxKind.AnyKeyword,u.SyntaxKind.BigIntKeyword,u.SyntaxKind.BooleanKeyword,u.SyntaxKind.NeverKeyword,u.SyntaxKind.NumberKeyword,u.SyntaxKind.ObjectKeyword,u.SyntaxKind.StringKeyword,u.SyntaxKind.SymbolKeyword,u.SyntaxKind.UndefinedKeyword,u.SyntaxKind.UnknownKeyword,u.SyntaxKind.VoidKeyword],_e=e=>pt.includes(e.kind);var{factory:l}=d,mt={[d.SyntaxKind.AnyKeyword]:"",[d.SyntaxKind.BigIntKeyword]:BigInt(0),[d.SyntaxKind.BooleanKeyword]:!1,[d.SyntaxKind.NumberKeyword]:0,[d.SyntaxKind.ObjectKeyword]:{},[d.SyntaxKind.StringKeyword]:"",[d.SyntaxKind.UndefinedKeyword]:void 0},Ne={name:h.path(["name","text"]),type:h.path(["type"]),optional:h.path(["questionToken"])},ut=({_zod:{def:e}})=>{let t=e.values.map(o=>o===void 0?M(d.SyntaxKind.UndefinedKeyword):V(o));return t.length===1?t[0]:l.createUnionTypeNode(t)},lt=({_zod:{def:e}},{next:t})=>{let o=[...e.parts],r=()=>{let s="";for(;o.length;){let a=o.shift();if(k(a)){o.unshift(a);break}s+=a??""}return s},n=l.createTemplateHead(r()),i=[];for(;o.length;){let s=t(o.shift()),a=r(),p=o.length?l.createTemplateMiddle:l.createTemplateTail;i.push(l.createTemplateLiteralTypeSpan(s,p(a)))}return i.length?l.createTemplateLiteralType(n,i):V(n.text)},ft=(e,{isResponse:t,next:o,makeAlias:r})=>{let n=()=>{let i=Object.entries(e._zod.def.shape).map(([s,a])=>{let{description:p,deprecated:f}=Oe.get(a)||{};return Le(s,o(a),{comment:p,isDeprecated:f,isOptional:(t?a._zod.optout:a._zod.optin)==="optional"})});return l.createTypeLiteralNode(i)};return Pe(e,{io:t?"output":"input"})?r(e,n):n()},yt=({_zod:{def:e}},{next:t})=>l.createArrayTypeNode(t(e.element)),ht=({_zod:{def:e}})=>l.createUnionTypeNode(Object.values(e.entries).map(V)),gt=({_zod:{def:e}},{next:t})=>{let o=new Map;for(let r of e.options){let n=t(r);o.set(_e(n)?n.kind:n,n)}return l.createUnionTypeNode(Array.from(o.values()))},St=e=>mt?.[e.kind],bt=({_zod:{def:e}},{next:t})=>l.createUnionTypeNode([t(e.innerType),V(null)]),xt=({_zod:{def:e}},{next:t})=>l.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:l.createRestTypeNode(t(e.rest)))),Tt=({_zod:{def:e}},{next:t})=>M("Record",[e.keyType,e.valueType].map(t)),Nt=h.tryCatch(e=>{if(!e.every(d.isTypeLiteralNode))throw new Error("Not objects");let t=h.chain(h.prop("members"),e),o=h.uniqWith((...r)=>{if(!h.eqBy(Ne.name,...r))return!1;if(h.both(h.eqBy(Ne.type),h.eqBy(Ne.optional))(...r))return!0;throw new Error("Has conflicting prop")},t);return l.createTypeLiteralNode(o)},(e,t)=>l.createIntersectionTypeNode(t)),Ot=({_zod:{def:e}},{next:t})=>Nt([e.left,e.right].map(t)),j=e=>()=>M(e),X=({_zod:{def:e}},{next:t})=>t(e.innerType),Be=e=>M(e?d.SyntaxKind.UnknownKeyword:d.SyntaxKind.AnyKeyword),kt=({_zod:{def:e}},{next:t,isResponse:o})=>{let r=e[o?"out":"in"],n=e[o?"in":"out"];if(!k(r,"transform"))return t(r);let i=t(n),s=oe(r,k(n,"date")?new Date:St(i)),a={number:d.SyntaxKind.NumberKeyword,bigint:d.SyntaxKind.BigIntKeyword,boolean:d.SyntaxKind.BooleanKeyword,string:d.SyntaxKind.StringKeyword,undefined:d.SyntaxKind.UndefinedKeyword,object:d.SyntaxKind.ObjectKeyword};return M(s&&a[s]||Be(o))},$t=()=>V(null),Et=({_zod:{def:e}},{makeAlias:t,next:o})=>t(e.getter,()=>o(e.getter())),Rt=()=>M("Date"),Zt=(e,{next:t})=>{let o=e._zod.bag.input._zod.def.items.map((n,i)=>{let{description:s}=Oe.get(n)||{};return l.createParameterDeclaration(void 0,void 0,l.createIdentifier(s?Z(y(s)):`${pe(n)?"cb":"p"}${i+1}`),void 0,t(n))}),{rest:r}=e._zod.bag.input._zod.def;if(r){let{description:n}=Oe.get(r)||{};o.push(l.createParameterDeclaration(void 0,l.createToken(d.SyntaxKind.DotDotDotToken),l.createIdentifier(n?Z(y(n)):"rest"),void 0,t(dt.array(r))))}return l.createFunctionTypeNode(void 0,o,t(e._zod.bag.output))},Mt={string:j(d.SyntaxKind.StringKeyword),number:j(d.SyntaxKind.NumberKeyword),bigint:j(d.SyntaxKind.BigIntKeyword),boolean:j(d.SyntaxKind.BooleanKeyword),any:j(d.SyntaxKind.AnyKeyword),undefined:j(d.SyntaxKind.UndefinedKeyword),never:j(d.SyntaxKind.NeverKeyword),void:j(d.SyntaxKind.VoidKeyword),unknown:j(d.SyntaxKind.UnknownKeyword),date:Rt,null:$t,array:yt,tuple:xt,record:Tt,object:ft,literal:ut,template_literal:lt,intersection:Ot,union:gt,default:X,enum:ht,optional:X,nonoptional:X,nullable:bt,catch:X,pipe:kt,lazy:Et,readonly:X,function:Zt},ke=(e,t)=>xe(e,{rules:Mt,onMissing:({},{isResponse:o})=>Be(o),ctx:t});var Ct="root",Ve=["emission","actions"],$e=class{#o=[];#t={};#e={path:c.createIdentifier("path"),socket:c.createIdentifier("Socket"),socketBase:c.createIdentifier("SocketBase"),ioClient:c.createStringLiteral("socket.io-client"),emission:c.createIdentifier(y(Ve[0])),actions:c.createIdentifier(y(Ve[1]))};registry={};#n(t,o,r){let n=this.#t[t].get(o)?.name?.text;if(!n){n=`Type${this.#t[t].size+1}`;let i=c.createLiteralTypeNode(c.createNull());this.#t[t].set(o,Te(n,i)),this.#t[t].set(o,Te(n,r()))}return c.createTypeReferenceNode(n)}constructor({config:{namespaces:t},actions:o,maxOverloads:r=3}){this.#o.push(c.createImportDeclaration(void 0,c.createImportClause(!0,void 0,c.createNamedImports([c.createImportSpecifier(!1,this.#e.socket,this.#e.socketBase)])),this.#e.ioClient));for(let[n,{emission:i}]of Object.entries(t)){this.#t[n]=new Map,this.registry[n]={emission:[],actions:[]};let s={makeAlias:this.#n.bind(this,n)};for(let[a,{schema:p,ack:f}]of Object.entries(i)){let S=ke(be(p,f,r),{isResponse:!0,...s});this.registry[n].emission.push({event:a,node:S})}for(let a of o)if(a.namespace===n){let{event:p,inputSchema:f,outputSchema:S}=a,x=ke(be(f,S,r),{isResponse:!1,...s});this.registry[n].actions.push({event:p,node:x})}}for(let n in this.registry){let i=y(n)||y(Ct),s=c.createVariableStatement(H,c.createVariableDeclarationList([c.createVariableDeclaration(this.#e.path,void 0,void 0,c.createStringLiteral(F(n)))],He.NodeFlags.Const));Q(s,`@desc The actual path of the ${i} namespace`);let a=Object.entries(this.registry[n]).map(([f,S])=>c.createInterfaceDeclaration(H,y(f),void 0,void 0,S.map(({event:x,node:J})=>c.createPropertySignature(void 0,x,void 0,J)))),p=c.createTypeAliasDeclaration(H,this.#e.socket,void 0,c.createTypeReferenceNode(this.#e.socketBase,[c.createTypeReferenceNode(this.#e.emission),c.createTypeReferenceNode(this.#e.actions)]));Q(p,`@example const socket: ${i}.${this.#e.socket.text} = io(${i}.${this.#e.path.text})`),this.#o.push(c.createModuleDeclaration(H,c.createIdentifier(i),c.createModuleBlock([s,...this.#t[n].values(),...a,p]),He.NodeFlags.Namespace))}}print(t){return this.#o.map(o=>Ue(o,t)).join(`
`)}};import{z as te}from"zod/v4";import Kt from"yaml";var fe=class{document;constructor(t){this.document={asyncapi:"3.0.0",...t,servers:{},channels:{},components:{}}}addServer(t,o){return this.document.servers={...this.document.servers,[t]:o},this}addChannel(t,o){return this.document.channels={...this.document.channels,[t]:o},this}addOperation(t,o){return this.document.operations={...this.document.operations,[t]:o},this}addSecurityScheme(t,o){return this.document.components={...this.document.components,securitySchemes:{...this.document.components?.securitySchemes,[t]:o}},this}addSchema(t,o){return this.document.components={...this.document.components,schemas:{...this.document.components?.schemas,[t]:o}},this}getSpec(){return this.document}getSpecAsJson(t,o){return JSON.stringify(this.document,t,o)}getSpecAsYaml(){return Kt.stringify(this.document)}};import*as D from"ramda";import{globalRegistry as zt,z as Re}from"zod/v4";function Ee(e){return"$ref"in e}var We={integer:0,number:0,string:"",boolean:!1,object:{},null:null,array:[]},wt=({zodSchema:e,jsonSchema:t})=>{if(!k(e,"union")||!("discriminator"in e._zod.def))return t;let o=e._zod.def.discriminator;return{...t,discriminator:t.discriminator??{propertyName:o}}},At=({jsonSchema:e})=>{if(!e.anyOf)return e;let t=e.anyOf[0];return Object.assign(t,{type:Ut(t.type)})},jt=()=>({type:"string",format:"bigint",pattern:/^-?\d+$/.source}),vt=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest!==null?t:{...t,items:{not:{}}},It=({zodSchema:e,jsonSchema:t},o)=>{let r=e._zod.def[o.isResponse?"out":"in"],n=e._zod.def[o.isResponse?"in":"out"];if(!k(r,"transform"))return t;let i=W(Me(n,{ctx:o}));if(!Ee(i))if(o.isResponse){let s=oe(r,k(n,"date")?new Date:Pt(i));if(s&&["number","string","boolean"].includes(s))return{...t,type:s}}else{let{type:s,...a}=i;return{...a,format:`${a.format||s} (preprocessed)`}}return t},Dt=e=>e in We,W=({$ref:e,type:t,allOf:o,oneOf:r,anyOf:n,not:i,...s})=>{if(e)return{$ref:e};let a={type:t&&Dt(t)?t:void 0,...s};for(let[p,f]of D.toPairs({allOf:o,oneOf:r,anyOf:n}))f&&(a[p]=f.map(W));return i&&(a.not=W(i)),a},Pt=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return We?.[t]},Ut=e=>e==="null"?e:typeof e=="string"?[e,"null"]:e&&[...new Set(e).add("null")],Lt=()=>({format:"date"}),Ft={nullable:At,union:wt,bigint:jt,tuple:vt,pipe:It,date:Lt},_t=(e,t,o)=>{let r=[e,t];for(;r.length;){let n=r.shift();if(D.is(Object,n)){if(Ee(n)&&!n.$ref.startsWith("#/components")){let i=n.$ref.split("/").pop(),s=t[i];s&&(n.$ref=o.makeRef(s.id||s,W(s)).$ref);continue}r.push(...D.values(n))}D.is(Array,n)&&r.push(...D.values(n))}return e},Me=(e,{ctx:t,rules:o=Ft})=>{let{$defs:r={},properties:n={}}=Re.toJSONSchema(Re.object({subject:e}),{unrepresentable:"any",io:t.isResponse?"output":"input",override:i=>{let s=o[i.zodSchema._zod.def.type];if(s){let a={...s(i,t)};for(let p in i.jsonSchema)delete i.jsonSchema[p];Object.assign(i.jsonSchema,a)}}});return _t(n.subject,r,t)},Ze=e=>{let{examples:t,example:o}=zt.get(e)||{};if(t)return Array.isArray(t)?t:Object.values(t).map(({value:r})=>r);if(o!==void 0)return[o];if(k(e,"tuple")){let r=[];for(let n of e._zod.def.items){let i=Ze(n);i.length&&r.push(i[0])}if(r.length!==e._zod.def.items.length)return[];if(e._zod.def.rest){let n=Ze(e._zod.def.rest);n.length&&r.push(n[0])}if(r.length)return[r]}return[]},ee=({event:e,schema:t,isResponse:o,isAck:r,makeRef:n})=>{let i={name:r?void 0:e,title:r?`Acknowledgement for ${e}`:e,payload:W(Me(t,{ctx:{isResponse:o,makeRef:n}}))},s=Ze(t).map(a=>({payload:a}));return s.length&&(i.examples=s),i},Ce=({isResponse:e,channelId:t,messageId:o,ackId:r,event:n,ns:i,securityIds:s})=>({action:e?"send":"receive",channel:{$ref:`#/channels/${t}`},messages:[{$ref:`#/channels/${t}/messages/${o}`}],title:n,summary:`${e?"Outgoing":"Incoming"} event ${n}`,description:`The message ${e?"produced":"consumed"} by the application within the ${i} namespace`,security:s&&s.length?s.map(a=>({$ref:`#/components/securitySchemes/${a}`})):void 0,reply:r?{address:{location:"$message.payload#",description:"Last argument: acknowledgement handler"},channel:{$ref:`#/channels/${t}`},messages:[{$ref:`#/channels/${t}/messages/${r}`}]}:void 0}),Ke=(e,{extra:t,makeRef:o})=>Object.assign(W(Me(Re.object(e),{ctx:{isResponse:!1,makeRef:o}})),t);var ze=class extends fe{#o=new Map;#t(t,o,r=this.#o.get(t)){return r||(r=`Schema${this.#o.size+1}`,this.#o.set(t,r)),this.addSchema(r,o),{$ref:`#/components/schemas/${r}`}}#e(){return{bindingVersion:"0.1.0",method:"GET",headers:Ke({connection:te.literal("Upgrade").optional(),upgrade:te.literal("websocket").optional()},{makeRef:this.#t.bind(this)}),query:Ke({EIO:te.literal("4").describe("The version of the protocol"),transport:te.enum(["polling","websocket"]).describe("The name of the transport"),sid:te.string().optional().describe("The session identifier")},{makeRef:this.#t.bind(this),extra:{externalDocs:{description:"Engine.IO Protocol",url:"https://socket.io/docs/v4/engine-io-protocol/"}}})}}constructor({actions:t,config:{namespaces:o,security:r},title:n,version:i,documentId:s,description:a,contact:p,license:f,servers:S={}}){super({info:{title:n,version:i,contact:p,license:f,description:a},id:s,defaultContentType:"text/plain"});let x=[];for(let[C,$]of Object.entries(r)){let v=Z(y(`server security ${C}`));this.addSecurityScheme(v,$),x.push(v)}for(let C in S){let $=new URL(S[C].url);this.addServer(C,{description:S[C].description,host:$.host,pathname:$.pathname,protocol:$.protocol.slice(0,-1),security:x.length?x.map(v=>({$ref:`#/components/securitySchemes/${v}`})):void 0}),this.document.id||(this.document.id=`urn:${$.host.split(".").concat($.pathname.slice(1).split("/")).join(":")}`)}let J=this.#e();for(let[C,{emission:$,security:v}]of Object.entries(o)){let I=F(C),T=y(I)||"Root",N={},Y=[];for(let[m,E]of Object.entries(v)){let R=Z(y(`${T} security ${m}`));this.addSecurityScheme(R,E),Y.push(R)}for(let[m,{schema:E,ack:R}]of Object.entries($)){let K={event:m,makeRef:this.#t.bind(this)},O=Z(y(`${T} outgoing ${m}`)),g=Z(y(`${T} ack for outgoing ${m}`));N[O]=ee({...K,schema:E,isResponse:!0}),R&&(N[g]=ee({...K,schema:R,isResponse:!1,isAck:!0})),this.addOperation(y(`${T} send operation ${m}`),Ce({...K,ns:I,channelId:T,messageId:O,isResponse:!0,ackId:R&&g}))}for(let m of t)if(m.namespace===I){let{event:E,inputSchema:R,outputSchema:K}=m,O={event:E,makeRef:this.#t.bind(this)},g=Z(y(`${T} incoming ${E}`)),z=Z(y(`${T} ack for incoming ${E}`));N[g]=ee({...O,schema:R,isResponse:!1}),K&&(N[z]=ee({...O,schema:K,isResponse:!0,isAck:!0})),this.addOperation(y(`${T} recv operation ${E}`),Ce({event:E,ns:I,channelId:T,messageId:g,isResponse:!1,ackId:K&&z,securityIds:Y}))}this.addChannel(T,{address:I,title:`Namespace ${I}`,bindings:{ws:J},messages:N})}}};export{me as AbstractAction,Se as ActionsFactory,ae as Config,ze as Documentation,_ as InputValidationError,$e as Integration,G as OutputValidationError,nt as attachSockets,it as createSimpleConfig};