UNPKG

@decaf-ts/for-couchdb

Version:
3 lines (2 loc) 38.2 kB
import{Metadata as e,Decoration as t}from"@decaf-ts/decoration";import{PersistenceKeys as r,Operator as n,OrderDirection as i,Condition as o,GroupOperator as s,Repository as a,Paginator as c,PagingError as u,Sequence as l,QueryError as d,Statement as f,UnsupportedError as g,Adapter as p,ConnectionError as h,applyViewDecorator as m}from"@decaf-ts/core";import{DefaultSeparator as y,OperationKeys as A,InternalError as b,enforceDBDecorators as w,ValidationError as v,BulkCrudOperationKeys as E,reduceErrorsToPrint as S,BaseError as N,DBKeys as O,prefixMethod as x,ConflictError as T,NotFoundError as D}from"@decaf-ts/db-decorators";import{Model as $}from"@decaf-ts/decorator-validation";import{__decorate as j,__metadata as C}from"tslib";import{final as B}from"@decaf-ts/logging";const k=/^_.*$/g,M={SEPARATOR:"__",ID:"_id",REV:"_rev",DELETED:"_deleted",TABLE:"??table",SEQUENCE:"??sequence",DDOC:"ddoc",NATIVE:"__native",INDEX:"index",VIEW:"view"},I=250,L={EQUAL:"$eq",DIFFERENT:"$ne",BIGGER:"$gt",BIGGER_EQ:"$gte",SMALLER:"$lt",SMALLER_EQ:"$lte",NOT:"$not",IN:"$in",REGEXP:"$regex"},P={AND:"$and",OR:"$or"},V={NULL:"null"};async function R(e,t,r){return e.auth(t,r)}function _(e,t,r,n){const i=e.use?e.use(t):e;return["insert","bulk","fetch","createIndex","get","put","destroy","find","view"].forEach(t=>{const o=i[t];"function"==typeof o&&Object.defineProperty(i,t,{enumerable:!1,configurable:!0,value:async(...t)=>(await R(e,r,n),o.call(i,...t))})}),Object.defineProperty(i,M.NATIVE,{enumerable:!1,configurable:!1,writable:!1,value:e}),i}function U(e){return e.match(/^_.*$/g)}function q(e,t,n,i,o=y){const s={};let a;if(s[M.TABLE]={},s[M.TABLE].$eq=t,i){const t={};t[e]=i;const r=(n||[]).map(e=>{const t={};return t[e]=i,t}),o={};o[M.TABLE]=i,a=[t,...r,o]}else a=[e,...n||[],M.TABLE];const c=((e,t,n,i,o=y)=>{const s=[r.INDEX,t,e];return n&&s.push(...n),i&&s.push(i),s.join(o)})(e,t,n,i,o);return{index:{fields:a},ddoc:[c,M.DDOC].join(o),name:c}}function Q(e){return e instanceof Date?JSON.stringify(e.toISOString()):e instanceof RegExp?`new RegExp(${JSON.stringify(e.source)}, ${JSON.stringify(e.flags)})`:JSON.stringify(e)}function J(e,t){const{attr1:r,operator:i,comparison:a}=e;if(r instanceof o){const e=J(r,t);if(i===n.NOT)return`!(${e})`;const o=J(a,t);return i===s.AND?`(${e} && ${o})`:i===s.OR?`(${e} || ${o})`:e}const c=`${t}[${JSON.stringify(r)}]`;switch(i){case n.EQUAL:return`${c} === ${Q(a)}`;case n.DIFFERENT:return`${c} !== ${Q(a)}`;case n.BIGGER:return`${c} > ${Q(a)}`;case n.BIGGER_EQ:return`${c} >= ${Q(a)}`;case n.SMALLER:return`${c} < ${Q(a)}`;case n.SMALLER_EQ:return`${c} <= ${Q(a)}`;case n.IN:return`(${Q(a)}).indexOf(${c}) !== -1`;case n.REGEXP:return`${a instanceof RegExp?Q(a):`new RegExp(${JSON.stringify(a)})`}.test(${c})`;case n.NOT:return`!(${c} === ${Q(a)})`;default:return"true"}}function F(e,t,r){return e?Array.isArray(e)?e:[e]:t?[t,...r||[]]:r||[]}function G(e,t,r,n,i=y){return n.name?n.name:[e,t,r,"view"].join(i).replace(/\s+/g,"_")}function z(e,t,r=y){return[e,t,M.DDOC].join(r)}function W(t,r,i){const o={view:n.VIEW,groupBy:n.GROUP_BY,count:n.COUNT,sum:n.SUM,max:n.MAX,min:n.MIN,distinct:n.DISTINCT}[r];if(!o)return[];const s=e.get(t,o)||{};return Object.entries(s).flatMap(([e,t])=>t&&"object"==typeof t?Object.values(t).map(t=>({...t,kind:r,attribute:t.attribute||e})).filter(e=>!i||e.attribute===i):[])}function X(t,r,n){const i=e.get(t,r)||{};return Object.entries(i).flatMap(([e,t])=>t&&"object"==typeof t?Object.values(t).map(t=>{const r=t;return{...r,kind:n,attribute:r.attribute||e}}):[])}function H(e){const t={},r=[[M.VIEW,"view"],[n.GROUP_BY,"groupBy"],[n.COUNT,"count"],[n.SUM,"sum"],[n.MAX,"max"],[n.MIN,"min"],[n.DISTINCT,"distinct"]];return e.forEach(e=>{const n=$.tableName(e);r.flatMap(([t,r])=>X(e,t,r)).forEach(e=>{const r=e.attribute,i=G(n,r,e.kind,e),s="_design/"+(e.ddoc||z(n,i)),a=((e,t,r,n)=>{const i=((e,t,r)=>{if(r.map)return"function"==typeof r.map?r.map.toString():r.map;const n=[];if(n.push(`doc[${JSON.stringify(M.TABLE)}] === ${JSON.stringify(e)}`),r.condition)if(r.condition instanceof o)n.push(J(r.condition,"doc"));else if("string"==typeof r.condition)n.push(r.condition);else{const e=o.from(r.condition);n.push(J(e,"doc"))}"count"===r.kind&&void 0!==r.value&&n.push(`doc[${JSON.stringify(t)}] === ${Q(r.value)}`);const i=((e,t="doc")=>{if(!e)return;if("string"==typeof e)return e;const r=e.field||"roles",n=e.roles||[];if(!n.length)return e.expression;const i=`${t}[${JSON.stringify(r)}] || []`;return"all"===(e.mode||"any")?n.map(e=>`${i}.indexOf(${JSON.stringify(e)}) !== -1`).join(" && "):n.map(e=>`${i}.indexOf(${JSON.stringify(e)}) !== -1`).join(" || ")})(r.auth,"doc");i&&n.push(i);const s=n.length?n.join(" && "):"true",a=((e,t,r)=>{const n=F(e,t,r);return 1===n.length?`doc[${JSON.stringify(n[0])}]`:`[${n.map(e=>`doc[${JSON.stringify(e)}]`).join(", ")}]`})(r.key,t,r.compositions),c=((e,t)=>"doc"===e?"doc":e?Array.isArray(e)?`[${e.map(e=>`doc[${JSON.stringify(e)}]`).join(", ")}]`:"string"==typeof e?`doc[${JSON.stringify(e)}]`:Q(e):`doc[${JSON.stringify(t)}]`)(r.value??(r.returnDocs&&"sum"!==r.kind?"doc":void 0),t);return`function (doc) {\n if (!(${s})) return;\n emit(${a}, ${c});\n}`})(n,t,r),s=r.reduce?"function"==typeof r.reduce?r.reduce.toString():r.reduce:(e=>{switch(e){case"count":case"groupBy":case"distinct":return"_count";case"sum":return"_sum";case"max":return"function (keys, values, rereduce) {\n var maxVal = null;\n for (var i = 0; i < values.length; i++) {\n var val = values[i];\n if (rereduce && val && typeof val === 'object' && 'value' in val) val = val.value;\n if (maxVal === null || val > maxVal) maxVal = val;\n }\n return maxVal;\n}";case"min":return"function (keys, values, rereduce) {\n var minVal = null;\n for (var i = 0; i < values.length; i++) {\n var val = values[i];\n if (rereduce && val && typeof val === 'object' && 'value' in val) val = val.value;\n if (minVal === null || val < minVal) minVal = val;\n }\n return minVal;\n}";default:return}})(e);return{map:i,reduce:s}})(e.kind,r,e,n);t[s]||(t[s]={_id:s,language:"javascript",views:{}}),t[s].views[i]=a})}),Object.values(t)}function K(e){const t={},r=[[M.VIEW,"view"],[n.GROUP_BY,"groupBy"],[n.COUNT,"count"],[n.SUM,"sum"],[n.MAX,"max"],[n.MIN,"min"],[n.DISTINCT,"distinct"]];return e.forEach(e=>{const n=$.tableName(e);r.flatMap(([t,r])=>X(e,t,r)).forEach(e=>{const r=F(e.key,e.attribute,e.compositions);if(!r.length)return;const o=r[0],s=r.slice(1),a=e.directions||[i.ASC,i.DSC],c=q(o,n,s);t[c.name||""]=c,a.forEach(e=>{const r=q(o,n,s,e);t[r.name||""]=r})})}),Object.values(t)}function Y(e){const t=F(e.key,e.attribute);return{attribute:t[0],compositions:t.slice(1).concat(e.compositions||[]),directions:e.directions}}function Z(e,t,r,n=y){return[...e.map(e=>e===M.TABLE?"table":e),...r||[],...t?[t]:[],M.INDEX].join(n)}function ee(e,t,n=[],i,o=y){return[e,t,...n,...i?[i]:[],r.INDEX].join(o)}function te(e){const t=Z([M.TABLE]),r={};return r[t]={index:{fields:[M.TABLE]},name:t,ddoc:t,type:"json"},e.forEach(e=>{const t=$.tableName(e);let n=[];try{n=$.defaultQueryAttributes(e)}catch(e){n=[]}n.forEach(e=>{const n=Z([t,e,"defaultQuery"]),o={[M.TABLE]:{$eq:t}};r[n]={index:{fields:[M.TABLE,e]},name:n,ddoc:n,type:"json"},r[n].index.partial_filter_selector=o,[i.ASC,i.DSC].forEach(n=>{const i=Z([t,e,"defaultQuery"],n);r[i]={index:{fields:[{[M.TABLE]:n},{[e]:n}]},name:i,ddoc:i,type:"json"}})});const o=$.indexes(e);Object.entries(o).forEach(([e,n])=>{const o=[];Object.entries(n||{}).forEach(([,t])=>{if(!t)return;const r=t;void 0===r.directions&&void 0===r.compositions?"object"!=typeof t||Array.isArray(t)||Object.entries(t).forEach(([e,t])=>{t&&o.push([e,t])}):o.push([e,r])}),o.forEach(([e,n])=>{if(!n)return;let{directions:o,compositions:s}=n;s=s||[];const a=[e,...s],c={[M.TABLE]:{$eq:t}};function u(n,i){const o=ee(t,e,s,i),u=[M.TABLE,...a],l=n?[{[M.TABLE]:n},...a.map(e=>({[e]:n}))]:u;r[o]={index:{fields:l},name:o,ddoc:o,type:"json"},n||(r[o].index.partial_filter_selector=c)}u(),Array.from(new Set((o||[i.ASC]).map(e=>(e+"").toLowerCase()))).filter(e=>e===i.ASC||e===i.DSC).forEach(e=>{u(e,e)})})})}),K(e).forEach(e=>{e.name&&(r[e.name]=e)}),Object.values(r)}function re(e,t){Object.defineProperty(e,r.METADATA,{enumerable:!1,configurable:!0,writable:!0,value:t})}function ne(e){const t=Object.getOwnPropertyDescriptor(e,r.METADATA);return t?t.value:void 0}function ie(e){Object.getOwnPropertyDescriptor(e,r.METADATA)&&delete e[r.METADATA]}class oe extends a{constructor(e,t,r=!1){super(e,t,r)}assignMetadata(e,t){const r=(e,t)=>{const r=ne(t??e);return r&&re(e,r),e};return Array.isArray(e)?e.map((e,n)=>{const i=Array.isArray(t)?t[n]:t;return r(e,i)}):r(e,Array.isArray(t)?t?.[0]:t)}async create(e,...t){const r=await super.create(e,...t);return this.assignMetadata(r),this.assignMetadata(e,r),r}async createAll(e,...t){const r=await super.createAll(e,...t);return this.assignMetadata(r),this.assignMetadata(e,r),r}async read(e,...t){const r=await super.read(e,...t);return this.assignMetadata(r)}async readAll(e,...t){const r=await super.readAll(e,...t);return this.assignMetadata(r)}async update(e,...t){const r=await super.update(e,...t);return this.assignMetadata(r),this.assignMetadata(e,r),r}async updateAll(e,...t){const r=await super.updateAll(e,...t);return this.assignMetadata(r),this.assignMetadata(e,r),r}async delete(e,...t){const r=await super.delete(e,...t);return this.assignMetadata(r)}async deleteAll(e,...t){const r=await super.deleteAll(e,...t);return this.assignMetadata(r)}async updatePrefix(e,...t){const{ctx:r,ctxArgs:n,log:i}=(await this.logCtx(t,A.UPDATE,!0)).for(this.updatePrefix),o=r.get("ignoreHandlers"),s=r.get("ignoreValidation");i.silly(`handlerSetting: ${o}, validationSetting: ${s}`);const a=e[this.pk];if(!a)throw new b("No value for the Id is defined under the property "+this.pk);let c,u;if(r.get("applyUpdateValidation")&&(c=await this.read(a),u=c?ne(c):void 0,r.get("mergeForUpdate")&&(e=$.merge(c,e,this.class))),o||await w(this,r,e,A.UPDATE,A.ON,c),!s){const t=r.get("ignoredValidationProperties")||[];i.silly("ignored validation properties: "+t);const n=await Promise.resolve(e.hasErrors(c,...t));if(n)throw new v(n.toString())}return u&&re(e,u),[e,...n,c]}async updateAllPrefix(e,...t){const{ctx:r,ctxArgs:n,log:i}=(await this.logCtx(t,E.UPDATE_ALL,!0)).for(this.updateAllPrefix),o=r.get("ignoreHandlers"),s=r.get("ignoreValidation");i.silly(`handlerSetting: ${o}, ignoredValidation: ${s}`);const a=e.map(e=>{const t=e[this.pk];if(!t)throw new b("missing id on update operation");return t});let c;if(r.get("applyUpdateValidation")&&(c=await this.readAll(a,r),e=e.map((e,t)=>{r.get("mergeForUpdate")&&(e=$.merge(c[t],e,this.class));const n=ne(c[t]);return n&&re(e,n),e})),o||await Promise.all(e.map((e,t)=>w(this,r,e,A.UPDATE,A.ON,c?c[t]:void 0))),!s){const t=r.get("ignoredValidationProperties")||[];let n;i.silly("ignored validation properties: "+t),n=r.get("applyUpdateValidation")?await Promise.all(e.map((e,r)=>Promise.resolve(e.hasErrors(c[r],...t)))):await Promise.resolve(e.map(e=>e.hasErrors(...t)));const o=S(n);if(o)throw new v(o)}return[e,...n,c]}}class se extends N{constructor(e){super(se.name,e,404)}}class ae extends se{constructor(e,t,r){super(e),this.name="IndexPlanningError",this.suggestion=t,this.query=r}}class ce extends c{constructor(e,t,r,n){super(e,t,r,n),this._bookmarks=new Map}isValidBookmark(e){return"string"==typeof e&&e.length>0}prepare(e){const t=Object.assign({},e);return t.limit&&(this.limit=t.limit),t.limit=this.size,delete t.skip,t}async page(t=1,r,...n){const{log:i,ctxArgs:o,ctx:s}=this.adapter.logCtx([r,...n],this.page);if(this.isPreparedStatement())return await this.pagePrepared(t,...o);t=this.validatePage(t??1);const a=Object.assign({},this.statement);if(a.limit=this.size,1===t)this.isValidBookmark(r)?a.bookmark=r:delete a.bookmark;else{const e=r||this._bookmarks.get(t);if(!this.isValidBookmark(e))throw new u("Random page access requires a cached CouchDB bookmark. Start at page 1 and page forward, or pass an explicit bookmark.");delete a.skip,a.bookmark=e}delete a.skip;const c=await this.adapter.raw(a,!1,...o),{docs:d,bookmark:f,warning:g}=c;if(g&&i.warn(g),c.execution_stats&&i.debug("Mango execution stats: "+JSON.stringify(c.execution_stats)),!this.clazz)throw new u("No statement target defined");const p=$.pk(this.clazz),h=e.get(this.clazz,e.key(O.ID,p))?.type,m=a.fields&&a.fields.length?d:d.map(e=>this.adapter.revert(e,this.clazz,l.parseValue(h,e[p]),void 0,s));return this._bookmark=this.isValidBookmark(f)?f:void 0,this._currentPage=t,this.isValidBookmark(f)&&this._bookmarks.set(t+1,f),this.isValidBookmark(f)&&d.length>=this.size||(this._knownLastPage=t,this._totalPages=t,this._recordCount=(t-1)*this.size+d.length),m}}function ue(e){for(const t of[L,P]){const r=Object.keys(t).find(t=>t===e);if(r)return t[r]}throw new d("Could not find adapter translation for operator "+e)}const le=new Set(["$or","$in","$regex","$nin","$not","$ne","$nor"]);function de(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function fe(e,t){return!(!e||"object"!=typeof e)&&(Array.isArray(e)?e.some(e=>fe(e,t)):Object.entries(e).some(([e,r])=>e===t||fe(r,t)))}function ge(e){if("string"==typeof e)return{field:e};if(Array.isArray(e))return e.length?{field:e[0]+""}:void 0;const[t,r]=Object.entries(e||{})[0]||[];return t?{field:t,direction:((r||i.ASC)+"").toLowerCase()}:void 0}function pe(e){return(e.sort||[]).map(ge).filter(Boolean).map(e=>e.field)}function he(e){return(e.sort||[]).map(ge).find(Boolean)?.direction}function me(e={}){const t=new Set,r=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(r);else if(Array.isArray(e[P.AND]))e[P.AND].forEach(r);else for(const[n,i]of Object.entries(e))n!==P.OR&&n!==P.AND?de(i)?Object.prototype.hasOwnProperty.call(i,"$eq")&&t.add(n):t.add(n):r(i)};return r(e),t}function ye(e={}){const t=new Set,r=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(r);else if(Array.isArray(e[P.AND]))e[P.AND].forEach(r);else for(const[n,i]of Object.entries(e))n!==P.OR&&n!==P.AND?de(i)&&(Object.prototype.hasOwnProperty.call(i,"$gt")||Object.prototype.hasOwnProperty.call(i,"$gte")||Object.prototype.hasOwnProperty.call(i,"$lt")||Object.prototype.hasOwnProperty.call(i,"$lte"))&&t.add(n):r(i)};return r(e),t}function Ae(e){const t=$.tableName(e),r=[],n=Z([M.TABLE]);r.push({name:n,ddoc:n,fields:[M.TABLE],source:"table"});let o=[];try{o=$.defaultQueryAttributes(e)}catch{o=[]}for(const e of o){const n=Z([t,e,"defaultQuery"]);r.push({name:n,ddoc:n,fields:[M.TABLE,e],source:"defaultQuery"});for(const n of[i.ASC,i.DSC]){const i=Z([t,e,"defaultQuery"],n);r.push({name:i,ddoc:i,fields:[M.TABLE,e],direction:n,source:"defaultQuery"})}}const s=$.indexes(e);return Object.entries(s||{}).forEach(([e,n])=>{Object.values(n||{}).forEach(n=>{if(!n||!de(n))return;const o=n,s=o.compositions||[],a=o.directions||[i.ASC],c=[M.TABLE,e,...s],u=ee(t,e,s);r.push({name:u,ddoc:u,fields:c,source:"index"});const l=Array.from(new Set(a.map(e=>(e+"").toLowerCase()))).filter(e=>e===i.ASC||e===i.DSC);for(const n of l){const i=ee(t,e,s,n);r.push({name:i,ddoc:i,fields:c,direction:n,source:"index"})}})}),r}function be(e){return Ae(e)}function we(e,t){return Ae(e).find(e=>e.name===t||e.ddoc===t)}function ve(e,t,r={}){if(t.use_index)return;if(fe(t.selector,P.OR)||fe(t.selector,"$nor"))return;const n=!1!==r.preserveDefaultQuery,i=Ae(e),o=me(t.selector),s=ye(t.selector),a=pe(t),c=he(t);o.add(M.TABLE);const u=i.map(e=>{if(e.direction&&c&&e.direction!==c)return;if(!e.fields.includes(M.TABLE))return;if(e.fields[0]!==M.TABLE)return;const t=e.fields.filter(e=>e!==M.TABLE),i=0===a.length||a.every(e=>t.includes(e)),u=a.some(e=>t.includes(e)),l=0===s.size||Array.from(s).every(e=>t.includes(e)),d=Array.from(s).some(e=>t.includes(e));if(r.requireSortCoverage&&a.length&&!i)return;const f=t.filter(e=>o.has(e)).length,g=t.filter(e=>s.has(e)).length,p=t.filter(e=>a.includes(e)).length;if(!f&&!g&&!p)return;let h=0;return"defaultQuery"===e.source&&n&&(h+=100),"index"===e.source&&(h+=50),h+=30*f,h+=25*g,h+=20*p,i&&a.length&&(h+=20),l&&s.size&&(h+=20),u&&(h+=5),d&&(h+=5),e.direction&&c&&(h+=10),{candidate:e,score:h}}).filter(Boolean);if(!u.length)return;u.sort((e,t)=>t.score!==e.score?t.score-e.score:e.candidate.fields.length-t.candidate.fields.length);const l=u[0].candidate;return{candidate:l,use_index:[l.ddoc,l.name]}}function Ee(e,t){const r=$.tableName(e),n=e.name,i=Array.from(me(t.selector)),o=Array.from(ye(t.selector)),s=pe(t),a=he(t),c=[M.TABLE];for(const e of i)e===M.TABLE||c.includes(e)||c.push(e);for(const e of o)e===M.TABLE||c.includes(e)||c.push(e);for(const e of s)e===M.TABLE||c.includes(e)||c.push(e);return{tableName:r,modelName:n,equalityFields:i,rangeFields:o,sortFields:s,sortDirection:a,requiredFields:c}}function Se(e,t){const r=Ee(e,t),n=r.requiredFields.filter(e=>e!==M.TABLE);if(!n.length)throw new ae("Cannot infer @index declaration for query with no model fields.",{modelName:r.modelName,tableName:r.tableName,attribute:"",compositions:[],directions:[],expectedName:"",expectedDdoc:"",expectedFields:[M.TABLE],decorator:""},t);const o=n[0],s=n.slice(1),a=r.sortDirection||i.ASC,c=ee(r.tableName,o,s,a),u=[{[M.TABLE]:a},{[o]:a},...s.map(e=>({[e]:a}))],l=["@index({",s.length?` compositions: ${JSON.stringify(s)},`:void 0," directions: "+JSON.stringify([a]),"})",o+"!: <type>;"].filter(Boolean).join("\n");return{attribute:o,compositions:s,directions:[a],name:c,ddoc:c,fields:u,decorator:l}}function Ne(e,t,r,n={}){if(!e||t.use_index)return;if(!1===n.forceNamedIndexes&&!n.requireIndex)return;const i=ve(e,t,{preserveDefaultQuery:n.preserveDefaultQuery??!0,requireSortCoverage:n.requireSortCoverage??!1});if(i)return t.use_index=i.use_index,void r?.debug?.(`Attached Mango use_index=${JSON.stringify(i.use_index)} from ${i.candidate.source} metadata`);if(!n.requireIndex)return;const o=Se(e,t);throw new ae(["No generated CouchDB index can satisfy this Mango query.\n","Model: "+e.name,"Table: "+Oe(e),"\nTo allow this query, declare the following index on the model attribute:\n",o.decorator,"\nThen regenerate/deploy indexes.\n\nExpected generated index:"," ddoc: "+o.ddoc," name: "+o.name," fields: "+JSON.stringify(o.fields)].join("\n"),{modelName:e.name,tableName:Oe(e),attribute:o.attribute,compositions:o.compositions,directions:o.directions,expectedName:o.name,expectedDdoc:o.ddoc,expectedFields:o.fields,decorator:o.decorator},t)}function Oe(e){return $.tableName(e)}function xe(e,t,r,n={}){Ne(e,t,r,{preserveDefaultQuery:!0,requireSortCoverage:n.requireSortCoverage??!0,requireIndex:!0,forceNamedIndexes:!0})}function Te(e,t,r="selector"){if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach((e,n)=>Te(e,t,`${r}[${n}]`));else for(const[n,i]of Object.entries(e))le.has(n)&&t?.warn?.(`Mango query contains scan-prone operator ${n} at ${r}. This may bypass or weaken index usage and can produce slow queries.`),Te(i,t,`${r}.${n}`)}function De(e,t,r){if(!e.sort?.length)return;if(pe(e).includes(t))return;const n=r||he(e)||i.ASC;e.sort=[...e.sort,{[t]:n}]}function $e(e){e.execution_stats=!0}function je(e){if(!e)return"\0";const t=Array.from(e);for(let e=t.length-1;e>=0;e-=1){const r=t[e].codePointAt(0);if(void 0!==r&&1114111>r)return t[e]=String.fromCodePoint(r+1),t.slice(0,e+1).join("")}return e+"\0"}class Ce extends f{constructor(e,t){super(e,t),this.attributeTypeCache=new Map}toColumnName(e){return e===M.TABLE||e===M.SEQUENCE?e:$.columnName(this.fromSelector,e)}build(){const e=this.log.for(this.build);this.manualAggregation=void 0;const t=this.buildAggregateInfo();if(t){if(!this.shouldUseManualAggregation())return this.createAggregateQuery(t);this.manualAggregation=t}const r={};r[M.TABLE]={},r[M.TABLE]=$.tableName(this.fromSelector);const n={selector:r};if(this.selectSelector&&(n.fields=this.selectSelector.map(e=>this.toColumnName(e))),this.whereCondition){const t=this.parseCondition(o.and(this.whereCondition,o.attribute(M.TABLE).eq(n.selector[M.TABLE]))).selector,r=Object.keys(t);if(1===r.length&&-1!==Object.values(P).indexOf(r[0]))switch(r[0]){case P.AND:t[P.AND]=[...Object.values(t[P.AND]).reduce((e,t)=>{const r=Object.keys(t);if(1!==r.length)throw Error("Too many keys in query selector. should be one");const n=r[0];return n===P.AND?e.push(...t[n]):e.push(t),e},[])],n.selector=t;break;case P.OR:{const e={};e[P.AND]=[t,...Object.entries(n.selector).map(([e,t])=>{const r={};return r[e]=t,r})],n.selector=e;break}default:throw Error("This should be impossible")}else Object.entries(t).forEach(([t,r])=>{n.selector[t]&&e.warn(`A ${t} query param is about to be overridden: ${n.selector[t]} by ${r}`),n.selector[t]=r})}if(this.orderBySelectors?.length){n.sort=n.sort||[],n.selector=n.selector||{};for(const[e,t]of this.orderBySelectors){const r=this.toColumnName(e),i={};i[r]=t,n.sort.push(i),n.selector[r]||(n.selector[r]={},n.selector[r].$gt=null)}}const i=!!this.manualAggregation;return this.limitSelector?n.limit=this.limitSelector:i||(e.warn("No limit selector defined. Using default couchdb limit of 250"),n.limit=250),this.offsetSelector&&(n.skip=this.offsetSelector),this.attachDefaultQueryIndex(n),(this.overrides?.forceNamedIndexes??!0)&&Ne(this.fromSelector,n,e,{preserveDefaultQuery:!0,requireSortCoverage:!1,forceNamedIndexes:!0}),Te(n.selector,e),n}attachDefaultQueryIndex(e){if(!this.fromSelector||e.use_index)return;const t=$.tableName(this.fromSelector);let r=[];try{r=$.defaultQueryAttributes(this.fromSelector)}catch{r=[]}if(!r.length)return;const n=this.collectStartsWithRangeAttrs(e.selector||{}),i=r.filter(e=>n.has(e));if(!i.length)return;const o=(Array.isArray(e.sort)?e.sort:[]).map(e=>Object.entries(e||{})[0]).find(e=>e&&i.includes(e[0])),s=Z([t,o?.[0]||i[0],"defaultQuery"],o?.[1]||void 0);e.use_index=s}collectStartsWithRangeAttrs(e){const t=new Set,r=e=>{e&&"object"==typeof e&&(Array.isArray(e)?e.forEach(e=>r(e)):Object.entries(e).forEach(([e,n])=>{if(e!==P.AND&&e!==P.OR&&n&&"object"==typeof n&&!Array.isArray(n)){const r=Object.prototype.hasOwnProperty.call(n,"$gte"),i=Object.prototype.hasOwnProperty.call(n,"$lt");r&&i&&t.add(e)}r(n)}))};return r(e),t}processRecord(t,r){const n=$.pk(this.fromSelector),i=e.get(this.fromSelector,e.key(O.ID,n))?.type;if(t[M.ID]){const[,...e]=t[M.ID].split(M.SEPARATOR),r=e.join("_");t[n]=l.parseValue(i,r)}return this.adapter.revert(t,this.fromSelector,t[n],void 0,r)}async raw(e,...t){const{ctx:r}=this.logCtx(t,this.raw),n=e?.aggregateInfo;if(e?.aggregate&&n)return this.executeAggregate(n,r);const i=this.scopeToTable(e),o=await this.adapter.raw(i,!0,r);if(this.manualAggregation){const e=o.map(e=>this.processRecord(e,r)),t=this.executeManualAggregation(e,this.manualAggregation,r);return this.manualAggregation=void 0,t}if(!this.selectSelector&&this.groupBySelectors?.length){const e=o.map(e=>this.processRecord(e,r));return this.groupSelectResults(e)}if(!this.selectSelector)return o;const s=e=>this.processRecord(e,r);if(Array.isArray(o)){const e=o.map(s);return await this.applyAfterHandlersToResult(e,r)}const a=s(o);return await this.applyAfterHandlersToResult(a,r)}scopeToTable(e){if(!this.fromSelector)return e;const t=$.tableName(this.fromSelector),r=e&&"object"==typeof e?e:{},n=Object.assign({},r.selector||{});return n[M.TABLE]=t,Object.assign({},r,{selector:n})}buildAggregateInfo(){if(this.fromSelector){if(this.avgSelector){const e=this.avgSelector+"",t=this.createAggregateDescriptor("sum",e);if(!t)throw this.missingDecorator("sum",e);const r=this.createAggregateDescriptor("count",e);if(!r)throw this.missingDecorator("count",e);return{kind:"avg",attribute:e,sumDescriptor:t.descriptor,countDescriptor:r.descriptor}}if(void 0!==this.countDistinctSelector){const e=this.resolveSelectorAttribute(this.countDistinctSelector),t=this.createAggregateDescriptor("distinct",e);if(!t)throw this.missingDecorator("distinct",e);return t.countDistinct=!0,t}if(void 0!==this.countSelector){const e=this.resolveSelectorAttribute(this.countSelector),t=this.createAggregateDescriptor("count",e);if(!t)throw this.missingDecorator("count",e);return t}if(this.maxSelector){const e=this.resolveSelectorAttribute(this.maxSelector),t=this.createAggregateDescriptor("max",e);if(!t)throw this.missingDecorator("max",e);return t}if(this.minSelector){const e=this.resolveSelectorAttribute(this.minSelector),t=this.createAggregateDescriptor("min",e);if(!t)throw this.missingDecorator("min",e);return t}if(this.sumSelector){const e=this.resolveSelectorAttribute(this.sumSelector),t=this.createAggregateDescriptor("sum",e);if(!t)throw this.missingDecorator("sum",e);return t}if(this.distinctSelector){const e=this.resolveSelectorAttribute(this.distinctSelector),t=this.createAggregateDescriptor("distinct",e);if(!t)throw this.missingDecorator("distinct",e);return t}}}createAggregateDescriptor(e,t){if(!this.fromSelector)return;const r=W(this.fromSelector,e,t);if(!r.length)return;const n=r[0],i=$.tableName(this.fromSelector),o=G(i,n.attribute,e,n),s=n.ddoc||z(i,o),a={reduce:void 0!==n.reduce||!n.returnDocs};return"distinct"!==e&&"groupBy"!==e||(a.group=!0),{kind:e,meta:n,descriptor:{ddoc:s,view:o,options:a}}}createAggregateQuery(e){return{selector:{},aggregate:!0,aggregateInfo:e}}shouldUseManualAggregation(){return!!this.whereCondition}async executeAggregate(e,t){if(!this.isViewAggregate(e))return this.handleAverage(e,t);const r=this.getCouchAdapter(),n=e,i=await r.view(n.descriptor.ddoc,n.descriptor.view,n.descriptor.options,t);return this.processViewResponse(e,i)}async handleAverage(e,t){if("avg"!==e.kind)throw new d("Average descriptor is not valid");const[r,n]=[e.sumDescriptor,e.countDescriptor],i=this.getCouchAdapter(),[o,s]=await Promise.all([i.view(r.ddoc,r.view,r.options,t),i.view(n.ddoc,n.view,n.options,t)]),a=o.rows?.[0]?.value??0,c=s.rows?.[0]?.value??0;return c?a/c:0}executeManualAggregation(e,t,r){if(!this.fromSelector)throw new d("Manual aggregation requires a target model");if("avg"===t.kind)return this.computeAverage(e,t.attribute);if("groupBy"===t.kind)return this.computeGroupBy(e,t.meta.attribute);const n=t.meta.attribute;switch(t.kind){case"count":return t.countDistinct?this.computeDistinctCount(e,n):this.computeCount(e,n);case"distinct":return t.countDistinct?this.computeDistinctCount(e,n):this.computeDistinctValues(e,n);case"sum":return this.computeSum(e,n);case"min":return this.computeMinMax(e,n,"min");case"max":return this.computeMinMax(e,n,"max");default:throw new d("Unsupported manual aggregation "+t.kind)}}computeCount(e,t){return t?this.collectValues(e,t).filter(e=>null!=e).length:e.length}computeDistinctCount(e,t){const r=t?this.collectValues(e,t).filter(e=>null!=e):e,n=new Set;return r.forEach(e=>n.add(JSON.stringify(e))),n.size}computeDistinctValues(e,t){if(!t)return[];const r=this.collectValues(e,t),n=new Set,i=[];return r.forEach(e=>{const t=JSON.stringify(e);n.has(t)||(n.add(t),i.push(e))}),i}computeSum(e,t){return t?this.collectValues(e,t).filter(e=>null!=e).reduce((e,r)=>e+this.toNumericValue(r,t,"SUM operation"),0):e.length}computeAverage(e,t){if(!t)return 0;const r=this.collectValues(e,t).filter(e=>null!=e);return r.length?r.reduce((e,r)=>e+this.toNumericValue(r,t,"AVG operation"),0)/r.length:0}computeMinMax(e,t,r){if(!t)return null;const n=this.collectValues(e,t).filter(e=>null!=e);let i=null,o=null;for(const e of n){const t=this.normalizeComparable(e);null!==t&&(null!==o?("min"===r&&o>t||"max"===r&&t>o)&&(o=t,i=e):(o=t,i=e))}return i}computeGroupBy(e,t){const r={},n=this.collectValues(e,t);return e.forEach((e,t)=>{const i=this.groupKey(n[t]);r[i]||(r[i]=[]),r[i].push(e)}),r}groupSelectResults(e){if(!this.groupBySelectors?.length)return{};const t=this.resolveSelectorAttribute(this.groupBySelectors[0]);if(!t)return{};const r={};return e.forEach(e=>{const n=this.groupKey(this.convertValueByAttribute(t,e[t]));r[n]||(r[n]=[]),r[n].push(e)}),r}collectValues(e,t){return e.map(e=>{if(e&&"object"==typeof e)return this.convertValueByAttribute(t,e[t])})}convertValueByAttribute(e,t){if(!this.fromSelector)return t;if("date"===this.getAttributeType(e)){if(t instanceof Date)return t;const e=new Date(t);if(!Number.isNaN(e.getTime()))return e}if("string"==typeof t&&e.toLowerCase().includes("date")){const e=new Date(t);if(!Number.isNaN(e.getTime()))return e}return t}getAttributeType(t){if(!t||!this.fromSelector)return;if(this.attributeTypeCache.has(t))return this.attributeTypeCache.get(t);const r=e.type(this.fromSelector,t)??e.getPropDesignTypes?.(this.fromSelector,t)?.designType,n=this.normalizeMetaType(r);return this.attributeTypeCache.set(t,n),n}normalizeMetaType(e){if(e)return"string"==typeof e?e.toLowerCase():"function"==typeof e&&e.name?e.name.toLowerCase():void 0}normalizeComparable(e){return"number"==typeof e?e:"bigint"==typeof e?Number(e):e instanceof Date?e.getTime():"string"!=typeof e||isNaN(Number(e))?null:Number(e)}groupKey(e){if(void 0===e)return"undefined";if(null===e)return"null";if("symbol"==typeof e)return e.toString();if("object"==typeof e)try{return JSON.stringify(e)}catch{return e+""}return e+""}toNumericValue(e,t,r){if("number"==typeof e)return e;if("bigint"==typeof e)return Number(e);if(e instanceof Date)return e.getTime();if("string"==typeof e&&!isNaN(Number(e)))return Number(e);throw new d(`${r} on "${t}" requires numeric values, but got ${typeof e}`)}convertAggregateValue(e,t){return e?this.convertValueByAttribute(e,t):t}resolveSelectorAttribute(e){if(null!=e)return e+""}missingDecorator(e,t){const r=this.decoratorForKind(e),n=this.fromSelector?$.tableName(this.fromSelector):"<unknown table>";return new g(`${r} decorator is required for CouchDB ${e} aggregation${t?` on "${t}"`:""} on table "${n}".`)}decoratorForKind(e){return{count:"@count",sum:"@sum",min:"@min",max:"@max",distinct:"@distinct",groupBy:"@groupBy",view:"@view",avg:"@avg"}[e]||"@"+e}processViewResponse(e,t){if("avg"===e.kind)throw new d("Average results should be handled before processing rows");const r=t.rows||[],n=e,i=n.meta;return n.countDistinct?r.length||0:"distinct"===n.kind||"groupBy"===n.kind?r.map(e=>this.convertAggregateValue(n.meta.attribute,e.key??e.value)):i.returnDocs?r.map(e=>e.value??e.doc??e):r.length?this.convertAggregateValue(n.meta.attribute,r[0].value??r[0].key??null):"count"===n.kind?0:null}isViewAggregate(e){return"avg"!==e.kind}getCouchAdapter(){return this.adapter}parseCondition(e){const{attr1:t,operator:r,comparison:i}=e;if(r===n.STARTS_WITH){if("string"!=typeof t)throw new d("STARTS_WITH requires an attribute name");if("string"!=typeof i)throw new d("STARTS_WITH requires a string comparison");const e={start:o=i,end:je(o)};return{selector:{[this.toColumnName(t)]:{$gte:e.start,$lt:e.end}}}}var o,a;if(r===n.ENDS_WITH){if("string"!=typeof t)throw new d("ENDS_WITH requires an attribute name");if("string"!=typeof i)throw new d("ENDS_WITH requires a string comparison");return{selector:{[this.toColumnName(t)]:{$regex:(a=i,a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"$")}}}}if(r===n.BETWEEN){const e=this.toColumnName(t);if(!Array.isArray(i)||2!==i.length)throw new d("BETWEEN operator requires [min, max] comparison");const[r,o]=i,s={};return s[e]={},s[e][ue(n.BIGGER_EQ)]=r,s[e][ue(n.SMALLER_EQ)]=o,{selector:s}}let c={};if(-1===[s.AND,s.OR,n.NOT].indexOf(r)){const e=this.toColumnName(t);c[e]={},c[e][ue(r)]=i}else if(r===n.NOT)c=this.parseCondition(t).selector,c[ue(n.NOT)]={},c[ue(n.NOT)][this.toColumnName(t.attr1)]=i;else{const e=this.parseCondition(t).selector,n=this.parseCondition(i).selector;c=((e,t,r)=>{const n={selector:{}};return n.selector[e]=[t,r],n})(ue(r),e,n).selector}return{selector:c}}}class Be extends p{constructor(e,t,r){super(e,t,r),[this.create,this.createAll,this.update,this.updateAll].forEach(e=>{const t=e.name;x(this,e,this[t+"Prefix"])})}Statement(e){return new Ce(this,e)}Paginator(e,t,r){return new ce(this,e,t,r)}async initialize(){const e=p.models(this.flavour);return this.index(...e)}repository(){return oe}assignMetadata(e,t){return t?(re(e,t),e):e}assignMultipleMetadata(e,t){return e.forEach((e,r)=>(re(e,t[r]),e)),e}prepare(e,...t){const{log:n}=this.logCtx(t,this.prepare),i=e.segregate(),o=Object.entries(i.model).reduce((t,[r,n])=>{if(void 0===n)return t;const i=$.columnName(e.constructor,r);if(this.isReserved(i))throw new b(`Property name ${i} is reserved`);return n=n instanceof Date?new Date(n):n,t[i]=n,t},{});return e[r.METADATA]&&(n.silly("Passing along persistence metadata for "+e[r.METADATA]),Object.defineProperty(o,r.METADATA,{enumerable:!1,writable:!0,configurable:!0,value:e[r.METADATA]})),{record:o,id:e[$.pk(e.constructor)],transient:i.transient}}createPrefix(e,t,r,...n){const{ctxArgs:i}=this.logCtx(n,this.createPrefix),o=$.tableName(e),s={};return Object.assign(s,r),s[M.TABLE]=o,s[M.ID]=this.generateId(o,t),[e,t,s,...i]}createAllPrefix(e,t,r,...n){const i=$.tableName(e);if(t.length!==r.length)throw new b("Ids and models must have the same length");const{ctxArgs:o}=this.logCtx(n,this.createAllPrefix),s=t.map((e,t)=>{const n={};return Object.assign(n,r[t]),n[M.TABLE]=i,n[M.ID]=this.generateId(i,e),n});return[e,t,s,...o]}updatePrefix(e,t,n,...i){const o=$.tableName(e),{ctxArgs:s}=this.logCtx(i,this.updatePrefix),a={},c=n[r.METADATA];if(!c)throw new b("No revision number found for record with id "+t);return Object.assign(a,n),a[M.TABLE]=o,a[M.ID]=this.generateId(o,t),a[M.REV]=c,[e,t,a,...s]}updateAllPrefix(e,t,n,...i){const o=$.tableName(e);if(t.length!==n.length)throw new b("Ids and models must have the same length");const{ctxArgs:s}=this.logCtx(i,this.updateAllPrefix),a=t.map((e,t)=>{const i={},s=n[t][r.METADATA];if(!s)throw new b("No revision number found for record with id "+e);return Object.assign(i,n[t]),i[M.TABLE]=o,i[M.ID]=this.generateId(o,e),i[M.REV]=s,i});return[e,t,a,...s]}generateId(e,t){const r=M.SEPARATOR;return"string"==typeof t&&t.startsWith(`${e}${r}`)&&t.split(r).length>=2?t:`${e}${r}${t+""}`}parseError(e,t){return Be.parseError(e,t)}isReserved(e){return!!e.match(k)||e===M.TABLE||e===M.SEQUENCE}static parseError(e,t){if(e instanceof N)return e;let r="";if("string"==typeof e){if(r=e,r.match(/already exist|update conflict/g))return new T(r);if(r.match(/missing|deleted/g))return new D(r)}else e.code?(r=e.code,t=t||e.message):e.statusCode?(r=e.statusCode,t=t||e.message):r=e.message;switch(r.toString()){case"401":case"412":case"409":return new T(t);case"404":return new D(t);case"400":return r.toString().match(/No\sindex\sexists/g)?new se(e):new b(e);default:return r.toString().match(/ECONNREFUSED/g)?new h(e):new b(e)}}static setMetadata(e,t){re(e,t)}static getMetadata(e){return ne(e)}static removeMetadata(e){ie(e)}}function ke(e,r){let i={};return Array.isArray(e)?i.compositions=e:"string"==typeof e?i.name=e:e&&(i=e),"string"==typeof r?i.name=r:r&&(i=Object.assign({},i,r)),void 0===i.returnDocs&&(i.returnDocs=!0),t.for(n.GROUP_BY).define({decorator:e=>m(n.GROUP_BY,"groupBy",e),args:[i]}).apply()}function Me(e,r){let i={};return e instanceof o?i.condition=e:"object"==typeof e&&e?i=e:void 0!==e&&(i.value=e),r&&(i=Object.assign({},i,r)),t.for(n.COUNT).define({decorator:e=>m(n.COUNT,"count",e),args:[i]}).apply()}function Ie(e,r){let i={};return e instanceof o?i.condition=e:e&&(i=e),r&&(i=Object.assign({},i,r)),t.for(n.SUM).define({decorator:e=>m(n.SUM,"sum",e),args:[i]}).apply()}function Le(e,r){let i={};return e instanceof o?i.condition=e:e&&(i=e),r&&(i=Object.assign({},i,r)),t.for(n.MAX).define({decorator:e=>m(n.MAX,"max",e),args:[i]}).apply()}function Pe(e,r){let i={};return e instanceof o?i.condition=e:e&&(i=e),r&&(i=Object.assign({},i,r)),t.for(n.MIN).define({decorator:e=>m(n.MIN,"min",e),args:[i]}).apply()}function Ve(e,r){let i={};return e instanceof o?i.condition=e:e&&(i=e),r&&(i=Object.assign({},i,r)),t.for(n.DISTINCT).define({decorator:e=>m(n.DISTINCT,"distinct",e),args:[i]}).apply()}j([B(),C("design:type",Function),C("design:paramtypes",[Object]),C("design:returntype",Ce)],Be.prototype,"Statement",null),j([B(),C("design:type",Function),C("design:paramtypes",[Object,String]),C("design:returntype",Object)],Be.prototype,"assignMetadata",null),j([B(),C("design:type",Function),C("design:paramtypes",[Array,Array]),C("design:returntype",Array)],Be.prototype,"assignMultipleMetadata",null),j([B(),C("design:type",Function),C("design:paramtypes",[Object,Object,Object,Object]),C("design:returntype",Array)],Be.prototype,"createPrefix",null),j([B(),C("design:type",Function),C("design:paramtypes",[Object,Array,Array,Object]),C("design:returntype",void 0)],Be.prototype,"createAllPrefix",null),j([B(),C("design:type",Function),C("design:paramtypes",[Object,Object,Object,Object]),C("design:returntype",void 0)],Be.prototype,"updatePrefix",null),j([B(),C("design:type",Function),C("design:paramtypes",[Object,Array,Array,Object]),C("design:returntype",void 0)],Be.prototype,"updateAllPrefix",null);const Re="##VERSION##",_e="##COMMIT##",Ue="##FULL_VERSION##",qe="##PACKAGE##";e.registerLibrary(qe,Re);export{_e as COMMIT,Be as CouchDBAdapter,V as CouchDBConst,P as CouchDBGroupOperator,M as CouchDBKeys,L as CouchDBOperator,ce as CouchDBPaginator,I as CouchDBQueryLimit,oe as CouchDBRepository,Ce as CouchDBStatement,Ue as FULL_VERSION,se as IndexError,ae as IndexPlanningError,qe as PACKAGE_NAME,Re as VERSION,Ne as attachGeneratedUseIndex,be as buildGeneratedIndexCandidates,X as collectViewMetadata,Me as count,Ve as distinct,$e as enableMangoExecutionStats,De as ensureDeterministicSort,we as findGeneratedIndexCandidateByName,W as findViewMetadata,z as generateDesignDocName,q as generateIndexDoc,Z as generateIndexName,te as generateIndexes,ee as generateModelIndexName,K as generateViewIndexes,G as generateViewName,H as generateViews,me as getEqualitySelectorFields,ne as getMetadata,ye as getRangeSelectorFields,Ee as getRequiredMangoIndexShape,he as getSortDirection,pe as getSortFields,ke as groupBy,Le as max,Pe as min,ge as normalizeSortField,R as reAuth,ie as removeMetadata,xe as requireGeneratedUseIndex,k as reservedAttributes,ve as resolveGeneratedIndexForQuery,Se as reverseRequiredShapeToIndexDeclaration,re as setMetadata,Ie as sum,U as testReservedAttributes,ue as translateOperators,Y as viewIndexDefinition,Te as warnScanProneMangoOperators,_ as wrapDocumentScope}; //# sourceMappingURL=for-couchdb.js.map