@lowerdeck/rpc-server 1.0.9 → 1.0.10
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 +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.module.js +1 -1
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/rpcMux.d.ts +1 -0
- package/dist/rpcMux.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/package.json +4 -4
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"),s=require("@lowerdeck/validation");function i(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__*/i(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),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 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({},i,{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 s=o._validation.validate(r.body);if(!s.success)throw new e.ServiceError(e.validationError({errors:s.errors,entity:"call_data"}));a=s.value}var i=d({},t,r,{body:a}),u=function(e,r){if("function"==typeof e[f]){var t,n,o,a=function(e){try{for(;!(t=s.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)}},s=e[f]();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=[],c=0;c<e.length;c++)u.push(e[c]);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(!v(s))return void s.then(a,n||(n=h.bind(null,t=new p,2)));s=s.v}t?h(t,1,s):t=s}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(i)).then(function(e){e&&(i=d({},i,e))})});return Promise.resolve(u&&u.then?u.then(n):n())}catch(e){return Promise.reject(e)}},r}(),g="production"!==process.env.NODE_ENV,w=o.getSentry(),b=s.v.object({calls:s.v.array(s.v.object({id:s.v.string(),name:s.v.string(),payload:s.v.any()}))}),P=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,s){try{return Promise.resolve(function(n,o,a){try{var s=d({},n,{body:o.payload});return Promise.resolve(function(r,a){try{var i=(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(s,{})).then(function(e){return{status:200,request:n,response:e.response}}):{request:s,status:404,response:e.notFoundError({entity:"handler"}).toResponse()}}catch(e){return a(e)}var u;return i&&i.then?i.then(void 0,a):i}(0,function(t){return console.error(t),e.isServiceError(t)?(t.data.status>=500&&P.captureException(t,{tags:{reqId:a}}),{request:s,status:t.data.status,response:t.toResponse()}):(P.captureException(t,{tags:{reqId:a}}),null==r.onError||r.onError({callName:o.name,callId:o.id,request:n,error:t,reqId:a}),{request:s,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){P.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,s){var i=new Map(s.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,v=function(o){var d,f,h,v;if(p)return o;var m=c.headers.get("sentry-trace"),P=null!=(d=Array.isArray(m)?m.join(","):m)?d:void 0,j=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!=(h=null!=(v=c.headers.get("lowerdeck-connecting-ip"))?v:c.headers.get("cf-connecting-ip"))?h:c.headers.get("x-forwarded-for"))?f:c.headers.get("x-real-ip")),E=new Headers;if(y)for(var x=0,O=Object.entries(q);x<O.length;x++){var R=O[x];E.append(R[0],R[1])}return Promise.resolve(w.withIsolationScope(function(){try{return Promise.resolve(w.continueTrace({sentryTrace:P,baggage:j},function(){try{var o,d;return Promise.resolve(w.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:S.searchParams,body:_,rawBody:_,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);E.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 s,i=l(a);!(s=i()).done;)E.append(o,s.value);else E.append(o,a)}}};return w.getCurrentScope().setContext("rpc.request",{url:c.url,query:Object.fromEntries(S.searchParams.entries())}),w.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:_,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=S.pathname.split("/").filter(Boolean),u=o[o.length-1],c="$"==u[0];if(c){var h,v=u.slice(1),m=i.get(v);if(null==m)return Promise.resolve(new Response(JSON.stringify(e.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:E}));var y=null!=(h=r.get(m))?h:[];y.push({id:t.generateCustomId("call_"),name:v,payload:_}),r.set(m,y)}else{var g=b.validate(_);if(!g.success)return Promise.resolve(new Response(JSON.stringify(e.validationError({errors:g.errors,entity:"request_data"}).toResponse()),{status:406,headers:E}));for(var w,P=l(g.value.calls);!(w=P()).done;){var j,q=w.value,M=i.get(q.name);if(null==M)return Promise.resolve(new Response(JSON.stringify(e.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:E}));var x=null!=(j=r.get(M))?j:[];x.push(q),r.set(M,x)}}return Promise.resolve(Promise.all(Array.from(r.entries()).map(function(e){var r=e[0],t=e[1];try{return Promise.resolve(s[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 E.append("x-req-id",f),E.append("content-type","application/rpc+json"),E.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:E})})})}catch(e){return Promise.reject(e)}}))}catch(r){return g&&console.error(r),w.captureException(r),Promise.resolve(new Response(JSON.stringify(e.internalServerError({inner:g?r instanceof Error?{message:r.message,stack:r.stack}:{error:r}:void 0}).toResponse()),{status:500,headers:E}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))},m=null!=(d=c.headers.get("origin"))?d:"",y=!1;if(o.cors&&"domains"in o.cors)try{var P=new URL(m).hostname.split(".").slice(-2).join(".");y=o.cors.domains.includes(P)}catch(e){}else o.cors&&"check"in o.cors&&(y=o.cors.check(m));var S=new URL(c.url),j=null==(f=o.cors)||null==(f=f.headers)?void 0:f.join(", ");j&&(j=(", "+j).trim());var q=y?{"access-control-allow-origin":m,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace"+(null!=j?j:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==c.method)return Promise.resolve(y?new Response(null,{status:204,headers:q}):new Response(null,{status:403}));var M=null!=(h=c.headers.get("content-type"))?h:"";if(!M.includes("application/rpc+json")&&!M.includes("application/json"))return Promise.resolve(new Response(JSON.stringify(e.notAcceptableError({message:"Content-Type must be application/rpc+json"}).toResponse()),{status:406,headers:q}));var _=null,E=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){_=e.call(a.serialize,r)})},function(){var r=new Response(JSON.stringify(e.notAcceptableError({message:"Invalid JSON"}).toResponse()),{status:406});return p=1,r});return Promise.resolve(E&&E.then?E.then(v):v(E))}catch(e){return Promise.reject(e)}}}};
|
|
1
|
+
var e=require("@lowerdeck/error"),r=require("@lowerdeck/execution-context"),t=require("@lowerdeck/id"),n=require("@lowerdeck/memo"),o=require("@lowerdeck/sentry"),s=require("@lowerdeck/serialize"),a=require("@lowerdeck/telemetry"),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 p(){return p=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},p.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 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(p({},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=p({},t,r,{body:s}),u=function(e,r){if("function"==typeof e[f]){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[f]();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=p({},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=o.getSentry(),S=a.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=o.getSentry(),R=a.trace.getTracer("lowerdeck.rpc-server.calls"),_="production"!==process.env.NODE_ENV;exports.Group=y,exports.Handler=g,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 g?[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(s,i){try{return Promise.resolve(function(n,o,s){try{var i,u=function(r){if(i)return r;var t="rpc call: "+o.name;return Promise.resolve(R.startActiveSpan(t,function(r){try{r.setAttribute("sentry.op","rpc.server.call"),r.setAttribute("rpc.system","lowerdeck"),r.setAttribute("rpc.method",o.name),r.setAttribute("rpc.request_id",s),r.setAttribute("rpc.call_id",o.id),r.setAttribute("rpc.description",t),r.setAttribute("sentry.description",t);var n=function(e){return r.setAttribute("rpc.response.status_code",e.status),e.status>=500&&r.setStatus({code:a.SpanStatusCode.ERROR,message:"RPC call failed with status "+e.status}),e};return Promise.resolve(function(t,o){try{var s=j(function(){return Promise.resolve(l()).then(function(e){return n({request:e.request,status:e.status,response:e.response})})},function(t){return r.recordException(t),r.setStatus({code:a.SpanStatusCode.ERROR,message:t instanceof Error?t.message:String(t)}),n({request:c,status:500,response:e.internalServerError().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(e,t){if(r.end(),e)throw t;return t}))}catch(e){return Promise.reject(e)}}))},c=p({},n,{body:o.payload}),l=function(){try{return Promise.resolve(j(function(){var r=function(e){for(var r=e.split(":"),n=t;n&&r.length>0;)if(!(n=n[r.shift()]))return null;return n&&n instanceof g?n:null}(o.name);return r?Promise.resolve(r.run(c,{})).then(function(e){return{status:200,request:n,response:e.response}}):{request:c,status:404,response:e.notFoundError({entity:"handler"}).toResponse()}},function(t){if(_&&console.error(t),e.isServiceError(t))return t.data.status>=500&&E.captureException(t,{tags:{reqId:s}}),{request:c,status:t.data.status,response:t.toResponse()};throw E.captureException(t,{tags:{reqId:s}}),null==r.onError||r.onError({callName:o.name,callId:o.id,request:n,error:t,reqId:s}),t}))}catch(e){return Promise.reject(e)}},d=a.isTelemetryEnabled()&&a.hasActiveSpan(),f=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(f&&f.then?f.then(u):u(f))}catch(e){return Promise.reject(e)}}(n,s,o.requestId)).then(function(e){try{null==r.onRequest||r.onRequest({reqId:o.requestId,callId:s.id,callName:s.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:s.id,name:s.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 u=new Map(i.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:o.path,fetch:function(l){try{var p,f,h,v,m=function(p){var f,h,m,y;if(v)return p;var j=l.headers.get("sentry-trace"),R=null!=(f=Array.isArray(j)?j.join(","):j)?f:void 0,x=l.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!=(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")),A=new Headers;if(g)for(var k=0,C=Object.entries(_);k<C.length;k++){var I=C[k];A.append(I[0],I[1])}var N=a.propagation.extract(a.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=a.trace.getSpanContext(N),J=a.isTelemetryEnabled()&&(!!T||!!o.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 o,a;return Promise.resolve(P.startSpan({name:B,op:H,attributes:{"sentry.op":H,"rpc.request.target":z,"rpc.description":B,"sentry.description":B,ip:O,transport:"http",ua:null!=(o=l.headers.get("user-agent"))?o:"",origin:null!=(a=l.headers.get("origin"))?a:""}},function(){try{try{var o,a=[],p=t.generateCustomId("req_"),f=n.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:O,requestId:p,getCookies:function(){return f()},getCookie:function(e){return f()[e]},setCookie:function(e,r,t){var n=c.serialize(e,r,t);A.append("Set-Cookie",n)},beforeSend:function(e){a.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;)A.append(o,a.value);else A.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(r.provideExecutionContext(r.createExecutionContext({type:"request",contextId:p,ip:null!=O?O:"0.0.0.0",userAgent:null!=(o=l.headers.get("user-agent"))?o:""}),function(){try{var r=new Map,n={body:{__typename:"rpc.response",calls:[]},status:200},o=E.pathname.split("/").filter(Boolean),c=o[o.length-1],l="$"==c[0];if(l){var f,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:A}));var y=null!=(f=r.get(m))?f:[];y.push({id:t.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:A}));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:A}));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],t=e[1];try{return Promise.resolve(i[r].runMany(h,{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 A.append("x-req-id",p),A.append("content-type","application/rpc+json"),A.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(a.map(function(e){return e()}))).then(function(){return new Response(s.serialize.encode(l?n.body.calls[0].result:n.body),{status:n.status,headers:A})})})}catch(e){return Promise.reject(e)}}))}catch(r){return b&&console.error(r),P.captureException(r,{extra:{url:l.url,method:l.method,ip:O,body:M}}),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:A}))}}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(a.otelContext.with(N,function(){try{var e,r=function(r){var t,n;return e?r:Promise.resolve(S.startActiveSpan(B,{kind:a.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!=O?O:"",transport:"http",ua:null!=(t=l.headers.get("user-agent"))?t:"",origin:null!=(n=l.headers.get("origin"))?n:""}},function(e){try{return Promise.resolve(function(r,t){try{var n=w(function(){return Promise.resolve(K()).then(function(r){return e.setAttribute("http.response.status_code",r.status),r.status>=500&&e.setStatus({code:a.SpanStatusCode.ERROR,message:"RPC request failed with status "+r.status}),r})},function(r){throw e.recordException(r),e.setStatus({code:a.SpanStatusCode.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(!J)return Promise.resolve(K()).then(function(r){return e=1,r})}();return Promise.resolve(t&&t.then?t.then(r):r(t))}catch(e){return Promise.reject(e)}}))},y=null!=(p=l.headers.get("origin"))?p:"",g=!1;if(o.cors&&"domains"in o.cors)try{var j=new URL(y).hostname.split(".").slice(-2).join(".");g=o.cors.domains.includes(j)}catch(e){}else o.cors&&"check"in o.cors&&(g=o.cors.check(y));var E=new URL(l.url),R=null==(f=o.cors)||null==(f=f.headers)?void 0:f.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,O=w(function(){var e=s.serialize.decode;return Promise.resolve(l.text()).then(function(r){M=e.call(s.serialize,r)})},function(){var r=new Response(JSON.stringify(e.notAcceptableError({message:"Invalid JSON"}).toResponse()),{status:406});return v=1,r});return Promise.resolve(O&&O.then?O.then(m):m(O))}catch(e){return Promise.reject(e)}}}};
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 verbose = process.env.NODE_ENV !== 'production';\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 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 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 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 };\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","verbose","process","env","NODE_ENV","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","_req$headers$get7","_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","_step2","_iterator2","_callsByRpc$get2","from","_ref4","_resRef$body$calls","encode","inner","message","stack","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","method","notAcceptableError","_decode","decode","text","_req$text","_Response"],"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 { 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 {\n isTelemetryEnabled,\n otelContext,\n propagation,\n SpanKind,\n SpanStatusCode,\n trace\n} from '@lowerdeck/telemetry';\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 extra: { url: req.url, method: req.method, ip, body }\n });\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\nlet verbose = process.env.NODE_ENV !== 'production';\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 if (verbose) 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 if (verbose) 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","_request$status$respo","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","_iterator2","_step2","_callsByRpc$get2","_ref4","_resRef$body$calls","encode","extra","method","inner","stack","_req$headers$get6","_req$headers$get7","kind","SpanKind","SERVER","_result3","_await$executeRequest","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","notAcceptableError","_decode","decode","text","_req$text","_Response"],"mappings":"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"}
|
package/dist/index.module.js
CHANGED
|
@@ -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 c}from"@lowerdeck/memo";import{getSentry as l}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}),c=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=[],c=0;c<e.length;c++)u.push(e[c]);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(c&&c.then?c.then(o):o())}catch(e){return Promise.reject(e)}},t}(),S="production"!==process.env.NODE_ENV,M=l(),_=f.object({calls:f.array(f.object({id:f.string(),name:f.string(),payload:f.any()}))}),q=function(e,a){var l=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,w=function(e){var o,p,v,y;if(g)return e;var w=f.headers.get("sentry-trace"),b=null!=(o=Array.isArray(w)?w.join(","):w)?o:void 0,j=f.headers.get("baggage"),R=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!=(y=f.headers.get("lowerdeck-connecting-ip"))?y:f.headers.get("cf-connecting-ip"))?v:f.headers.get("x-forwarded-for"))?p:f.headers.get("x-real-ip")),k=new Headers;if(P)for(var I=0,E=Object.entries(O);I<E.length;I++){var N=E[I];k.append(N[0],N[1])}return Promise.resolve(M.withIsolationScope(function(){try{return Promise.resolve(M.continueTrace({sentryTrace:b,baggage:j},function(){try{var e,o;return Promise.resolve(M.startSpan({name:"rpc request",op:"rpc.server",attributes:{ip:R,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=c(function(){var e;return h.parse(null!=(e=f.headers.get("cookie"))?e:"")}),y={url:f.url,headers:f.headers,query:q.searchParams,body:x,rawBody:x,ip:R,requestId:p,getCookies:function(){return v()},getCookie:function(e){return v()[e]},setCookie:function(e,r,t){var n=h.serialize(e,r,t);k.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;)k.append(o,s.value);else k.append(o,a)}}};return M.getCurrentScope().setContext("rpc.request",{url:f.url,query:Object.fromEntries(q.searchParams.entries())}),M.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:x,contentType:"application/json"}),Promise.resolve(s(i({type:"request",contextId:p,ip:null!=R?R:"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=q.pathname.split("/").filter(Boolean),i=s[s.length-1],c="$"==i[0];if(c){var f,h=i.slice(1),v=l.get(h);if(null==v)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:k}));var g=null!=(f=e.get(v))?f:[];g.push({id:u("call_"),name:h,payload:x}),e.set(v,g)}else{var w=_.validate(x);if(!w.success)return Promise.resolve(new Response(JSON.stringify(r({errors:w.errors,entity:"request_data"}).toResponse()),{status:406,headers:k}));for(var b,P=m(w.value.calls);!(b=P()).done;){var j,S=b.value,M=l.get(S.name);if(null==M)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:k}));var R=null!=(j=e.get(M))?j:[];R.push(S),e.set(M,R)}}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 k.append("x-req-id",p),k.append("content-type","application/rpc+json"),k.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(o.map(function(e){return e()}))).then(function(){return new Response(d.encode(c?n.body.calls[0].result:n.body),{status:n.status,headers:k})})})}catch(e){return Promise.reject(e)}}))}catch(e){return S&&console.error(e),M.captureException(e),Promise.resolve(new Response(JSON.stringify(n({inner:S?e instanceof Error?{message:e.message,stack:e.stack}:{error:e}:void 0}).toResponse()),{status:500,headers:k}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))},b=null!=(p=f.headers.get("origin"))?p:"",P=!1;if(e.cors&&"domains"in e.cors)try{var j=new URL(b).hostname.split(".").slice(-2).join(".");P=e.cors.domains.includes(j)}catch(e){}else e.cors&&"check"in e.cors&&(P=e.cors.check(b));var q=new URL(f.url),R=null==(v=e.cors)||null==(v=v.headers)?void 0:v.join(", ");R&&(R=(", "+R).trim());var O=P?{"access-control-allow-origin":b,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace"+(null!=R?R:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==f.method)return Promise.resolve(P?new Response(null,{status:204,headers:O}):new Response(null,{status:403}));var k=null!=(y=f.headers.get("content-type"))?y:"";if(!k.includes("application/rpc+json")&&!k.includes("application/json"))return Promise.resolve(new Response(JSON.stringify(o({message:"Content-Type must be application/rpc+json"}).toResponse()),{status:406,headers:O}));var x=null,I=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){x=e.call(d,r)})},function(){var e=new Response(JSON.stringify(o({message:"Invalid JSON"}).toResponse()),{status:406});return g=1,e});return Promise.resolve(I&&I.then?I.then(w):w(I))}catch(e){return Promise.reject(e)}}}},R=l(),O=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&&R.captureException(r,{tags:{reqId:i}}),{request:u,status:r.data.status,response:r.toResponse()}):(R.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){R.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,O as createServer,q 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{provideExecutionContext as a,createExecutionContext as i}from"@lowerdeck/execution-context";import{generateCustomId as u}from"@lowerdeck/id";import{memo as c}from"@lowerdeck/memo";import{getSentry as l}from"@lowerdeck/sentry";import{serialize as d}from"@lowerdeck/serialize";import{trace as f,propagation as p,otelContext as h,isTelemetryEnabled as m,SpanKind as v,SpanStatusCode as y,hasActiveSpan as g}from"@lowerdeck/telemetry";import{v as w}from"@lowerdeck/validation";import*as b 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 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 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 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 E(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var O="production"!==process.env.NODE_ENV,x=l(),I=f.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 l=new Map(s.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:e.path,fetch:function(g){try{var w,P,j,R,q=function(o){var w,P,j,q;if(R)return o;var _=g.headers.get("sentry-trace"),A=null!=(w=Array.isArray(_)?_.join(","):_)?w:void 0,C=g.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!=(P=null!=(j=null!=(q=g.headers.get("lowerdeck-connecting-ip"))?q:g.headers.get("cf-connecting-ip"))?j:g.headers.get("x-forwarded-for"))?P:g.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 V=p.extract(h.active(),g.headers,{get:function(e,r){var t;return null!=(t=e.get(r))?t:void 0},keys:function(e){return Array.from(e.keys())}}),$=f.getSpanContext(V),D=m()&&(!!$||!!e.allowRootSpan),L=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: "+L,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":L,"rpc.description":W,"sentry.description":W,ip:J,transport:"http",ua:null!=(e=g.headers.get("user-agent"))?e:"",origin:null!=(o=g.headers.get("origin"))?o:""}},function(){try{try{var e,o=[],f=u("req_"),p=c(function(){var e;return b.parse(null!=(e=g.headers.get("cookie"))?e:"")}),h={url:g.url,headers:g.headers,query:k.searchParams,body:B,rawBody:B,ip:J,requestId:f,getCookies:function(){return p()},getCookie:function(e){return p()[e]},setCookie:function(e,r,t){var n=b.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:g.url,query:Object.fromEntries(k.searchParams.entries())}),x.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:B,contentType:"application/json"}),Promise.resolve(a(i({type:"request",contextId:f,ip:null!=J?J:"0.0.0.0",userAgent:null!=(e=g.headers.get("user-agent"))?e:""}),function(){try{var e=new Map,n={body:{__typename:"rpc.response",calls:[]},status:200},a=k.pathname.split("/").filter(Boolean),i=a[a.length-1],c="$"==i[0];if(c){var p,m=i.slice(1),v=l.get(m);if(null==v)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:H}));var y=null!=(p=e.get(v))?p:[];y.push({id:u("call_"),name:m,payload:B}),e.set(v,y)}else{var g=N.validate(B);if(!g.success)return Promise.resolve(new Response(JSON.stringify(r({errors:g.errors,entity:"request_data"}).toResponse()),{status:406,headers:H}));for(var w,b=S(g.value.calls);!(w=b()).done;){var P,j=w.value,R=l.get(j.name);if(null==R)return Promise.resolve(new Response(JSON.stringify(t({entity:"handler"}).toResponse()),{status:404,headers:H}));var q=null!=(P=e.get(R))?P:[];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(h,{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 H.append("x-req-id",f),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(d.encode(c?n.body.calls[0].result:n.body),{status:n.status,headers:H})})})}catch(e){return Promise.reject(e)}}))}catch(e){return O&&console.error(e),x.captureException(e,{extra:{url:g.url,method:g.method,ip:J,body:B}}),Promise.resolve(new Response(JSON.stringify(n({inner:O?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(h.with(V,function(){try{var e,r=function(r){var t,n;return e?r:Promise.resolve(I.startActiveSpan(W,{kind:v.SERVER,attributes:{"sentry.op":F,"rpc.system":"lowerdeck","rpc.request.target":L,"rpc.description":W,"sentry.description":W,"http.request.method":g.method,"url.path":k.pathname,ip:null!=J?J:"",transport:"http",ua:null!=(t=g.headers.get("user-agent"))?t:"",origin:null!=(n=g.headers.get("origin"))?n:""}},function(e){try{return Promise.resolve(function(r,t){try{var n=E(function(){return Promise.resolve(G()).then(function(r){return e.setAttribute("http.response.status_code",r.status),r.status>=500&&e.setStatus({code:y.ERROR,message:"RPC request failed with status "+r.status}),r})},function(r){throw e.recordException(r),e.setStatus({code:y.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(!D)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=g.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(g.url),C=null==(P=e.cors)||null==(P=P.headers)?void 0:P.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"==g.method)return Promise.resolve(M?new Response(null,{status:204,headers:T}):new Response(null,{status:403}));var J=null!=(j=g.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=E(function(){var e=d.decode;return Promise.resolve(g.text()).then(function(r){B=e.call(d,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=l(),B=f.getTracer("lowerdeck.rpc-server.calls"),H="production"!==process.env.NODE_ENV,K=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,c=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:y.ERROR,message:"RPC call failed with status "+r.status}),r};return Promise.resolve(function(r,o){try{var s=T(function(){return Promise.resolve(d()).then(function(e){return t({request:e.request,status:e.status,response:e.response})})},function(r){return e.recordException(r),e.setStatus({code:y.ERROR,message:r instanceof Error?r.message:String(r)}),t({request:l,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)}}))},l=j({},o,{body:a.payload}),d=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(l,{})).then(function(e){return{status:200,request:o,response:e.response}}):{request:l,status:404,response:t({entity:"handler"}).toResponse()}},function(r){if(H&&console.error(r),s(r))return r.data.status>=500&&J.captureException(r,{tags:{reqId:i}}),{request:l,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)}},f=m()&&g(),p=function(){if(!f)return Promise.resolve(d()).then(function(e){return u=1,{request:e.request,status:e.status,response:e.response}})}();return Promise.resolve(p&&p.then?p.then(c):c(p))}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),H&&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,K as createServer,C as rpcMux};
|
|
2
2
|
//# sourceMappingURL=index.module.js.map
|
package/dist/index.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.module.js","sources":["../src/controller.ts","../src/rpcMux.ts","../src/extractIp.ts","../src/server.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 verbose = process.env.NODE_ENV !== 'production';\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 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 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 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 };\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","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"],"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","object","calls","array","id","string","name","payload","any","rpcMux","rpcs","handlerNameToRpcMap","Map","flatMap","rpc","i","handlerNames","map","path","fetch","_req$headers$get6","_opts$cors","_req$headers$get7","_ref","_ref2","_ref3","_req$headers$get","sentryTraceHeaders","headers","sentryTrace","Array","isArray","join","baggage","ip","xForwardedForHeader","ips","split","trim","filter","Boolean","length","parseForwardedFor","Headers","corsOk","_i","_Object$entries","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","request","url","query","searchParams","rawBody","requestId","getCookies","getCookie","setCookie","cookie","serialize","beforeSend","appendHeaders","newHeaders","_i2","_Object$entries2","_Object$entries2$_i","_iterator","_step","_createForOfIteratorHelperLoose","done","getCurrentScope","setContext","fromEntries","addAttachment","filename","data","contentType","provideExecutionContext","createExecutionContext","type","contextId","userAgent","callsByRpc","resRef","__typename","status","pathParts","pathname","lastPart","isSingle","_callsByRpc$get","slice","rpcIndex","Response","JSON","stringify","notFoundError","toResponse","_step2","_iterator2","_callsByRpc$get2","call","all","from","_ref4","runMany","_resRef$body$calls","Math","max","apply","encode","console","error","captureException","internalServerError","inner","message","stack","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","method","notAcceptableError","_catch","_decode","decode","text","_req$text","_Response","createServer","getSupportedHandlerNames","reqId","parts","current","shift","findHandler","isServiceError","tags","onError","callName","callId","onRequest","callRes","c"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.module.js","sources":["../src/controller.ts","../src/rpcMux.ts","../src/extractIp.ts","../src/server.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 {\n isTelemetryEnabled,\n otelContext,\n propagation,\n SpanKind,\n SpanStatusCode,\n trace\n} from '@lowerdeck/telemetry';\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 extra: { url: req.url, method: req.method, ip, body }\n });\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","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","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\nlet verbose = process.env.NODE_ENV !== 'production';\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 if (verbose) 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 if (verbose) 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"],"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","rpcMux","rpcs","handlerNameToRpcMap","Map","flatMap","rpc","i","handlerNames","map","path","fetch","_req$headers$get8","_opts$cors","_req$headers$get9","_ref","_ref2","_ref3","_req$headers$get","sentryTraceHeaders","headers","sentryTrace","Array","isArray","join","baggage","ip","xForwardedForHeader","ips","split","trim","filter","Boolean","length","parseForwardedFor","Headers","corsOk","_i","_Object$entries","Object","entries","corsHeaders","_Object$entries$_i","append","extractedTraceContext","propagation","extract","otelContext","active","carrier","_carrier$get","keys","from","incomingParent","getSpanContext","canTrace","isTelemetryEnabled","allowRootSpan","requestSpanTarget","url","_pathParts","pathParts","pathname","lastPart","startsWith","slice","callNames","call","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","request","query","searchParams","rawBody","requestId","getCookies","getCookie","setCookie","cookie","serialize","beforeSend","appendHeaders","newHeaders","_i2","_Object$entries2","_Object$entries2$_i","_iterator","_step","_createForOfIteratorHelperLoose","done","getCurrentScope","setContext","fromEntries","addAttachment","filename","data","contentType","provideExecutionContext","createExecutionContext","type","contextId","userAgent","callsByRpc","resRef","__typename","status","isSingle","_callsByRpc$get","rpcIndex","Response","JSON","stringify","notFoundError","toResponse","_iterator2","_step2","_callsByRpc$get2","all","_ref4","runMany","_resRef$body$calls","Math","max","apply","encode","console","error","captureException","extra","method","internalServerError","inner","message","stack","_req$headers$get6","_req$headers$get7","startActiveSpan","kind","SpanKind","SERVER","span","_catch","setAttribute","setStatus","code","SpanStatusCode","ERROR","recordException","String","_finallyRethrows","_wasThrown","_result3","end","_await$executeRequest","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","notAcceptableError","_decode","decode","text","_req$text","_Response","createServer","getSupportedHandlerNames","reqId","callSpanName","finalize","executeCall","parts","current","shift","findHandler","isServiceError","tags","onError","callName","callId","hasActiveSpan","_request$status$respo","onRequest","callRes","c"],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@lowerdeck/error"),require("@lowerdeck/execution-context"),require("@lowerdeck/id"),require("@lowerdeck/memo"),require("@lowerdeck/sentry"),require("@lowerdeck/serialize"),require("@lowerdeck/validation"),require("cookie")):"function"==typeof define&&define.amd?define(["exports","@lowerdeck/error","@lowerdeck/execution-context","@lowerdeck/id","@lowerdeck/memo","@lowerdeck/sentry","@lowerdeck/serialize","@lowerdeck/validation","cookie"],r):r((e||self).rpcServer={},e.error,e.executionContext,e.id,e.memo,e.sentry,e.serialize,e.validation$1,e.cookie)}(this,function(e,r,t,n,o,a,i,s,u){function c(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 l=/*#__PURE__*/c(u);function d(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 f(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 d(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)?d(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 h(){return h=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},h.apply(null,arguments)}const p="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function v(e,r,t){if(!e.s){if(t instanceof m){if(!t.s)return void(t.o=v.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(v.bind(null,e,r),v.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}var m=/*#__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{v(n,1,a(this.v))}catch(e){v(n,2,e)}return n}return this}return this.o=function(e){try{var o=e.v;1&e.s?v(n,1,r?r(o):o):t?v(n,1,t(o)):v(n,2,o)}catch(e){v(n,2,e)}},n},e}();function y(e){return e instanceof m&&1&e.s}var g=/*#__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 w([].concat(this._middleware))},r.controller=function(e){return e},e}(),w=/*#__PURE__*/function(){function e(e){void 0===e&&(e=[]),this._middleware=void 0,this._handler=void 0,this._validation=void 0,this._middleware=e}var t=e.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(e,t){try{var n=function(){return Promise.resolve(o._handler(h({},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=e.body;if(o._validation){var i=o._validation.validate(e.body);if(!i.success)throw new r.ServiceError(r.validationError({errors:i.errors,entity:"call_data"}));a=i.value}var s=h({},t,e,{body:a}),u=function(e,r){if("function"==typeof e[p]){var t,n,o,a=function(e){try{for(;!(t=i.next()).done;)if((e=r(t.value))&&e.then){if(!y(e))return void e.then(a,o||(o=v.bind(null,n=new m,2)));e=e.v}n?v(n,1,e):n=e}catch(e){v(n||(n=new m),2,e)}},i=e[p]();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(!y(i))return void i.then(a,n||(n=v.bind(null,t=new m,2)));i=i.v}t?v(t,1,i):t=i}catch(e){v(t||(t=new m),2,e)}}(),t}(u,function(e){return r(u[e])})}(o._middleware,function(e){return Promise.resolve(e(s)).then(function(e){e&&(s=h({},s,e))})});return Promise.resolve(u&&u.then?u.then(n):n())}catch(e){return Promise.reject(e)}},e}(),b="production"!==process.env.NODE_ENV,P=a.getSentry(),S=s.v.object({calls:s.v.array(s.v.object({id:s.v.string(),name:s.v.string(),payload:s.v.any()}))}),j=a.getSentry();e.Group=g,e.Handler=w,e.createServer=function(e){return function(t){var n=function(e){return Object.entries(e).flatMap(function(e){var r=e[0],t=e[1];return t instanceof w?[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=h({},n,{body:o.payload});return Promise.resolve(function(e,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 w?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:r.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),r.isServiceError(t)?(t.data.status>=500&&j.captureException(t,{tags:{reqId:a}}),{request:i,status:t.data.status,response:t.toResponse()}):(j.captureException(t,{tags:{reqId:a}}),null==e.onError||e.onError({callName:o.name,callId:o.id,request:n,error:t,reqId:a}),{request:i,status:500,response:r.internalServerError().toResponse()})}))}catch(e){return Promise.reject(e)}}(n,a,o.requestId)).then(function(r){try{null==e.onRequest||e.onRequest({reqId:o.requestId,callId:a.id,callName:a.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:a.id,name:a.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)}}}}},e.rpcMux=function(e,a){var s=new Map(a.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:e.path,fetch:function(u){try{var c,d,h,p,v=function(e){var c,d,h,v;if(p)return e;var m=u.headers.get("sentry-trace"),g=null!=(c=Array.isArray(m)?m.join(","):m)?c:void 0,j=u.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!=(d=null!=(h=null!=(v=u.headers.get("lowerdeck-connecting-ip"))?v:u.headers.get("cf-connecting-ip"))?h:u.headers.get("x-forwarded-for"))?d:u.headers.get("x-real-ip")),x=new Headers;if(y)for(var k=0,E=Object.entries(q);k<E.length;k++){var O=E[k];x.append(O[0],O[1])}return Promise.resolve(P.withIsolationScope(function(){try{return Promise.resolve(P.continueTrace({sentryTrace:g,baggage:j},function(){try{var e,c;return Promise.resolve(P.startSpan({name:"rpc request",op:"rpc.server",attributes:{ip:M,transport:"http",ua:null!=(e=u.headers.get("user-agent"))?e:"",origin:null!=(c=u.headers.get("origin"))?c:""}},function(){try{try{var e,c=[],d=n.generateCustomId("req_"),h=o.memo(function(){var e;return l.parse(null!=(e=u.headers.get("cookie"))?e:"")}),p={url:u.url,headers:u.headers,query:w.searchParams,body:_,rawBody:_,ip:M,requestId:d,getCookies:function(){return h()},getCookie:function(e){return h()[e]},setCookie:function(e,r,t){var n=l.serialize(e,r,t);x.append("Set-Cookie",n)},beforeSend:function(e){c.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=f(a);!(i=s()).done;)x.append(o,i.value);else x.append(o,a)}}};return P.getCurrentScope().setContext("rpc.request",{url:u.url,query:Object.fromEntries(w.searchParams.entries())}),P.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:_,contentType:"application/json"}),Promise.resolve(t.provideExecutionContext(t.createExecutionContext({type:"request",contextId:d,ip:null!=M?M:"0.0.0.0",userAgent:null!=(e=u.headers.get("user-agent"))?e:""}),function(){try{var e=new Map,t={body:{__typename:"rpc.response",calls:[]},status:200},o=w.pathname.split("/").filter(Boolean),u=o[o.length-1],l="$"==u[0];if(l){var h,v=u.slice(1),m=s.get(v);if(null==m)return Promise.resolve(new Response(JSON.stringify(r.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:x}));var y=null!=(h=e.get(m))?h:[];y.push({id:n.generateCustomId("call_"),name:v,payload:_}),e.set(m,y)}else{var g=S.validate(_);if(!g.success)return Promise.resolve(new Response(JSON.stringify(r.validationError({errors:g.errors,entity:"request_data"}).toResponse()),{status:406,headers:x}));for(var b,P=f(g.value.calls);!(b=P()).done;){var j,q=b.value,M=s.get(q.name);if(null==M)return Promise.resolve(new Response(JSON.stringify(r.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:x}));var k=null!=(j=e.get(M))?j:[];k.push(q),e.set(M,k)}}return Promise.resolve(Promise.all(Array.from(e.entries()).map(function(e){var r=e[0],n=e[1];try{return Promise.resolve(a[r].runMany(p,{requestId:d,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 x.append("x-req-id",d),x.append("content-type","application/rpc+json"),x.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(c.map(function(e){return e()}))).then(function(){return new Response(i.serialize.encode(l?t.body.calls[0].result:t.body),{status:t.status,headers:x})})})}catch(e){return Promise.reject(e)}}))}catch(e){return b&&console.error(e),P.captureException(e),Promise.resolve(new Response(JSON.stringify(r.internalServerError({inner:b?e instanceof Error?{message:e.message,stack:e.stack}:{error:e}:void 0}).toResponse()),{status:500,headers:x}))}}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))}catch(e){return Promise.reject(e)}}))},m=null!=(c=u.headers.get("origin"))?c:"",y=!1;if(e.cors&&"domains"in e.cors)try{var g=new URL(m).hostname.split(".").slice(-2).join(".");y=e.cors.domains.includes(g)}catch(e){}else e.cors&&"check"in e.cors&&(y=e.cors.check(m));var w=new URL(u.url),j=null==(d=e.cors)||null==(d=d.headers)?void 0:d.join(", ");j&&(j=(", "+j).trim());var q=y?{"access-control-allow-origin":m,"access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"Content-Type, Authorization, Baggage, Sentry-Trace"+(null!=j?j:""),"access-control-max-age":"604800","access-control-allow-credentials":"true"}:{};if("OPTIONS"==u.method)return Promise.resolve(y?new Response(null,{status:204,headers:q}):new Response(null,{status:403}));var M=null!=(h=u.headers.get("content-type"))?h:"";if(!M.includes("application/rpc+json")&&!M.includes("application/json"))return Promise.resolve(new Response(JSON.stringify(r.notAcceptableError({message:"Content-Type must be application/rpc+json"}).toResponse()),{status:406,headers:q}));var _=null,x=function(e,r){try{var t=e()}catch(e){return r()}return t&&t.then?t.then(void 0,r):t}(function(){var e=i.serialize.decode;return Promise.resolve(u.text()).then(function(r){_=e.call(i.serialize,r)})},function(){var e=new Response(JSON.stringify(r.notAcceptableError({message:"Invalid JSON"}).toResponse()),{status:406});return p=1,e});return Promise.resolve(x&&x.then?x.then(v):v(x))}catch(e){return Promise.reject(e)}}}}});
|
|
1
|
+
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@lowerdeck/error"),require("@lowerdeck/execution-context"),require("@lowerdeck/id"),require("@lowerdeck/memo"),require("@lowerdeck/sentry"),require("@lowerdeck/serialize"),require("@lowerdeck/telemetry"),require("@lowerdeck/validation"),require("cookie")):"function"==typeof define&&define.amd?define(["exports","@lowerdeck/error","@lowerdeck/execution-context","@lowerdeck/id","@lowerdeck/memo","@lowerdeck/sentry","@lowerdeck/serialize","@lowerdeck/telemetry","@lowerdeck/validation","cookie"],r):r((e||self).rpcServer={},e.error,e.executionContext,e.id,e.memo,e.sentry,e.serialize,e.telemetry,e.validation$1,e.cookie)}(this,function(e,r,t,n,o,s,i,a,u,c){function l(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 d=/*#__PURE__*/l(c);function f(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 p(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 f(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)?f(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 h(){return h=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},h.apply(null,arguments)}const v="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function m(e,r,t){if(!e.s){if(t instanceof y){if(!t.s)return void(t.o=m.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(m.bind(null,e,r),m.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}var y=/*#__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{m(n,1,s(this.v))}catch(e){m(n,2,e)}return n}return this}return this.o=function(e){try{var o=e.v;1&e.s?m(n,1,r?r(o):o):t?m(n,1,t(o)):m(n,2,o)}catch(e){m(n,2,e)}},n},e}();function g(e){return e instanceof y&&1&e.s}var w=/*#__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),i=function(){if(s&&e.sharedMiddlewareMemo.has(s))return Promise.resolve(e.sharedMiddlewareMemo.get(s)).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,s=function(r){if(o)return r;var s=e(n,t);return i&&n.sharedMiddlewareMemo.set(i,s),Promise.resolve(s)},i=null==r||null==r.getSharedMemoKey?void 0:r.getSharedMemoKey(n,t),a=function(){if(i&&n.sharedMiddlewareMemo.has(i))return Promise.resolve(n.sharedMiddlewareMemo.get(i)).then(function(e){return o=1,e})}();return Promise.resolve(a&&a.then?a.then(s):s(a))}catch(e){return Promise.reject(e)}}}},r.handler=function(){return new b([].concat(this._middleware))},r.controller=function(e){return e},e}(),b=/*#__PURE__*/function(){function e(e){void 0===e&&(e=[]),this._middleware=void 0,this._handler=void 0,this._validation=void 0,this._middleware=e}var t=e.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(e,t){try{var n=function(){return Promise.resolve(o._handler(h({},a,{input:s,body:void 0}))).then(function(e){return{response:e}})},o=this;if(!o._handler)throw new Error("Handler not defined");var s=e.body;if(o._validation){var i=o._validation.validate(e.body);if(!i.success)throw new r.ServiceError(r.validationError({errors:i.errors,entity:"call_data"}));s=i.value}var a=h({},t,e,{body:s}),u=function(e,r){if("function"==typeof e[v]){var t,n,o,s=function(e){try{for(;!(t=i.next()).done;)if((e=r(t.value))&&e.then){if(!g(e))return void e.then(s,o||(o=m.bind(null,n=new y,2)));e=e.v}n?m(n,1,e):n=e}catch(e){m(n||(n=new y),2,e)}},i=e[v]();if(s(),i.return){var a=function(e){try{t.done||i.return()}catch(e){}return e};if(n&&n.then)return n.then(a,function(e){throw a(e)});a()}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(i){try{for(;++o<e.length;)if((i=r(o))&&i.then){if(!g(i))return void i.then(s,n||(n=m.bind(null,t=new y,2)));i=i.v}t?m(t,1,i):t=i}catch(e){m(t||(t=new y),2,e)}}(),t}(u,function(e){return r(u[e])})}(o._middleware,function(e){return Promise.resolve(e(a)).then(function(e){e&&(a=h({},a,e))})});return Promise.resolve(u&&u.then?u.then(n):n())}catch(e){return Promise.reject(e)}},e}();function P(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var S="production"!==process.env.NODE_ENV,j=s.getSentry(),q=a.trace.getTracer("lowerdeck.rpc-server"),E=u.v.object({calls:u.v.array(u.v.object({id:u.v.string(),name:u.v.string(),payload:u.v.any()}))});function R(e,r){try{var t=e()}catch(e){return r(e)}return t&&t.then?t.then(void 0,r):t}var k=s.getSentry(),x=a.trace.getTracer("lowerdeck.rpc-server.calls"),_="production"!==process.env.NODE_ENV;e.Group=w,e.Handler=b,e.createServer=function(e){return function(t){var n=function(e){return Object.entries(e).flatMap(function(e){var r=e[0],t=e[1];return t instanceof b?[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(s,i){try{return Promise.resolve(function(n,o,s){try{var i,u=function(e){if(i)return e;var t="rpc call: "+o.name;return Promise.resolve(x.startActiveSpan(t,function(e){try{e.setAttribute("sentry.op","rpc.server.call"),e.setAttribute("rpc.system","lowerdeck"),e.setAttribute("rpc.method",o.name),e.setAttribute("rpc.request_id",s),e.setAttribute("rpc.call_id",o.id),e.setAttribute("rpc.description",t),e.setAttribute("sentry.description",t);var n=function(r){return e.setAttribute("rpc.response.status_code",r.status),r.status>=500&&e.setStatus({code:a.SpanStatusCode.ERROR,message:"RPC call failed with status "+r.status}),r};return Promise.resolve(function(t,o){try{var s=R(function(){return Promise.resolve(l()).then(function(e){return n({request:e.request,status:e.status,response:e.response})})},function(t){return e.recordException(t),e.setStatus({code:a.SpanStatusCode.ERROR,message:t instanceof Error?t.message:String(t)}),n({request:c,status:500,response:r.internalServerError().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)}}))},c=h({},n,{body:o.payload}),l=function(){try{return Promise.resolve(R(function(){var e=function(e){for(var r=e.split(":"),n=t;n&&r.length>0;)if(!(n=n[r.shift()]))return null;return n&&n instanceof b?n:null}(o.name);return e?Promise.resolve(e.run(c,{})).then(function(e){return{status:200,request:n,response:e.response}}):{request:c,status:404,response:r.notFoundError({entity:"handler"}).toResponse()}},function(t){if(_&&console.error(t),r.isServiceError(t))return t.data.status>=500&&k.captureException(t,{tags:{reqId:s}}),{request:c,status:t.data.status,response:t.toResponse()};throw k.captureException(t,{tags:{reqId:s}}),null==e.onError||e.onError({callName:o.name,callId:o.id,request:n,error:t,reqId:s}),t}))}catch(e){return Promise.reject(e)}},d=a.isTelemetryEnabled()&&a.hasActiveSpan(),f=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(f&&f.then?f.then(u):u(f))}catch(e){return Promise.reject(e)}}(n,s,o.requestId)).then(function(r){try{null==e.onRequest||e.onRequest({reqId:o.requestId,callId:s.id,callName:s.name,request:r.request,response:{status:r.status,body:r.response}})}catch(e){k.captureException(e),_&&console.error(e)}return{__typename:"rpc.response.call",id:s.id,name:s.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)}}}}},e.rpcMux=function(e,s){var u=new Map(s.flatMap(function(e,r){return e.handlerNames.map(function(e){return[e,r]})}));return{path:e.path,fetch:function(c){try{var l,f,h,v,m=function(l){var f,h,m,y;if(v)return l;var w=c.headers.get("sentry-trace"),R=null!=(f=Array.isArray(w)?w.join(","):w)?f:void 0,x=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!=(h=null!=(m=null!=(y=c.headers.get("lowerdeck-connecting-ip"))?y:c.headers.get("cf-connecting-ip"))?m:c.headers.get("x-forwarded-for"))?h:c.headers.get("x-real-ip")),O=new Headers;if(g)for(var A=0,C=Object.entries(k);A<C.length;A++){var I=C[A];O.append(I[0],I[1])}var N=a.propagation.extract(a.otelContext.active(),c.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=a.trace.getSpanContext(N),z=a.isTelemetryEnabled()&&(!!T||!!e.allowRootSpan),J=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 i=s.slice(0,3).join(", ");return s.length>3?i+", +"+(s.length-3)+" more":i}return e.pathname}(b,_),B="rpc request: "+J,H="rpc.server.request",K=function(){try{return Promise.resolve(j.withIsolationScope(function(){try{return Promise.resolve(j.continueTrace({sentryTrace:R,baggage:x},function(){try{var e,a;return Promise.resolve(j.startSpan({name:B,op:H,attributes:{"sentry.op":H,"rpc.request.target":J,"rpc.description":B,"sentry.description":B,ip:M,transport:"http",ua:null!=(e=c.headers.get("user-agent"))?e:"",origin:null!=(a=c.headers.get("origin"))?a:""}},function(){try{try{var e,a=[],l=n.generateCustomId("req_"),f=o.memo(function(){var e;return d.parse(null!=(e=c.headers.get("cookie"))?e:"")}),h={url:c.url,headers:c.headers,query:b.searchParams,body:_,rawBody:_,ip:M,requestId:l,getCookies:function(){return f()},getCookie:function(e){return f()[e]},setCookie:function(e,r,t){var n=d.serialize(e,r,t);O.append("Set-Cookie",n)},beforeSend:function(e){a.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 i,a=p(s);!(i=a()).done;)O.append(o,i.value);else O.append(o,s)}}};return j.getCurrentScope().setContext("rpc.request",{url:c.url,query:Object.fromEntries(b.searchParams.entries())}),j.getCurrentScope().addAttachment({filename:"rpc.request.body.json",data:_,contentType:"application/json"}),Promise.resolve(t.provideExecutionContext(t.createExecutionContext({type:"request",contextId:l,ip:null!=M?M:"0.0.0.0",userAgent:null!=(e=c.headers.get("user-agent"))?e:""}),function(){try{var e=new Map,t={body:{__typename:"rpc.response",calls:[]},status:200},o=b.pathname.split("/").filter(Boolean),c=o[o.length-1],d="$"==c[0];if(d){var f,v=c.slice(1),m=u.get(v);if(null==m)return Promise.resolve(new Response(JSON.stringify(r.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:O}));var y=null!=(f=e.get(m))?f:[];y.push({id:n.generateCustomId("call_"),name:v,payload:_}),e.set(m,y)}else{var g=E.validate(_);if(!g.success)return Promise.resolve(new Response(JSON.stringify(r.validationError({errors:g.errors,entity:"request_data"}).toResponse()),{status:406,headers:O}));for(var w,P=p(g.value.calls);!(w=P()).done;){var S,j=w.value,q=u.get(j.name);if(null==q)return Promise.resolve(new Response(JSON.stringify(r.notFoundError({entity:"handler"}).toResponse()),{status:404,headers:O}));var R=null!=(S=e.get(q))?S:[];R.push(j),e.set(q,R)}}return Promise.resolve(Promise.all(Array.from(e.entries()).map(function(e){var r=e[0],n=e[1];try{return Promise.resolve(s[r].runMany(h,{requestId:l,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",l),O.append("content-type","application/rpc+json"),O.append("x-powered-by","lowerdeck RPC"),Promise.resolve(Promise.all(a.map(function(e){return e()}))).then(function(){return new Response(i.serialize.encode(d?t.body.calls[0].result:t.body),{status:t.status,headers:O})})})}catch(e){return Promise.reject(e)}}))}catch(e){return S&&console.error(e),j.captureException(e,{extra:{url:c.url,method:c.method,ip:M,body:_}}),Promise.resolve(new Response(JSON.stringify(r.internalServerError({inner:S?e instanceof Error?{message:e.message,stack:e.stack}:{error:e}: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(a.otelContext.with(N,function(){try{var e,r=function(r){var t,n;return e?r:Promise.resolve(q.startActiveSpan(B,{kind:a.SpanKind.SERVER,attributes:{"sentry.op":H,"rpc.system":"lowerdeck","rpc.request.target":J,"rpc.description":B,"sentry.description":B,"http.request.method":c.method,"url.path":b.pathname,ip:null!=M?M:"",transport:"http",ua:null!=(t=c.headers.get("user-agent"))?t:"",origin:null!=(n=c.headers.get("origin"))?n:""}},function(e){try{return Promise.resolve(function(r,t){try{var n=P(function(){return Promise.resolve(K()).then(function(r){return e.setAttribute("http.response.status_code",r.status),r.status>=500&&e.setStatus({code:a.SpanStatusCode.ERROR,message:"RPC request failed with status "+r.status}),r})},function(r){throw e.recordException(r),e.setStatus({code:a.SpanStatusCode.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(!z)return Promise.resolve(K()).then(function(r){return e=1,r})}();return Promise.resolve(t&&t.then?t.then(r):r(t))}catch(e){return Promise.reject(e)}}))},y=null!=(l=c.headers.get("origin"))?l:"",g=!1;if(e.cors&&"domains"in e.cors)try{var w=new URL(y).hostname.split(".").slice(-2).join(".");g=e.cors.domains.includes(w)}catch(e){}else e.cors&&"check"in e.cors&&(g=e.cors.check(y));var b=new URL(c.url),R=null==(f=e.cors)||null==(f=f.headers)?void 0:f.join(", ");R&&(R=(", "+R).trim());var k=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"==c.method)return Promise.resolve(g?new Response(null,{status:204,headers:k}):new Response(null,{status:403}));var x=null!=(h=c.headers.get("content-type"))?h:"";if(!x.includes("application/rpc+json")&&!x.includes("application/json"))return Promise.resolve(new Response(JSON.stringify(r.notAcceptableError({message:"Content-Type must be application/rpc+json"}).toResponse()),{status:406,headers:k}));var _=null,M=P(function(){var e=i.serialize.decode;return Promise.resolve(c.text()).then(function(r){_=e.call(i.serialize,r)})},function(){var e=new Response(JSON.stringify(r.notAcceptableError({message:"Invalid JSON"}).toResponse()),{status:406});return v=1,e});return Promise.resolve(M&&M.then?M.then(m):m(M))}catch(e){return Promise.reject(e)}}}}});
|
|
2
2
|
//# sourceMappingURL=index.umd.js.map
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","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 verbose = process.env.NODE_ENV !== 'production';\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 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 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 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 };\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","verbose","process","env","NODE_ENV","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","_req$headers$get7","_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","_step2","_iterator2","_callsByRpc$get2","from","_ref4","_resRef$body$calls","encode","inner","message","stack","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","method","notAcceptableError","_decode","decode","text","_req$text","_Response"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","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 {\n isTelemetryEnabled,\n otelContext,\n propagation,\n SpanKind,\n SpanStatusCode,\n trace\n} from '@lowerdeck/telemetry';\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 extra: { url: req.url, method: req.method, ip, body }\n });\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\nlet verbose = process.env.NODE_ENV !== 'production';\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 if (verbose) 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 if (verbose) 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","_request$status$respo","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","_iterator2","_step2","_callsByRpc$get2","_ref4","_resRef$body$calls","encode","extra","method","inner","stack","_req$headers$get6","_req$headers$get7","kind","SpanKind","SERVER","_result3","_await$executeRequest","cors","rootDomain","URL","hostname","domains","includes","check","additionalCorsHeaders","notAcceptableError","_decode","decode","text","_req$text","_Response"],"mappings":"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"}
|
package/dist/rpcMux.d.ts
CHANGED
package/dist/rpcMux.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpcMux.d.ts","sourceRoot":"","sources":["../src/rpcMux.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rpcMux.d.ts","sourceRoot":"","sources":["../src/rpcMux.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA8C9C,eAAO,IAAI,MAAM,GACf,MAAM;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,GAAG,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;KAAE,CAAC,CAAC;CACtE,EACD,MAAM;IACJ,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,CACP,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,GAAG,CAAC;SACd,EAAE,CAAC;KACL,KACE,OAAO,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE;YACJ,KAAK,EAAE,GAAG,EAAE,CAAC;SACd,CAAC;KACH,CAAC,CAAC;CACJ,EAAE;;iBASkB,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC;CA2WxC,CAAC"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAW,cAAc,EAAE,MAAM,cAAc,CAAC;AAOnE,eAAO,IAAI,YAAY,GACpB,MAAM;IACL,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,cAAc,CAAC;QACxB,KAAK,EAAE,GAAG,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,GAAG,CAAA;SAAE,CAAC;KACzC,KAAK,IAAI,CAAC;CACZ,MACA,YAAY,UAAU,CAAC,GAAG,CAAC;;mBA0JnB,cAAc,QACb;QACJ,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,GAAG,CAAC;SACd,EAAE,CAAC;QACJ,SAAS,EAAE,MAAM,CAAC;KACnB,KACA,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,GAAG,CAAC;KACX,CAAC;CA4EH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowerdeck/rpc-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"vitest": "^3.2.4"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@lowerdeck/error": "^1.2.
|
|
39
|
+
"@lowerdeck/error": "^1.2.2",
|
|
40
40
|
"@lowerdeck/execution-context": "^1.0.4",
|
|
41
|
-
"@lowerdeck/id": "^1.0.
|
|
41
|
+
"@lowerdeck/id": "^1.0.8",
|
|
42
42
|
"@lowerdeck/memo": "^1.0.4",
|
|
43
43
|
"@lowerdeck/sentry": "^1.0.2",
|
|
44
44
|
"@lowerdeck/serialize": "^1.0.4",
|
|
45
45
|
"@lowerdeck/telemetry": "^1.0.1",
|
|
46
|
-
"@lowerdeck/validation": "^1.0.
|
|
46
|
+
"@lowerdeck/validation": "^1.0.8",
|
|
47
47
|
"cookie": "^1.1.1"
|
|
48
48
|
}
|
|
49
49
|
}
|