@autofleet/sadot 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.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{DataTypes as e,Op as t,ValidationError as n}from"sequelize";import r from"@autofleet/logger";import{AfterSave as i,AfterUpsert as a,BeforeBulkCreate as o,BeforeBulkUpdate as s,BeforeCreate as c,BeforeUpdate as l,BeforeUpsert as u,BelongsTo as d,Column as f,DataType as p,Default as m,DefaultScope as ee,ForeignKey as te,HasMany as ne,Is as re,Model as h,PrimaryKey as g,Sequelize as _,Table as v}from"sequelize-typescript";import{customFields as ie}from"@autofleet/common-types";import y,{ValidationError as ae}from"joi";import oe from"@autofleet/events";import{getUser as se}from"@autofleet/zehut";import{BadRequest as b,ResourceNotFoundError as x,handleError as ce}from"@autofleet/errors";import{randomInt as le,randomUUID as ue}from"node:crypto";import{Router as de}from"@autofleet/node-common";import{StatusCodes as S}from"http-status-codes";import fe from"ajv";import pe from"ajv-formats";import{CUSTOM_FIELDS_SORT_SCOPE as me}from"@autofleet/common-types/lib/custom-fields";import he from"ajv-errors";const ge=r();async function _e(){try{let{outbreak:e}=await import(`@autofleet/zehut`);ge.addContextMiddleware(()=>({traceId:e.getCurrentContextTraceId()}))}catch(e){ge.error(`Failed to add traceId middleware`,{err:e})}}var C=ge;const ve=[`businessModelId`,`fleetId`,`demandSourceId`];let w=function(e){return e.NUMBER=`number`,e.BOOLEAN=`boolean`,e.DATE=`date`,e.DATETIME=`datetime`,e.TEXT=`text`,e.IMAGE=`image`,e.SELECT=`select`,e.STATUS=`status`,e.FILE=`file`,e}({});const ye=ie.CUSTOM_FIELDS_FILTER_SCOPE,be=(e,t)=>y.string().allow(null).valid(...t).validate(e),xe=(e,t)=>y.string().allow(null).valid(...t.map(e=>e.value)).validate(e),Se={[w.SELECT]:w.SELECT,[w.STATUS]:w.STATUS},Ce={[w.SELECT]:be,[w.STATUS]:xe,[w.TEXT]:e=>y.string().min(0).validate(e),[w.NUMBER]:e=>y.number().strict(!0).validate(e),[w.BOOLEAN]:e=>y.boolean().strict().validate(e),[w.DATE]:e=>y.date().validate(e),[w.DATETIME]:e=>y.date().validate(e),[w.IMAGE]:e=>y.array().min(1).unique().items(y.string().uri()).validate(e),[w.FILE]:e=>y.array().min(1).unique().items(y.object({name:y.string().required(),type:y.string(),size:y.string(),addedBy:y.string().uuid()})).validate(e)},we=new oe({logger:C,getUserId:e=>e?.user_id??se()?.id??null}),Te=[`value`,`defaultValue`,`blockEditingFromUI`],Ee=(e,t)=>{let n=new Set(Object.keys(e));return t.every(e=>!n.has(e))?e:{...e,...Object.fromEntries(t.map(t=>[t,typeof e[t]==`boolean`?e[t].toString():e[t]]))}},De={CustomFieldDefinition:{tableName:`dim_custom_field_definition`,eventVersion:`1`},CustomFieldValue:{tableName:`dim_custom_field_value`,eventVersion:`1`},CustomFieldEntries:{tableName:`dim_custom_field_entries`,eventVersion:`1`}},T=e=>{let t=De[e.constructor.name];if(!t)return;let n=e.get();try{n=Ee(e.get(),Te)}catch(e){C.error(`Failed to convert booleans in dim event payload`,e)}we.sendObject(t.tableName,t.eventVersion,n).catch(()=>{})};var Oe=class extends b{constructor(e){let t=Error(`The following custom fields are required: ${e.join(`,`)}`);super([t],null,e),this.message=`MISSING_REQUIRED_CUSTOM_FIELDS`}},ke=class extends b{constructor(e){let t=Error(`Type "${e}" is not supported`);super([t],null,null),this.message=`UNSUPPORTED_CUSTOM_FIELD_TYPE`}},Ae=class extends b{constructor(e){let t=Error(`Validation for "${e}" is not supported`);super([t],null,null),this.message=`UNSUPPORTED_CUSTOM_VALIDATION_TYPE`}},je=class extends b{constructor(e){let t=Error(`Invalid field type ${e}`);super([t],null,null),this.message=`INVALID_FIELD_TYPE`}},E=class extends b{constructor(e,t,n){let r=n.message.replace(/"/g,``).replace(`value`,`'${t}'`),i=typeof e==`object`?JSON.stringify(e):e,a=`Invalid Value on field '${t}'. ${r}. received: '${i}'`;super([Error(a)],null,null),this.message=a}},Me=class extends b{constructor(e,t){let n=t.map(e=>new E(e.value,e.fieldDefinitionName,e.joiValidationError));super(n,null,null),this.message=`Invalid entries on ${e}\n${t.map(e=>`${e.fieldDefinitionName} - ${e.joiValidationError.message}`).join(`
|
|
2
|
-
`)}`}},Ne=class extends b{constructor(e){let t=Error(`Missing custom field definition for field ${e.join(`,`)}`);super([t],null,null),this.message=`MISSING_DEFINITION`}};const Pe=e=>Object.keys(Ce).includes(e),Fe=(e,t,n)=>{let r=Ce[t];return r(e,n)},Ie=(e,t,n=Fe)=>{let r=Object.entries(e.customFields).map(([e,r])=>{if(r===null)return null;let{validation:i,fieldType:a}=t[e],o=n(r,a,i);return o?.error?{joiValidationError:o.error,fieldDefinitionName:e,value:r}:null}).filter(e=>!!e);if(r?.length)throw new Me(e.modelId,r)};function D(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function O(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var Le,Re,ze,Be,Ve,He;let k=class extends h{static displayNameDefaultValue(e){if(e?.displayName||(e.displayName=e.name),![null,void 0].includes(e.defaultValue)){let t=Fe(e.defaultValue,e.fieldType,e.validation);if(t.error)throw new E(e.defaultValue,e.name,t.error)}}static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e)):T(e)}};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],k.prototype,`id`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],k.prototype,`name`,void 0),O([f({type:p.STRING}),D(`design:type`,String)],k.prototype,`displayName`,void 0),O([re(`SupportedType`,e=>{if(!Object.values(w).includes(e))throw new ke(`"${e}" is not a supported type.`)}),f({type:p.STRING,allowNull:!1}),D(`design:type`,typeof(Le=w!==void 0&&w)==`function`?Le:Object)],k.prototype,`fieldType`,void 0),O([f({type:p.JSONB}),D(`design:type`,Object)],k.prototype,`validation`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],k.prototype,`entityId`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],k.prototype,`entityType`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],k.prototype,`modelType`,void 0),O([f({type:p.TEXT}),D(`design:type`,String)],k.prototype,`description`,void 0),O([f({type:p.BOOLEAN,defaultValue:!1}),D(`design:type`,Boolean)],k.prototype,`required`,void 0),O([f({type:p.BOOLEAN,defaultValue:!1}),D(`design:type`,Boolean)],k.prototype,`disabled`,void 0),O([f({type:p.JSONB,allowNull:!0}),D(`design:type`,Object)],k.prototype,`defaultValue`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(Re=typeof Date<`u`&&Date)==`function`?Re:Object)],k.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(ze=typeof Date<`u`&&Date)==`function`?ze:Object)],k.prototype,`updatedAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(Be=typeof Date<`u`&&Date)==`function`?Be:Object)],k.prototype,`deletedAt`,void 0),O([f({type:p.BOOLEAN,defaultValue:!1,allowNull:!1}),D(`design:type`,Boolean)],k.prototype,`blockEditingFromUI`,void 0),O([ne(()=>N),D(`design:type`,Array)],k.prototype,`values`,void 0),O([c,D(`design:type`,Function),D(`design:paramtypes`,[typeof(Ve=k!==void 0&&k)==`function`?Ve:Object]),D(`design:returntype`,void 0)],k,`displayNameDefaultValue`,null),O([i,D(`design:type`,Function),D(`design:paramtypes`,[typeof(He=k!==void 0&&k)==`function`?He:Object,Object]),D(`design:returntype`,void 0)],k,`afterSaveHandler`,null),k=O([ee(()=>({where:{disabled:!1}})),v({indexes:[{name:`unique_name_model_type`,fields:[`model_type`,`entity_id`,`name`],unique:!0}],timestamps:!0,validate:{validationByType(){if(!this.validation&&Se[this.fieldType])throw C.error(`No custom validation for custom field type ${this.fieldType} found`),new Ae(`Validation provided for "${this.fieldType}" is not supported`)}}})],k);var A=k;const Ue=e=>A.create(e),j=(e,t={withDisabled:!1})=>(t.withDisabled?A.unscoped():A).scope(`userScope`).findAll({where:e,transaction:t.transaction,raw:!0,include:t.include}),We=(e,n={withDisabled:!1})=>j({id:{[t.in]:e}},n),Ge=(e,t={withDisabled:!1})=>{let{withDisabled:n}=t;return n?A.unscoped().scope(`userScope`).findByPk(e):A.scope(`userScope`).findByPk(e)},Ke=async(e,n,r={})=>{let{include:i,useEntityIdFromInclude:a}=r.modelOptions,o={modelType:e,...!a&&{entityId:{[t.in]:n}}};return A.findAll({where:o,transaction:r.transaction,include:i?.(n),raw:!0})},qe=e=>A.scope(`userScope`).findOne({where:e}),Je=async(e,t)=>(await A.scope(`userScope`).update(t,{where:{id:e},returning:!0,individualHooks:!0}))[1][0],Ye=async(e,{findAll:n,modelOptions:r={},withDisabled:i=!1,...a}={withDisabled:!1,modelOptions:{}})=>{let{modelType:o}=e[0]?.dataValues??{},s=new Set,c=[],l=new Set;e.forEach(e=>{let{dataValues:{modelId:t,entityId:n,customFields:r}}=e;c.push(t),l.add(n),Object.keys(r??{}).forEach(e=>{s.add(e)})});let u={modelType:o,entityId:{[t.in]:Array.from(l)},name:{[t.in]:Array.from(s)}},d=await(n??j)(u,{withDisabled:i,modelOptions:r,...a}),f=d.filter(e=>s.has(e.name)),p=Object.fromEntries(f.map(e=>[e.name,e]));if(!d?.length||f.length!==s.size){let e=Array.from(s).filter(e=>!p[e]);throw new Ne(e)}return p};var Xe,Ze,Qe,$e,et,tt;let M=class extends h{static validateValueAgainstDefinition(e,t){let{validation:n,fieldType:r,name:i}=t;if(!Pe(r))throw new je(r);if(e.value===null)return;let a=Fe(e.value,r,n);if(a.error)throw new E(e.value,i,a.error)}static async validateCustomFieldValues(e){let t=e.map(e=>e.customFieldDefinitionId),n=[...new Set(t)],r=await We(n,{withDisabled:!0});if(!r||r.length!==n.length)throw Error(`Definitions not found`);e.forEach(e=>{let t=r.find(t=>t.id===e.customFieldDefinitionId);t&&this.validateValueAgainstDefinition(e,t)})}static async validateCustomFieldValue(e){let{customFieldDefinitionId:t}=e,n=await Ge(t,{withDisabled:!0});this.validateValueAgainstDefinition(e,n)}static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e[0])):T(e[0])}};O([g,f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],M.prototype,`modelId`,void 0),O([g,te(()=>A),f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],M.prototype,`customFieldDefinitionId`,void 0),O([f({type:p.JSONB,allowNull:!0}),D(`design:type`,Object)],M.prototype,`value`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(Xe=typeof Date<`u`&&Date)==`function`?Xe:Object)],M.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(Ze=typeof Date<`u`&&Date)==`function`?Ze:Object)],M.prototype,`updatedAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(Qe=typeof Date<`u`&&Date)==`function`?Qe:Object)],M.prototype,`deletedAt`,void 0),O([d(()=>A,{scope:{disabled:!1}}),D(`design:type`,typeof($e=A!==void 0&&A)==`function`?$e:Object)],M.prototype,`customFieldDefinition`,void 0),O([o,s,D(`design:type`,Function),D(`design:paramtypes`,[Array]),D(`design:returntype`,Promise)],M,`validateCustomFieldValues`,null),O([l,c,u,D(`design:type`,Function),D(`design:paramtypes`,[typeof(et=M!==void 0&&M)==`function`?et:Object]),D(`design:returntype`,Promise)],M,`validateCustomFieldValue`,null),O([a,D(`design:type`,Function),D(`design:paramtypes`,[typeof(tt=M!==void 0&&M)==`function`?tt:Object,Object]),D(`design:returntype`,void 0)],M,`afterSaveHandler`,null),M=O([v({timestamps:!0})],M);var N=M,nt;let P=class extends h{};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],P.prototype,`id`,void 0),O([te(()=>I),f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],P.prototype,`testModelId`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],P.prototype,`fleetId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],P.prototype,`businessModelId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],P.prototype,`demandSourceId`,void 0),O([f({type:p.BOOLEAN}),D(`design:type`,Boolean)],P.prototype,`anotherAttribute`,void 0),O([d(()=>I),D(`design:type`,typeof(nt=I!==void 0&&I)==`function`?nt:Object)],P.prototype,`testModel`,void 0),P=O([v({schema:`custom-fields`,tableName:`associated_test_models`,createdAt:!1,updatedAt:!1})],P);var rt=P;let F=class extends h{};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],F.prototype,`id`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],F.prototype,`fleetId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],F.prototype,`businessModelId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],F.prototype,`demandSourceId`,void 0),O([f({type:p.BOOLEAN}),D(`design:type`,Boolean)],F.prototype,`coolAttribute`,void 0),O([ne(()=>rt),D(`design:type`,Array)],F.prototype,`associatedModels`,void 0),O([f({type:p.VIRTUAL}),D(`design:type`,Object)],F.prototype,`customFields`,void 0),F=O([v({schema:`custom-fields`,tableName:`test_models`,createdAt:!1,updatedAt:!1})],F);var I=F,it=function(e){return e.BUSINESS_MODEL=`businessModel`,e.CONTEXT=`context`,e.DEMAND_SOURCE=`demandSource`,e.FLEET=`fleet`,e}(it||{});let L=class extends h{};O([g,f({defaultValue:p.UUIDV4,type:p.UUID}),D(`design:type`,String)],L.prototype,`id`,void 0),O([f({type:p.UUID}),D(`design:type`,String)],L.prototype,`entityId`,void 0),O([f({type:p.ENUM(...Object.values(it))}),D(`design:type`,String)],L.prototype,`entityType`,void 0),L=O([v({createdAt:!1,updatedAt:!1})],L);var R=L,at;let z=class extends h{};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],z.prototype,`id`,void 0),O([te(()=>R),f({type:p.UUID}),D(`design:type`,String)],z.prototype,`contextId`,void 0),O([f({type:p.BOOLEAN}),D(`design:type`,Boolean)],z.prototype,`coolAttribute`,void 0),O([f({type:p.VIRTUAL}),D(`design:type`,Object)],z.prototype,`customFields`,void 0),O([d(()=>R),D(`design:type`,typeof(at=R!==void 0&&R)==`function`?at:Object)],z.prototype,`context`,void 0),z=O([v({createdAt:!1,updatedAt:!1})],z);var ot=z,st,ct,lt,ut;let B=class extends h{static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e[0])):T(e[0])}};O([g,f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],B.prototype,`modelId`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],B.prototype,`entityId`,void 0),O([f({type:p.JSONB,allowNull:!1,defaultValue:{}}),D(`design:type`,typeof(st=typeof Record<`u`&&Record)==`function`?st:Object)],B.prototype,`customFields`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],B.prototype,`modelType`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(ct=typeof Date<`u`&&Date)==`function`?ct:Object)],B.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(lt=typeof Date<`u`&&Date)==`function`?lt:Object)],B.prototype,`updatedAt`,void 0),O([a,D(`design:type`,Function),D(`design:paramtypes`,[typeof(ut=B!==void 0&&B)==`function`?ut:Object,Object]),D(`design:returntype`,void 0)],B,`afterSaveHandler`,null),B=O([v({timestamps:!0,indexes:[{name:`idx_cfe_custom_fields`,using:`gin`,operator:`jsonb_path_ops`,fields:[`custom_fields`]}],validate:{async validationByType(){if(!Object.keys(this.customFields??{}).length)return;let e=await Ye([this]);Ie(this,e)}}})],B);var V=B,dt,ft,pt;let H=class extends h{static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e)):T(e)}};O([g,m(()=>ue()),f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],H.prototype,`id`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],H.prototype,`entityId`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],H.prototype,`entityType`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],H.prototype,`modelType`,void 0),O([f({type:p.JSONB,allowNull:!1}),D(`design:type`,Object)],H.prototype,`schema`,void 0),O([f({type:p.BOOLEAN,allowNull:!1,defaultValue:!1}),D(`design:type`,Boolean)],H.prototype,`disabled`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(dt=typeof Date<`u`&&Date)==`function`?dt:Object)],H.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(ft=typeof Date<`u`&&Date)==`function`?ft:Object)],H.prototype,`updatedAt`,void 0),O([a,D(`design:type`,Function),D(`design:paramtypes`,[typeof(pt=H!==void 0&&H)==`function`?pt:Object,Object]),D(`design:returntype`,void 0)],H,`afterSaveHandler`,null),H=O([ee(()=>({where:{disabled:!1}})),v({timestamps:!0})],H);var U=H;const mt=[A,N,U],ht=[I,rt,ot,R],gt=async(n,r,{schemaPrefix:i=`sadot-migration`,schemaVersion:a=`49c9dd1d-b1cc-445b-a911-fd349d783110`,useCustomFieldsEntries:o=!1}={})=>{let s=`${i}_${a}${o?`_withEntries`:``}`;if(C.info(`custom-fields: initialize custom-fields tables`),!n.addModels)throw Error(`sequelize instance must have addModels function`);o&&mt.push(V),n.addModels(mt),A.addScope(`userScope`,()=>{let e=r();return e?.permissions?{where:{entityId:[...Object.keys(e.permissions.fleets),...Object.keys(e.permissions.businessModels),...Object.keys(e.permissions.demandSources)]}}:{}}),U.addScope(`userScope`,()=>{let e=r();return e?.permissions?{where:{entityId:[...Object.keys(e.permissions.fleets),...Object.keys(e.permissions.businessModels),...Object.keys(e.permissions.demandSources)]}}:{}}),C.info(`custom-fields: models added`);let c=n.define(`SequelizeMeta`,{name:{type:e.STRING,allowNull:!1,unique:!0,primaryKey:!0,autoIncrement:!1}},{tableName:`SequelizeMeta`,timestamps:!1,schema:`public`});C.info(`custom-fields: starting migrations`);let l=await c.findAll({where:{name:{[t.like]:`${i}%`}},raw:!0}),u=l.at(-1),d=l.findIndex(e=>e.name===s);if(C.info(`custom-fields: migrations`,{migrations:l,currentSadotSchemaVersion:u,expectedSchemaVersionIndex:d}),(!u||u.name!==s)&&(C.info(`custom-fields: syncing models`),await A.sync({alter:!0}),await N.sync({alter:!0}),o&&await V.sync({alter:!0}),await U.sync({alter:!0}),d===-1&&await c.create({name:s}),C.info(`custom-fields: models synced`),l.length&&d!==-1&&d<l.length-1)){let e=l.slice(d+1);await c.destroy({where:{name:{[t.in]:e.map(e=>e.name)}}})}},_t=async e=>{if(C.info(`custom-fields: initialize custom-fields test models`),!e.addModels)throw Error(`sequelize instance must have addModels function`);e.addModels(ht),await e.dropSchema(`custom-fields`,{logging:!1}),await e.createSchema(`custom-fields`,{logging:!1}),C.info(`custom-fields: test models added`),await I.sync({alter:!0}),await rt.sync({alter:!0}),await R.sync({alter:!0}),await ot.sync({alter:!0}),C.info(`custom-fields: test models synced`)};var W=(e,t,r=void 0)=>{let i=e;return[ae,n].some(t=>e instanceof t)&&(i=new b([e],null)),ce(i,t,r)};const vt=y.object({name:y.string().required(),type:y.string(),size:y.string(),addedBy:y.string().uuid()}),yt=y.object({value:y.string().required(),color:y.string().required()}),bt=y.when(`fieldType`,{is:w.SELECT,then:y.array().required().items(y.string()).min(1).unique(),otherwise:y.when(`fieldType`,{is:w.STATUS,then:y.array().required().items(yt).min(1).unique(`value`),otherwise:y.forbidden()})}),xt=y.when(`fieldType`,{switch:[{is:w.BOOLEAN,then:y.boolean().allow(null)},{is:w.DATE,then:y.date().allow(null)},{is:w.DATETIME,then:y.date().allow(null)},{is:w.FILE,then:y.array().items(vt).allow(null)},{is:w.IMAGE,then:y.array().items(y.string().uri()).allow(null)},{is:w.NUMBER,then:y.number().allow(null)},{is:w.SELECT,then:y.string().allow(null)},{is:w.STATUS,then:y.string().allow(null)},{is:w.TEXT,then:y.string().allow(null)}]}),St=y.object({name:y.string().required(),displayName:y.string().required(),validation:bt,defaultValue:xt,fieldType:y.string().valid(...Object.values(w)).required(),entityId:y.string().guid().required(),entityType:y.string().required(),description:y.string(),required:y.boolean(),disabled:y.boolean(),blockEditingFromUI:y.boolean()}).oxor(`required`,`blockEditingFromUI`,{isPresent:e=>e===!0}),Ct=y.object({displayName:y.string(),validation:bt,defaultValue:xt,fieldType:y.string().valid(...Object.values(w)),description:y.string().allow(null),required:y.boolean(),disabled:y.boolean(),blockEditingFromUI:y.boolean()}).oxor(`required`,`blockEditingFromUI`,{isPresent:e=>e===!0}),wt=e=>St.validateAsync(e,{abortEarly:!1}),Tt=e=>Ct.validateAsync(e,{abortEarly:!1}),G=de({logger:C}),Et=`CustomFieldDefinition`,Dt=e=>e.replace(/(^\w|-\w)/g,e=>e.replace(/-/,``).toUpperCase());G.post(`/`,async(e,t)=>{let{modelName:n}=e.params,r=Dt(n);try{let n=await wt(e.body),i=await Ue({...n,modelType:r});return t.status(201).json(i)}catch(e){return C.error(`Failed to create custom field definition`,e),W(e,t,{logger:C,message:`Error in create ${Et} request`})}}),G.get(`/:customFieldDefinitionId`,async(e,t)=>{let{customFieldDefinitionId:n}=e.params;try{let e=await Ge(n);if(!e)throw new x;return t.json(e)}catch(e){return C.error(`Failed to fetch custom field definition`,e),W(e,t,{logger:C,message:`Error in get ${Et} request`})}}),G.get(`/`,async(e,t)=>{let{params:{modelName:n},query:{entityIds:r}}=e,i=Dt(n);try{let e={modelType:i,...r?.length>0&&{entityId:r}},n=await j(e,{withDisabled:!0});return t.json(n)}catch(e){return C.error(`Failed to fetch custom field definitions`,e),W(e,t,{logger:C,message:`Error in get all ${Et} request`})}}),G.patch(`/:customFieldDefinitionId`,async(e,t)=>{let{customFieldDefinitionId:n,modelName:r}=e.params,i=Dt(r);try{let r=await Tt(e.body);if(!await qe({id:n,modelType:i}))throw new x;let a=await Je(n,{...r,modelType:i});return t.status(200).json(a)}catch(e){return C.error(`Failed to patch custom field definition`,e),W(e,t,{logger:C,message:`Error in update ${Et} request`})}});var Ot=G;const kt=async(e,t={})=>(C.debug(`custom-validator - create validator`),await U.create(e,t)),K=async(e={},t={})=>{C.debug(`custom-validator - find all validators`);let{transaction:n,withDisabled:r,include:i,attributes:a,raw:o}=t,s;return s=r?await U.unscoped().scope(`userScope`).findAll({where:e,transaction:n,include:i,attributes:a,raw:o}):await U.scope([`defaultScope`,`userScope`]).findAll({where:e,transaction:n,include:i,attributes:a,raw:o}),s},At=async(e,t,n={})=>(C.debug(`custom-validator - find all validators by model type`),K({modelType:e,...!n?.modelOptions?.useEntityIdFromInclude&&{entityId:t}},{...n,include:n?.modelOptions?.include?.(t)})),jt=async(e,t,n)=>(C.debug(`custom-validator - update validator`),U.update(t,{where:{id:e},returning:!0,...n})),Mt=async(e,t)=>(C.debug(`custom-validator - disable validator`),jt(e,{disabled:!0},t)),Nt=y.object().unknown(!0),Pt=y.object({type:y.string().valid(`object`),properties:y.object({before:Nt,after:Nt}).required(),required:y.array().items(y.string()),allOf:y.array().items(y.object()),anyOf:y.array().items(y.object()),oneOf:y.array().items(y.object()),additionalProperties:y.alternatives().try(y.boolean(),y.object()),$id:y.string(),$schema:y.string(),if:y.object(),then:y.object(),else:y.object()});var Ft={create:y.object({entityId:y.string().uuid().required(),entityType:y.string().required(),schema:Pt.required()}),update:y.object({entityId:y.string().uuid(),entityType:y.string(),schema:Pt,disabled:y.boolean()}).min(1)};const It=new fe({allErrors:!0,strict:!1,strictTypes:!1,$data:!0});pe(It);const Lt={type:`object`,properties:{type:{type:`string`,enum:[`object`]},properties:{type:`object`,properties:{before:{type:`object`,properties:{type:{type:`string`,enum:[`object`]},properties:{type:`object`}}},after:{type:`object`,properties:{type:{type:`string`,enum:[`object`]},properties:{type:`object`}}}}},required:{type:`array`,items:{type:`string`}},if:{type:`object`},then:{type:`object`},else:{type:`object`}},required:[`type`,`properties`]},Rt=e=>{try{let t=It.compile(Lt);if(!t(e)){let n=t.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid schema structure`}`).join(`, `);throw C.error(`Invalid validator schema structure`,{errors:t.errors,schema:e}),new b([Error(`Invalid validator schema structure: ${n}`)],[`Invalid validator schema structure`])}try{return It.compile(e),!0}catch(t){throw C.error(`Failed to compile validator schema`,{error:t,schema:e}),new b([Error(`Failed to compile validator schema: ${t.message}`)],[`Invalid validator schema`])}}catch(t){throw t instanceof b?t:(C.error(`Error validating validator schema`,{error:t,schema:e}),new b([Error(`Error validating validator schema: ${t.message}`)],[`Invalid validator schema`]))}},q=de({logger:C}),J=`CustomValidator`;q.post(`/`,async(e,t)=>{let{modelName:n}=e.params;try{let r=await Ft.create.validateAsync(e.body);Rt(r.schema);let i=await kt({...r,modelType:n});return t.status(S.CREATED).json(i)}catch(e){return W(e,t,{logger:C,message:`Error in create ${J} request`})}}),q.get(`/`,async(e,t)=>{try{let{modelName:n}=e.params,{entityId:r,entityType:i}=e.query,a={modelType:n,...r&&{entityId:r},...i&&{entityType:i}},o=await K(a);return t.status(S.OK).json({validators:o})}catch(e){return W(e,t,{logger:C,message:`Error in get all ${J} request`})}}),q.get(`/:validatorId`,async(e,t)=>{try{let{validatorId:n,modelName:r}=e.params,i=await K({id:n,modelType:r},{withDisabled:!0});if(!i.length)throw new x(`Validator not found`);return t.status(S.OK).json(i[0])}catch(e){return W(e,t,{logger:C,message:`Error in get ${J} request`})}}),q.patch(`/:validatorId`,async(e,t)=>{try{let{validatorId:n}=e.params,r=await Ft.update.validateAsync(e.body);if(r.schema&&Rt(r.schema),!(await K({id:n},{withDisabled:!0})).length)throw new x(`Validator not found`);let[i,a]=await jt(n,r);if(!i)throw new x(`Validator not found`);return t.status(S.OK).json(a[0])}catch(e){return W(e,t,{logger:C,message:`Error in update ${J} request`})}}),q.delete(`/:validatorId`,async(e,t)=>{try{let{validatorId:n}=e.params;if(!(await K({id:n},{withDisabled:!0})).length)throw new x(`Validator not found`);let[r]=await Mt(n);if(!r)throw new x(`Validator failed to be disabled`);return t.status(S.NO_CONTENT).send()}catch(e){return W(e,t,{logger:C,message:`Error in delete ${J} request`})}});var zt=q;const Bt=de({logger:C});Bt.use(`/custom-field-definitions/:modelName`,Ot),Bt.use(`/custom-validators/:modelName`,zt);var Vt=Bt;const Ht=de({logger:C});Ht.use(`/v1`,Vt);var Ut=Ht,Wt=e=>{let t=process.env.NODE_ENV||`test`,n=e[t],r;return r=n.use_env_variable?new _(process.env[n.use_env_variable],n):new _(n.database,n.username,n.password,n),r};const Gt={[w.DATE]:e=>{if(e){let t=new Date(e);if(t.toString()===`Invalid Date`)throw Error(`Invalid date value: ${e}`);return t.toISOString()}return null}},Kt=async(e,t)=>{let{transaction:n}=t;return N.findAll({where:{modelId:e},transaction:n,raw:!0,nest:!0})},qt=async(e,t,n,r,i={})=>{let a=Object.keys(r);C.debug(`custom-fields: updating values for ${e} ${t}`,{names:a,optionsKeys:i?Object.keys(i):null,valuesToUpdate:r,identifiers:n});let{modelOptions:o,transaction:s}=i,c={modelType:e,name:a,...!i.modelOptions?.useEntityIdFromInclude&&{entityId:n}},l=await j(c,{withDisabled:!0,transaction:s,include:o.include?.(n)})??[],u=l.filter(e=>e.disabled);if(l.length!==a.length){C.warn(`custom-fields: missing definitions for ${e} ${t}`,{names:a,fieldDefinitions:l});let n=a.filter(e=>!l.some(t=>t.name===e));throw new Ne(n)}let d=u?.map(e=>e.name)||[],f=a.filter(e=>d.includes(e));f?.length>0&&C.warn(`custom-fields: trying to update disabled values: ${f.join(`, `)}`);let p=a.map(e=>{let n=l.find(t=>t.name===e),i=Gt[n.fieldType],a=i?i(r[e]):r[e];return{modelId:t,updatedAt:new Date,customFieldDefinitionId:n.id,value:a===void 0?n.defaultValue:a}});return Promise.all(p.map(async e=>{let[t]=await N.upsert(e,{transaction:i.transaction});return t}))},Jt=async(e,t={})=>{let{transaction:n}=t;return V.findOne({where:{modelId:e},transaction:n})},Yt=async(e,t={})=>{let{transaction:n}=t;return V.findAll({where:{modelId:e},transaction:n})},Xt=async(e,t,n,r,i={})=>{let a=Object.keys(n);C.debug(`custom-fields: updating entries for ${t} ${e}`,{customFieldsNames:a,optionsKeys:i?Object.keys(i):null,customFields:n,identifiers:r});let{modelOptions:o,transaction:s}=i,c={modelType:t,name:a,...!i.modelOptions?.useEntityIdFromInclude&&{entityId:r}},l=await j(c,{withDisabled:!0,transaction:s,include:o.include?.(r)})??[],u=l.filter(e=>e.disabled);if(l.length!==a.length){C.warn(`custom-fields: missing definitions for ${t} ${e}`,{names:a,fieldDefinitions:l});let n=a.filter(e=>!l.some(t=>t.name===e));throw new Ne(n)}let d=u?.map(e=>e.name)||[],f=a.filter(e=>d.includes(e));f?.length>0&&C.warn(`custom-fields: trying to update disabled values: ${f.join(`, `)}`);let p=Object.fromEntries(l.map(e=>[e.name,e]));return Object.entries(n).filter(([e])=>Gt[p[e].fieldType]).forEach(([e,t])=>{let{fieldType:r}=p[e];n[e]=Gt[r](t)}),V.upsert({modelId:e,entityId:l[0].entityId,modelType:t,customFields:n},i)},Zt=(e,t)=>e.map(e=>t[e]);var Qt=(e,t)=>{let n=Array.from(new Set(t));return Array.isArray(e)?e.flatMap(e=>Zt(n,e)):Zt(n,e)};const $t=[`id`,`name`,`entityId`,`fieldType`,`displayName`,`validation`,`entityType`,`modelType`,`required`,`disabled`,`defaultValue`],en=async({instancesIds:e,options:t,sadotOptions:n})=>{if(!n.useCustomFieldsEntries)return{};let r=await Yt(e,t??{}),i=Object.fromEntries(r.map(e=>{let{modelId:t,customFields:n}=e?.dataValues??{};if(t)return[t,n]}).filter(Boolean));return e.forEach(e=>{i[e]??={}}),i},tn=async({instancesIds:e,options:t,sadotOptions:n})=>n.useCustomFieldsEntries?{}:(await Kt(e,t??{})).reduce((e,t)=>{let{modelId:n}=t;return e[n]??=[],e[n].push(t),e},{}),nn=(e,t)=>e.reduce((e,n)=>({...e,...t[n.customFieldDefinitionId]&&{[t[n.customFieldDefinitionId].name]:n.value}}),{});var rn=(e,t,n,r={},i={useCustomFieldsEntries:!1})=>async(a,o)=>{if(o.originalAttributes?.length>0&&!o.originalAttributes?.includes?.(`customFields`))return;let s=Array.isArray(a)?a:[a];s=s.filter(Boolean);let c=Qt(s,t),l=[...new Set(c)].filter(Boolean),u=l.reduce((e,t)=>({...e,[t]:[]}),{}),d,f;o.transaction&&(o.transaction.definitionCache||=new Map,f=`${e}:${l.slice().sort().join(`,`)}`,d=o.transaction.definitionCache.get(f)),d||(d=Ke(e,l,{transaction:o.transaction,modelOptions:r,attributes:$t}),o.transaction?.definitionCache?.set(f,d));let p=await d;if(p.length===0){s.forEach(e=>{e.customFields={}});return}r?.include&&r.useEntityIdFromInclude&&r.include(c).forEach(({model:e})=>{p.forEach(t=>{let n=t[`${e.name}.entityId`];u[n]=[]})});let m=p.reduce((e,t)=>({...e,[t.id]:t}),{});p.forEach(e=>{u[e.entityId].push(e)});let ee=s.map(e=>e.id),[te,ne]=await Promise.all([tn({instancesIds:ee,options:o,sadotOptions:i}),en({instancesIds:ee,options:o,sadotOptions:i})]);s.forEach(e=>{let{id:r}=e,a=te[r],s=a?nn(a,m):{},c=i.useCustomFieldsEntries?ne[r]:s;t.forEach(t=>{let n=e[t],r=u[n];r?.length>0&&r.forEach(e=>{c[e.name]===void 0&&(c[e.name]=null)})}),e.customFields=c,o.attributesToRemove?.forEach?.(t=>{delete e.dataValues?.[t],delete e?.[t]}),n===`afterFind`&&e?.changed?.(`customFields`,!1)})};const an=(e,t)=>{let n=e.filter(e=>!t.includes(e));return t.includes?.(`id`)||n.push(`id`),n},on=e=>t=>{let{attributes:n}=t;if(n?.includes?.(`customFields`)){let r=an(e,n);C.debug(`sadot - before find hook`),r?.length>0&&(n.push(...r),t.attributesToRemove=r)}};var sn=async({modelId:e,modelType:t,identifiers:n,customFields:r,options:i={modelOptions:{},useCustomFieldsEntries:!1}})=>{if(await qt(t,e,n,r,{...i,modelOptions:i.modelOptions??{}}),!i?.useCustomFieldsEntries)return;let{dataValues:{customFields:a}}=await Jt(e,i)??{dataValues:{}},o={...a,...r};await Xt(e,t,o,n,{...i,modelOptions:i.modelOptions??{}})};const cn=[`id`,`schema`,`modelType`,`entityId`,`disabled`],ln=new fe({allErrors:!0,strict:!1,strictTypes:!1,$data:!0});pe(ln),he(ln);const un=(e,t)=>({__proto__:null,...e,...t}),dn=async(e,t)=>{if(!e.id||!e.customFields||Object.keys(e.customFields).length===0)return e.customFields||{};try{let n=await e.constructor.findOne({where:{id:e.id},attributes:[`customFields`],transaction:t.transaction,raw:!0});if(n?.customFields){let t=un(n.customFields,e.customFields);return C.debug(`sadot - fetched complete custom fields for validation`,{fieldsCount:Object.keys(t).length,updateFieldsCount:Object.keys(e.customFields).length}),t}}catch(e){C.error(`sadot - error fetching complete model for validation`,{error:e})}return e.customFields||{}},fn=e=>{let t={...e.dataValues};(e.changed?.()||[]).forEach(n=>{let r=e.previous?.(n);r!==void 0&&(t[n]=r)});let n=e.previous?.(`customFields`);return n!==void 0&&(t.customFields=n),t},pn=e=>e.reduce((e,t)=>{let n=(t.instancePath||``).split(`/`).filter(Boolean).join(`.`).replace(/^after\./,``),r=t.keyword===`required`?`.${t.params?.missingProperty}`:``,i=(n+r).replace(/^\./,``)||`root`;return e[i]=t.message||`Invalid value`,e},{}),mn=async(e,t,n,r={},i=!1)=>{let a=e.constructor.name;C.debug(`sadot - validating model`,{isCreate:i,modelType:a});let o=Qt(e,n);if(C.debug(`sadot - identifiers`,{identifiers:o}),!o||Object.keys(o).length===0){C.debug(`sadot - skipping validation: no identifiers`);return}let s=Object.values(o)[0];if(C.debug(`sadot - entityId`,{entityId:s}),!s){C.debug(`sadot - skipping validation: no entityId`);return}let c,l;t.transaction&&(t.transaction.validationsCache||=new Map,l=`${a}-${s}`,c=t.transaction.validationsCache.get(l)),c||(c=At(a,s,{transaction:t.transaction,attributes:cn,modelOptions:r}),t.transaction&&t?.transaction?.validationsCache.set(l,c));let u=await c;if(C.debug(`sadot - validators found`,{count:u.length}),!u.length){C.debug(`sadot - skipping validation: no validators found`);return}let d=null;i||(d=fn(e));let f=i?e.customFields||{}:await dn(e,t);for(let t of u){let{schema:n}=t,r=n;if(C.debug(`sadot - validating with schema`,{schema:n,hasAfterProps:!!r.properties?.after,hasBeforeProps:!!r.properties?.before}),i){if(r.properties?.after){let t=ln.compile({...n,properties:{after:r.properties.after}});if(!t(JSON.parse(JSON.stringify({after:{...e.dataValues,customFields:f}})))){let e=t.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid value`}`).join(`, `),n=pn(t.errors);throw new b([Error(`Validation failed for ${a}: ${e}`)],void 0,{customError:n})}}}else{let t=ln.compile(r),n=un(e.dataValues);n.customFields=f;let i={before:d,after:n},o=t(JSON.parse(JSON.stringify(i)));if(C.debug(`sadot - validation result`,{isValid:o,test:{before:d,after:n}}),!o){let e=t.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid value`}`).join(`, `),n=pn(t.errors);throw new b([Error(`Validation failed for ${a}: ${e}`)],void 0,{customError:n})}}}},hn=async({modelType:e,modelOptions:t,identifiers:n,options:r})=>{let{include:i,useEntityIdFromInclude:a}=t,o={modelType:e,disabled:!1,...!a&&{entityId:n}};return await j(o,{withDisabled:!1,transaction:r.transaction,include:i?.(n)})},gn=(e,t)=>{(e||[]).forEach(e=>{let{fieldType:n,name:r}=e;if([w.DATE,w.DATETIME].includes(n)){let e=t.customFields?.[r];if(e){let{value:n,error:i}=y.date().validate(e);if(i)throw new E(e,r,i);t.customFields[r]=n.toISOString()}}})},_n=(e,t={},n={useCustomFieldsEntries:!1})=>async(r,i)=>{C.debug(`sadot - before create hook`);let{fields:a}=i,o=r.constructor.name,s=Qt(r,e),c=await hn({modelType:o,modelOptions:t,identifiers:s,options:i}),l=c.filter(e=>![null,void 0].includes(e.defaultValue));l.length&&(r.customFields||={},l.filter(e=>r.customFields?.[e.name]===void 0).forEach(({name:e,defaultValue:t})=>{r.customFields[e]=t}));let u=Array.from(new Set(c.filter(({required:e})=>e).map(({name:e})=>e))),{customFields:d}=r,f=Object.keys(d??{}),p=u.filter(e=>!f.includes(e));if(p?.length)throw new Oe(p);await mn(r,i,e,t,!0),gn(c,r);let m=a.indexOf(`customFields`);m===-1||!d||!Object.keys(d).length||(await sn({modelId:r.id,modelType:o,identifiers:s,customFields:d,options:{useCustomFieldsEntries:n.useCustomFieldsEntries,transaction:i.transaction,modelOptions:t}}),a.splice(m,1))},vn=(e,t={},n={useCustomFieldsEntries:!1})=>async(r,i)=>{C.debug(`sadot - before update hook`);let{fields:a}=i,o=r.constructor.name,s=Qt(r,e),c=await hn({modelType:o,modelOptions:t,identifiers:s,options:i});await mn(r,i,e,t,!1),gn(c,r);let l=a.indexOf(`customFields`);if(l>-1){let{customFields:e}=r;if(!Object.keys(e).length)return;await sn({modelId:r.id,modelType:o,identifiers:s,customFields:e,options:{useCustomFieldsEntries:n.useCustomFieldsEntries,transaction:i.transaction,modelOptions:t}}),a.splice(l,1)}},yn=e=>{e.individualHooks=!0},bn=e=>{e.individualHooks=!0},xn=(e=5)=>Array.from({length:e},()=>`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`.charAt(le(52))).join(``),Sn=(e,n,r,i=[w.DATETIME,w.DATE])=>{let a=i.map(e=>`'${e}'`).join(`,`),o=`EXISTS ( SELECT 1 FROM "custom_field_values" AS "cv" INNER JOIN custom_field_definitions AS cd ON cd.entity_id = '${r}' AND cv.custom_field_definition_id = cd.id AND cd.model_type = '${n.name}' ${a?`AND cd.field_type NOT IN (${a})`:``} WHERE "cv"."deleted_at" IS NULL AND "cv"."model_id" = "${n.name}"."id" AND CAST("cv"."value" AS TEXT) ILIKE :searchTerm)`;return{where:{[t.or]:[_.where(_.literal(o),!0)]},replacements:{searchTerm:`%${e}%`}}};let Y=function(e){return e.VALUES=`values`,e.ENTRIES=`entries`,e}({});const Cn=e=>Array.isArray(e)&&typeof e[0]==`string`,X=e=>[`true`,`false`].includes(e.toString()),wn=e=>e instanceof Date||Object.prototype.toString.call(e)===`[object Date]`,Tn=(e,t)=>`to_jsonb(${e}::${t})`,Z=e=>Tn(e,`text`),En=e=>Tn(e,`boolean`),Dn=e=>Tn(e,`numeric`),On=(e,t)=>wn(t)?Tn(e,`timestamp`):e,Q=` AND `,kn=` OR `,$=`cv.value`,An=(e,t,n,r)=>{let i=`text`;wn(e)?i=`date`:Number.isNaN(Number(e))?X(e)&&(i=`boolean`):i=`numeric`;let a=r.get(e);return`(jsonb_extract_path_text(ce.custom_fields, :${n})::${i}) ${t} :${a}`},jn=e=>{let t=e;return X(e)?t=e===`true`:Number.isNaN(Number(e))||(t=Number(e)),t},Mn=(e,t)=>{let n=jn(e),r=JSON.stringify({[t]:n}),i;return X(e)&&(i=`ce.custom_fields @> '${JSON.stringify({[t]:e})}'`),`
|
|
2
|
+
`)}`}},Ne=class extends b{constructor(e){let t=Error(`Missing custom field definition for field ${e.join(`,`)}`);super([t],null,null),this.message=`MISSING_DEFINITION`}};const Pe=e=>Object.keys(Ce).includes(e),Fe=(e,t,n)=>{let r=Ce[t];return r(e,n)},Ie=(e,t,n=Fe)=>{let r=Object.entries(e.customFields).map(([e,r])=>{if(r===null)return null;let{validation:i,fieldType:a}=t[e],o=n(r,a,i);return o?.error?{joiValidationError:o.error,fieldDefinitionName:e,value:r}:null}).filter(e=>!!e);if(r?.length)throw new Me(e.modelId,r)};function D(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function O(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var Le,Re,ze,Be,Ve,He;let k=class extends h{static displayNameDefaultValue(e){if(e?.displayName||(e.displayName=e.name),![null,void 0].includes(e.defaultValue)){let t=Fe(e.defaultValue,e.fieldType,e.validation);if(t.error)throw new E(e.defaultValue,e.name,t.error)}}static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e)):T(e)}};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],k.prototype,`id`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],k.prototype,`name`,void 0),O([f({type:p.STRING}),D(`design:type`,String)],k.prototype,`displayName`,void 0),O([re(`SupportedType`,e=>{if(!Object.values(w).includes(e))throw new ke(`"${e}" is not a supported type.`)}),f({type:p.STRING,allowNull:!1}),D(`design:type`,typeof(Le=w!==void 0&&w)==`function`?Le:Object)],k.prototype,`fieldType`,void 0),O([f({type:p.JSONB}),D(`design:type`,Object)],k.prototype,`validation`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],k.prototype,`entityId`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],k.prototype,`entityType`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],k.prototype,`modelType`,void 0),O([f({type:p.TEXT}),D(`design:type`,String)],k.prototype,`description`,void 0),O([f({type:p.BOOLEAN,defaultValue:!1}),D(`design:type`,Boolean)],k.prototype,`required`,void 0),O([f({type:p.BOOLEAN,defaultValue:!1}),D(`design:type`,Boolean)],k.prototype,`disabled`,void 0),O([f({type:p.JSONB,allowNull:!0}),D(`design:type`,Object)],k.prototype,`defaultValue`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(Re=typeof Date<`u`&&Date)==`function`?Re:Object)],k.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(ze=typeof Date<`u`&&Date)==`function`?ze:Object)],k.prototype,`updatedAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(Be=typeof Date<`u`&&Date)==`function`?Be:Object)],k.prototype,`deletedAt`,void 0),O([f({type:p.BOOLEAN,defaultValue:!1,allowNull:!1}),D(`design:type`,Boolean)],k.prototype,`blockEditingFromUI`,void 0),O([ne(()=>N),D(`design:type`,Array)],k.prototype,`values`,void 0),O([c,D(`design:type`,Function),D(`design:paramtypes`,[typeof(Ve=k!==void 0&&k)==`function`?Ve:Object]),D(`design:returntype`,void 0)],k,`displayNameDefaultValue`,null),O([i,D(`design:type`,Function),D(`design:paramtypes`,[typeof(He=k!==void 0&&k)==`function`?He:Object,Object]),D(`design:returntype`,void 0)],k,`afterSaveHandler`,null),k=O([ee(()=>({where:{disabled:!1}})),v({tableName:`custom_field_definitions`,indexes:[{name:`unique_name_model_type`,fields:[`model_type`,`entity_id`,`name`],unique:!0}],timestamps:!0,validate:{validationByType(){if(!this.validation&&Se[this.fieldType])throw C.error(`No custom validation for custom field type ${this.fieldType} found`),new Ae(`Validation provided for "${this.fieldType}" is not supported`)}}})],k);var A=k;const Ue=e=>A.create(e),j=(e,t={withDisabled:!1})=>(t.withDisabled?A.unscoped():A).scope(`userScope`).findAll({where:e,transaction:t.transaction,raw:!0,include:t.include}),We=(e,n={withDisabled:!1})=>j({id:{[t.in]:e}},n),Ge=(e,t={withDisabled:!1})=>{let{withDisabled:n}=t;return n?A.unscoped().scope(`userScope`).findByPk(e):A.scope(`userScope`).findByPk(e)},Ke=async(e,n,r={})=>{let{include:i,useEntityIdFromInclude:a}=r.modelOptions,o={modelType:e,...!a&&{entityId:{[t.in]:n}}};return A.findAll({where:o,transaction:r.transaction,include:i?.(n),raw:!0})},qe=e=>A.scope(`userScope`).findOne({where:e}),Je=async(e,t)=>(await A.scope(`userScope`).update(t,{where:{id:e},returning:!0,individualHooks:!0}))[1][0],Ye=async(e,{findAll:n,modelOptions:r={},withDisabled:i=!1,...a}={withDisabled:!1,modelOptions:{}})=>{let{modelType:o}=e[0]?.dataValues??{},s=new Set,c=[],l=new Set;e.forEach(e=>{let{dataValues:{modelId:t,entityId:n,customFields:r}}=e;c.push(t),l.add(n),Object.keys(r??{}).forEach(e=>{s.add(e)})});let u={modelType:o,entityId:{[t.in]:Array.from(l)},name:{[t.in]:Array.from(s)}},d=await(n??j)(u,{withDisabled:i,modelOptions:r,...a}),f=d.filter(e=>s.has(e.name)),p=Object.fromEntries(f.map(e=>[e.name,e]));if(!d?.length||f.length!==s.size){let e=Array.from(s).filter(e=>!p[e]);throw new Ne(e)}return p};var Xe,Ze,Qe,$e,et,tt;let M=class extends h{static validateValueAgainstDefinition(e,t){let{validation:n,fieldType:r,name:i}=t;if(!Pe(r))throw new je(r);if(e.value===null)return;let a=Fe(e.value,r,n);if(a.error)throw new E(e.value,i,a.error)}static async validateCustomFieldValues(e){let t=e.map(e=>e.customFieldDefinitionId),n=[...new Set(t)],r=await We(n,{withDisabled:!0});if(!r||r.length!==n.length)throw Error(`Definitions not found`);e.forEach(e=>{let t=r.find(t=>t.id===e.customFieldDefinitionId);t&&this.validateValueAgainstDefinition(e,t)})}static async validateCustomFieldValue(e){let{customFieldDefinitionId:t}=e,n=await Ge(t,{withDisabled:!0});this.validateValueAgainstDefinition(e,n)}static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e[0])):T(e[0])}};O([g,f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],M.prototype,`modelId`,void 0),O([g,te(()=>A),f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],M.prototype,`customFieldDefinitionId`,void 0),O([f({type:p.JSONB,allowNull:!0}),D(`design:type`,Object)],M.prototype,`value`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(Xe=typeof Date<`u`&&Date)==`function`?Xe:Object)],M.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(Ze=typeof Date<`u`&&Date)==`function`?Ze:Object)],M.prototype,`updatedAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(Qe=typeof Date<`u`&&Date)==`function`?Qe:Object)],M.prototype,`deletedAt`,void 0),O([d(()=>A,{scope:{disabled:!1}}),D(`design:type`,typeof($e=A!==void 0&&A)==`function`?$e:Object)],M.prototype,`customFieldDefinition`,void 0),O([o,s,D(`design:type`,Function),D(`design:paramtypes`,[Array]),D(`design:returntype`,Promise)],M,`validateCustomFieldValues`,null),O([l,c,u,D(`design:type`,Function),D(`design:paramtypes`,[typeof(et=M!==void 0&&M)==`function`?et:Object]),D(`design:returntype`,Promise)],M,`validateCustomFieldValue`,null),O([a,D(`design:type`,Function),D(`design:paramtypes`,[typeof(tt=M!==void 0&&M)==`function`?tt:Object,Object]),D(`design:returntype`,void 0)],M,`afterSaveHandler`,null),M=O([v({tableName:`custom_field_values`,timestamps:!0})],M);var N=M,nt;let P=class extends h{};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],P.prototype,`id`,void 0),O([te(()=>I),f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],P.prototype,`testModelId`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],P.prototype,`fleetId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],P.prototype,`businessModelId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],P.prototype,`demandSourceId`,void 0),O([f({type:p.BOOLEAN}),D(`design:type`,Boolean)],P.prototype,`anotherAttribute`,void 0),O([d(()=>I),D(`design:type`,typeof(nt=I!==void 0&&I)==`function`?nt:Object)],P.prototype,`testModel`,void 0),P=O([v({schema:`custom-fields`,tableName:`associated_test_models`,createdAt:!1,updatedAt:!1})],P);var rt=P;let F=class extends h{};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],F.prototype,`id`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],F.prototype,`fleetId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],F.prototype,`businessModelId`,void 0),O([f({type:p.UUID,allowNull:!0}),D(`design:type`,String)],F.prototype,`demandSourceId`,void 0),O([f({type:p.BOOLEAN}),D(`design:type`,Boolean)],F.prototype,`coolAttribute`,void 0),O([ne(()=>rt),D(`design:type`,Array)],F.prototype,`associatedModels`,void 0),O([f({type:p.VIRTUAL}),D(`design:type`,Object)],F.prototype,`customFields`,void 0),F=O([v({schema:`custom-fields`,tableName:`test_models`,createdAt:!1,updatedAt:!1})],F);var I=F,it=function(e){return e.BUSINESS_MODEL=`businessModel`,e.CONTEXT=`context`,e.DEMAND_SOURCE=`demandSource`,e.FLEET=`fleet`,e}(it||{});let L=class extends h{};O([g,f({defaultValue:p.UUIDV4,type:p.UUID}),D(`design:type`,String)],L.prototype,`id`,void 0),O([f({type:p.UUID}),D(`design:type`,String)],L.prototype,`entityId`,void 0),O([f({type:p.ENUM(...Object.values(it))}),D(`design:type`,String)],L.prototype,`entityType`,void 0),L=O([v({createdAt:!1,updatedAt:!1})],L);var R=L,at;let z=class extends h{};O([g,f({type:p.UUID,defaultValue:p.UUIDV4,allowNull:!1}),D(`design:type`,String)],z.prototype,`id`,void 0),O([te(()=>R),f({type:p.UUID}),D(`design:type`,String)],z.prototype,`contextId`,void 0),O([f({type:p.BOOLEAN}),D(`design:type`,Boolean)],z.prototype,`coolAttribute`,void 0),O([f({type:p.VIRTUAL}),D(`design:type`,Object)],z.prototype,`customFields`,void 0),O([d(()=>R),D(`design:type`,typeof(at=R!==void 0&&R)==`function`?at:Object)],z.prototype,`context`,void 0),z=O([v({createdAt:!1,updatedAt:!1})],z);var ot=z,st,ct,lt,ut;let B=class extends h{static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e[0])):T(e[0])}};O([g,f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],B.prototype,`modelId`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],B.prototype,`entityId`,void 0),O([f({type:p.JSONB,allowNull:!1,defaultValue:{}}),D(`design:type`,typeof(st=typeof Record<`u`&&Record)==`function`?st:Object)],B.prototype,`customFields`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],B.prototype,`modelType`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(ct=typeof Date<`u`&&Date)==`function`?ct:Object)],B.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(lt=typeof Date<`u`&&Date)==`function`?lt:Object)],B.prototype,`updatedAt`,void 0),O([a,D(`design:type`,Function),D(`design:paramtypes`,[typeof(ut=B!==void 0&&B)==`function`?ut:Object,Object]),D(`design:returntype`,void 0)],B,`afterSaveHandler`,null),B=O([v({tableName:`custom_field_entries`,timestamps:!0,indexes:[{name:`idx_cfe_custom_fields`,using:`gin`,operator:`jsonb_path_ops`,fields:[`custom_fields`]}],validate:{async validationByType(){if(!Object.keys(this.customFields??{}).length)return;let e=await Ye([this]);Ie(this,e)}}})],B);var V=B,dt,ft,pt;let H=class extends h{static afterSaveHandler(e,t){t.transaction?t.transaction.afterCommit(()=>T(e)):T(e)}};O([g,m(()=>ue()),f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],H.prototype,`id`,void 0),O([f({type:p.UUID,allowNull:!1}),D(`design:type`,String)],H.prototype,`entityId`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],H.prototype,`entityType`,void 0),O([f({type:p.STRING,allowNull:!1}),D(`design:type`,String)],H.prototype,`modelType`,void 0),O([f({type:p.JSONB,allowNull:!1}),D(`design:type`,Object)],H.prototype,`schema`,void 0),O([f({type:p.BOOLEAN,allowNull:!1,defaultValue:!1}),D(`design:type`,Boolean)],H.prototype,`disabled`,void 0),O([f({type:p.DATE,allowNull:!1}),D(`design:type`,typeof(dt=typeof Date<`u`&&Date)==`function`?dt:Object)],H.prototype,`createdAt`,void 0),O([f({type:p.DATE,allowNull:!0}),D(`design:type`,typeof(ft=typeof Date<`u`&&Date)==`function`?ft:Object)],H.prototype,`updatedAt`,void 0),O([a,D(`design:type`,Function),D(`design:paramtypes`,[typeof(pt=H!==void 0&&H)==`function`?pt:Object,Object]),D(`design:returntype`,void 0)],H,`afterSaveHandler`,null),H=O([ee(()=>({where:{disabled:!1}})),v({tableName:`custom_validators`,timestamps:!0})],H);var U=H;const mt=[A,N,U],ht=[I,rt,ot,R],gt=async(n,r,{schemaPrefix:i=`sadot-migration`,schemaVersion:a=`49c9dd1d-b1cc-445b-a911-fd349d783110`,useCustomFieldsEntries:o=!1}={})=>{let s=`${i}_${a}${o?`_withEntries`:``}`;if(C.info(`custom-fields: initialize custom-fields tables`),!n.addModels)throw Error(`sequelize instance must have addModels function`);o&&mt.push(V),n.addModels(mt),A.addScope(`userScope`,()=>{let e=r();return e?.permissions?{where:{entityId:[...Object.keys(e.permissions.fleets),...Object.keys(e.permissions.businessModels),...Object.keys(e.permissions.demandSources)]}}:{}}),U.addScope(`userScope`,()=>{let e=r();return e?.permissions?{where:{entityId:[...Object.keys(e.permissions.fleets),...Object.keys(e.permissions.businessModels),...Object.keys(e.permissions.demandSources)]}}:{}}),C.info(`custom-fields: models added`);let c=n.define(`SequelizeMeta`,{name:{type:e.STRING,allowNull:!1,unique:!0,primaryKey:!0,autoIncrement:!1}},{tableName:`SequelizeMeta`,timestamps:!1,schema:`public`});C.info(`custom-fields: starting migrations`);let l=await c.findAll({where:{name:{[t.like]:`${i}%`}},raw:!0}),u=l.at(-1),d=l.findIndex(e=>e.name===s);if(C.info(`custom-fields: migrations`,{migrations:l,currentSadotSchemaVersion:u,expectedSchemaVersionIndex:d}),(!u||u.name!==s)&&(C.info(`custom-fields: syncing models`),await A.sync({alter:!0}),await N.sync({alter:!0}),o&&await V.sync({alter:!0}),await U.sync({alter:!0}),d===-1&&await c.create({name:s}),C.info(`custom-fields: models synced`),l.length&&d!==-1&&d<l.length-1)){let e=l.slice(d+1);await c.destroy({where:{name:{[t.in]:e.map(e=>e.name)}}})}},_t=async e=>{if(C.info(`custom-fields: initialize custom-fields test models`),!e.addModels)throw Error(`sequelize instance must have addModels function`);e.addModels(ht),await e.dropSchema(`custom-fields`,{logging:!1}),await e.createSchema(`custom-fields`,{logging:!1}),C.info(`custom-fields: test models added`),await I.sync({alter:!0}),await rt.sync({alter:!0}),await R.sync({alter:!0}),await ot.sync({alter:!0}),C.info(`custom-fields: test models synced`)};var W=(e,t,r=void 0)=>{let i=e;return[ae,n].some(t=>e instanceof t)&&(i=new b([e],null)),ce(i,t,r)};const vt=y.object({name:y.string().required(),type:y.string(),size:y.string(),addedBy:y.string().uuid()}),yt=y.object({value:y.string().required(),color:y.string().required()}),bt=y.when(`fieldType`,{is:w.SELECT,then:y.array().required().items(y.string()).min(1).unique(),otherwise:y.when(`fieldType`,{is:w.STATUS,then:y.array().required().items(yt).min(1).unique(`value`),otherwise:y.forbidden()})}),xt=y.when(`fieldType`,{switch:[{is:w.BOOLEAN,then:y.boolean().allow(null)},{is:w.DATE,then:y.date().allow(null)},{is:w.DATETIME,then:y.date().allow(null)},{is:w.FILE,then:y.array().items(vt).allow(null)},{is:w.IMAGE,then:y.array().items(y.string().uri()).allow(null)},{is:w.NUMBER,then:y.number().allow(null)},{is:w.SELECT,then:y.string().allow(null)},{is:w.STATUS,then:y.string().allow(null)},{is:w.TEXT,then:y.string().allow(null)}]}),St=y.object({name:y.string().required(),displayName:y.string().required(),validation:bt,defaultValue:xt,fieldType:y.string().valid(...Object.values(w)).required(),entityId:y.string().guid().required(),entityType:y.string().required(),description:y.string(),required:y.boolean(),disabled:y.boolean(),blockEditingFromUI:y.boolean()}).oxor(`required`,`blockEditingFromUI`,{isPresent:e=>e===!0}),Ct=y.object({displayName:y.string(),validation:bt,defaultValue:xt,fieldType:y.string().valid(...Object.values(w)),description:y.string().allow(null),required:y.boolean(),disabled:y.boolean(),blockEditingFromUI:y.boolean()}).oxor(`required`,`blockEditingFromUI`,{isPresent:e=>e===!0}),wt=e=>St.validateAsync(e,{abortEarly:!1}),Tt=e=>Ct.validateAsync(e,{abortEarly:!1}),G=de({logger:C}),Et=`CustomFieldDefinition`,Dt=e=>e.replace(/(^\w|-\w)/g,e=>e.replace(/-/,``).toUpperCase());G.post(`/`,async(e,t)=>{let{modelName:n}=e.params,r=Dt(n);try{let n=await wt(e.body),i=await Ue({...n,modelType:r});return t.status(201).json(i)}catch(e){return C.error(`Failed to create custom field definition`,e),W(e,t,{logger:C,message:`Error in create ${Et} request`})}}),G.get(`/:customFieldDefinitionId`,async(e,t)=>{let{customFieldDefinitionId:n}=e.params;try{let e=await Ge(n);if(!e)throw new x;return t.json(e)}catch(e){return C.error(`Failed to fetch custom field definition`,e),W(e,t,{logger:C,message:`Error in get ${Et} request`})}}),G.get(`/`,async(e,t)=>{let{params:{modelName:n},query:{entityIds:r}}=e,i=Dt(n);try{let e={modelType:i,...r?.length>0&&{entityId:r}},n=await j(e,{withDisabled:!0});return t.json(n)}catch(e){return C.error(`Failed to fetch custom field definitions`,e),W(e,t,{logger:C,message:`Error in get all ${Et} request`})}}),G.patch(`/:customFieldDefinitionId`,async(e,t)=>{let{customFieldDefinitionId:n,modelName:r}=e.params,i=Dt(r);try{let r=await Tt(e.body);if(!await qe({id:n,modelType:i}))throw new x;let a=await Je(n,{...r,modelType:i});return t.status(200).json(a)}catch(e){return C.error(`Failed to patch custom field definition`,e),W(e,t,{logger:C,message:`Error in update ${Et} request`})}});var Ot=G;const kt=async(e,t={})=>(C.debug(`custom-validator - create validator`),await U.create(e,t)),K=async(e={},t={})=>{C.debug(`custom-validator - find all validators`);let{transaction:n,withDisabled:r,include:i,attributes:a,raw:o}=t,s;return s=r?await U.unscoped().scope(`userScope`).findAll({where:e,transaction:n,include:i,attributes:a,raw:o}):await U.scope([`defaultScope`,`userScope`]).findAll({where:e,transaction:n,include:i,attributes:a,raw:o}),s},At=async(e,t,n={})=>(C.debug(`custom-validator - find all validators by model type`),K({modelType:e,...!n?.modelOptions?.useEntityIdFromInclude&&{entityId:t}},{...n,include:n?.modelOptions?.include?.(t)})),jt=async(e,t,n)=>(C.debug(`custom-validator - update validator`),U.update(t,{where:{id:e},returning:!0,...n})),Mt=async(e,t)=>(C.debug(`custom-validator - disable validator`),jt(e,{disabled:!0},t)),Nt=y.object().unknown(!0),Pt=y.object({type:y.string().valid(`object`),properties:y.object({before:Nt,after:Nt}).required(),required:y.array().items(y.string()),allOf:y.array().items(y.object()),anyOf:y.array().items(y.object()),oneOf:y.array().items(y.object()),additionalProperties:y.alternatives().try(y.boolean(),y.object()),$id:y.string(),$schema:y.string(),if:y.object(),then:y.object(),else:y.object()});var Ft={create:y.object({entityId:y.string().uuid().required(),entityType:y.string().required(),schema:Pt.required()}),update:y.object({entityId:y.string().uuid(),entityType:y.string(),schema:Pt,disabled:y.boolean()}).min(1)};const It=new fe({allErrors:!0,strict:!1,strictTypes:!1,$data:!0});pe(It);const Lt={type:`object`,properties:{type:{type:`string`,enum:[`object`]},properties:{type:`object`,properties:{before:{type:`object`,properties:{type:{type:`string`,enum:[`object`]},properties:{type:`object`}}},after:{type:`object`,properties:{type:{type:`string`,enum:[`object`]},properties:{type:`object`}}}}},required:{type:`array`,items:{type:`string`}},if:{type:`object`},then:{type:`object`},else:{type:`object`}},required:[`type`,`properties`]},Rt=e=>{try{let t=It.compile(Lt);if(!t(e)){let n=t.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid schema structure`}`).join(`, `);throw C.error(`Invalid validator schema structure`,{errors:t.errors,schema:e}),new b([Error(`Invalid validator schema structure: ${n}`)],[`Invalid validator schema structure`])}try{return It.compile(e),!0}catch(t){throw C.error(`Failed to compile validator schema`,{error:t,schema:e}),new b([Error(`Failed to compile validator schema: ${t.message}`)],[`Invalid validator schema`])}}catch(t){throw t instanceof b?t:(C.error(`Error validating validator schema`,{error:t,schema:e}),new b([Error(`Error validating validator schema: ${t.message}`)],[`Invalid validator schema`]))}},q=de({logger:C}),J=`CustomValidator`;q.post(`/`,async(e,t)=>{let{modelName:n}=e.params;try{let r=await Ft.create.validateAsync(e.body);Rt(r.schema);let i=await kt({...r,modelType:n});return t.status(S.CREATED).json(i)}catch(e){return W(e,t,{logger:C,message:`Error in create ${J} request`})}}),q.get(`/`,async(e,t)=>{try{let{modelName:n}=e.params,{entityId:r,entityType:i}=e.query,a={modelType:n,...r&&{entityId:r},...i&&{entityType:i}},o=await K(a);return t.status(S.OK).json({validators:o})}catch(e){return W(e,t,{logger:C,message:`Error in get all ${J} request`})}}),q.get(`/:validatorId`,async(e,t)=>{try{let{validatorId:n,modelName:r}=e.params,i=await K({id:n,modelType:r},{withDisabled:!0});if(!i.length)throw new x(`Validator not found`);return t.status(S.OK).json(i[0])}catch(e){return W(e,t,{logger:C,message:`Error in get ${J} request`})}}),q.patch(`/:validatorId`,async(e,t)=>{try{let{validatorId:n}=e.params,r=await Ft.update.validateAsync(e.body);if(r.schema&&Rt(r.schema),!(await K({id:n},{withDisabled:!0})).length)throw new x(`Validator not found`);let[i,a]=await jt(n,r);if(!i)throw new x(`Validator not found`);return t.status(S.OK).json(a[0])}catch(e){return W(e,t,{logger:C,message:`Error in update ${J} request`})}}),q.delete(`/:validatorId`,async(e,t)=>{try{let{validatorId:n}=e.params;if(!(await K({id:n},{withDisabled:!0})).length)throw new x(`Validator not found`);let[r]=await Mt(n);if(!r)throw new x(`Validator failed to be disabled`);return t.status(S.NO_CONTENT).send()}catch(e){return W(e,t,{logger:C,message:`Error in delete ${J} request`})}});var zt=q;const Bt=de({logger:C});Bt.use(`/custom-field-definitions/:modelName`,Ot),Bt.use(`/custom-validators/:modelName`,zt);var Vt=Bt;const Ht=de({logger:C});Ht.use(`/v1`,Vt);var Ut=Ht,Wt=e=>{let t=process.env.NODE_ENV||`test`,n=e[t],r;return r=n.use_env_variable?new _(process.env[n.use_env_variable],n):new _(n.database,n.username,n.password,n),r};const Gt={[w.DATE]:e=>{if(e){let t=new Date(e);if(t.toString()===`Invalid Date`)throw Error(`Invalid date value: ${e}`);return t.toISOString()}return null}},Kt=async(e,t)=>{let{transaction:n}=t;return N.findAll({where:{modelId:e},transaction:n,raw:!0,nest:!0})},qt=async(e,t,n,r,i={})=>{let a=Object.keys(r);C.debug(`custom-fields: updating values for ${e} ${t}`,{names:a,optionsKeys:i?Object.keys(i):null,valuesToUpdate:r,identifiers:n});let{modelOptions:o,transaction:s}=i,c={modelType:e,name:a,...!i.modelOptions?.useEntityIdFromInclude&&{entityId:n}},l=await j(c,{withDisabled:!0,transaction:s,include:o.include?.(n)})??[],u=l.filter(e=>e.disabled);if(l.length!==a.length){C.warn(`custom-fields: missing definitions for ${e} ${t}`,{names:a,fieldDefinitions:l});let n=a.filter(e=>!l.some(t=>t.name===e));throw new Ne(n)}let d=u?.map(e=>e.name)||[],f=a.filter(e=>d.includes(e));f?.length>0&&C.warn(`custom-fields: trying to update disabled values: ${f.join(`, `)}`);let p=a.map(e=>{let n=l.find(t=>t.name===e),i=Gt[n.fieldType],a=i?i(r[e]):r[e];return{modelId:t,updatedAt:new Date,customFieldDefinitionId:n.id,value:a===void 0?n.defaultValue:a}});return Promise.all(p.map(async e=>{let[t]=await N.upsert(e,{transaction:i.transaction});return t}))},Jt=async(e,t={})=>{let{transaction:n}=t;return V.findOne({where:{modelId:e},transaction:n})},Yt=async(e,t={})=>{let{transaction:n}=t;return V.findAll({where:{modelId:e},transaction:n})},Xt=async(e,t,n,r,i={})=>{let a=Object.keys(n);C.debug(`custom-fields: updating entries for ${t} ${e}`,{customFieldsNames:a,optionsKeys:i?Object.keys(i):null,customFields:n,identifiers:r});let{modelOptions:o,transaction:s}=i,c={modelType:t,name:a,...!i.modelOptions?.useEntityIdFromInclude&&{entityId:r}},l=await j(c,{withDisabled:!0,transaction:s,include:o.include?.(r)})??[],u=l.filter(e=>e.disabled);if(l.length!==a.length){C.warn(`custom-fields: missing definitions for ${t} ${e}`,{names:a,fieldDefinitions:l});let n=a.filter(e=>!l.some(t=>t.name===e));throw new Ne(n)}let d=u?.map(e=>e.name)||[],f=a.filter(e=>d.includes(e));f?.length>0&&C.warn(`custom-fields: trying to update disabled values: ${f.join(`, `)}`);let p=Object.fromEntries(l.map(e=>[e.name,e]));return Object.entries(n).filter(([e])=>Gt[p[e].fieldType]).forEach(([e,t])=>{let{fieldType:r}=p[e];n[e]=Gt[r](t)}),V.upsert({modelId:e,entityId:l[0].entityId,modelType:t,customFields:n},i)},Zt=(e,t)=>e.map(e=>t[e]);var Qt=(e,t)=>{let n=Array.from(new Set(t));return Array.isArray(e)?e.flatMap(e=>Zt(n,e)):Zt(n,e)};const $t=[`id`,`name`,`entityId`,`fieldType`,`displayName`,`validation`,`entityType`,`modelType`,`required`,`disabled`,`defaultValue`],en=async({instancesIds:e,options:t,sadotOptions:n})=>{if(!n.useCustomFieldsEntries)return{};let r=await Yt(e,t??{}),i=Object.fromEntries(r.map(e=>{let{modelId:t,customFields:n}=e?.dataValues??{};if(t)return[t,n]}).filter(Boolean));return e.forEach(e=>{i[e]??={}}),i},tn=async({instancesIds:e,options:t,sadotOptions:n})=>n.useCustomFieldsEntries?{}:(await Kt(e,t??{})).reduce((e,t)=>{let{modelId:n}=t;return e[n]??=[],e[n].push(t),e},{}),nn=(e,t)=>e.reduce((e,n)=>({...e,...t[n.customFieldDefinitionId]&&{[t[n.customFieldDefinitionId].name]:n.value}}),{});var rn=(e,t,n,r={},i={useCustomFieldsEntries:!1})=>async(a,o)=>{if(o.originalAttributes?.length>0&&!o.originalAttributes?.includes?.(`customFields`))return;let s=Array.isArray(a)?a:[a];s=s.filter(Boolean);let c=Qt(s,t),l=[...new Set(c)].filter(Boolean),u=l.reduce((e,t)=>({...e,[t]:[]}),{}),d,f;o.transaction&&(o.transaction.definitionCache||=new Map,f=`${e}:${l.slice().sort().join(`,`)}`,d=o.transaction.definitionCache.get(f)),d||(d=Ke(e,l,{transaction:o.transaction,modelOptions:r,attributes:$t}),o.transaction?.definitionCache?.set(f,d));let p=await d;if(p.length===0){s.forEach(e=>{e.customFields={}});return}r?.include&&r.useEntityIdFromInclude&&r.include(c).forEach(({model:e})=>{p.forEach(t=>{let n=t[`${e.name}.entityId`];u[n]=[]})});let m=p.reduce((e,t)=>({...e,[t.id]:t}),{});p.forEach(e=>{u[e.entityId].push(e)});let ee=s.map(e=>e.id),[te,ne]=await Promise.all([tn({instancesIds:ee,options:o,sadotOptions:i}),en({instancesIds:ee,options:o,sadotOptions:i})]);s.forEach(e=>{let{id:r}=e,a=te[r],s=a?nn(a,m):{},c=i.useCustomFieldsEntries?ne[r]:s;t.forEach(t=>{let n=e[t],r=u[n];r?.length>0&&r.forEach(e=>{c[e.name]===void 0&&(c[e.name]=null)})}),e.customFields=c,o.attributesToRemove?.forEach?.(t=>{delete e.dataValues?.[t],delete e?.[t]}),n===`afterFind`&&e?.changed?.(`customFields`,!1)})};const an=(e,t)=>{let n=e.filter(e=>!t.includes(e));return t.includes?.(`id`)||n.push(`id`),n},on=e=>t=>{let{attributes:n}=t;if(n?.includes?.(`customFields`)){let r=an(e,n);C.debug(`sadot - before find hook`),r?.length>0&&(n.push(...r),t.attributesToRemove=r)}};var sn=async({modelId:e,modelType:t,identifiers:n,customFields:r,options:i={modelOptions:{},useCustomFieldsEntries:!1}})=>{if(await qt(t,e,n,r,{...i,modelOptions:i.modelOptions??{}}),!i?.useCustomFieldsEntries)return;let{dataValues:{customFields:a}}=await Jt(e,i)??{dataValues:{}},o={...a,...r};await Xt(e,t,o,n,{...i,modelOptions:i.modelOptions??{}})};const cn=[`id`,`schema`,`modelType`,`entityId`,`disabled`],ln=new fe({allErrors:!0,strict:!1,strictTypes:!1,$data:!0});pe(ln),he(ln);const un=(e,t)=>({__proto__:null,...e,...t}),dn=async(e,t)=>{if(!e.id||!e.customFields||Object.keys(e.customFields).length===0)return e.customFields||{};try{let n=await e.constructor.findOne({where:{id:e.id},attributes:[`customFields`],transaction:t.transaction,raw:!0});if(n?.customFields){let t=un(n.customFields,e.customFields);return C.debug(`sadot - fetched complete custom fields for validation`,{fieldsCount:Object.keys(t).length,updateFieldsCount:Object.keys(e.customFields).length}),t}}catch(e){C.error(`sadot - error fetching complete model for validation`,{error:e})}return e.customFields||{}},fn=e=>{let t={...e.dataValues};(e.changed?.()||[]).forEach(n=>{let r=e.previous?.(n);r!==void 0&&(t[n]=r)});let n=e.previous?.(`customFields`);return n!==void 0&&(t.customFields=n),t},pn=e=>e.reduce((e,t)=>{let n=(t.instancePath||``).split(`/`).filter(Boolean).join(`.`).replace(/^after\./,``),r=t.keyword===`required`?`.${t.params?.missingProperty}`:``,i=(n+r).replace(/^\./,``)||`root`;return e[i]=t.message||`Invalid value`,e},{}),mn=async(e,t,n,r={},i=!1)=>{let a=e.constructor.name;C.debug(`sadot - validating model`,{isCreate:i,modelType:a});let o=Qt(e,n);if(C.debug(`sadot - identifiers`,{identifiers:o}),!o||Object.keys(o).length===0){C.debug(`sadot - skipping validation: no identifiers`);return}let s=Object.values(o)[0];if(C.debug(`sadot - entityId`,{entityId:s}),!s){C.debug(`sadot - skipping validation: no entityId`);return}let c,l;t.transaction&&(t.transaction.validationsCache||=new Map,l=`${a}-${s}`,c=t.transaction.validationsCache.get(l)),c||(c=At(a,s,{transaction:t.transaction,attributes:cn,modelOptions:r}),t.transaction&&t?.transaction?.validationsCache.set(l,c));let u=await c;if(C.debug(`sadot - validators found`,{count:u.length}),!u.length){C.debug(`sadot - skipping validation: no validators found`);return}let d=null;i||(d=fn(e));let f=i?e.customFields||{}:await dn(e,t);for(let t of u){let{schema:n}=t,r=n;if(C.debug(`sadot - validating with schema`,{schema:n,hasAfterProps:!!r.properties?.after,hasBeforeProps:!!r.properties?.before}),i){if(r.properties?.after){let t=ln.compile({...n,properties:{after:r.properties.after}});if(!t(JSON.parse(JSON.stringify({after:{...e.dataValues,customFields:f}})))){let e=t.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid value`}`).join(`, `),n=pn(t.errors);throw new b([Error(`Validation failed for ${a}: ${e}`)],void 0,{customError:n})}}}else{let t=ln.compile(r),n=un(e.dataValues);n.customFields=f;let i={before:d,after:n},o=t(JSON.parse(JSON.stringify(i)));if(C.debug(`sadot - validation result`,{isValid:o,test:{before:d,after:n}}),!o){let e=t.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid value`}`).join(`, `),n=pn(t.errors);throw new b([Error(`Validation failed for ${a}: ${e}`)],void 0,{customError:n})}}}},hn=async({modelType:e,modelOptions:t,identifiers:n,options:r})=>{let{include:i,useEntityIdFromInclude:a}=t,o={modelType:e,disabled:!1,...!a&&{entityId:n}};return await j(o,{withDisabled:!1,transaction:r.transaction,include:i?.(n)})},gn=(e,t)=>{(e||[]).forEach(e=>{let{fieldType:n,name:r}=e;if([w.DATE,w.DATETIME].includes(n)){let e=t.customFields?.[r];if(e){let{value:n,error:i}=y.date().validate(e);if(i)throw new E(e,r,i);t.customFields[r]=n.toISOString()}}})},_n=(e,t={},n={useCustomFieldsEntries:!1})=>async(r,i)=>{C.debug(`sadot - before create hook`);let{fields:a}=i,o=r.constructor.name,s=Qt(r,e),c=await hn({modelType:o,modelOptions:t,identifiers:s,options:i}),l=c.filter(e=>![null,void 0].includes(e.defaultValue));l.length&&(r.customFields||={},l.filter(e=>r.customFields?.[e.name]===void 0).forEach(({name:e,defaultValue:t})=>{r.customFields[e]=t}));let u=Array.from(new Set(c.filter(({required:e})=>e).map(({name:e})=>e))),{customFields:d}=r,f=Object.keys(d??{}),p=u.filter(e=>!f.includes(e));if(p?.length)throw new Oe(p);await mn(r,i,e,t,!0),gn(c,r);let m=a.indexOf(`customFields`);m===-1||!d||!Object.keys(d).length||(await sn({modelId:r.id,modelType:o,identifiers:s,customFields:d,options:{useCustomFieldsEntries:n.useCustomFieldsEntries,transaction:i.transaction,modelOptions:t}}),a.splice(m,1))},vn=(e,t={},n={useCustomFieldsEntries:!1})=>async(r,i)=>{C.debug(`sadot - before update hook`);let{fields:a}=i,o=r.constructor.name,s=Qt(r,e),c=await hn({modelType:o,modelOptions:t,identifiers:s,options:i});await mn(r,i,e,t,!1),gn(c,r);let l=a.indexOf(`customFields`);if(l>-1){let{customFields:e}=r;if(!Object.keys(e).length)return;await sn({modelId:r.id,modelType:o,identifiers:s,customFields:e,options:{useCustomFieldsEntries:n.useCustomFieldsEntries,transaction:i.transaction,modelOptions:t}}),a.splice(l,1)}},yn=e=>{e.individualHooks=!0},bn=e=>{e.individualHooks=!0},xn=(e=5)=>Array.from({length:e},()=>`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`.charAt(le(52))).join(``),Sn=(e,n,r,i=[w.DATETIME,w.DATE])=>{let a=i.map(e=>`'${e}'`).join(`,`),o=`EXISTS ( SELECT 1 FROM "custom_field_values" AS "cv" INNER JOIN custom_field_definitions AS cd ON cd.entity_id = '${r}' AND cv.custom_field_definition_id = cd.id AND cd.model_type = '${n.name}' ${a?`AND cd.field_type NOT IN (${a})`:``} WHERE "cv"."deleted_at" IS NULL AND "cv"."model_id" = "${n.name}"."id" AND CAST("cv"."value" AS TEXT) ILIKE :searchTerm)`;return{where:{[t.or]:[_.where(_.literal(o),!0)]},replacements:{searchTerm:`%${e}%`}}};let Y=function(e){return e.VALUES=`values`,e.ENTRIES=`entries`,e}({});const Cn=e=>Array.isArray(e)&&typeof e[0]==`string`,X=e=>[`true`,`false`].includes(e.toString()),wn=e=>e instanceof Date||Object.prototype.toString.call(e)===`[object Date]`,Tn=(e,t)=>`to_jsonb(${e}::${t})`,Z=e=>Tn(e,`text`),En=e=>Tn(e,`boolean`),Dn=e=>Tn(e,`numeric`),On=(e,t)=>wn(t)?Tn(e,`timestamp`):e,Q=` AND `,kn=` OR `,$=`cv.value`,An=(e,t,n,r)=>{let i=`text`;wn(e)?i=`date`:Number.isNaN(Number(e))?X(e)&&(i=`boolean`):i=`numeric`;let a=r.get(e);return`(jsonb_extract_path_text(ce.custom_fields, :${n})::${i}) ${t} :${a}`},jn=e=>{let t=e;return X(e)?t=e===`true`:Number.isNaN(Number(e))||(t=Number(e)),t},Mn=(e,t)=>{let n=jn(e),r=JSON.stringify({[t]:n}),i;return X(e)&&(i=`ce.custom_fields @> '${JSON.stringify({[t]:e})}'`),`
|
|
3
3
|
(
|
|
4
4
|
${i?`${i} OR`:``}
|
|
5
5
|
ce.custom_fields @> '${r}'
|