@medplum/fhir-router 4.3.10 → 4.3.12

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.
@@ -316,7 +316,6 @@ export declare function updateResourceImpl<T extends Resource>(resourceType: T['
316
316
 
317
317
  export declare type UpdateResourceOptions = {
318
318
  ifMatch?: string;
319
- inheritAccounts?: boolean;
320
319
  };
321
320
 
322
321
  export { }
@@ -316,7 +316,6 @@ export declare function updateResourceImpl<T extends Resource>(resourceType: T['
316
316
 
317
317
  export declare type UpdateResourceOptions = {
318
318
  ifMatch?: string;
319
- inheritAccounts?: boolean;
320
319
  };
321
320
 
322
321
  export { }
@@ -1,4 +1,4 @@
1
- import{append as vo,badRequest as K,getReferenceString as ct,getStatus as li,isOk as fi,normalizeOperationOutcome as No,notFound as ci,OperationOutcomeError as M,parseSearchRequest as ui}from"@medplum/core";var Io=50,bo=8,Ro=/urn(:|%3A)uuid(:|%3A)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/,pi="urn:uuid";async function Cn(e,t,n,r){return new kn(n,t,r,e).run()}var kn=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 M(K("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>Io)throw new M(K("Transaction contains more update operations than allowed"));if(r.requiresStrongTransaction&&n.length>bo)throw new M(K("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 M(K("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]=at(K("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]=at(d);continue}throw new M(d)}let T=this.getRouteForEntry(p)?.data?.interaction;if(!T||!r[T])throw new M(K(`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 K("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 M)return o.outcome;throw o}if(i&&(this.resolvedIdentities[i.placeholder]=i.reference,this.isTransaction())){if(r.has(i.reference))throw new M(K("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 M(ci);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(pi))return;let n=t.fullUrl;if(t.request?.ifNoneExist){let r=await this.repo.searchResources(ui(t.request.url+"?"+t.request.ifNoneExist));if(r.length===1)return{placeholder:n,reference:ct(r[0])}}if(t.resource)return t.resource.id=this.repo.generateId(),{placeholder:n,reference:ct(t.resource)}}async resolveModificationIdentity(t,n){if(!t.fullUrl?.startsWith(pi))return;let r=t.fullUrl;if(t.request?.url?.includes("?")){let i=t.request.method,o=ui(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 M(K("Cannot provide ID for create by update"));return t.resource.id=this.repo.generateId(),{placeholder:r,reference:ct(t.resource)}}return;default:throw new M(K(`Conditional ${t.request.method} did not match any resources`,n+".request.url"))}if(a)throw new M(K(`Conditional ${t.request.method} matched multiple resources`,n+".request.url"));let c=ct(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 M(K("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=vo(s,m.message),m instanceof M&&li(m.outcome)===429){for(let T=c;T<t.ordering.length;T++){let g=t.ordering[T];n[g]=at(m.outcome)}break}n[p]=at(No(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 M(ci);let r=this.parseBatchRequest(t,n),[i,o]=await n.handler(r,this.repo,this.router,{batch:!0});if(!fi(i)&&this.isTransaction())throw new M(i);return at(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 M(K("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 M(K("Patch entry must include a Binary or Parameters resource"));if(!Array.isArray(r))throw new M(K("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 M(K("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=Ro.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 at(e,t){return{response:{outcome:e,status:li(e).toString(),location:fi(e)&&t?.id?ct(t):void 0},resource:t}}import{EventTarget as Dc,OperationOutcomeError as Ac,allOk as fe,badRequest as Ie,created as Fc,normalizeOperationOutcome as kc,notFound as Cc,parseSearchRequest as je,singularize as Mc}from"@medplum/core";import{allOk as nc,badRequest as kt,ContentType as rc,deepClone as To,DEFAULT_SEARCH_COUNT as ic,forbidden as oc,getResourceTypes as yo,LRUCache as sc,normalizeOperationOutcome as ac,OperationOutcomeError as Dn}from"@medplum/core";import cc from"dataloader";function R(e,t){if(!!!e)throw new Error(t)}function se(e){return typeof e?.then=="function"}function G(e){return typeof e=="object"&&e!==null}function k(e,t){if(!!!e)throw new Error(t??"Unexpected invariant triggered.")}var Oo=/\r\n|[\n\r]/g;function Qe(e,t){let n=0,r=1;for(let i of e.body.matchAll(Oo)){if(typeof i.index=="number"||k(!1),i.index>=t)break;n=i.index+i[0].length,r+=1}return{line:r,column:t+1-n}}function Mn(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}
1
+ import{append as vo,badRequest as K,getReferenceString as ct,getStatus as li,isOk as fi,normalizeOperationOutcome as No,notFound as ci,OperationOutcomeError as M,parseSearchRequest as ui}from"@medplum/core";var Io=50,bo=8,Ro=/urn(:|%3A)uuid(:|%3A)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/,pi="urn:uuid";async function Cn(e,t,n,r){return new kn(n,t,r,e).run()}var kn=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 M(K("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>Io)throw new M(K("Transaction contains more update operations than allowed"));if(r.requiresStrongTransaction&&n.length>bo)throw new M(K("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 M(K("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]=at(K("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]=at(d);continue}throw new M(d)}let T=this.getRouteForEntry(p)?.data?.interaction;if(!T||!r[T])throw new M(K(`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 K("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 M)return o.outcome;throw o}if(i&&(this.resolvedIdentities[i.placeholder]=i.reference,this.isTransaction())){if(r.has(i.reference))throw new M(K("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 M(ci);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(pi))return;let n=t.fullUrl;if(t.request?.ifNoneExist){let r=await this.repo.searchResources(ui(t.request.url+"?"+t.request.ifNoneExist));if(r.length===1)return{placeholder:n,reference:ct(r[0])}}if(t.resource)return t.resource.id=this.repo.generateId(),{placeholder:n,reference:ct(t.resource)}}async resolveModificationIdentity(t,n){if(!t.fullUrl?.startsWith(pi))return;let r=t.fullUrl;if(t.request?.url?.includes("?")){let i=t.request.method,o=ui(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 M(K("Cannot provide ID for create by update"));return t.resource.id=this.repo.generateId(),{placeholder:r,reference:ct(t.resource)}}return;default:throw new M(K(`Conditional ${t.request.method} did not match any resources`,n+".request.url"))}if(a)throw new M(K(`Conditional ${t.request.method} matched multiple resources`,n+".request.url"));let c=ct(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 M(K("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=vo(s,m.message),m instanceof M&&li(m.outcome)===429){for(let T=c;T<t.ordering.length;T++){let g=t.ordering[T];n[g]=at(m.outcome)}break}n[p]=at(No(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 M(ci);let r=this.parseBatchRequest(t,n),[i,o]=await n.handler(r,this.repo,this.router,{batch:!0});if(!fi(i)&&this.isTransaction())throw new M(i);return at(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,config:this.req.config}}parsePatchBody(t){let n=t.resource,r;if(n?.resourceType==="Binary"){if(!n.data)throw new M(K("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 M(K("Patch entry must include a Binary or Parameters resource"));if(!Array.isArray(r))throw new M(K("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 M(K("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=Ro.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 at(e,t){return{response:{outcome:e,status:li(e).toString(),location:fi(e)&&t?.id?ct(t):void 0},resource:t}}import{EventTarget as Dc,OperationOutcomeError as Ac,allOk as fe,badRequest as Ie,created as Fc,normalizeOperationOutcome as kc,notFound as Cc,parseSearchRequest as je,singularize as Mc}from"@medplum/core";import{allOk as nc,badRequest as kt,ContentType as rc,deepClone as To,DEFAULT_SEARCH_COUNT as ic,forbidden as oc,getResourceTypes as yo,LRUCache as sc,normalizeOperationOutcome as ac,OperationOutcomeError as Dn}from"@medplum/core";import cc from"dataloader";function R(e,t){if(!!!e)throw new Error(t)}function se(e){return typeof e?.then=="function"}function G(e){return typeof e=="object"&&e!==null}function k(e,t){if(!!!e)throw new Error(t??"Unexpected invariant triggered.")}var Oo=/\r\n|[\n\r]/g;function Qe(e,t){let n=0,r=1;for(let i of e.body.matchAll(Oo)){if(typeof i.index=="number"||k(!1),i.index>=t)break;n=i.index+i[0].length,r+=1}return{line:r,column:t+1-n}}function Mn(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 D=0;D<d.length;D+=80)g.push(d.slice(D,D+80));return p+di([[`${s} |`,g[0]],...g.slice(1,m+1).map(D=>["|",D]),["|","^".padStart(T)],["|",g[m+1]]])}return p+di([[`${s-1} |`,l[i-1]],[`${s} |`,d],["|","^".padStart(c)],[`${s+1} |`,l[i+1]]])}function di(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 So(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}=So(n);super(t),this.name="GraphQLError",this.path=p??void 0,this.originalError=l??void 0,this.nodes=mi(Array.isArray(s)?s:s?[s]:void 0);let m=mi((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=G(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