@medplum/fhir-router 4.3.3 → 4.3.4
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/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/cjs/index.d.ts +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.mjs +12 -12
- package/dist/esm/index.mjs.map +3 -3
- package/package.json +4 -4
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var ao=Object.create;var Ft=Object.defineProperty;var co=Object.getOwnPropertyDescriptor;var uo=Object.getOwnPropertyNames;var po=Object.getPrototypeOf,lo=Object.prototype.hasOwnProperty;var fo=(e,t)=>{for(var n in t)Ft(e,n,{get:t[n],enumerable:!0})},oi=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of uo(t))!lo.call(e,i)&&i!==n&&Ft(e,i,{get:()=>t[i],enumerable:!(r=co(t,i))||r.enumerable});return e};var si=(e,t,n)=>(n=e!=null?ao(po(e)):{},oi(t||!e||!e.__esModule?Ft(n,"default",{value:e,enumerable:!0}):n,e)),mo=e=>oi(Ft({},"__esModule",{value:!0}),e);var ac={};fo(ac,{FhirRepository:()=>Sn,FhirRouter:()=>ti,MemoryRepository:()=>Hr,RepositoryMode:()=>Lt,Router:()=>At,createResourceImpl:()=>oo,makeSimpleRequest:()=>sc,processBatch:()=>kt,updateResourceImpl:()=>so});module.exports=mo(ac);var I=require("@medplum/core"),ho=50,yo=8,To=/urn(:|%3A)uuid(:|%3A)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/,ai="urn:uuid";async function kt(e,t,n,r){return new Dn(n,t,r,e).run()}var Dn=class{constructor(t,n,r,i){this.router=t,this.repo=n,this.bundle=r,this.req=i,this.resolvedIdentities=Object.create(null)}async run(){let t=this.bundle.type;if(t!=="batch"&&t!=="transaction")throw new I.OperationOutcomeError((0,I.badRequest)("Unrecognized bundle type: "+t));let n=new Array(this.bundle.entry?.length??0),r=await this.preprocessBundle(n);if(!this.isTransaction())return this.processBatch(r,n);if(r.updates>ho)throw new I.OperationOutcomeError((0,I.badRequest)("Transaction contains more update operations than allowed"));if(r.requiresStrongTransaction&&n.length>yo)throw new I.OperationOutcomeError((0,I.badRequest)("Transaction requires strict isolation but has too many entries"));return this.repo.withTransaction(()=>this.processBatch(r,n),{serializable:r.requiresStrongTransaction})}async preprocessBundle(t){let n=this.bundle.entry;if(!n?.length)throw new I.OperationOutcomeError((0,I.badRequest)("Missing bundle entries"));let r={transaction:[],batch:[],delete:[],create:[],update:[],patch:[],operation:[],"search-system":[],"search-type":[],read:[],vread:[],"history-system":[],"history-type":[],"history-instance":[]},i=new Set,o=!1,s=0;for(let c=0;c<n.length;c++){let p=n[c];if(!p.request?.method){t[c]=st((0,I.badRequest)("Missing Bundle entry request method",`Bundle.entry[${c}].request.method`));continue}let d=await this.preprocessEntry(p,c,i);if(d){if(!this.isTransaction()){t[c]=st(d);continue}throw new I.OperationOutcomeError(d)}let T=this.getRouteForEntry(p)?.data?.interaction;if(!T||!r[T])throw new I.OperationOutcomeError((0,I.badRequest)(`Invalid REST interaction in batch: ${p.request?.method} ${p.request?.url}`));T==="create"&&p.request?.ifNoneExist?o=!0:T==="update"?(p.request?.url.includes("?")&&(o=!0),s++):T==="delete"&&p.request?.url.includes("?")&&(o=!0),r[T].push(c)}let a=[];for(let c of Object.values(r))a.push(...c);return{ordering:a,requiresStrongTransaction:o,updates:s}}async preprocessEntry(t,n,r){if(!t.request?.url)return(0,I.badRequest)("Missing Bundle entry request URL",`Bundle.entry[${n}].request.url`);let i;try{i=await this.resolveIdentity(t,`Bundle.entry[${n}]`)}catch(o){if(o instanceof I.OperationOutcomeError)return o.outcome;throw o}if(i&&(this.resolvedIdentities[i.placeholder]=i.reference,this.isTransaction())){if(r.has(i.reference))throw new I.OperationOutcomeError((0,I.badRequest)("Duplicate resource identity found in Bundle"));r.add(i.reference)}}async resolveIdentity(t,n){let i=this.getRouteForEntry(t)?.data?.interaction;if(!i)throw new I.OperationOutcomeError(I.notFound);switch(i){case"create":return this.resolveCreateIdentity(t);case"delete":case"update":case"patch":return this.resolveModificationIdentity(t,n);default:return}}getRouteForEntry(t){return this.router.find(t.request?.method,t.request?.url??"")}async resolveCreateIdentity(t){if(!t.fullUrl?.startsWith(ai))return;let n=t.fullUrl;if(t.request?.ifNoneExist){let r=await this.repo.searchResources((0,I.parseSearchRequest)(t.request.url+"?"+t.request.ifNoneExist));if(r.length===1)return{placeholder:n,reference:(0,I.getReferenceString)(r[0])}}if(t.resource)return t.resource.id=this.repo.generateId(),{placeholder:n,reference:(0,I.getReferenceString)(t.resource)}}async resolveModificationIdentity(t,n){if(!t.fullUrl?.startsWith(ai))return;let r=t.fullUrl;if(t.request?.url?.includes("?")){let i=t.request.method,o=(0,I.parseSearchRequest)(t.request.url);o.count=2,o.offset=0,o.sortRules=void 0;let[s,a]=await this.repo.searchResources(o);if(!s)switch(i){case"DELETE":return;case"PUT":if(t.resource){if(t.resource.id)throw new I.OperationOutcomeError((0,I.badRequest)("Cannot provide ID for create by update"));return t.resource.id=this.repo.generateId(),{placeholder:r,reference:(0,I.getReferenceString)(t.resource)}}return;default:throw new I.OperationOutcomeError((0,I.badRequest)(`Conditional ${t.request.method} did not match any resources`,n+".request.url"))}if(a)throw new I.OperationOutcomeError((0,I.badRequest)(`Conditional ${t.request.method} matched multiple resources`,n+".request.url"));let c=(0,I.getReferenceString)(s);return t.request.url=c,t.resource&&(t.resource.id=s.id),{placeholder:r,reference:c}}if(t.request?.url.includes("/"))return{placeholder:r,reference:t.request.url}}async processBatch(t,n){let r=this.bundle.type,i=this.bundle.entry;if(!i)throw new I.OperationOutcomeError((0,I.badRequest)("Missing bundle entry"));let o={type:"batch",bundleType:r,count:i.length,size:JSON.stringify(this.bundle).length};this.router.dispatchEvent(o);let s
|
|
1
|
+
"use strict";var ao=Object.create;var Ft=Object.defineProperty;var co=Object.getOwnPropertyDescriptor;var uo=Object.getOwnPropertyNames;var po=Object.getPrototypeOf,lo=Object.prototype.hasOwnProperty;var fo=(e,t)=>{for(var n in t)Ft(e,n,{get:t[n],enumerable:!0})},oi=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of uo(t))!lo.call(e,i)&&i!==n&&Ft(e,i,{get:()=>t[i],enumerable:!(r=co(t,i))||r.enumerable});return e};var si=(e,t,n)=>(n=e!=null?ao(po(e)):{},oi(t||!e||!e.__esModule?Ft(n,"default",{value:e,enumerable:!0}):n,e)),mo=e=>oi(Ft({},"__esModule",{value:!0}),e);var ac={};fo(ac,{FhirRepository:()=>Sn,FhirRouter:()=>ti,MemoryRepository:()=>Hr,RepositoryMode:()=>Lt,Router:()=>At,createResourceImpl:()=>oo,makeSimpleRequest:()=>sc,processBatch:()=>kt,updateResourceImpl:()=>so});module.exports=mo(ac);var I=require("@medplum/core"),ho=50,yo=8,To=/urn(:|%3A)uuid(:|%3A)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/,ai="urn:uuid";async function kt(e,t,n,r){return new Dn(n,t,r,e).run()}var Dn=class{constructor(t,n,r,i){this.router=t,this.repo=n,this.bundle=r,this.req=i,this.resolvedIdentities=Object.create(null)}async run(){let t=this.bundle.type;if(t!=="batch"&&t!=="transaction")throw new I.OperationOutcomeError((0,I.badRequest)("Unrecognized bundle type: "+t));let n=new Array(this.bundle.entry?.length??0),r=await this.preprocessBundle(n);if(!this.isTransaction())return this.processBatch(r,n);if(r.updates>ho)throw new I.OperationOutcomeError((0,I.badRequest)("Transaction contains more update operations than allowed"));if(r.requiresStrongTransaction&&n.length>yo)throw new I.OperationOutcomeError((0,I.badRequest)("Transaction requires strict isolation but has too many entries"));return this.repo.withTransaction(()=>this.processBatch(r,n),{serializable:r.requiresStrongTransaction})}async preprocessBundle(t){let n=this.bundle.entry;if(!n?.length)throw new I.OperationOutcomeError((0,I.badRequest)("Missing bundle entries"));let r={transaction:[],batch:[],delete:[],create:[],update:[],patch:[],operation:[],"search-system":[],"search-type":[],read:[],vread:[],"history-system":[],"history-type":[],"history-instance":[]},i=new Set,o=!1,s=0;for(let c=0;c<n.length;c++){let p=n[c];if(!p.request?.method){t[c]=st((0,I.badRequest)("Missing Bundle entry request method",`Bundle.entry[${c}].request.method`));continue}let d=await this.preprocessEntry(p,c,i);if(d){if(!this.isTransaction()){t[c]=st(d);continue}throw new I.OperationOutcomeError(d)}let T=this.getRouteForEntry(p)?.data?.interaction;if(!T||!r[T])throw new I.OperationOutcomeError((0,I.badRequest)(`Invalid REST interaction in batch: ${p.request?.method} ${p.request?.url}`));T==="create"&&p.request?.ifNoneExist?o=!0:T==="update"?(p.request?.url.includes("?")&&(o=!0),s++):T==="delete"&&p.request?.url.includes("?")&&(o=!0),r[T].push(c)}let a=[];for(let c of Object.values(r))a.push(...c);return{ordering:a,requiresStrongTransaction:o,updates:s}}async preprocessEntry(t,n,r){if(!t.request?.url)return(0,I.badRequest)("Missing Bundle entry request URL",`Bundle.entry[${n}].request.url`);let i;try{i=await this.resolveIdentity(t,`Bundle.entry[${n}]`)}catch(o){if(o instanceof I.OperationOutcomeError)return o.outcome;throw o}if(i&&(this.resolvedIdentities[i.placeholder]=i.reference,this.isTransaction())){if(r.has(i.reference))throw new I.OperationOutcomeError((0,I.badRequest)("Duplicate resource identity found in Bundle"));r.add(i.reference)}}async resolveIdentity(t,n){let i=this.getRouteForEntry(t)?.data?.interaction;if(!i)throw new I.OperationOutcomeError(I.notFound);switch(i){case"create":return this.resolveCreateIdentity(t);case"delete":case"update":case"patch":return this.resolveModificationIdentity(t,n);default:return}}getRouteForEntry(t){return this.router.find(t.request?.method,t.request?.url??"")}async resolveCreateIdentity(t){if(!t.fullUrl?.startsWith(ai))return;let n=t.fullUrl;if(t.request?.ifNoneExist){let r=await this.repo.searchResources((0,I.parseSearchRequest)(t.request.url+"?"+t.request.ifNoneExist));if(r.length===1)return{placeholder:n,reference:(0,I.getReferenceString)(r[0])}}if(t.resource)return t.resource.id=this.repo.generateId(),{placeholder:n,reference:(0,I.getReferenceString)(t.resource)}}async resolveModificationIdentity(t,n){if(!t.fullUrl?.startsWith(ai))return;let r=t.fullUrl;if(t.request?.url?.includes("?")){let i=t.request.method,o=(0,I.parseSearchRequest)(t.request.url);o.count=2,o.offset=0,o.sortRules=void 0;let[s,a]=await this.repo.searchResources(o);if(!s)switch(i){case"DELETE":return;case"PUT":if(t.resource){if(t.resource.id)throw new I.OperationOutcomeError((0,I.badRequest)("Cannot provide ID for create by update"));return t.resource.id=this.repo.generateId(),{placeholder:r,reference:(0,I.getReferenceString)(t.resource)}}return;default:throw new I.OperationOutcomeError((0,I.badRequest)(`Conditional ${t.request.method} did not match any resources`,n+".request.url"))}if(a)throw new I.OperationOutcomeError((0,I.badRequest)(`Conditional ${t.request.method} matched multiple resources`,n+".request.url"));let c=(0,I.getReferenceString)(s);return t.request.url=c,t.resource&&(t.resource.id=s.id),{placeholder:r,reference:c}}if(t.request?.url.includes("/"))return{placeholder:r,reference:t.request.url}}async processBatch(t,n){let r=this.bundle.type,i=this.bundle.entry;if(!i)throw new I.OperationOutcomeError((0,I.badRequest)("Missing bundle entry"));let o={type:"batch",bundleType:r,count:i.length,size:JSON.stringify(this.bundle).length};this.router.dispatchEvent(o);let s;for(let c=0;c<t.ordering.length;c++){let p=t.ordering[c],l=i[p],d=this.rewriteIdsInObject(l);try{n[p]=await this.processBatchEntry(d)}catch(m){if(this.isTransaction())throw m;if(s=(0,I.append)(s,m.message),m instanceof I.OperationOutcomeError&&(0,I.getStatus)(m.outcome)===429){for(let T=c;T<t.ordering.length;T++){let g=t.ordering[T];n[g]=st(m.outcome)}break}n[p]=st((0,I.normalizeOperationOutcome)(m));continue}}let a={type:"batch",bundleType:r,errors:s};return this.router.dispatchEvent(a),{resourceType:"Bundle",type:`${r}-response`,entry:n}}async processBatchEntry(t){let n=this.getRouteForEntry(t);if(!n)throw new I.OperationOutcomeError(I.notFound);let r=this.parseBatchRequest(t,n),[i,o]=await n.handler(r,this.repo,this.router,{batch:!0});if(!(0,I.isOk)(i)&&this.isTransaction())throw new I.OperationOutcomeError(i);return st(i,o)}parseBatchRequest(t,n){let r=t.request,i=Object.create(null);r.ifNoneExist&&(i["if-none-exist"]=r.ifNoneExist),r.ifMatch&&(i["if-match"]=r.ifMatch),r.ifNoneMatch&&(i["if-none-match"]=r.ifNoneMatch),r.ifModifiedSince&&(i["if-modified-since"]=r.ifModifiedSince);let o;return r.method==="PATCH"?o=this.parsePatchBody(t):o=t.resource,{method:r.method,url:n?.query?r.url.slice(0,r.url.indexOf("?")):r.url,pathname:"",params:n?.params??Object.create(null),query:n?.query??Object.create(null),body:o,headers:i}}parsePatchBody(t){let n=t.resource,r;if(n?.resourceType==="Binary"){if(!n.data)throw new I.OperationOutcomeError((0,I.badRequest)("Missing entry.resource.data"));r=JSON.parse(Buffer.from(n.data,"base64").toString("utf8"))}else if(n?.resourceType==="Parameters"){if(n.parameter){r=[];for(let i of n.parameter)if(i.name==="operation"){let o=this.parsePatchParameter(i);r.push(o)}}}else throw new I.OperationOutcomeError((0,I.badRequest)("Patch entry must include a Binary or Parameters resource"));if(!Array.isArray(r))throw new I.OperationOutcomeError((0,I.badRequest)("Decoded PATCH body must be an array"));return this.rewriteIdsInArray(r)}parsePatchParameter(t){let n=t.part?.find(i=>i.name==="op")?.valueCode;if(!n)throw new I.OperationOutcomeError((0,I.badRequest)("PATCH Parameters missing op"));let r={op:n};switch(n){case"add":case"replace":case"test":for(let i of t.part)i.name==="path"?r.path=i.valueString:i.name==="value"&&(r.value=JSON.parse(i.valueString??""));break;case"copy":case"move":for(let i of t.part)i.name==="path"?r.path=i.valueString:i.name==="from"&&(r.from=i.valueString);break;case"remove":r.path=t.part?.find(i=>i.name==="path")?.valueString;break}return r}rewriteIds(t){return Array.isArray(t)?this.rewriteIdsInArray(t):typeof t=="string"?this.rewriteIdsInString(t):typeof t=="object"&&t!==null?this.rewriteIdsInObject(t):t}rewriteIdsInArray(t){return t.map(n=>this.rewriteIds(n))}rewriteIdsInObject(t){return Object.fromEntries(Object.entries(t).map(([n,r])=>[n,this.rewriteIds(r)]))}rewriteIdsInString(t){let n=To.exec(t)?.[0];if(!n)return t;let r=n.replaceAll("%3A",":"),i=this.resolvedIdentities[r];return i?t.replaceAll(n,i):t}isTransaction(){return this.bundle.type==="transaction"&&!!this.req.config?.transactions}};function st(e,t){return{response:{outcome:e,status:(0,I.getStatus)(e).toString(),location:(0,I.isOk)(e)&&t?.id?(0,I.getReferenceString)(t):void 0},resource:t}}var S=require("@medplum/core");var k=require("@medplum/core"),ro=si(require("dataloader"));function _(e,t){if(!!!e)throw new Error(t)}function ce(e){return typeof e?.then=="function"}function q(e){return typeof e=="object"&&e!==null}function $(e,t){if(!!!e)throw new Error(t??"Unexpected invariant triggered.")}var go=/\r\n|[\n\r]/g;function Qe(e,t){let n=0,r=1;for(let i of e.body.matchAll(go)){if(typeof i.index=="number"||$(!1),i.index>=t)break;n=i.index+i[0].length,r+=1}return{line:r,column:t+1-n}}function An(e){return Ct(e.source,Qe(e.source,e.start))}function Ct(e,t){let n=e.locationOffset.column-1,r="".padStart(n)+e.body,i=t.line-1,o=e.locationOffset.line-1,s=t.line+o,a=t.line===1?n:0,c=t.column+a,p=`${e.name}:${s}:${c}
|
|
2
2
|
`,l=r.split(/\r\n|[\n\r]/g),d=l[i];if(d.length>120){let m=Math.floor(c/80),T=c%80,g=[];for(let M=0;M<d.length;M+=80)g.push(d.slice(M,M+80));return p+ci([[`${s} |`,g[0]],...g.slice(1,m+1).map(M=>["|",M]),["|","^".padStart(T)],["|",g[m+1]]])}return p+ci([[`${s-1} |`,l[i-1]],[`${s} |`,d],["|","^".padStart(c)],[`${s+1} |`,l[i+1]]])}function ci(e){let t=e.filter(([r,i])=>i!==void 0),n=Math.max(...t.map(([r])=>r.length));return t.map(([r,i])=>r.padStart(n)+(i?" "+i:"")).join(`
|
|
3
3
|
`)}function Eo(e){let t=e[0];return t==null||"kind"in t||"length"in t?{nodes:t,source:e[1],positions:e[2],path:e[3],originalError:e[4],extensions:e[5]}:t}var f=class e extends Error{constructor(t,...n){var r,i,o;let{nodes:s,source:a,positions:c,path:p,originalError:l,extensions:d}=Eo(n);super(t),this.name="GraphQLError",this.path=p??void 0,this.originalError=l??void 0,this.nodes=ui(Array.isArray(s)?s:s?[s]:void 0);let m=ui((r=this.nodes)===null||r===void 0?void 0:r.map(g=>g.loc).filter(g=>g!=null));this.source=a??(m==null||(i=m[0])===null||i===void 0?void 0:i.source),this.positions=c??m?.map(g=>g.start),this.locations=c&&a?c.map(g=>Qe(a,g)):m?.map(g=>Qe(g.source,g.start));let T=q(l?.extensions)?l?.extensions:void 0;this.extensions=(o=d??T)!==null&&o!==void 0?o:Object.create(null),Object.defineProperties(this,{message:{writable:!0,enumerable:!0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),l!=null&&l.stack?Object.defineProperty(this,"stack",{value:l.stack,writable:!0,configurable:!0}):Error.captureStackTrace?Error.captureStackTrace(this,e):Object.defineProperty(this,"stack",{value:Error().stack,writable:!0,configurable:!0})}get[Symbol.toStringTag](){return"GraphQLError"}toString(){let t=this.message;if(this.nodes)for(let n of this.nodes)n.loc&&(t+=`
|
|
4
4
|
|