@lowerdeck/rpc-server 1.0.6 → 1.0.8

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/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=require("@lowerdeck/error"),r=require("@lowerdeck/execution-context"),t=require("@lowerdeck/id"),n=require("@lowerdeck/memo"),o=require("@lowerdeck/sentry"),a=require("@lowerdeck/serialize"),i=require("@lowerdeck/validation");function s(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach(function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}}),r.default=e,r}var u=/*#__PURE__*/s(require("cookie"));function c(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=Array(r);t<r;t++)n[t]=e[t];return n}function l(e,r){var t="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(t)return(t=t.call(e)).next.bind(t);if(Array.isArray(e)||(t=function(e,r){if(e){if("string"==typeof e)return c(e,r);var t={}.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?c(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){t&&(e=t);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},d.apply(null,arguments)}const f="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function h(e,r,t){if(!e.s){if(t instanceof p){if(!t.s)return void(t.o=h.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(h.bind(null,e,r),h.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}var p=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){var n=new e,o=this.s;if(o){var a=1&o?r:t;if(a){try{h(n,1,a(this.v))}catch(e){h(n,2,e)}return n}return this}return this.o=function(e){try{var o=e.v;1&e.s?h(n,1,r?r(o):o):t?h(n,1,t(o)):h(n,2,o)}catch(e){h(n,2,e)}},n},e}();function v(e){return e instanceof p&&1&e.s}var m=/*#__PURE__*/function(){function e(e){void 0===e&&(e=[]),this._middleware=void 0,this._middleware=e}var r=e.prototype;return r.use=function(r,t){return new e([].concat(this._middleware,[function(e){try{var n,o=function(t){if(n)return t;var o=r(e);return a&&e.sharedMiddlewareMemo.set(a,o),Promise.resolve(o)},a=null==t||null==t.getSharedMemoKey?void 0:t.getSharedMemoKey(e),i=function(){if(a&&e.sharedMiddlewareMemo.has(a))return Promise.resolve(e.sharedMiddlewareMemo.get(a)).then(function(e){return n=1,e})}();return Promise.resolve(i&&i.then?i.then(o):o(i))}catch(e){return Promise.reject(e)}}]))},r.createMiddleware=function(e,r){return function(t){return function(n){try{var o,a=function(r){if(o)return r;var a=e(n,t);return i&&n.sharedMiddlewareMemo.set(i,a),Promise.resolve(a)},i=null==r||null==r.getSharedMemoKey?void 0:r.getSharedMemoKey(n,t),s=function(){if(i&&n.sharedMiddlewareMemo.has(i))return Promise.resolve(n.sharedMiddlewareMemo.get(i)).then(function(e){return o=1,e})}();return Promise.resolve(s&&s.then?s.then(a):a(s))}catch(e){return Promise.reject(e)}}}},r.handler=function(){return new y([].concat(this._middleware))},r.controller=function(e){return e},e}(),y=/*#__PURE__*/function(){function r(e){void 0===e&&(e=[]),this._middleware=void 0,this._handler=void 0,this._validation=void 0,this._middleware=e}var t=r.prototype;return t.do=function(e){if(null!=this._handler)throw new Error("Handler already defined");return this._handler=e,this},t.use=function(e){return this._middleware.push(e),this},t.input=function(e){if(null!=this._validation)throw new Error("Input validation already defined");return this._validation=e,this},t.run=function(r,t){try{var n=function(){return Promise.resolve(o._handler(d({},s,{input:a,body:void 0}))).then(function(e){return{response:e}})},o=this;if(!o._handler)throw new Error("Handler not defined");var a=r.body;if(o._validation){var i=o._validation.validate(r.body);if(!i.success)throw new e.ServiceError(e.validationError({errors:i.errors,entity:"call_data"}));a=i.value}var s=d({},t,r,{body:a}),u=function(e,r){if("function"==typeof e[f]){var t,n,o,a=function(e){try{for(;!(t=i.next()).done;)if((e=r(t.value))&&e.then){if(!v(e))return void e.then(a,o||(o=h.bind(null,n=new p,2)));e=e.v}n?h(n,1,e):n=e}catch(e){h(n||(n=new p),2,e)}},i=e[f]();if(a(),i.return){var s=function(e){try{t.done||i.return()}catch(e){}return e};if(n&&n.then)return n.then(s,function(e){throw s(e)});s()}return n}if(!("length"in e))throw new TypeError("Object is not iterable");for(var u=[],c=0;c<e.length;c++)u.push(e[c]);return function(e,r){var t,n,o=-1;return function a(i){try{for(;++o<e.length;)if((i=r(o))&&i.then){if(!v(i))return void i.then(a,n||(n=h.bind(null,t=new p,2)));i=i.v}t?h(t,1,i):t=i}catch(e){h(t||(t=new p),2,e)}}(),t}(u,function(e){return r(u[e])})}(o._middleware,function(e){return Promise.resolve(e(s)).then(function(e){e&&(s=d({},s,e))})});return Promise.resolve(u&&u.then?u.then(n):n())}catch(e){return Promise.reject(e)}},r}(),g=o.getSentry(),w=i.v.object({calls:i.v.array(i.v.object({id:i.v.string(),name:i.v.string(),payload:i.v.any()}))}),b=o.getSentry();exports.Group=m,exports.Handler=y,exports.createServer=function(r){return function(t){var n=function(e){return Object.entries(e).flatMap(function(e){var r=e[0],t=e[1];return t instanceof y?[r]:"object"==typeof t?n(t).map(function(e){return r+":"+e}):[]})};return{handlerNames:n(t),runMany:function(n,o){try{return Promise.resolve(Promise.all(o.calls.map(function(a,i){try{return Promise.resolve(function(n,o,a){try{var i=d({},n,{body:o.payload});return Promise.resolve(function(r,a){try{var s=(u=function(e){for(var r=e.split(":"),n=t;n&&r.length>0;)if(!(n=n[r.shift()]))return null;return n&&n instanceof y?n:null}(o.name))?Promise.resolve(u.run(i,{})).then(function(e){return{status:200,request:n,response:e.response}}):{request:i,status:404,response:e.notFoundError({entity:"handler"}).toResponse()}}catch(e){return a(e)}var u;return s&&s.then?s.then(void 0,a):s}(0,function(t){return console.error(t),e.isServiceError(t)?(t.data.status>=500&&b.captureException(t,{tags:{reqId:a}}),{request:i,status:t.data.status,response:t.toResponse()}):(b.captureException(t,{tags:{reqId:a}}),null==r.onError||r.onError({callName:o.name,callId:o.id,request:n,error:t,reqId:a}),{request:i,status:500,response:e.internalServerError().toResponse()})}))}catch(e){return Promise.reject(e)}}(n,a,o.requestId)).then(function(e){try{null==r.onRequest||r.onRequest({reqId:o.requestId,callId:a.id,callName:a.name,request:e.request,response:{status:e.status,body:e.response}})}catch(e){b.captureException(e),console.error(e)}return{__typename:"rpc.response.call",id:a.id,name:a.name,status:e.status,result:e.response}})}catch(e){return Promise.reject(e)}}))).then(function(e){return{status:Math.max.apply(Math,e.map(function(e){return e.status})),body:{__typename:"rpc.response",calls:e}}})}catch(e){return Promise.reject(e)}}}}},exports.rpcMux=function(o,i){var s=new Map(i.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:o.path,fetch:function(c){try{var d,f,h,p=function(o){var d,f,p,v;if(h)return o;var y=c.headers.get("sentry-trace"),P=null!=(d=Array.isArray(y)?y.join(","):y)?d:void 0,q=c.headers.get("baggage"),M=function(e){if("string"==typeof e){var r=e.split(",").map(function(e){return e.trim()}).filter(Boolean);return r.length>0?r[0]:void 0}}(null!=(f=null!=(p=null!=(v=c.headers.get("lowerdeck-connecting-ip"))?v:c.headers.get("cf-connecting-ip"))?p:c.headers.get("x-forwarded-for"))?f:c.headers.get("x-real-ip")),_=new Headers;if(m)for(var x=0,E=Object.entries(S);x<E.length;x++){var O=E[x];_.append(O[0],O[1])}return Promise.resolve(g.withIsolationScope(function(){try{return Promise.resolve(g.continueTrace({sentryTrace:P,baggage:q},function(){try{var o,d;return Promise.resolve(g.startSpan({name:"rpc request",op:"rpc.server",attributes:{ip:M,transport:"http",ua:null!=(o=c.headers.get("user-agent"))?o:"",origin:null!=(d=c.headers.get("origin"))?d:""}},function(){try{try{var o,d=[],f=t.generateCustomId("req_"),h=n.memo(function(){var e;return u.parse(null!=(e=c.headers.get("cookie"))?e:"")}),p={url:c.url,headers:c.headers,query:b.searchParams,body:j,rawBody:j,ip:M,requestId:f,getCookies:function(){return h()},getCookie:function(e){return h()[e]},setCookie:function(e,r,t){var n=u.serialize(e,r,t);_.append("Set-Cookie",n)},beforeSend:function(e){d.push(e)},sharedMiddlewareMemo:new Map,appendHeaders:function(e){for(var r=0,t=Object.entries(e);r<t.length;r++){var n=t[r],o=n[0],a=n[1];if(Array.isArray(a))for(var i,s=l(a);!(i=s()).done;)_.append(o,i.value);else _.append(o,a)}}};return g.getCurrentScope().setContext("rpc.request",{url:c.url,query:Object.fromEntries(b.searchParams.entries())}),g.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:j,contentType:"application/json"}),Promise.resolve(r.provideExecutionContext(r.createExecutionContext({type:"request",contextId:f,ip:null!=M?M:"0.0.0.0",userAgent:null!=(o=c.headers.get("user-agent"))?o:""}),function(){try{var r=new Map,n={body:{__typename:"rpc.response",calls:[]},status:200},o=b.pathname.split("/").filter(Boolean),u=o[o.length-1],c="$"==u[0];if(c){var h,v=u.slice(1),m=s.get(v);if(null==m)return Promise.resolve(new Response(JSON.stringify(e.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:_}));var y=null!=(h=r.get(m))?h:[];y.push({id:t.generateCustomId("call_"),name:v,payload:j}),r.set(m,y)}else{var g=w.validate(j);if(!g.success)return Promise.resolve(new Response(JSON.stringify(e.validationError({errors:g.errors,entity:"request_data"}).toResponse()),{status:406,headers:_}));for(var P,S=l(g.value.calls);!(P=S()).done;){var q,M=P.value,x=s.get(M.name);if(null==x)return Promise.resolve(new Response(JSON.stringify(e.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:_}));var E=null!=(q=r.get(x))?q:[];E.push(M),r.set(x,E)}}return Promise.resolve(Promise.all(Array.from(r.entries()).map(function(e){var r=e[0],t=e[1];try{return Promise.resolve(i[r].runMany(p,{requestId:f,calls:t})).then(function(e){var r;n.status=Math.max(n.status,e.status),(r=n.body.calls).push.apply(r,e.body.calls)})}catch(e){return Promise.reject(e)}}))).then(function(){return _.append("x-req-id",f),_.append("content-type","application/rpc+json"),_.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(d.map(function(e){return e()}))).then(function(){return new Response(a.serialize.encode(c?n.body.calls[0].result:n.body),{status:n.status,headers:_})})})}catch(e){return Promise.reject(e)}}))}catch(r){return console.error(r),g.captureException(r),Promise.resolve(new Response(JSON.stringify(e.internalServerError().toResponse()),{status:500,headers:_}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))},v=null!=(d=c.headers.get("origin"))?d:"",m=!1;if(o.cors&&"domains"in o.cors)try{var y=new URL(v).hostname.split(".").slice(-2).join(".");m=o.cors.domains.includes(y)}catch(e){}else o.cors&&"check"in o.cors&&(m=o.cors.check(v));var b=new URL(c.url),P=null==(f=o.cors)||null==(f=f.headers)?void 0:f.join(", ");P&&(P=(", "+P).trim());var S=m?{"access-control-allow-origin":v,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace"+(null!=P?P:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==c.method)return Promise.resolve(m?new Response(null,{status:204,headers:S}):new Response(null,{status:403}));var j=null,q=function(e,r){try{var t=e()}catch(e){return r()}return t&&t.then?t.then(void 0,r):t}(function(){var e=a.serialize.decode;return Promise.resolve(c.text()).then(function(r){j=e.call(a.serialize,r)})},function(){var r=new Response(JSON.stringify(e.notAcceptableError({message:"Invalid JSON"}).toResponse()),{status:406});return h=1,r});return Promise.resolve(q&&q.then?q.then(p):p(q))}catch(e){return Promise.reject(e)}}}};
1
+ var e=require("@lowerdeck/error"),r=require("@lowerdeck/telemetry"),t=require("@lowerdeck/execution-context"),n=require("@lowerdeck/id"),o=require("@lowerdeck/memo"),s=require("@lowerdeck/sentry"),a=require("@lowerdeck/serialize"),i=require("@lowerdeck/validation");function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach(function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}}),r.default=e,r}var c=/*#__PURE__*/u(require("cookie"));function l(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=Array(r);t<r;t++)n[t]=e[t];return n}function d(e,r){var t="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(t)return(t=t.call(e)).next.bind(t);if(Array.isArray(e)||(t=function(e,r){if(e){if("string"==typeof e)return l(e,r);var t={}.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?l(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){t&&(e=t);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function f(){return f=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},f.apply(null,arguments)}const p="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function h(e,r,t){if(!e.s){if(t instanceof v){if(!t.s)return void(t.o=h.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(h.bind(null,e,r),h.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}var v=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){var n=new e,o=this.s;if(o){var s=1&o?r:t;if(s){try{h(n,1,s(this.v))}catch(e){h(n,2,e)}return n}return this}return this.o=function(e){try{var o=e.v;1&e.s?h(n,1,r?r(o):o):t?h(n,1,t(o)):h(n,2,o)}catch(e){h(n,2,e)}},n},e}();function m(e){return e instanceof v&&1&e.s}var y=/*#__PURE__*/function(){function e(e){void 0===e&&(e=[]),this._middleware=void 0,this._middleware=e}var r=e.prototype;return r.use=function(r,t){return new e([].concat(this._middleware,[function(e){try{var n,o=function(t){if(n)return t;var o=r(e);return s&&e.sharedMiddlewareMemo.set(s,o),Promise.resolve(o)},s=null==t||null==t.getSharedMemoKey?void 0:t.getSharedMemoKey(e),a=function(){if(s&&e.sharedMiddlewareMemo.has(s))return Promise.resolve(e.sharedMiddlewareMemo.get(s)).then(function(e){return n=1,e})}();return Promise.resolve(a&&a.then?a.then(o):o(a))}catch(e){return Promise.reject(e)}}]))},r.createMiddleware=function(e,r){return function(t){return function(n){try{var o,s=function(r){if(o)return r;var s=e(n,t);return a&&n.sharedMiddlewareMemo.set(a,s),Promise.resolve(s)},a=null==r||null==r.getSharedMemoKey?void 0:r.getSharedMemoKey(n,t),i=function(){if(a&&n.sharedMiddlewareMemo.has(a))return Promise.resolve(n.sharedMiddlewareMemo.get(a)).then(function(e){return o=1,e})}();return Promise.resolve(i&&i.then?i.then(s):s(i))}catch(e){return Promise.reject(e)}}}},r.handler=function(){return new g([].concat(this._middleware))},r.controller=function(e){return e},e}(),g=/*#__PURE__*/function(){function r(e){void 0===e&&(e=[]),this._middleware=void 0,this._handler=void 0,this._validation=void 0,this._middleware=e}var t=r.prototype;return t.do=function(e){if(null!=this._handler)throw new Error("Handler already defined");return this._handler=e,this},t.use=function(e){return this._middleware.push(e),this},t.input=function(e){if(null!=this._validation)throw new Error("Input validation already defined");return this._validation=e,this},t.run=function(r,t){try{var n=function(){return Promise.resolve(o._handler(f({},i,{input:s,body:void 0}))).then(function(e){return{response:e}})},o=this;if(!o._handler)throw new Error("Handler not defined");var s=r.body;if(o._validation){var a=o._validation.validate(r.body);if(!a.success)throw new e.ServiceError(e.validationError({errors:a.errors,entity:"call_data"}));s=a.value}var i=f({},t,r,{body:s}),u=function(e,r){if("function"==typeof e[p]){var t,n,o,s=function(e){try{for(;!(t=a.next()).done;)if((e=r(t.value))&&e.then){if(!m(e))return void e.then(s,o||(o=h.bind(null,n=new v,2)));e=e.v}n?h(n,1,e):n=e}catch(e){h(n||(n=new v),2,e)}},a=e[p]();if(s(),a.return){var i=function(e){try{t.done||a.return()}catch(e){}return e};if(n&&n.then)return n.then(i,function(e){throw i(e)});i()}return n}if(!("length"in e))throw new TypeError("Object is not iterable");for(var u=[],c=0;c<e.length;c++)u.push(e[c]);return function(e,r){var t,n,o=-1;return function s(a){try{for(;++o<e.length;)if((a=r(o))&&a.then){if(!m(a))return void a.then(s,n||(n=h.bind(null,t=new v,2)));a=a.v}t?h(t,1,a):t=a}catch(e){h(t||(t=new v),2,e)}}(),t}(u,function(e){return r(u[e])})}(o._middleware,function(e){return Promise.resolve(e(i)).then(function(e){e&&(i=f({},i,e))})});return Promise.resolve(u&&u.then?u.then(n):n())}catch(e){return Promise.reject(e)}},r}();function w(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var b="production"!==process.env.NODE_ENV,P=s.getSentry(),S=r.trace.getTracer("lowerdeck.rpc-server"),q=i.v.object({calls:i.v.array(i.v.object({id:i.v.string(),name:i.v.string(),payload:i.v.any()}))});function j(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var E=s.getSentry(),R=r.trace.getTracer("lowerdeck.rpc-server.calls");exports.Group=y,exports.Handler=g,exports.createServer=function(t){return function(n){var o=function(e){return Object.entries(e).flatMap(function(e){var r=e[0],t=e[1];return t instanceof g?[r]:"object"==typeof t?o(t).map(function(e){return r+":"+e}):[]})};return{handlerNames:o(n),runMany:function(o,s){try{return Promise.resolve(Promise.all(s.calls.map(function(a,i){try{return Promise.resolve(function(o,s,a){try{var i,u=function(t){if(i)return t;var n="rpc call: "+s.name;return Promise.resolve(R.startActiveSpan(n,function(t){try{t.setAttribute("sentry.op","rpc.server.call"),t.setAttribute("rpc.system","lowerdeck"),t.setAttribute("rpc.method",s.name),t.setAttribute("rpc.request_id",a),t.setAttribute("rpc.call_id",s.id),t.setAttribute("rpc.description",n),t.setAttribute("sentry.description",n);var o=function(e){return t.setAttribute("rpc.response.status_code",e.status),e.status>=500&&t.setStatus({code:r.SpanStatusCode.ERROR,message:"RPC call failed with status "+e.status}),e};return Promise.resolve(function(n,s){try{var a=j(function(){return Promise.resolve(l()).then(function(e){return o({request:e.request,status:e.status,response:e.response})})},function(n){return t.recordException(n),t.setStatus({code:r.SpanStatusCode.ERROR,message:n instanceof Error?n.message:String(n)}),o({request:c,status:500,response:e.internalServerError().toResponse()})})}catch(e){return s(!0,e)}return a&&a.then?a.then(s.bind(null,!1),s.bind(null,!0)):s(!1,a)}(0,function(e,r){if(t.end(),e)throw r;return r}))}catch(e){return Promise.reject(e)}}))},c=f({},o,{body:s.payload}),l=function(){try{return Promise.resolve(j(function(){var r=function(e){for(var r=e.split(":"),t=n;t&&r.length>0;)if(!(t=t[r.shift()]))return null;return t&&t instanceof g?t:null}(s.name);return r?Promise.resolve(r.run(c,{})).then(function(e){return{status:200,request:o,response:e.response}}):{request:c,status:404,response:e.notFoundError({entity:"handler"}).toResponse()}},function(r){if(console.error(r),e.isServiceError(r))return r.data.status>=500&&E.captureException(r,{tags:{reqId:a}}),{request:c,status:r.data.status,response:r.toResponse()};throw E.captureException(r,{tags:{reqId:a}}),null==t.onError||t.onError({callName:s.name,callId:s.id,request:o,error:r,reqId:a}),r}))}catch(e){return Promise.reject(e)}},d=r.isTelemetryEnabled()&&r.hasActiveSpan(),p=function(){if(!d)return Promise.resolve(l()).then(function(e){return i=1,{request:e.request,status:e.status,response:e.response}})}();return Promise.resolve(p&&p.then?p.then(u):u(p))}catch(e){return Promise.reject(e)}}(o,a,s.requestId)).then(function(e){try{null==t.onRequest||t.onRequest({reqId:s.requestId,callId:a.id,callName:a.name,request:e.request,response:{status:e.status,body:e.response}})}catch(e){E.captureException(e),console.error(e)}return{__typename:"rpc.response.call",id:a.id,name:a.name,status:e.status,result:e.response}})}catch(e){return Promise.reject(e)}}))).then(function(e){return{status:Math.max.apply(Math,e.map(function(e){return e.status})),body:{__typename:"rpc.response",calls:e}}})}catch(e){return Promise.reject(e)}}}}},exports.rpcMux=function(s,i){var u=new Map(i.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:s.path,fetch:function(l){try{var f,p,h,v,m=function(f){var p,h,m,y;if(v)return f;var j=l.headers.get("sentry-trace"),R=null!=(p=Array.isArray(j)?j.join(","):j)?p:void 0,x=l.headers.get("baggage"),A=function(e){if("string"==typeof e){var r=e.split(",").map(function(e){return e.trim()}).filter(Boolean);return r.length>0?r[0]:void 0}}(null!=(h=null!=(m=null!=(y=l.headers.get("lowerdeck-connecting-ip"))?y:l.headers.get("cf-connecting-ip"))?m:l.headers.get("x-forwarded-for"))?h:l.headers.get("x-real-ip")),O=new Headers;if(g)for(var k=0,C=Object.entries(_);k<C.length;k++){var I=C[k];O.append(I[0],I[1])}var N=r.propagation.extract(r.otelContext.active(),l.headers,{get:function(e,r){var t;return null!=(t=e.get(r))?t:void 0},keys:function(e){return Array.from(e.keys())}}),T=r.trace.getSpanContext(N),J=r.isTelemetryEnabled()&&(!!T||!!s.allowRootSpan),z=function(e,r){var t,n=e.pathname.split("/").filter(Boolean),o=null!=(t=n[n.length-1])?t:"";if(o.startsWith("$")&&o.length>1)return o.slice(1);var s=[];if(r&&"object"==typeof r&&Array.isArray(r.calls)&&(s=r.calls.map(function(e){return"string"==typeof(null==e?void 0:e.name)?e.name.trim():""}).filter(Boolean)),1==s.length)return s[0];if(s.length>1){var a=s.slice(0,3).join(", ");return s.length>3?a+", +"+(s.length-3)+" more":a}return e.pathname}(E,M),B="rpc request: "+z,H="rpc.server.request",K=function(){try{return Promise.resolve(P.withIsolationScope(function(){try{return Promise.resolve(P.continueTrace({sentryTrace:R,baggage:x},function(){try{var r,s;return Promise.resolve(P.startSpan({name:B,op:H,attributes:{"sentry.op":H,"rpc.request.target":z,"rpc.description":B,"sentry.description":B,ip:A,transport:"http",ua:null!=(r=l.headers.get("user-agent"))?r:"",origin:null!=(s=l.headers.get("origin"))?s:""}},function(){try{try{var r,s=[],f=n.generateCustomId("req_"),p=o.memo(function(){var e;return c.parse(null!=(e=l.headers.get("cookie"))?e:"")}),h={url:l.url,headers:l.headers,query:E.searchParams,body:M,rawBody:M,ip:A,requestId:f,getCookies:function(){return p()},getCookie:function(e){return p()[e]},setCookie:function(e,r,t){var n=c.serialize(e,r,t);O.append("Set-Cookie",n)},beforeSend:function(e){s.push(e)},sharedMiddlewareMemo:new Map,appendHeaders:function(e){for(var r=0,t=Object.entries(e);r<t.length;r++){var n=t[r],o=n[0],s=n[1];if(Array.isArray(s))for(var a,i=d(s);!(a=i()).done;)O.append(o,a.value);else O.append(o,s)}}};return P.getCurrentScope().setContext("rpc.request",{url:l.url,query:Object.fromEntries(E.searchParams.entries())}),P.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:M,contentType:"application/json"}),Promise.resolve(t.provideExecutionContext(t.createExecutionContext({type:"request",contextId:f,ip:null!=A?A:"0.0.0.0",userAgent:null!=(r=l.headers.get("user-agent"))?r:""}),function(){try{var r=new Map,t={body:{__typename:"rpc.response",calls:[]},status:200},o=E.pathname.split("/").filter(Boolean),c=o[o.length-1],l="$"==c[0];if(l){var p,v=c.slice(1),m=u.get(v);if(null==m)return Promise.resolve(new Response(JSON.stringify(e.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:O}));var y=null!=(p=r.get(m))?p:[];y.push({id:n.generateCustomId("call_"),name:v,payload:M}),r.set(m,y)}else{var g=q.validate(M);if(!g.success)return Promise.resolve(new Response(JSON.stringify(e.validationError({errors:g.errors,entity:"request_data"}).toResponse()),{status:406,headers:O}));for(var w,b=d(g.value.calls);!(w=b()).done;){var P,S=w.value,j=u.get(S.name);if(null==j)return Promise.resolve(new Response(JSON.stringify(e.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:O}));var R=null!=(P=r.get(j))?P:[];R.push(S),r.set(j,R)}}return Promise.resolve(Promise.all(Array.from(r.entries()).map(function(e){var r=e[0],n=e[1];try{return Promise.resolve(i[r].runMany(h,{requestId:f,calls:n})).then(function(e){var r;t.status=Math.max(t.status,e.status),(r=t.body.calls).push.apply(r,e.body.calls)})}catch(e){return Promise.reject(e)}}))).then(function(){return O.append("x-req-id",f),O.append("content-type","application/rpc+json"),O.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(s.map(function(e){return e()}))).then(function(){return new Response(a.serialize.encode(l?t.body.calls[0].result:t.body),{status:t.status,headers:O})})})}catch(e){return Promise.reject(e)}}))}catch(r){return b&&console.error(r),P.captureException(r),Promise.resolve(new Response(JSON.stringify(e.internalServerError({inner:b?r instanceof Error?{message:r.message,stack:r.stack}:{error:r}:void 0}).toResponse()),{status:500,headers:O}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}};return Promise.resolve(r.otelContext.with(N,function(){try{var e,t=function(t){var n,o;return e?t:Promise.resolve(S.startActiveSpan(B,{kind:r.SpanKind.SERVER,attributes:{"sentry.op":H,"rpc.system":"lowerdeck","rpc.request.target":z,"rpc.description":B,"sentry.description":B,"http.request.method":l.method,"url.path":E.pathname,ip:null!=A?A:"",transport:"http",ua:null!=(n=l.headers.get("user-agent"))?n:"",origin:null!=(o=l.headers.get("origin"))?o:""}},function(e){try{return Promise.resolve(function(t,n){try{var o=w(function(){return Promise.resolve(K()).then(function(t){return e.setAttribute("http.response.status_code",t.status),t.status>=500&&e.setStatus({code:r.SpanStatusCode.ERROR,message:"RPC request failed with status "+t.status}),t})},function(t){throw e.recordException(t),e.setStatus({code:r.SpanStatusCode.ERROR,message:t instanceof Error?t.message:String(t)}),t})}catch(e){return n(!0,e)}return o&&o.then?o.then(n.bind(null,!1),n.bind(null,!0)):n(!1,o)}(0,function(r,t){if(e.end(),r)throw t;return t}))}catch(e){return Promise.reject(e)}}))},n=function(){if(!J)return Promise.resolve(K()).then(function(r){return e=1,r})}();return Promise.resolve(n&&n.then?n.then(t):t(n))}catch(e){return Promise.reject(e)}}))},y=null!=(f=l.headers.get("origin"))?f:"",g=!1;if(s.cors&&"domains"in s.cors)try{var j=new URL(y).hostname.split(".").slice(-2).join(".");g=s.cors.domains.includes(j)}catch(e){}else s.cors&&"check"in s.cors&&(g=s.cors.check(y));var E=new URL(l.url),R=null==(p=s.cors)||null==(p=p.headers)?void 0:p.join(", ");R&&(R=(", "+R).trim());var _=g?{"access-control-allow-origin":y,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace, traceparent, tracestate"+(null!=R?R:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==l.method)return Promise.resolve(g?new Response(null,{status:204,headers:_}):new Response(null,{status:403}));var x=null!=(h=l.headers.get("content-type"))?h:"";if(!x.includes("application/rpc+json")&&!x.includes("application/json"))return Promise.resolve(new Response(JSON.stringify(e.notAcceptableError({message:"Content-Type must be application/rpc+json"}).toResponse()),{status:406,headers:_}));var M=null,A=w(function(){var e=a.serialize.decode;return Promise.resolve(l.text()).then(function(r){M=e.call(a.serialize,r)})},function(){var r=new Response(JSON.stringify(e.notAcceptableError({message:"Invalid JSON"}).toResponse()),{status:406});return v=1,r});return Promise.resolve(A&&A.then?A.then(m):m(A))}catch(e){return Promise.reject(e)}}}};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/controller.ts","../src/rpcMux.ts","../src/server.ts","../src/extractIp.ts"],"sourcesContent":["import { ServiceError, validationError } from '@lowerdeck/error';\nimport { ValidationType } from '@lowerdeck/validation';\nimport * as Cookie from 'cookie';\n\nexport type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\nexport interface ServiceRequest {\n query: URLSearchParams;\n headers: Headers;\n url: string;\n ip?: string;\n body: any;\n rawBody: any;\n requestId: string;\n\n getCookies: () => Record<string, string | undefined>;\n getCookie: (name: string) => string | undefined;\n setCookie: (name: string, value: string, opts?: Cookie.SerializeOptions) => void;\n\n sharedMiddlewareMemo: Map<string, Promise<any>>;\n beforeSend: (handler: () => Promise<any>) => void;\n appendHeaders: (headers: Record<string, string | string[]>) => void;\n}\n\nexport type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};\nexport type ExtendContext<C extends object, E> = E extends object ? Simplify<C & E> : C;\n\nexport class Group<Context extends { [key: string]: any } = {}> {\n constructor(\n private _middleware: Array<(ctx: Context & ServiceRequest) => Promise<any>> = []\n ) {}\n\n use<T extends { [key: string]: any } | undefined | void>(\n handler: (ctx: Context & ServiceRequest) => Promise<T>,\n opts?: {\n getSharedMemoKey?: (ctx: Context & ServiceRequest) => string;\n }\n ) {\n let middleware = async (ctx: Parameters<typeof handler>[0]): Promise<T> => {\n let key = opts?.getSharedMemoKey?.(ctx);\n if (key && ctx.sharedMiddlewareMemo.has(key)) {\n return await ctx.sharedMiddlewareMemo.get(key)!;\n }\n\n let res = handler(ctx);\n if (key) ctx.sharedMiddlewareMemo.set(key, res);\n\n return await res;\n };\n\n return new Group<Simplify<Context & T>>([...this._middleware, middleware]);\n }\n\n createMiddleware<T extends { [key: string]: any }, P = void>(\n handler: (ctx: Context & ServiceRequest, input: P) => Promise<T>,\n opts?: {\n getSharedMemoKey?: (ctx: Context & ServiceRequest, input: P) => string;\n }\n ) {\n return (input: P) =>\n async (ctx: Context & ServiceRequest): Promise<T> => {\n let key = opts?.getSharedMemoKey?.(ctx, input);\n if (key && ctx.sharedMiddlewareMemo.has(key)) {\n return await ctx.sharedMiddlewareMemo.get(key)!;\n }\n\n let res = handler(ctx, input);\n if (key) ctx.sharedMiddlewareMemo.set(key, res);\n\n return await res;\n };\n }\n\n handler() {\n return new Handler([...this._middleware]);\n }\n\n controller<\n HandlersAndSubControllers extends {\n [key: string]: Handler<any, any, any> | Controller<any>;\n }\n >(handlers: HandlersAndSubControllers): Controller<HandlersAndSubControllers> {\n return handlers;\n }\n}\n\nexport type Controller<\n HandlersAndSubControllers extends { [key: string]: Handler<any, any, any> | Controller<any> }\n> = HandlersAndSubControllers;\n\nexport type InferControllerType<T> = T extends Controller<infer U> ? U : never;\n\nexport type InferClient<\n HandlersAndSubControllers extends { [key: string]: Handler<any, any, any> | Controller<any> }\n> = {\n [K in keyof HandlersAndSubControllers]: HandlersAndSubControllers[K] extends Handler<\n infer I,\n infer O,\n infer C\n >\n ? ((\n input: I,\n opts?: { headers?: Record<string, string>; query?: Record<string, string> }\n ) => Promise<O>) & {\n getFull: (\n input: I,\n opts?: { headers?: Record<string, string>; query?: Record<string, string> }\n ) => Promise<{\n data: O;\n status: number;\n headers: Record<string, string>;\n }>;\n }\n : HandlersAndSubControllers[K] extends Controller<infer U>\n ? InferClient<U>\n : never;\n};\n\nexport class Handler<Input, Output, Context extends { [key: string]: any } = {}> {\n private _handler!: (\n ctx: Context & Omit<ServiceRequest, 'body'> & { input: Input }\n ) => Promise<Output>;\n private _validation: ValidationType<Input> | undefined;\n\n constructor(\n private _middleware: Array<(ctx: Context & ServiceRequest) => Promise<any>> = []\n ) {}\n\n do<HandlerOutput>(\n handler: (\n ctx: Context & Omit<ServiceRequest, 'body'> & { input: Input }\n ) => Promise<HandlerOutput>\n ) {\n if (this._handler != undefined) throw new Error('Handler already defined');\n\n // @ts-ignore\n this._handler = handler;\n\n return this as any as Handler<Input, HandlerOutput, Context>;\n }\n\n use<T extends { [key: string]: any } = {}>(\n handler: (ctx: Context & ServiceRequest) => Promise<T | undefined | void>\n ) {\n this._middleware.push(handler);\n return this as any as Handler<Input, Output, ExtendContext<Context, T>>;\n }\n\n input<HandlerInput>(validation: ValidationType<HandlerInput>) {\n if (this._validation != undefined) throw new Error('Input validation already defined');\n\n // @ts-ignore\n this._validation = validation;\n\n return this as any as Handler<HandlerInput, Output, Context>;\n }\n\n async run(\n req: ServiceRequest,\n initialContext: any\n ): Promise<{\n response: Output;\n }> {\n if (!this._handler) throw new Error('Handler not defined');\n\n let input = req.body as Input;\n\n if (this._validation) {\n let valRes = this._validation.validate(req.body);\n\n if (!valRes.success) {\n throw new ServiceError(\n validationError({ errors: valRes.errors, entity: 'call_data' })\n );\n }\n\n input = valRes.value;\n }\n\n let ctx = {\n ...initialContext,\n ...req,\n\n // Always use the sanitized input\n body: input\n };\n\n for (let mw of this._middleware) {\n let res = await mw(ctx);\n if (res) ctx = { ...ctx, ...res };\n }\n\n let res = await this._handler({\n ...ctx,\n input,\n body: undefined\n });\n\n return {\n response: res\n };\n }\n}\n","import {\n internalServerError,\n notAcceptableError,\n notFoundError,\n validationError\n} from '@lowerdeck/error';\nimport { createExecutionContext, provideExecutionContext } from '@lowerdeck/execution-context';\nimport { generateCustomId } from '@lowerdeck/id';\nimport { memo } from '@lowerdeck/memo';\nimport { getSentry } from '@lowerdeck/sentry';\nimport { serialize } from '@lowerdeck/serialize';\nimport { v } from '@lowerdeck/validation';\nimport * as Cookie from 'cookie';\nimport { ServiceRequest } from './controller';\nimport { parseForwardedFor } from './extractIp';\n\nlet Sentry = getSentry();\n\nlet validation = v.object({\n calls: v.array(\n v.object({\n id: v.string(),\n name: v.string(),\n payload: v.any()\n })\n )\n});\n\nexport let rpcMux = (\n opts: {\n path: string;\n cors?: {\n headers?: string[];\n } & ({ domains: string[] } | { check: (origin: string) => boolean });\n },\n rpcs: {\n handlerNames: string[];\n runMany: (\n req: ServiceRequest,\n body: {\n requestId: string;\n calls: {\n id: string;\n name: string;\n payload: any;\n }[];\n }\n ) => Promise<{\n status: number;\n body: {\n calls: any[];\n };\n }>;\n }[]\n) => {\n let handlerNameToRpcMap = new Map<string, number>(\n rpcs.flatMap((rpc, i) => rpc.handlerNames.map(name => [name, i]))\n );\n\n return {\n path: opts.path,\n\n fetch: async (req: any): Promise<any> => {\n let origin = req.headers.get('origin') ?? '';\n let corsOk = false;\n\n if (opts.cors && 'domains' in opts.cors) {\n try {\n let url = new URL(origin);\n let rootDomain = url.hostname.split('.').slice(-2).join('.');\n corsOk = opts.cors.domains.includes(rootDomain);\n } catch (e) {\n // Ignore -> no cors\n }\n } else if (opts.cors && 'check' in opts.cors) {\n corsOk = opts.cors.check(origin);\n }\n\n let url = new URL(req.url);\n\n let additionalCorsHeaders = opts.cors?.headers?.join(', ');\n if (additionalCorsHeaders) additionalCorsHeaders = `, ${additionalCorsHeaders}`.trim();\n\n let corsHeaders: Record<string, string> = corsOk\n ? {\n 'access-control-allow-origin': origin,\n 'access-control-allow-methods': 'POST, OPTIONS',\n 'access-control-allow-headers': `Content-Type, Authorization, Baggage, Sentry-Trace${\n additionalCorsHeaders ?? ''\n }`,\n 'access-control-max-age': '604800',\n 'access-control-allow-credentials': 'true'\n }\n : {};\n\n if (req.method == 'OPTIONS') {\n if (corsOk) {\n return new Response(null, {\n status: 204,\n headers: corsHeaders\n });\n }\n\n return new Response(null, { status: 403 });\n }\n\n let body: any = null;\n\n try {\n body = serialize.decode(await req.text());\n } catch (e) {\n return new Response(\n JSON.stringify(notAcceptableError({ message: 'Invalid JSON' }).toResponse()),\n { status: 406 }\n );\n }\n\n let sentryTraceHeaders = req.headers.get('sentry-trace');\n let sentryTrace =\n (Array.isArray(sentryTraceHeaders)\n ? sentryTraceHeaders.join(',')\n : sentryTraceHeaders) ?? undefined;\n let baggage = req.headers.get('baggage');\n\n let ip = parseForwardedFor(\n req.headers.get('lowerdeck-connecting-ip') ??\n req.headers.get('cf-connecting-ip') ??\n req.headers.get('x-forwarded-for') ??\n req.headers.get('x-real-ip')\n );\n\n let headers = new Headers();\n\n if (corsOk) {\n for (let [key, value] of Object.entries(corsHeaders)) {\n headers.append(key, value);\n }\n }\n\n return await Sentry.withIsolationScope(\n async () =>\n await Sentry.continueTrace(\n { sentryTrace, baggage },\n async () =>\n await Sentry.startSpan(\n {\n name: 'rpc request',\n op: 'rpc.server',\n attributes: {\n ip,\n transport: 'http',\n ua: req.headers.get('user-agent') ?? '',\n origin: req.headers.get('origin') ?? ''\n }\n },\n async () => {\n try {\n let beforeSends: Array<() => Promise<any>> = [];\n let id = generateCustomId('req_');\n\n let parseCookies = memo(() =>\n Cookie.parse(req.headers.get('cookie') ?? '')\n );\n\n let request: ServiceRequest = {\n url: req.url,\n headers: req.headers,\n query: url.searchParams,\n body,\n rawBody: body,\n ip,\n requestId: id,\n\n getCookies: () => parseCookies(),\n getCookie: (name: string) => parseCookies()[name],\n setCookie: (name: string, value: string, opts?: any) => {\n let cookie = Cookie.serialize(name, value, opts);\n // @ts-ignore\n headers.append('Set-Cookie', cookie);\n },\n\n beforeSend: (handler: () => Promise<any>) => {\n beforeSends.push(handler);\n },\n\n sharedMiddlewareMemo: new Map<string, Promise<any>>(),\n\n appendHeaders: (newHeaders: Record<string, string | string[]>) => {\n for (let [key, value] of Object.entries(newHeaders)) {\n if (Array.isArray(value)) {\n for (let v of value) headers.append(key, v);\n } else {\n headers.append(key, value);\n }\n }\n }\n };\n\n Sentry.getCurrentScope().setContext('rpc.request', {\n url: req.url,\n query: Object.fromEntries(url.searchParams.entries())\n });\n\n Sentry.getCurrentScope().addAttachment({\n filename: 'rpc.request.body.json',\n data: body,\n contentType: 'application/json'\n });\n\n return provideExecutionContext(\n createExecutionContext({\n type: 'request',\n contextId: id,\n ip: ip ?? '0.0.0.0',\n userAgent: req.headers.get('user-agent') ?? ''\n }),\n async () => {\n let callsByRpc = new Map<\n number,\n { id: string; name: string; payload: any }[]\n >();\n\n let resRef = {\n body: {\n __typename: 'rpc.response',\n calls: [] as any[]\n },\n status: 200\n };\n\n let pathParts = url.pathname.split('/').filter(Boolean);\n let lastPart = pathParts[pathParts.length - 1];\n\n let isSingle = lastPart[0] == '$';\n\n if (isSingle) {\n let id = lastPart.slice(1);\n let rpcIndex = handlerNameToRpcMap.get(id);\n if (rpcIndex == undefined) {\n return new Response(\n JSON.stringify(\n notFoundError({ entity: 'handler' }).toResponse()\n ),\n { status: 404, headers }\n );\n }\n\n let calls = callsByRpc.get(rpcIndex) ?? [];\n calls.push({\n id: generateCustomId('call_'),\n name: id,\n payload: body\n });\n callsByRpc.set(rpcIndex, calls);\n } else {\n let valRes = validation.validate(body);\n if (!valRes.success) {\n return new Response(\n JSON.stringify(\n validationError({\n errors: valRes.errors,\n entity: 'request_data'\n }).toResponse()\n ),\n { status: 406, headers }\n );\n }\n\n for (let call of valRes.value.calls) {\n let rpcIndex = handlerNameToRpcMap.get(call.name);\n if (rpcIndex == undefined) {\n return new Response(\n JSON.stringify(\n notFoundError({ entity: 'handler' }).toResponse()\n ),\n { status: 404, headers }\n );\n }\n\n let calls = callsByRpc.get(rpcIndex) ?? [];\n calls.push(call as any);\n callsByRpc.set(rpcIndex, calls);\n }\n }\n\n await Promise.all(\n Array.from(callsByRpc.entries()).map(async ([rpcIndex, calls]) => {\n let rpc = rpcs[rpcIndex];\n let res = await rpc.runMany(request, {\n requestId: id,\n calls\n });\n\n resRef.status = Math.max(resRef.status, res.status);\n resRef.body.calls.push(...res.body.calls);\n })\n );\n\n headers.append('x-req-id', id);\n headers.append('content-type', 'application/rpc+json');\n headers.append('x-powered-by', 'lowerdeck RPC');\n\n await Promise.all(beforeSends.map(s => s()));\n\n return new Response(\n serialize.encode(\n isSingle ? resRef.body.calls[0].result : resRef.body\n ),\n {\n status: resRef.status,\n headers\n }\n );\n }\n );\n } catch (e) {\n console.error(e);\n\n Sentry.captureException(e);\n\n return new Response(JSON.stringify(internalServerError().toResponse()), {\n status: 500,\n headers\n });\n }\n }\n )\n )\n );\n }\n };\n};\n","import { internalServerError, isServiceError, notFoundError } from '@lowerdeck/error';\nimport { getSentry } from '@lowerdeck/sentry';\nimport { Controller, Handler, ServiceRequest } from './controller';\n\nlet Sentry = getSentry();\n\nexport let createServer =\n (opts: {\n onError?: (opts: {\n request: ServiceRequest;\n error: any;\n reqId: string;\n callId: string;\n callName: string;\n }) => void;\n onRequest?: (opts: {\n reqId: string;\n callId: string;\n callName: string;\n request: ServiceRequest;\n response: { status: number; body: any };\n }) => void;\n }) =>\n (controller: Controller<any>) => {\n let findHandler = (name: string): Handler<any, any, any> | null => {\n let parts = name.split(':');\n let current = controller;\n\n while (current && parts.length > 0) {\n current = current[parts.shift()!];\n if (!current) return null;\n }\n\n if (current && current instanceof Handler) return current;\n\n return null;\n };\n\n let getSupportedHandlerNames = (controller: Controller<any>): string[] =>\n Object.entries(controller).flatMap(([key, value]) => {\n if (value instanceof Handler) return [key];\n if (typeof value == 'object')\n return getSupportedHandlerNames(value).map(name => `${key}:${name}`);\n return [];\n });\n\n let handlerNames = getSupportedHandlerNames(controller);\n\n let run = async (\n req: ServiceRequest,\n call: { id: string; name: string; payload: any },\n reqId: string\n ): Promise<{\n response: any;\n status: number;\n request: ServiceRequest;\n }> => {\n let request = { ...req, body: call.payload };\n\n try {\n let handler = findHandler(call.name);\n\n if (!handler) {\n return {\n request,\n status: 404,\n response: notFoundError({ entity: 'handler' }).toResponse()\n };\n }\n\n let response = await handler.run(request, {});\n\n return {\n status: 200,\n request: req,\n response: response.response\n };\n } catch (e) {\n console.error(e);\n\n if (isServiceError(e)) {\n if (e.data.status >= 500) {\n Sentry.captureException(e, {\n tags: { reqId }\n });\n }\n\n return {\n request,\n status: e.data.status,\n response: e.toResponse()\n };\n }\n\n Sentry.captureException(e, {\n tags: { reqId }\n });\n\n opts.onError?.({\n callName: call.name,\n callId: call.id,\n request: req,\n error: e,\n reqId\n });\n\n return {\n request,\n status: 500,\n response: internalServerError().toResponse()\n };\n }\n };\n\n let runMany = async (\n req: ServiceRequest,\n body: {\n calls: {\n id: string;\n name: string;\n payload: any;\n }[];\n requestId: string;\n }\n ): Promise<{\n status: number;\n body: any;\n }> => {\n let callRes = await Promise.all(\n body.calls.map(async (call, i) => {\n let res = await run(req, call as any, body.requestId);\n\n try {\n opts.onRequest?.({\n reqId: body.requestId,\n callId: call.id,\n callName: call.name,\n request: res.request,\n response: { status: res.status, body: res.response }\n });\n } catch (e) {\n Sentry.captureException(e);\n console.error(e);\n }\n\n return {\n __typename: 'rpc.response.call',\n id: call.id,\n name: call.name,\n status: res.status,\n result: res.response\n };\n })\n );\n\n return {\n status: Math.max(...callRes.map(c => c.status)),\n body: {\n __typename: 'rpc.response',\n calls: callRes\n }\n };\n };\n\n return {\n handlerNames,\n runMany\n\n // fetch,\n\n // http: async (\n // req: IncomingMessage & {\n // body: any;\n // },\n // res: ServerResponse & { send: (body: any) => void }\n // ) => {\n // let headers = new Headers(\n // Object.fromEntries(\n // Object.entries(req.headers).map(([key, value]) => [\n // key,\n // value === undefined ? '' : String(value)\n // ])\n // )\n // );\n // let url = new URL(req.url ?? '', `http://${req.headers.host}`);\n\n // let request = new Request(url.toString(), {\n // method: req.method,\n // headers,\n // body: JSON.stringify(req.body)\n // });\n\n // let response = await fetch(request);\n\n // res.statusCode = response.status;\n\n // for (let [key, value] of response.headers.entries()) {\n // res.setHeader(key, value);\n // }\n\n // res.send(response.body);\n // }\n };\n };\n","export let parseForwardedFor = (xForwardedForHeader?: string | null | undefined) => {\n if (typeof xForwardedForHeader != 'string') return undefined;\n\n let ips = xForwardedForHeader\n .split(',')\n .map(ip => ip.trim())\n .filter(Boolean);\n return ips.length > 0 ? ips[0] : undefined;\n};\n"],"names":["_settle","pact","state","value","s","_Pact","o","bind","v","then","observer","prototype","onFulfilled","onRejected","result","this","callback","e","_this","_isSettledPact","thenable","Group","_middleware","_proto","use","handler","opts","concat","ctx","_exit","_temp2","_result","res","key","sharedMiddlewareMemo","set","Promise","resolve","getSharedMemoKey","_temp","has","get","_await$ctx$sharedMidd","reject","createMiddleware","input","_exit2","_temp4","_result2","_temp3","_await$ctx$sharedMidd2","Handler","controller","handlers","_handler","_validation","_proto2","undefined","Error","push","validation","run","req","initialContext","_temp6","_extends","body","response","valRes","validate","success","ServiceError","validationError","errors","entity","_temp5","_forOf","mw","Sentry","getSentry","object","calls","array","id","string","name","payload","any","getSupportedHandlerNames","Object","entries","flatMap","_ref","map","handlerNames","runMany","all","call","i","reqId","request","parts","split","current","length","shift","findHandler","status","notFoundError","toResponse","_catch","console","error","isServiceError","data","captureException","tags","onError","callName","callId","internalServerError","requestId","onRequest","__typename","callRes","Math","max","apply","c","rpcs","handlerNameToRpcMap","Map","rpc","path","fetch","_req$headers$get6","_opts$cors","_ref2","_ref3","_req$headers$get","sentryTraceHeaders","headers","sentryTrace","Array","isArray","join","baggage","ip","xForwardedForHeader","ips","trim","filter","Boolean","parseForwardedFor","Headers","corsOk","_i","_Object$entries","corsHeaders","_Object$entries$_i","append","withIsolationScope","continueTrace","_req$headers$get2","_req$headers$get3","startSpan","op","attributes","transport","ua","origin","_req$headers$get5","beforeSends","generateCustomId","parseCookies","memo","_req$headers$get4","Cookie","parse","url","query","searchParams","rawBody","getCookies","getCookie","setCookie","cookie","serialize","beforeSend","appendHeaders","newHeaders","_i2","_Object$entries2","_Object$entries2$_i","_iterator","_step","_createForOfIteratorHelperLoose","done","getCurrentScope","setContext","fromEntries","addAttachment","filename","contentType","provideExecutionContext","createExecutionContext","type","contextId","userAgent","callsByRpc","resRef","pathParts","pathname","lastPart","isSingle","_callsByRpc$get","slice","rpcIndex","Response","JSON","stringify","_iterator2","_step2","_callsByRpc$get2","from","_ref4","_resRef$body$calls","encode","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","method","_decode","decode","text","_req$text","_Response","notAcceptableError","message"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/controller.ts","../src/rpcMux.ts","../src/server.ts","../src/extractIp.ts"],"sourcesContent":["import { ServiceError, validationError } from '@lowerdeck/error';\nimport { ValidationType } from '@lowerdeck/validation';\nimport * as Cookie from 'cookie';\n\nexport type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\nexport interface ServiceRequest {\n query: URLSearchParams;\n headers: Headers;\n url: string;\n ip?: string;\n body: any;\n rawBody: any;\n requestId: string;\n\n getCookies: () => Record<string, string | undefined>;\n getCookie: (name: string) => string | undefined;\n setCookie: (name: string, value: string, opts?: Cookie.SerializeOptions) => void;\n\n sharedMiddlewareMemo: Map<string, Promise<any>>;\n beforeSend: (handler: () => Promise<any>) => void;\n appendHeaders: (headers: Record<string, string | string[]>) => void;\n}\n\nexport type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};\nexport type ExtendContext<C extends object, E> = E extends object ? Simplify<C & E> : C;\n\nexport class Group<Context extends { [key: string]: any } = {}> {\n constructor(\n private _middleware: Array<(ctx: Context & ServiceRequest) => Promise<any>> = []\n ) {}\n\n use<T extends { [key: string]: any } | undefined | void>(\n handler: (ctx: Context & ServiceRequest) => Promise<T>,\n opts?: {\n getSharedMemoKey?: (ctx: Context & ServiceRequest) => string;\n }\n ) {\n let middleware = async (ctx: Parameters<typeof handler>[0]): Promise<T> => {\n let key = opts?.getSharedMemoKey?.(ctx);\n if (key && ctx.sharedMiddlewareMemo.has(key)) {\n return await ctx.sharedMiddlewareMemo.get(key)!;\n }\n\n let res = handler(ctx);\n if (key) ctx.sharedMiddlewareMemo.set(key, res);\n\n return await res;\n };\n\n return new Group<Simplify<Context & T>>([...this._middleware, middleware]);\n }\n\n createMiddleware<T extends { [key: string]: any }, P = void>(\n handler: (ctx: Context & ServiceRequest, input: P) => Promise<T>,\n opts?: {\n getSharedMemoKey?: (ctx: Context & ServiceRequest, input: P) => string;\n }\n ) {\n return (input: P) =>\n async (ctx: Context & ServiceRequest): Promise<T> => {\n let key = opts?.getSharedMemoKey?.(ctx, input);\n if (key && ctx.sharedMiddlewareMemo.has(key)) {\n return await ctx.sharedMiddlewareMemo.get(key)!;\n }\n\n let res = handler(ctx, input);\n if (key) ctx.sharedMiddlewareMemo.set(key, res);\n\n return await res;\n };\n }\n\n handler() {\n return new Handler([...this._middleware]);\n }\n\n controller<\n HandlersAndSubControllers extends {\n [key: string]: Handler<any, any, any> | Controller<any>;\n }\n >(handlers: HandlersAndSubControllers): Controller<HandlersAndSubControllers> {\n return handlers;\n }\n}\n\nexport type Controller<\n HandlersAndSubControllers extends { [key: string]: Handler<any, any, any> | Controller<any> }\n> = HandlersAndSubControllers;\n\nexport type InferControllerType<T> = T extends Controller<infer U> ? U : never;\n\nexport type InferClient<\n HandlersAndSubControllers extends { [key: string]: Handler<any, any, any> | Controller<any> }\n> = {\n [K in keyof HandlersAndSubControllers]: HandlersAndSubControllers[K] extends Handler<\n infer I,\n infer O,\n infer C\n >\n ? ((\n input: I,\n opts?: { headers?: Record<string, string>; query?: Record<string, string> }\n ) => Promise<O>) & {\n getFull: (\n input: I,\n opts?: { headers?: Record<string, string>; query?: Record<string, string> }\n ) => Promise<{\n data: O;\n status: number;\n headers: Record<string, string>;\n }>;\n }\n : HandlersAndSubControllers[K] extends Controller<infer U>\n ? InferClient<U>\n : never;\n};\n\nexport class Handler<Input, Output, Context extends { [key: string]: any } = {}> {\n private _handler!: (\n ctx: Context & Omit<ServiceRequest, 'body'> & { input: Input }\n ) => Promise<Output>;\n private _validation: ValidationType<Input> | undefined;\n\n constructor(\n private _middleware: Array<(ctx: Context & ServiceRequest) => Promise<any>> = []\n ) {}\n\n do<HandlerOutput>(\n handler: (\n ctx: Context & Omit<ServiceRequest, 'body'> & { input: Input }\n ) => Promise<HandlerOutput>\n ) {\n if (this._handler != undefined) throw new Error('Handler already defined');\n\n // @ts-ignore\n this._handler = handler;\n\n return this as any as Handler<Input, HandlerOutput, Context>;\n }\n\n use<T extends { [key: string]: any } = {}>(\n handler: (ctx: Context & ServiceRequest) => Promise<T | undefined | void>\n ) {\n this._middleware.push(handler);\n return this as any as Handler<Input, Output, ExtendContext<Context, T>>;\n }\n\n input<HandlerInput>(validation: ValidationType<HandlerInput>) {\n if (this._validation != undefined) throw new Error('Input validation already defined');\n\n // @ts-ignore\n this._validation = validation;\n\n return this as any as Handler<HandlerInput, Output, Context>;\n }\n\n async run(\n req: ServiceRequest,\n initialContext: any\n ): Promise<{\n response: Output;\n }> {\n if (!this._handler) throw new Error('Handler not defined');\n\n let input = req.body as Input;\n\n if (this._validation) {\n let valRes = this._validation.validate(req.body);\n\n if (!valRes.success) {\n throw new ServiceError(\n validationError({ errors: valRes.errors, entity: 'call_data' })\n );\n }\n\n input = valRes.value;\n }\n\n let ctx = {\n ...initialContext,\n ...req,\n\n // Always use the sanitized input\n body: input\n };\n\n for (let mw of this._middleware) {\n let res = await mw(ctx);\n if (res) ctx = { ...ctx, ...res };\n }\n\n let res = await this._handler({\n ...ctx,\n input,\n body: undefined\n });\n\n return {\n response: res\n };\n }\n}\n","import {\n internalServerError,\n notAcceptableError,\n notFoundError,\n validationError\n} from '@lowerdeck/error';\nimport {\n isTelemetryEnabled,\n otelContext,\n propagation,\n SpanKind,\n SpanStatusCode,\n trace\n} from '@lowerdeck/telemetry';\nimport { createExecutionContext, provideExecutionContext } from '@lowerdeck/execution-context';\nimport { generateCustomId } from '@lowerdeck/id';\nimport { memo } from '@lowerdeck/memo';\nimport { getSentry } from '@lowerdeck/sentry';\nimport { serialize } from '@lowerdeck/serialize';\nimport { v } from '@lowerdeck/validation';\nimport * as Cookie from 'cookie';\nimport { ServiceRequest } from './controller';\nimport { parseForwardedFor } from './extractIp';\n\nlet verbose = process.env.NODE_ENV !== 'production';\n\nlet Sentry = getSentry();\nlet tracer = trace.getTracer('lowerdeck.rpc-server');\n\nlet validation = v.object({\n calls: v.array(\n v.object({\n id: v.string(),\n name: v.string(),\n payload: v.any()\n })\n )\n});\n\nlet summarizeRpcTarget = (url: URL, body: any) => {\n let pathParts = url.pathname.split('/').filter(Boolean);\n let lastPart = pathParts[pathParts.length - 1] ?? '';\n\n if (lastPart.startsWith('$') && lastPart.length > 1) {\n return lastPart.slice(1);\n }\n\n let callNames: string[] = [];\n if (body && typeof body == 'object' && Array.isArray(body.calls)) {\n callNames = body.calls\n .map((call: { name?: unknown }) =>\n typeof call?.name == 'string' ? call.name.trim() : ''\n )\n .filter(Boolean);\n }\n\n if (callNames.length == 1) return callNames[0];\n\n if (callNames.length > 1) {\n let preview = callNames.slice(0, 3).join(', ');\n if (callNames.length > 3) return `${preview}, +${callNames.length - 3} more`;\n return preview;\n }\n\n return url.pathname;\n};\n\nexport let rpcMux = (\n opts: {\n path: string;\n allowRootSpan?: boolean;\n cors?: {\n headers?: string[];\n } & ({ domains: string[] } | { check: (origin: string) => boolean });\n },\n rpcs: {\n handlerNames: string[];\n runMany: (\n req: ServiceRequest,\n body: {\n requestId: string;\n calls: {\n id: string;\n name: string;\n payload: any;\n }[];\n }\n ) => Promise<{\n status: number;\n body: {\n calls: any[];\n };\n }>;\n }[]\n) => {\n let handlerNameToRpcMap = new Map<string, number>(\n rpcs.flatMap((rpc, i) => rpc.handlerNames.map(name => [name, i]))\n );\n\n return {\n path: opts.path,\n\n fetch: async (req: any): Promise<any> => {\n let origin = req.headers.get('origin') ?? '';\n let corsOk = false;\n\n if (opts.cors && 'domains' in opts.cors) {\n try {\n let url = new URL(origin);\n let rootDomain = url.hostname.split('.').slice(-2).join('.');\n corsOk = opts.cors.domains.includes(rootDomain);\n } catch (e) {\n // Ignore -> no cors\n }\n } else if (opts.cors && 'check' in opts.cors) {\n corsOk = opts.cors.check(origin);\n }\n\n let url = new URL(req.url);\n\n let additionalCorsHeaders = opts.cors?.headers?.join(', ');\n if (additionalCorsHeaders) additionalCorsHeaders = `, ${additionalCorsHeaders}`.trim();\n\n let corsHeaders: Record<string, string> = corsOk\n ? {\n 'access-control-allow-origin': origin,\n 'access-control-allow-methods': 'POST, OPTIONS',\n 'access-control-allow-headers': `Content-Type, Authorization, Baggage, Sentry-Trace, traceparent, tracestate${\n additionalCorsHeaders ?? ''\n }`,\n 'access-control-max-age': '604800',\n 'access-control-allow-credentials': 'true'\n }\n : {};\n\n if (req.method == 'OPTIONS') {\n if (corsOk) {\n return new Response(null, {\n status: 204,\n headers: corsHeaders\n });\n }\n\n return new Response(null, { status: 403 });\n }\n\n let contentType = req.headers.get('content-type') ?? '';\n if (\n !contentType.includes('application/rpc+json') &&\n !contentType.includes('application/json')\n ) {\n return new Response(\n JSON.stringify(\n notAcceptableError({\n message: 'Content-Type must be application/rpc+json'\n }).toResponse()\n ),\n { status: 406, headers: corsHeaders }\n );\n }\n\n let body: any = null;\n\n try {\n body = serialize.decode(await req.text());\n } catch (e) {\n return new Response(\n JSON.stringify(notAcceptableError({ message: 'Invalid JSON' }).toResponse()),\n { status: 406 }\n );\n }\n\n let sentryTraceHeaders = req.headers.get('sentry-trace');\n let sentryTrace =\n (Array.isArray(sentryTraceHeaders)\n ? sentryTraceHeaders.join(',')\n : sentryTraceHeaders) ?? undefined;\n let baggage = req.headers.get('baggage');\n\n let ip = parseForwardedFor(\n req.headers.get('lowerdeck-connecting-ip') ??\n req.headers.get('cf-connecting-ip') ??\n req.headers.get('x-forwarded-for') ??\n req.headers.get('x-real-ip')\n );\n\n let headers = new Headers();\n\n if (corsOk) {\n for (let [key, value] of Object.entries(corsHeaders)) {\n headers.append(key, value);\n }\n }\n\n let extractedTraceContext = propagation.extract(otelContext.active(), req.headers, {\n get: (carrier, key) => carrier.get(key) ?? undefined,\n keys: carrier => Array.from(carrier.keys())\n });\n\n let incomingParent = trace.getSpanContext(extractedTraceContext);\n let canTrace = isTelemetryEnabled() && (!!incomingParent || !!opts.allowRootSpan);\n let requestSpanTarget = summarizeRpcTarget(url, body);\n let requestSpanName = `rpc request: ${requestSpanTarget}`;\n let requestSpanOp = 'rpc.server.request';\n\n let executeRequest = async () =>\n await Sentry.withIsolationScope(\n async () =>\n await Sentry.continueTrace(\n { sentryTrace, baggage },\n async () =>\n await Sentry.startSpan(\n {\n name: requestSpanName,\n op: requestSpanOp,\n attributes: {\n 'sentry.op': requestSpanOp,\n 'rpc.request.target': requestSpanTarget,\n 'rpc.description': requestSpanName,\n 'sentry.description': requestSpanName,\n ip,\n transport: 'http',\n ua: req.headers.get('user-agent') ?? '',\n origin: req.headers.get('origin') ?? ''\n }\n },\n async () => {\n try {\n let beforeSends: Array<() => Promise<any>> = [];\n let id = generateCustomId('req_');\n\n let parseCookies = memo(() =>\n Cookie.parse(req.headers.get('cookie') ?? '')\n );\n\n let request: ServiceRequest = {\n url: req.url,\n headers: req.headers,\n query: url.searchParams,\n body,\n rawBody: body,\n ip,\n requestId: id,\n\n getCookies: () => parseCookies(),\n getCookie: (name: string) => parseCookies()[name],\n setCookie: (name: string, value: string, opts?: any) => {\n let cookie = Cookie.serialize(name, value, opts);\n // @ts-ignore\n headers.append('Set-Cookie', cookie);\n },\n\n beforeSend: (handler: () => Promise<any>) => {\n beforeSends.push(handler);\n },\n\n sharedMiddlewareMemo: new Map<string, Promise<any>>(),\n\n appendHeaders: (newHeaders: Record<string, string | string[]>) => {\n for (let [key, value] of Object.entries(newHeaders)) {\n if (Array.isArray(value)) {\n for (let v of value) headers.append(key, v);\n } else {\n headers.append(key, value);\n }\n }\n }\n };\n\n Sentry.getCurrentScope().setContext('rpc.request', {\n url: req.url,\n query: Object.fromEntries(url.searchParams.entries())\n });\n\n Sentry.getCurrentScope().addAttachment({\n filename: 'rpc.request.body.json',\n data: body,\n contentType: 'application/json'\n });\n\n return provideExecutionContext(\n createExecutionContext({\n type: 'request',\n contextId: id,\n ip: ip ?? '0.0.0.0',\n userAgent: req.headers.get('user-agent') ?? ''\n }),\n async () => {\n let callsByRpc = new Map<\n number,\n { id: string; name: string; payload: any }[]\n >();\n\n let resRef = {\n body: {\n __typename: 'rpc.response',\n calls: [] as any[]\n },\n status: 200\n };\n\n let pathParts = url.pathname.split('/').filter(Boolean);\n let lastPart = pathParts[pathParts.length - 1];\n\n let isSingle = lastPart[0] == '$';\n\n if (isSingle) {\n let id = lastPart.slice(1);\n let rpcIndex = handlerNameToRpcMap.get(id);\n if (rpcIndex == undefined) {\n return new Response(\n JSON.stringify(\n notFoundError({ entity: 'handler' }).toResponse()\n ),\n { status: 404, headers }\n );\n }\n\n let calls = callsByRpc.get(rpcIndex) ?? [];\n calls.push({\n id: generateCustomId('call_'),\n name: id,\n payload: body\n });\n callsByRpc.set(rpcIndex, calls);\n } else {\n let valRes = validation.validate(body);\n if (!valRes.success) {\n return new Response(\n JSON.stringify(\n validationError({\n errors: valRes.errors,\n entity: 'request_data'\n }).toResponse()\n ),\n { status: 406, headers }\n );\n }\n\n for (let call of valRes.value.calls) {\n let rpcIndex = handlerNameToRpcMap.get(call.name);\n if (rpcIndex == undefined) {\n return new Response(\n JSON.stringify(\n notFoundError({ entity: 'handler' }).toResponse()\n ),\n { status: 404, headers }\n );\n }\n\n let calls = callsByRpc.get(rpcIndex) ?? [];\n calls.push(call as any);\n callsByRpc.set(rpcIndex, calls);\n }\n }\n\n await Promise.all(\n Array.from(callsByRpc.entries()).map(async ([rpcIndex, calls]) => {\n let rpc = rpcs[rpcIndex];\n let res = await rpc.runMany(request, {\n requestId: id,\n calls\n });\n\n resRef.status = Math.max(resRef.status, res.status);\n resRef.body.calls.push(...res.body.calls);\n })\n );\n\n headers.append('x-req-id', id);\n headers.append('content-type', 'application/rpc+json');\n headers.append('x-powered-by', 'lowerdeck RPC');\n\n await Promise.all(beforeSends.map(s => s()));\n\n return new Response(\n serialize.encode(\n isSingle ? resRef.body.calls[0].result : resRef.body\n ),\n {\n status: resRef.status,\n headers\n }\n );\n }\n );\n } catch (e) {\n if (verbose) console.error(e);\n\n Sentry.captureException(e);\n\n return new Response(\n JSON.stringify(\n internalServerError({\n inner: verbose\n ? e instanceof Error\n ? { message: e.message, stack: e.stack }\n : { error: e }\n : undefined\n }).toResponse()\n ),\n {\n status: 500,\n headers\n }\n );\n }\n }\n )\n )\n );\n\n return await otelContext.with(extractedTraceContext, async () => {\n if (!canTrace) {\n return await executeRequest();\n }\n\n return await tracer.startActiveSpan(\n requestSpanName,\n {\n kind: SpanKind.SERVER,\n attributes: {\n 'sentry.op': requestSpanOp,\n 'rpc.system': 'lowerdeck',\n 'rpc.request.target': requestSpanTarget,\n 'rpc.description': requestSpanName,\n 'sentry.description': requestSpanName,\n 'http.request.method': req.method,\n 'url.path': url.pathname,\n ip: ip ?? '',\n transport: 'http',\n ua: req.headers.get('user-agent') ?? '',\n origin: req.headers.get('origin') ?? ''\n }\n },\n async span => {\n try {\n let response = await executeRequest();\n\n span.setAttribute('http.response.status_code', response.status);\n if (response.status >= 500) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: `RPC request failed with status ${response.status}`\n });\n }\n\n return response;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error)\n });\n throw error;\n } finally {\n span.end();\n }\n }\n );\n });\n }\n };\n};\n","import { internalServerError, isServiceError, notFoundError } from '@lowerdeck/error';\nimport { getSentry } from '@lowerdeck/sentry';\nimport {\n hasActiveSpan,\n isTelemetryEnabled,\n SpanStatusCode,\n trace\n} from '@lowerdeck/telemetry';\nimport { Controller, Handler, ServiceRequest } from './controller';\n\nlet Sentry = getSentry();\nlet tracer = trace.getTracer('lowerdeck.rpc-server.calls');\n\nexport let createServer =\n (opts: {\n onError?: (opts: {\n request: ServiceRequest;\n error: any;\n reqId: string;\n callId: string;\n callName: string;\n }) => void;\n onRequest?: (opts: {\n reqId: string;\n callId: string;\n callName: string;\n request: ServiceRequest;\n response: { status: number; body: any };\n }) => void;\n }) =>\n (controller: Controller<any>) => {\n let findHandler = (name: string): Handler<any, any, any> | null => {\n let parts = name.split(':');\n let current = controller;\n\n while (current && parts.length > 0) {\n current = current[parts.shift()!];\n if (!current) return null;\n }\n\n if (current && current instanceof Handler) return current;\n\n return null;\n };\n\n let getSupportedHandlerNames = (controller: Controller<any>): string[] =>\n Object.entries(controller).flatMap(([key, value]) => {\n if (value instanceof Handler) return [key];\n if (typeof value == 'object')\n return getSupportedHandlerNames(value).map(name => `${key}:${name}`);\n return [];\n });\n\n let handlerNames = getSupportedHandlerNames(controller);\n\n let run = async (\n req: ServiceRequest,\n call: { id: string; name: string; payload: any },\n reqId: string\n ): Promise<{\n response: any;\n status: number;\n request: ServiceRequest;\n }> => {\n let request = { ...req, body: call.payload };\n\n let executeCall = async () => {\n try {\n let handler = findHandler(call.name);\n\n if (!handler) {\n return {\n request,\n status: 404,\n response: notFoundError({ entity: 'handler' }).toResponse()\n };\n }\n\n let response = await handler.run(request, {});\n\n return {\n status: 200,\n request: req,\n response: response.response\n };\n } catch (e) {\n console.error(e);\n\n if (isServiceError(e)) {\n if (e.data.status >= 500) {\n Sentry.captureException(e, {\n tags: { reqId }\n });\n }\n\n return {\n request,\n status: e.data.status,\n response: e.toResponse()\n };\n }\n\n Sentry.captureException(e, {\n tags: { reqId }\n });\n\n opts.onError?.({\n callName: call.name,\n callId: call.id,\n request: req,\n error: e,\n reqId\n });\n\n throw e;\n }\n };\n\n let canTrace = isTelemetryEnabled() && hasActiveSpan();\n if (!canTrace) {\n let result = await executeCall();\n\n return {\n request: result.request,\n status: result.status,\n response: result.response\n };\n }\n\n let callSpanName = `rpc call: ${call.name}`;\n let callSpanOp = 'rpc.server.call';\n\n return await tracer.startActiveSpan(callSpanName, async span => {\n span.setAttribute('sentry.op', callSpanOp);\n span.setAttribute('rpc.system', 'lowerdeck');\n span.setAttribute('rpc.method', call.name);\n span.setAttribute('rpc.request_id', reqId);\n span.setAttribute('rpc.call_id', call.id);\n span.setAttribute('rpc.description', callSpanName);\n span.setAttribute('sentry.description', callSpanName);\n\n let finalize = (result: {\n request: ServiceRequest;\n status: number;\n response: any;\n }) => {\n span.setAttribute('rpc.response.status_code', result.status);\n if (result.status >= 500) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: `RPC call failed with status ${result.status}`\n });\n }\n\n return result;\n };\n\n try {\n let result = await executeCall();\n\n return finalize({\n request: result.request,\n status: result.status,\n response: result.response\n });\n } catch (e) {\n span.recordException(e as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: e instanceof Error ? e.message : String(e)\n });\n\n return finalize({\n request,\n status: 500,\n response: internalServerError().toResponse()\n });\n } finally {\n span.end();\n }\n });\n };\n\n let runMany = async (\n req: ServiceRequest,\n body: {\n calls: {\n id: string;\n name: string;\n payload: any;\n }[];\n requestId: string;\n }\n ): Promise<{\n status: number;\n body: any;\n }> => {\n let callRes = await Promise.all(\n body.calls.map(async (call, i) => {\n let res = await run(req, call as any, body.requestId);\n\n try {\n opts.onRequest?.({\n reqId: body.requestId,\n callId: call.id,\n callName: call.name,\n request: res.request,\n response: { status: res.status, body: res.response }\n });\n } catch (e) {\n Sentry.captureException(e);\n console.error(e);\n }\n\n return {\n __typename: 'rpc.response.call',\n id: call.id,\n name: call.name,\n status: res.status,\n result: res.response\n };\n })\n );\n\n return {\n status: Math.max(...callRes.map(c => c.status)),\n body: {\n __typename: 'rpc.response',\n calls: callRes\n }\n };\n };\n\n return {\n handlerNames,\n runMany\n\n // fetch,\n\n // http: async (\n // req: IncomingMessage & {\n // body: any;\n // },\n // res: ServerResponse & { send: (body: any) => void }\n // ) => {\n // let headers = new Headers(\n // Object.fromEntries(\n // Object.entries(req.headers).map(([key, value]) => [\n // key,\n // value === undefined ? '' : String(value)\n // ])\n // )\n // );\n // let url = new URL(req.url ?? '', `http://${req.headers.host}`);\n\n // let request = new Request(url.toString(), {\n // method: req.method,\n // headers,\n // body: JSON.stringify(req.body)\n // });\n\n // let response = await fetch(request);\n\n // res.statusCode = response.status;\n\n // for (let [key, value] of response.headers.entries()) {\n // res.setHeader(key, value);\n // }\n\n // res.send(response.body);\n // }\n };\n };\n","export let parseForwardedFor = (xForwardedForHeader?: string | null | undefined) => {\n if (typeof xForwardedForHeader != 'string') return undefined;\n\n let ips = xForwardedForHeader\n .split(',')\n .map(ip => ip.trim())\n .filter(Boolean);\n return ips.length > 0 ? ips[0] : undefined;\n};\n"],"names":["_settle","pact","state","value","s","_Pact","o","bind","v","then","observer","prototype","onFulfilled","onRejected","result","this","callback","e","_this","_isSettledPact","thenable","Group","_middleware","_proto","use","handler","opts","concat","ctx","_exit","_temp2","_result","res","key","sharedMiddlewareMemo","set","Promise","resolve","getSharedMemoKey","_temp","has","get","_await$ctx$sharedMidd","reject","createMiddleware","input","_exit2","_temp4","_result2","_temp3","_await$ctx$sharedMidd2","Handler","controller","handlers","_handler","_validation","_proto2","undefined","Error","push","validation","run","req","initialContext","_temp6","_extends","body","response","valRes","validate","success","ServiceError","validationError","errors","entity","_temp5","_forOf","mw","verbose","process","env","NODE_ENV","Sentry","getSentry","tracer","trace","getTracer","object","calls","array","id","string","name","payload","any","getSupportedHandlerNames","Object","entries","flatMap","_ref","map","handlerNames","runMany","all","call","i","reqId","callSpanName","startActiveSpan","span","setAttribute","finalize","status","setStatus","code","SpanStatusCode","ERROR","message","_catch","executeCall","request","recordException","String","internalServerError","toResponse","_finallyRethrows","_wasThrown","end","parts","split","current","length","shift","findHandler","notFoundError","console","error","isServiceError","data","captureException","tags","onError","callName","callId","canTrace","isTelemetryEnabled","hasActiveSpan","requestId","onRequest","__typename","callRes","Math","max","apply","c","rpcs","handlerNameToRpcMap","Map","rpc","path","fetch","_req$headers$get8","_opts$cors","_req$headers$get9","_ref2","_ref3","_req$headers$get","sentryTraceHeaders","headers","sentryTrace","Array","isArray","join","baggage","ip","xForwardedForHeader","ips","trim","filter","Boolean","parseForwardedFor","Headers","corsOk","_i","_Object$entries","corsHeaders","_Object$entries$_i","append","extractedTraceContext","propagation","extract","otelContext","active","carrier","_carrier$get","keys","from","incomingParent","getSpanContext","allowRootSpan","requestSpanTarget","url","_pathParts","pathParts","pathname","lastPart","startsWith","slice","callNames","preview","summarizeRpcTarget","requestSpanName","requestSpanOp","executeRequest","withIsolationScope","continueTrace","_req$headers$get2","_req$headers$get3","startSpan","op","attributes","transport","ua","origin","_req$headers$get5","beforeSends","generateCustomId","parseCookies","memo","_req$headers$get4","Cookie","parse","query","searchParams","rawBody","getCookies","getCookie","setCookie","cookie","serialize","beforeSend","appendHeaders","newHeaders","_i2","_Object$entries2","_Object$entries2$_i","_iterator","_step","_createForOfIteratorHelperLoose","done","getCurrentScope","setContext","fromEntries","addAttachment","filename","contentType","provideExecutionContext","createExecutionContext","type","contextId","userAgent","callsByRpc","resRef","isSingle","_callsByRpc$get","rpcIndex","Response","JSON","stringify","_step2","_iterator2","_callsByRpc$get2","_ref4","_resRef$body$calls","encode","inner","stack","_req$headers$get6","_req$headers$get7","kind","SpanKind","SERVER","method","_result3","_await$executeRequest","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","notAcceptableError","_decode","decode","text","_req$text","_Response"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ServiceError as e,validationError as r,notFoundError as t,internalServerError as n,notAcceptableError as o,isServiceError as a}from"@lowerdeck/error";import{provideExecutionContext as s,createExecutionContext as i}from"@lowerdeck/execution-context";import{generateCustomId as u}from"@lowerdeck/id";import{memo as l}from"@lowerdeck/memo";import{getSentry as c}from"@lowerdeck/sentry";import{serialize as d}from"@lowerdeck/serialize";import{v as f}from"@lowerdeck/validation";import*as h from"cookie";function p(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=Array(r);t<r;t++)n[t]=e[t];return n}function m(e,r){var t="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(t)return(t=t.call(e)).next.bind(t);if(Array.isArray(e)||(t=function(e,r){if(e){if("string"==typeof e)return p(e,r);var t={}.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?p(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){t&&(e=t);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function v(){return v=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},v.apply(null,arguments)}const y="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function g(e,r,t){if(!e.s){if(t instanceof w){if(!t.s)return void(t.o=g.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(g.bind(null,e,r),g.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}var w=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){var n=new e,o=this.s;if(o){var a=1&o?r:t;if(a){try{g(n,1,a(this.v))}catch(e){g(n,2,e)}return n}return this}return this.o=function(e){try{var o=e.v;1&e.s?g(n,1,r?r(o):o):t?g(n,1,t(o)):g(n,2,o)}catch(e){g(n,2,e)}},n},e}();function b(e){return e instanceof w&&1&e.s}var P=/*#__PURE__*/function(){function e(e){void 0===e&&(e=[]),this._middleware=void 0,this._middleware=e}var r=e.prototype;return r.use=function(r,t){return new e([].concat(this._middleware,[function(e){try{var n,o=function(t){if(n)return t;var o=r(e);return a&&e.sharedMiddlewareMemo.set(a,o),Promise.resolve(o)},a=null==t||null==t.getSharedMemoKey?void 0:t.getSharedMemoKey(e),s=function(){if(a&&e.sharedMiddlewareMemo.has(a))return Promise.resolve(e.sharedMiddlewareMemo.get(a)).then(function(e){return n=1,e})}();return Promise.resolve(s&&s.then?s.then(o):o(s))}catch(e){return Promise.reject(e)}}]))},r.createMiddleware=function(e,r){return function(t){return function(n){try{var o,a=function(r){if(o)return r;var a=e(n,t);return s&&n.sharedMiddlewareMemo.set(s,a),Promise.resolve(a)},s=null==r||null==r.getSharedMemoKey?void 0:r.getSharedMemoKey(n,t),i=function(){if(s&&n.sharedMiddlewareMemo.has(s))return Promise.resolve(n.sharedMiddlewareMemo.get(s)).then(function(e){return o=1,e})}();return Promise.resolve(i&&i.then?i.then(a):a(i))}catch(e){return Promise.reject(e)}}}},r.handler=function(){return new j([].concat(this._middleware))},r.controller=function(e){return e},e}(),j=/*#__PURE__*/function(){function t(e){void 0===e&&(e=[]),this._middleware=void 0,this._handler=void 0,this._validation=void 0,this._middleware=e}var n=t.prototype;return n.do=function(e){if(null!=this._handler)throw new Error("Handler already defined");return this._handler=e,this},n.use=function(e){return this._middleware.push(e),this},n.input=function(e){if(null!=this._validation)throw new Error("Input validation already defined");return this._validation=e,this},n.run=function(t,n){try{var o=function(){return Promise.resolve(a._handler(v({},u,{input:s,body:void 0}))).then(function(e){return{response:e}})},a=this;if(!a._handler)throw new Error("Handler not defined");var s=t.body;if(a._validation){var i=a._validation.validate(t.body);if(!i.success)throw new e(r({errors:i.errors,entity:"call_data"}));s=i.value}var u=v({},n,t,{body:s}),l=function(e,r){if("function"==typeof e[y]){var t,n,o,a=function(e){try{for(;!(t=s.next()).done;)if((e=r(t.value))&&e.then){if(!b(e))return void e.then(a,o||(o=g.bind(null,n=new w,2)));e=e.v}n?g(n,1,e):n=e}catch(e){g(n||(n=new w),2,e)}},s=e[y]();if(a(),s.return){var i=function(e){try{t.done||s.return()}catch(e){}return e};if(n&&n.then)return n.then(i,function(e){throw i(e)});i()}return n}if(!("length"in e))throw new TypeError("Object is not iterable");for(var u=[],l=0;l<e.length;l++)u.push(e[l]);return function(e,r){var t,n,o=-1;return function a(s){try{for(;++o<e.length;)if((s=r(o))&&s.then){if(!b(s))return void s.then(a,n||(n=g.bind(null,t=new w,2)));s=s.v}t?g(t,1,s):t=s}catch(e){g(t||(t=new w),2,e)}}(),t}(u,function(e){return r(u[e])})}(a._middleware,function(e){return Promise.resolve(e(u)).then(function(e){e&&(u=v({},u,e))})});return Promise.resolve(l&&l.then?l.then(o):o())}catch(e){return Promise.reject(e)}},t}(),M=c(),S=f.object({calls:f.array(f.object({id:f.string(),name:f.string(),payload:f.any()}))}),_=function(e,a){var c=new Map(a.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:e.path,fetch:function(f){try{var p,v,y,g=function(e){var o,p,v,g;if(y)return e;var w=f.headers.get("sentry-trace"),P=null!=(o=Array.isArray(w)?w.join(","):w)?o:void 0,_=f.headers.get("baggage"),O=function(e){if("string"==typeof e){var r=e.split(",").map(function(e){return e.trim()}).filter(Boolean);return r.length>0?r[0]:void 0}}(null!=(p=null!=(v=null!=(g=f.headers.get("lowerdeck-connecting-ip"))?g:f.headers.get("cf-connecting-ip"))?v:f.headers.get("x-forwarded-for"))?p:f.headers.get("x-real-ip")),x=new Headers;if(b)for(var I=0,k=Object.entries(q);I<k.length;I++){var A=k[I];x.append(A[0],A[1])}return Promise.resolve(M.withIsolationScope(function(){try{return Promise.resolve(M.continueTrace({sentryTrace:P,baggage:_},function(){try{var e,o;return Promise.resolve(M.startSpan({name:"rpc request",op:"rpc.server",attributes:{ip:O,transport:"http",ua:null!=(e=f.headers.get("user-agent"))?e:"",origin:null!=(o=f.headers.get("origin"))?o:""}},function(){try{try{var e,o=[],p=u("req_"),v=l(function(){var e;return h.parse(null!=(e=f.headers.get("cookie"))?e:"")}),y={url:f.url,headers:f.headers,query:j.searchParams,body:R,rawBody:R,ip:O,requestId:p,getCookies:function(){return v()},getCookie:function(e){return v()[e]},setCookie:function(e,r,t){var n=h.serialize(e,r,t);x.append("Set-Cookie",n)},beforeSend:function(e){o.push(e)},sharedMiddlewareMemo:new Map,appendHeaders:function(e){for(var r=0,t=Object.entries(e);r<t.length;r++){var n=t[r],o=n[0],a=n[1];if(Array.isArray(a))for(var s,i=m(a);!(s=i()).done;)x.append(o,s.value);else x.append(o,a)}}};return M.getCurrentScope().setContext("rpc.request",{url:f.url,query:Object.fromEntries(j.searchParams.entries())}),M.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:R,contentType:"application/json"}),Promise.resolve(s(i({type:"request",contextId:p,ip:null!=O?O:"0.0.0.0",userAgent:null!=(e=f.headers.get("user-agent"))?e:""}),function(){try{var e=new Map,n={body:{__typename:"rpc.response",calls:[]},status:200},s=j.pathname.split("/").filter(Boolean),i=s[s.length-1],l="$"==i[0];if(l){var f,h=i.slice(1),v=c.get(h);if(null==v)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:x}));var g=null!=(f=e.get(v))?f:[];g.push({id:u("call_"),name:h,payload:R}),e.set(v,g)}else{var w=S.validate(R);if(!w.success)return Promise.resolve(new Response(JSON.stringify(r({errors:w.errors,entity:"request_data"}).toResponse()),{status:406,headers:x}));for(var b,P=m(w.value.calls);!(b=P()).done;){var M,_=b.value,q=c.get(_.name);if(null==q)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:x}));var O=null!=(M=e.get(q))?M:[];O.push(_),e.set(q,O)}}return Promise.resolve(Promise.all(Array.from(e.entries()).map(function(e){var r=e[0],t=e[1];try{return Promise.resolve(a[r].runMany(y,{requestId:p,calls:t})).then(function(e){var r;n.status=Math.max(n.status,e.status),(r=n.body.calls).push.apply(r,e.body.calls)})}catch(e){return Promise.reject(e)}}))).then(function(){return x.append("x-req-id",p),x.append("content-type","application/rpc+json"),x.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(o.map(function(e){return e()}))).then(function(){return new Response(d.encode(l?n.body.calls[0].result:n.body),{status:n.status,headers:x})})})}catch(e){return Promise.reject(e)}}))}catch(e){return console.error(e),M.captureException(e),Promise.resolve(new Response(JSON.stringify(n().toResponse()),{status:500,headers:x}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))},w=null!=(p=f.headers.get("origin"))?p:"",b=!1;if(e.cors&&"domains"in e.cors)try{var P=new URL(w).hostname.split(".").slice(-2).join(".");b=e.cors.domains.includes(P)}catch(e){}else e.cors&&"check"in e.cors&&(b=e.cors.check(w));var j=new URL(f.url),_=null==(v=e.cors)||null==(v=v.headers)?void 0:v.join(", ");_&&(_=(", "+_).trim());var q=b?{"access-control-allow-origin":w,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace"+(null!=_?_:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==f.method)return Promise.resolve(b?new Response(null,{status:204,headers:q}):new Response(null,{status:403}));var R=null,O=function(e,r){try{var t=e()}catch(e){return r()}return t&&t.then?t.then(void 0,r):t}(function(){var e=d.decode;return Promise.resolve(f.text()).then(function(r){R=e.call(d,r)})},function(){var e=new Response(JSON.stringify(o({message:"Invalid JSON"}).toResponse()),{status:406});return y=1,e});return Promise.resolve(O&&O.then?O.then(g):g(O))}catch(e){return Promise.reject(e)}}}},q=c(),R=function(e){return function(r){var o=function(e){return Object.entries(e).flatMap(function(e){var r=e[0],t=e[1];return t instanceof j?[r]:"object"==typeof t?o(t).map(function(e){return r+":"+e}):[]})};return{handlerNames:o(r),runMany:function(o,s){try{return Promise.resolve(Promise.all(s.calls.map(function(i,u){try{return Promise.resolve(function(o,s,i){try{var u=v({},o,{body:s.payload});return Promise.resolve(function(e,n){try{var a=(i=function(e){for(var t=e.split(":"),n=r;n&&t.length>0;)if(!(n=n[t.shift()]))return null;return n&&n instanceof j?n:null}(s.name))?Promise.resolve(i.run(u,{})).then(function(e){return{status:200,request:o,response:e.response}}):{request:u,status:404,response:t({entity:"handler"}).toResponse()}}catch(e){return n(e)}var i;return a&&a.then?a.then(void 0,n):a}(0,function(r){return console.error(r),a(r)?(r.data.status>=500&&q.captureException(r,{tags:{reqId:i}}),{request:u,status:r.data.status,response:r.toResponse()}):(q.captureException(r,{tags:{reqId:i}}),null==e.onError||e.onError({callName:s.name,callId:s.id,request:o,error:r,reqId:i}),{request:u,status:500,response:n().toResponse()})}))}catch(e){return Promise.reject(e)}}(o,i,s.requestId)).then(function(r){try{null==e.onRequest||e.onRequest({reqId:s.requestId,callId:i.id,callName:i.name,request:r.request,response:{status:r.status,body:r.response}})}catch(e){q.captureException(e),console.error(e)}return{__typename:"rpc.response.call",id:i.id,name:i.name,status:r.status,result:r.response}})}catch(e){return Promise.reject(e)}}))).then(function(e){return{status:Math.max.apply(Math,e.map(function(e){return e.status})),body:{__typename:"rpc.response",calls:e}}})}catch(e){return Promise.reject(e)}}}}};export{P as Group,j as Handler,R as createServer,_ as rpcMux};
1
+ import{ServiceError as e,validationError as r,notFoundError as t,internalServerError as n,notAcceptableError as o,isServiceError as s}from"@lowerdeck/error";import{trace as a,propagation as i,otelContext as u,isTelemetryEnabled as c,SpanKind as l,SpanStatusCode as d,hasActiveSpan as f}from"@lowerdeck/telemetry";import{provideExecutionContext as h,createExecutionContext as p}from"@lowerdeck/execution-context";import{generateCustomId as m}from"@lowerdeck/id";import{memo as v}from"@lowerdeck/memo";import{getSentry as y}from"@lowerdeck/sentry";import{serialize as g}from"@lowerdeck/serialize";import{v as w}from"@lowerdeck/validation";import*as P from"cookie";function b(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=Array(r);t<r;t++)n[t]=e[t];return n}function S(e,r){var t="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(t)return(t=t.call(e)).next.bind(t);if(Array.isArray(e)||(t=function(e,r){if(e){if("string"==typeof e)return b(e,r);var t={}.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?b(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){t&&(e=t);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function j(){return j=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},j.apply(null,arguments)}const R="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function q(e,r,t){if(!e.s){if(t instanceof _){if(!t.s)return void(t.o=q.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(q.bind(null,e,r),q.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}var _=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){var n=new e,o=this.s;if(o){var s=1&o?r:t;if(s){try{q(n,1,s(this.v))}catch(e){q(n,2,e)}return n}return this}return this.o=function(e){try{var o=e.v;1&e.s?q(n,1,r?r(o):o):t?q(n,1,t(o)):q(n,2,o)}catch(e){q(n,2,e)}},n},e}();function M(e){return e instanceof _&&1&e.s}var A=/*#__PURE__*/function(){function e(e){void 0===e&&(e=[]),this._middleware=void 0,this._middleware=e}var r=e.prototype;return r.use=function(r,t){return new e([].concat(this._middleware,[function(e){try{var n,o=function(t){if(n)return t;var o=r(e);return s&&e.sharedMiddlewareMemo.set(s,o),Promise.resolve(o)},s=null==t||null==t.getSharedMemoKey?void 0:t.getSharedMemoKey(e),a=function(){if(s&&e.sharedMiddlewareMemo.has(s))return Promise.resolve(e.sharedMiddlewareMemo.get(s)).then(function(e){return n=1,e})}();return Promise.resolve(a&&a.then?a.then(o):o(a))}catch(e){return Promise.reject(e)}}]))},r.createMiddleware=function(e,r){return function(t){return function(n){try{var o,s=function(r){if(o)return r;var s=e(n,t);return a&&n.sharedMiddlewareMemo.set(a,s),Promise.resolve(s)},a=null==r||null==r.getSharedMemoKey?void 0:r.getSharedMemoKey(n,t),i=function(){if(a&&n.sharedMiddlewareMemo.has(a))return Promise.resolve(n.sharedMiddlewareMemo.get(a)).then(function(e){return o=1,e})}();return Promise.resolve(i&&i.then?i.then(s):s(i))}catch(e){return Promise.reject(e)}}}},r.handler=function(){return new k([].concat(this._middleware))},r.controller=function(e){return e},e}(),k=/*#__PURE__*/function(){function t(e){void 0===e&&(e=[]),this._middleware=void 0,this._handler=void 0,this._validation=void 0,this._middleware=e}var n=t.prototype;return n.do=function(e){if(null!=this._handler)throw new Error("Handler already defined");return this._handler=e,this},n.use=function(e){return this._middleware.push(e),this},n.input=function(e){if(null!=this._validation)throw new Error("Input validation already defined");return this._validation=e,this},n.run=function(t,n){try{var o=function(){return Promise.resolve(s._handler(j({},u,{input:a,body:void 0}))).then(function(e){return{response:e}})},s=this;if(!s._handler)throw new Error("Handler not defined");var a=t.body;if(s._validation){var i=s._validation.validate(t.body);if(!i.success)throw new e(r({errors:i.errors,entity:"call_data"}));a=i.value}var u=j({},n,t,{body:a}),c=function(e,r){if("function"==typeof e[R]){var t,n,o,s=function(e){try{for(;!(t=a.next()).done;)if((e=r(t.value))&&e.then){if(!M(e))return void e.then(s,o||(o=q.bind(null,n=new _,2)));e=e.v}n?q(n,1,e):n=e}catch(e){q(n||(n=new _),2,e)}},a=e[R]();if(s(),a.return){var i=function(e){try{t.done||a.return()}catch(e){}return e};if(n&&n.then)return n.then(i,function(e){throw i(e)});i()}return n}if(!("length"in e))throw new TypeError("Object is not iterable");for(var u=[],c=0;c<e.length;c++)u.push(e[c]);return function(e,r){var t,n,o=-1;return function s(a){try{for(;++o<e.length;)if((a=r(o))&&a.then){if(!M(a))return void a.then(s,n||(n=q.bind(null,t=new _,2)));a=a.v}t?q(t,1,a):t=a}catch(e){q(t||(t=new _),2,e)}}(),t}(u,function(e){return r(u[e])})}(s._middleware,function(e){return Promise.resolve(e(u)).then(function(e){e&&(u=j({},u,e))})});return Promise.resolve(c&&c.then?c.then(o):o())}catch(e){return Promise.reject(e)}},t}();function O(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var E="production"!==process.env.NODE_ENV,x=y(),I=a.getTracer("lowerdeck.rpc-server"),N=w.object({calls:w.array(w.object({id:w.string(),name:w.string(),payload:w.any()}))}),C=function(e,s){var f=new Map(s.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:e.path,fetch:function(y){try{var w,b,j,R,q=function(o){var w,b,j,q;if(R)return o;var _=y.headers.get("sentry-trace"),A=null!=(w=Array.isArray(_)?_.join(","):_)?w:void 0,C=y.headers.get("baggage"),J=function(e){if("string"==typeof e){var r=e.split(",").map(function(e){return e.trim()}).filter(Boolean);return r.length>0?r[0]:void 0}}(null!=(b=null!=(j=null!=(q=y.headers.get("lowerdeck-connecting-ip"))?q:y.headers.get("cf-connecting-ip"))?j:y.headers.get("x-forwarded-for"))?b:y.headers.get("x-real-ip")),H=new Headers;if(M)for(var K=0,z=Object.entries(T);K<z.length;K++){var U=z[K];H.append(U[0],U[1])}var $=i.extract(u.active(),y.headers,{get:function(e,r){var t;return null!=(t=e.get(r))?t:void 0},keys:function(e){return Array.from(e.keys())}}),L=a.getSpanContext($),V=c()&&(!!L||!!e.allowRootSpan),D=function(e,r){var t,n=e.pathname.split("/").filter(Boolean),o=null!=(t=n[n.length-1])?t:"";if(o.startsWith("$")&&o.length>1)return o.slice(1);var s=[];if(r&&"object"==typeof r&&Array.isArray(r.calls)&&(s=r.calls.map(function(e){return"string"==typeof(null==e?void 0:e.name)?e.name.trim():""}).filter(Boolean)),1==s.length)return s[0];if(s.length>1){var a=s.slice(0,3).join(", ");return s.length>3?a+", +"+(s.length-3)+" more":a}return e.pathname}(k,B),W="rpc request: "+D,F="rpc.server.request",G=function(){try{return Promise.resolve(x.withIsolationScope(function(){try{return Promise.resolve(x.continueTrace({sentryTrace:A,baggage:C},function(){try{var e,o;return Promise.resolve(x.startSpan({name:W,op:F,attributes:{"sentry.op":F,"rpc.request.target":D,"rpc.description":W,"sentry.description":W,ip:J,transport:"http",ua:null!=(e=y.headers.get("user-agent"))?e:"",origin:null!=(o=y.headers.get("origin"))?o:""}},function(){try{try{var e,o=[],a=m("req_"),i=v(function(){var e;return P.parse(null!=(e=y.headers.get("cookie"))?e:"")}),u={url:y.url,headers:y.headers,query:k.searchParams,body:B,rawBody:B,ip:J,requestId:a,getCookies:function(){return i()},getCookie:function(e){return i()[e]},setCookie:function(e,r,t){var n=P.serialize(e,r,t);H.append("Set-Cookie",n)},beforeSend:function(e){o.push(e)},sharedMiddlewareMemo:new Map,appendHeaders:function(e){for(var r=0,t=Object.entries(e);r<t.length;r++){var n=t[r],o=n[0],s=n[1];if(Array.isArray(s))for(var a,i=S(s);!(a=i()).done;)H.append(o,a.value);else H.append(o,s)}}};return x.getCurrentScope().setContext("rpc.request",{url:y.url,query:Object.fromEntries(k.searchParams.entries())}),x.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:B,contentType:"application/json"}),Promise.resolve(h(p({type:"request",contextId:a,ip:null!=J?J:"0.0.0.0",userAgent:null!=(e=y.headers.get("user-agent"))?e:""}),function(){try{var e=new Map,n={body:{__typename:"rpc.response",calls:[]},status:200},i=k.pathname.split("/").filter(Boolean),c=i[i.length-1],l="$"==c[0];if(l){var d,h=c.slice(1),p=f.get(h);if(null==p)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:H}));var v=null!=(d=e.get(p))?d:[];v.push({id:m("call_"),name:h,payload:B}),e.set(p,v)}else{var y=N.validate(B);if(!y.success)return Promise.resolve(new Response(JSON.stringify(r({errors:y.errors,entity:"request_data"}).toResponse()),{status:406,headers:H}));for(var w,P=S(y.value.calls);!(w=P()).done;){var b,j=w.value,R=f.get(j.name);if(null==R)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:H}));var q=null!=(b=e.get(R))?b:[];q.push(j),e.set(R,q)}}return Promise.resolve(Promise.all(Array.from(e.entries()).map(function(e){var r=e[0],t=e[1];try{return Promise.resolve(s[r].runMany(u,{requestId:a,calls:t})).then(function(e){var r;n.status=Math.max(n.status,e.status),(r=n.body.calls).push.apply(r,e.body.calls)})}catch(e){return Promise.reject(e)}}))).then(function(){return H.append("x-req-id",a),H.append("content-type","application/rpc+json"),H.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(o.map(function(e){return e()}))).then(function(){return new Response(g.encode(l?n.body.calls[0].result:n.body),{status:n.status,headers:H})})})}catch(e){return Promise.reject(e)}}))}catch(e){return E&&console.error(e),x.captureException(e),Promise.resolve(new Response(JSON.stringify(n({inner:E?e instanceof Error?{message:e.message,stack:e.stack}:{error:e}:void 0}).toResponse()),{status:500,headers:H}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}};return Promise.resolve(u.with($,function(){try{var e,r=function(r){var t,n;return e?r:Promise.resolve(I.startActiveSpan(W,{kind:l.SERVER,attributes:{"sentry.op":F,"rpc.system":"lowerdeck","rpc.request.target":D,"rpc.description":W,"sentry.description":W,"http.request.method":y.method,"url.path":k.pathname,ip:null!=J?J:"",transport:"http",ua:null!=(t=y.headers.get("user-agent"))?t:"",origin:null!=(n=y.headers.get("origin"))?n:""}},function(e){try{return Promise.resolve(function(r,t){try{var n=O(function(){return Promise.resolve(G()).then(function(r){return e.setAttribute("http.response.status_code",r.status),r.status>=500&&e.setStatus({code:d.ERROR,message:"RPC request failed with status "+r.status}),r})},function(r){throw e.recordException(r),e.setStatus({code:d.ERROR,message:r instanceof Error?r.message:String(r)}),r})}catch(e){return t(!0,e)}return n&&n.then?n.then(t.bind(null,!1),t.bind(null,!0)):t(!1,n)}(0,function(r,t){if(e.end(),r)throw t;return t}))}catch(e){return Promise.reject(e)}}))},t=function(){if(!V)return Promise.resolve(G()).then(function(r){return e=1,r})}();return Promise.resolve(t&&t.then?t.then(r):r(t))}catch(e){return Promise.reject(e)}}))},_=null!=(w=y.headers.get("origin"))?w:"",M=!1;if(e.cors&&"domains"in e.cors)try{var A=new URL(_).hostname.split(".").slice(-2).join(".");M=e.cors.domains.includes(A)}catch(e){}else e.cors&&"check"in e.cors&&(M=e.cors.check(_));var k=new URL(y.url),C=null==(b=e.cors)||null==(b=b.headers)?void 0:b.join(", ");C&&(C=(", "+C).trim());var T=M?{"access-control-allow-origin":_,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace, traceparent, tracestate"+(null!=C?C:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==y.method)return Promise.resolve(M?new Response(null,{status:204,headers:T}):new Response(null,{status:403}));var J=null!=(j=y.headers.get("content-type"))?j:"";if(!J.includes("application/rpc+json")&&!J.includes("application/json"))return Promise.resolve(new Response(JSON.stringify(o({message:"Content-Type must be application/rpc+json"}).toResponse()),{status:406,headers:T}));var B=null,H=O(function(){var e=g.decode;return Promise.resolve(y.text()).then(function(r){B=e.call(g,r)})},function(){var e=new Response(JSON.stringify(o({message:"Invalid JSON"}).toResponse()),{status:406});return R=1,e});return Promise.resolve(H&&H.then?H.then(q):q(H))}catch(e){return Promise.reject(e)}}}};function T(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var J=y(),B=a.getTracer("lowerdeck.rpc-server.calls"),H=function(e){return function(r){var o=function(e){return Object.entries(e).flatMap(function(e){var r=e[0],t=e[1];return t instanceof k?[r]:"object"==typeof t?o(t).map(function(e){return r+":"+e}):[]})};return{handlerNames:o(r),runMany:function(o,a){try{return Promise.resolve(Promise.all(a.calls.map(function(i,u){try{return Promise.resolve(function(o,a,i){try{var u,l=function(e){if(u)return e;var r="rpc call: "+a.name;return Promise.resolve(B.startActiveSpan(r,function(e){try{e.setAttribute("sentry.op","rpc.server.call"),e.setAttribute("rpc.system","lowerdeck"),e.setAttribute("rpc.method",a.name),e.setAttribute("rpc.request_id",i),e.setAttribute("rpc.call_id",a.id),e.setAttribute("rpc.description",r),e.setAttribute("sentry.description",r);var t=function(r){return e.setAttribute("rpc.response.status_code",r.status),r.status>=500&&e.setStatus({code:d.ERROR,message:"RPC call failed with status "+r.status}),r};return Promise.resolve(function(r,o){try{var s=T(function(){return Promise.resolve(p()).then(function(e){return t({request:e.request,status:e.status,response:e.response})})},function(r){return e.recordException(r),e.setStatus({code:d.ERROR,message:r instanceof Error?r.message:String(r)}),t({request:h,status:500,response:n().toResponse()})})}catch(e){return o(!0,e)}return s&&s.then?s.then(o.bind(null,!1),o.bind(null,!0)):o(!1,s)}(0,function(r,t){if(e.end(),r)throw t;return t}))}catch(e){return Promise.reject(e)}}))},h=j({},o,{body:a.payload}),p=function(){try{return Promise.resolve(T(function(){var e=function(e){for(var t=e.split(":"),n=r;n&&t.length>0;)if(!(n=n[t.shift()]))return null;return n&&n instanceof k?n:null}(a.name);return e?Promise.resolve(e.run(h,{})).then(function(e){return{status:200,request:o,response:e.response}}):{request:h,status:404,response:t({entity:"handler"}).toResponse()}},function(r){if(console.error(r),s(r))return r.data.status>=500&&J.captureException(r,{tags:{reqId:i}}),{request:h,status:r.data.status,response:r.toResponse()};throw J.captureException(r,{tags:{reqId:i}}),null==e.onError||e.onError({callName:a.name,callId:a.id,request:o,error:r,reqId:i}),r}))}catch(e){return Promise.reject(e)}},m=c()&&f(),v=function(){if(!m)return Promise.resolve(p()).then(function(e){return u=1,{request:e.request,status:e.status,response:e.response}})}();return Promise.resolve(v&&v.then?v.then(l):l(v))}catch(e){return Promise.reject(e)}}(o,i,a.requestId)).then(function(r){try{null==e.onRequest||e.onRequest({reqId:a.requestId,callId:i.id,callName:i.name,request:r.request,response:{status:r.status,body:r.response}})}catch(e){J.captureException(e),console.error(e)}return{__typename:"rpc.response.call",id:i.id,name:i.name,status:r.status,result:r.response}})}catch(e){return Promise.reject(e)}}))).then(function(e){return{status:Math.max.apply(Math,e.map(function(e){return e.status})),body:{__typename:"rpc.response",calls:e}}})}catch(e){return Promise.reject(e)}}}}};export{A as Group,k as Handler,H as createServer,C as rpcMux};
2
2
  //# sourceMappingURL=index.module.js.map