@budibase/server 3.4.16 → 3.4.17
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.
|
@@ -516,7 +516,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
516
516
|
enhance user experience.
|
|
517
517
|
|
|
518
518
|
<p>Breaking the form into multiple steps can significantly improve usability by
|
|
519
|
-
making the process more digestible for your users.</p>`},m(eo,no){insert$2(eo,ue,no)},p:noop$7,i:noop$7,o:noop$7,d(eo){eo&&detach(ue)}}}class NewFormSteps extends SvelteComponent{constructor(ue){super(),init$3(this,ue,null,create_fragment$9h,safe_not_equal,{})}}const ONBOARDING_EVENT_PREFIX="onboarding",TOUR_STEP_KEYS={BUILDER_APP_PUBLISH:"builder-app-publish",BUILDER_DATA_SECTION:"builder-data-section",BUILDER_DESIGN_SECTION:"builder-design-section",BUILDER_USER_MANAGEMENT:"builder-user-management",BUILDER_AUTOMATION_SECTION:"builder-automation-section",FEATURE_USER_MANAGEMENT:"feature-user-management",BUILDER_FORM_CREATE_STEPS:"builder-form-create-steps",BUILDER_FORM_VIEW_UPDATE_STEPS:"builder-form-view-update-steps",BUILDER_FORM_ROW_ID:"builder-form-row-id"},TOUR_KEYS={TOUR_BUILDER_ONBOARDING:"builder-onboarding",FEATURE_ONBOARDING:"feature-onboarding",BUILDER_FORM_CREATE:"builder-form-create",BUILDER_FORM_VIEW_UPDATE:"builder-form-view-update"},getCurrentStepIdx=(to,ue)=>{if(to!=null&&to.length)return to!=null&&to.length&&!ue?0:to.findIndex(eo=>eo.id===ue)},endUserOnboarding=async({skipped:to=!1}={})=>{if(get_store_value(auth).user){try{await API.updateSelf({onboardedAt:new Date().toISOString()}),to&&tourEvent("skipped"),await auth.getSelf(),builderStore.endBuilderOnboarding(),builderStore.setTour()}catch(ue){return console.error("Onboarding failed",ue),!1}return!0}},endTour=async({key:to,skipped:ue=!1}={})=>{const{tours:eo={}}=get_store_value(auth).user;eo[to]=new Date().toISOString(),await API.updateSelf({tours:eo}),ue&&tourEvent(to,ue),await auth.getSelf(),builderStore.setTour()},tourEvent=(to,ue)=>{analytics.captureEvent(`${ONBOARDING_EVENT_PREFIX}:${to}`,{eventSource:EventSource.PORTAL,skipped:ue})},getTours=()=>({[TOUR_KEYS.TOUR_BUILDER_ONBOARDING]:{steps:[{id:TOUR_STEP_KEYS.BUILDER_DATA_SECTION,title:"Data",route:"/builder/app/:application/data",layout:OnboardingData,query:".topleftnav .spectrum-Tabs-item#builder-data-tab",onLoad:async()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_DATA_SECTION)},align:"left"},{id:TOUR_STEP_KEYS.BUILDER_DESIGN_SECTION,title:"Design",route:"/builder/app/:application/design",layout:OnboardingDesign,query:".topleftnav .spectrum-Tabs-item#builder-design-tab",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_DESIGN_SECTION)},align:"left"},{id:TOUR_STEP_KEYS.BUILDER_AUTOMATION_SECTION,title:"Automations",route:"/builder/app/:application/automation",query:".topleftnav .spectrum-Tabs-item#builder-automation-tab",body:"Once you have your app screens made, you can set up automations to fit in with your current workflow",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_AUTOMATION_SECTION)},align:"left"},{id:TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT,title:"Users",query:".toprightnav #builder-app-users-button",body:"Add users to your app and control what level of access they have.",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT)}},{id:TOUR_STEP_KEYS.BUILDER_APP_PUBLISH,title:"Publish",layout:OnboardingPublish,route:"/builder/app/:application/design",query:".toprightnav #builder-app-publish-button",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_APP_PUBLISH)},onComplete:endUserOnboarding}],onSkip:async()=>{await endUserOnboarding({skipped:!0})},endRoute:"/builder/app/:application/data"},[TOUR_KEYS.FEATURE_ONBOARDING]:{steps:[{id:TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT,title:"Users",query:".toprightnav #builder-app-users-button",body:"Add users to your app and control what level of access they have.",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT)},onComplete:endUserOnboarding}]},[TOUR_KEYS.BUILDER_FORM_CREATE]:{steps:[{id:TOUR_STEP_KEYS.BUILDER_FORM_CREATE_STEPS,title:"Add multiple steps",layout:NewFormSteps,query:"#steps-prop-control-wrap",onComplete:()=>{builderStore.highlightSetting(),endTour({key:TOUR_KEYS.BUILDER_FORM_CREATE})},onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_FORM_CREATE_STEPS),builderStore.highlightSetting("steps","info")},align:"left-outside"}]},[TOUR_KEYS.BUILDER_FORM_VIEW_UPDATE]:{steps:[{id:TOUR_STEP_KEYS.BUILDER_FORM_ROW_ID,title:"Add row ID to update a row",layout:NewViewUpdateFormRowId,query:"#rowId-prop-control-wrap",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_FORM_ROW_ID),builderStore.highlightSetting("rowId","info")},align:"left-outside"},{id:TOUR_STEP_KEYS.BUILDER_FORM_VIEW_UPDATE_STEPS,title:"Add multiple steps",layout:NewFormSteps,query:"#steps-prop-control-wrap",onComplete:()=>{builderStore.highlightSetting(),endTour({key:TOUR_KEYS.BUILDER_FORM_VIEW_UPDATE})},onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_FORM_VIEW_UPDATE_STEPS),builderStore.highlightSetting("steps","info")},align:"left-outside",scrollIntoView:!0}],onSkip:async()=>{builderStore.highlightSetting(),endTour({key:TOUR_KEYS.BUILDER_FORM_VIEW_UPDATE,skipped:!0})}}}),TOURS=getTours(),TOURSBYSTEP=Object.keys(TOURS).reduce((to,ue)=>(TOURS[ue].steps.forEach(eo=>{to[eo.id]=eo,to[eo.id].tour=ue}),to),{}),INITIAL_BUILDER_STATE={previousTopNavPath:{},highlightedSetting:null,propertyFocus:null,builderSidePanel:!1,onboarding:!1,tourNodes:null,tourKey:null,tourStepKey:null,hoveredComponentId:null};class BuilderStore extends BudiStore{constructor(){super({...INITIAL_BUILDER_STATE}),this.init=this.init.bind(this),this.refresh=this.refresh.bind(this),this.reset=this.reset.bind(this),this.highlightSetting=this.highlightSetting.bind(this),this.propertyFocus=this.propertyFocus.bind(this),this.hideBuilderSidePanel=this.hideBuilderSidePanel.bind(this),this.showBuilderSidePanel=this.showBuilderSidePanel.bind(this),this.setPreviousTopNavPath=this.setPreviousTopNavPath.bind(this),this.selectResource=this.selectResource.bind(this),this.registerTourNode=this.registerTourNode.bind(this),this.destroyTourNode=this.destroyTourNode.bind(this),this.startBuilderOnboarding=this.startBuilderOnboarding.bind(this)}init(ue){if(!(ue!=null&&ue.appId)){console.error("BuilderStore: No appId supplied for websocket");return}this.websocket||(this.websocket=createBuilderWebsocket(ue.appId))}refresh(){const ue=get_store_value(this.store);this.store.set(ue)}reset(){var ue;this.store.set({...INITIAL_BUILDER_STATE}),(ue=this.websocket)==null||ue.disconnect(),this.websocket=void 0}highlightSetting(ue,eo){this.update(no=>({...no,highlightedSetting:ue?{key:ue,type:eo||"info"}:null}))}propertyFocus(ue){this.update(eo=>({...eo,propertyFocus:ue}))}showBuilderSidePanel(){this.update(ue=>({...ue,builderSidePanel:!0}))}hideBuilderSidePanel(){this.update(ue=>({...ue,builderSidePanel:!1}))}setPreviousTopNavPath(ue,eo){this.update(no=>({...no,previousTopNavPath:{...no.previousTopNavPath||{},[ue]:eo}}))}selectResource(ue){var eo;(eo=this.websocket)==null||eo.emit(BuilderSocketEvent.SelectResource,{resourceId:ue})}registerTourNode(ue,eo){this.update(no=>({...no,tourNodes:{...no.tourNodes,[ue]:eo}}))}destroyTourNode(ue){var no;const eo=get_store_value(this.store);if((no=eo.tourNodes)!=null&&no[ue]){const ro={...eo.tourNodes};delete ro[ue],this.update(io=>({...io,tourNodes:ro}))}}startBuilderOnboarding(){this.update(ue=>({...ue,onboarding:!0,tourKey:TOUR_KEYS.TOUR_BUILDER_ONBOARDING}))}endBuilderOnboarding(){this.update(ue=>({...ue,onboarding:!1}))}setTour(ue){this.update(eo=>({...eo,tourStepKey:null,tourNodes:null,tourKey:ue||null}))}}const builderStore=new BuilderStore,INITIAL_HOVER_STATE={componentId:null};class HoverStore extends BudiStore{constructor(){super({...INITIAL_HOVER_STATE}),this.hover=this.hover.bind(this)}hover(ue,eo=!0){clearTimeout(this.hoverTimeout),ue?this.processHover(ue,eo):this.hoverTimeout=setTimeout(()=>{this.processHover(ue,eo)},10)}processHover(ue,eo){ue!==get_store_value(this.store).componentId&&(this.update(no=>(no.componentId=ue,no)),eo&&previewStore.sendEvent("hover-component",ue))}}const hoverStore=new HoverStore,INITIAL_PREVIEW_STATE={previewDevice:"desktop",previewEventHandler:null,showPreview:!1,selectedComponentContext:null};class PreviewStore extends BudiStore{constructor(){super(INITIAL_PREVIEW_STATE),this.setDevice=this.setDevice.bind(this),this.sendEvent=this.sendEvent.bind(this),this.registerEventHandler=this.registerEventHandler.bind(this),this.startDrag=this.startDrag.bind(this),this.stopDrag=this.stopDrag.bind(this),this.showPreview=this.showPreview.bind(this),this.setSelectedComponentContext=this.setSelectedComponentContext.bind(this),this.requestComponentContext=this.requestComponentContext.bind(this)}setDevice(ue){this.update(eo=>({...eo,previewDevice:ue}))}sendEvent(ue,eo){const{previewEventHandler:no}=get_store_value(this.store);no==null||no(ue,eo)}registerEventHandler(ue){this.update(eo=>({...eo,previewEventHandler:ue}))}async startDrag(ue){this.sendEvent("dragging-new-component",{dragging:!0,component:ue})}stopDrag(){this.sendEvent("dragging-new-component",{dragging:!1})}showPreview(ue){this.update(eo=>({...eo,showPreview:ue}))}setSelectedComponentContext(ue){this.update(eo=>({...eo,selectedComponentContext:ue}))}updateState(ue){this.sendEvent("builder-state",ue)}setUrlTestData(ue){this.sendEvent("builder-url-test-data",ue)}requestComponentContext(){this.sendEvent("request-context")}}const previewStore=new PreviewStore,TriggerStepID={ROW_SAVED:"ROW_SAVED",ROW_UPDATED:"ROW_UPDATED",ROW_DELETED:"ROW_DELETED",ROW_ACTION:"ROW_ACTION",WEBHOOK:"WEBHOOK",APP:"APP",CRON:"CRON"},ActionStepID={SEND_EMAIL_SMTP:"SEND_EMAIL_SMTP",CREATE_ROW:"CREATE_ROW",UPDATE_ROW:"UPDATE_ROW",DELETE_ROW:"DELETE_ROW",OUTGOING_WEBHOOK:"OUTGOING_WEBHOOK",EXECUTE_SCRIPT:"EXECUTE_SCRIPT",EXECUTE_QUERY:"EXECUTE_QUERY",SERVER_LOG:"SERVER_LOG",DELAY:"DELAY",FILTER:"FILTER",QUERY_ROWS:"QUERY_ROWS",LOOP:"LOOP",COLLECT:"COLLECT",TRIGGER_AUTOMATION_RUN:"TRIGGER_AUTOMATION_RUN",discord:"discord",slack:"slack",zapier:"zapier",integromat:"integromat",n8n:"n8n"},Features={LOOPING:"LOOPING"};class TableStore extends DerivedBudiStore{constructor(){const ue=eo=>derived(eo,no=>{var ro;return{...no,selected:(ro=no.list)==null?void 0:ro.find(io=>io._id===no.selectedTableId)}});super({list:[],selectedTableId:void 0},ue),this.select=this.select.bind(this)}async init(){return this.fetch()}async fetch(){const ue=await API.getTables();this.store.update(eo=>({...eo,list:ue}))}async singleFetch(ue){const eo=await API.getTable(ue);this.store.update(no=>{const ro=[];for(let io of no.list)eo._id===io._id?ro.push(eo):ro.push(io);return no.list=ro,no})}select(ue){this.store.update(eo=>({...eo,selectedTableId:ue}))}async save(ue){var lo;const eo=fp$1.cloneDeep(ue),no=get_store_value(this.store).list.filter(co=>co._id===ue._id)[0],ro=[];for(let co of Object.keys(eo.schema)){if(ro.indexOf(co.toLowerCase())!==-1){delete eo.schema[co];continue}const uo=eo.schema[co],fo=no==null?void 0:no.schema[co];fo!=null&&(fo==null?void 0:fo.type)!==uo.type&&!((lo=SWITCHABLE_TYPES[fo==null?void 0:fo.type])!=null&&lo.includes(uo.type))&&(eo.schema[co]=fo),uo.name&&uo.name!==co&&(eo.schema[uo.name]=uo,eo._rename={old:co,updated:uo.name},delete eo.schema[co]),ro.push(co.toLowerCase())}const io=await API.saveTable(eo);this.replaceTable(io._id,io),this.select(io._id);let oo=[];for(let co of Object.values((eo==null?void 0:eo.schema)||{}))co.type===FieldType.LINK&&oo.push(co.tableId);let ao=[];for(let co of Object.values((no==null?void 0:no.schema)||{}))co.type===FieldType.LINK&&ao.push(co.tableId);const so=[...new Set([...oo,...ao])];return so.length>3?await this.fetch():await Promise.all(so.map(co=>this.singleFetch(co))),io}async delete(ue){await API.deleteTable(ue._id,ue._rev),this.replaceTable(ue._id,null)}async saveField({originalName:ue,field:eo,primaryDisplay:no=!1,indexes:ro}){const io=fp$1.cloneDeep(get_store_value(this.derivedStore).selected);if(ue!=null&&ue!==eo.name&&(delete io.schema[ue],io._rename={old:ue,updated:eo.name}),no)io.primaryDisplay=eo.name;else if(io.primaryDisplay===ue){const oo=Object.keys(io.schema);io.primaryDisplay=oo.filter(ao=>ao!==ue||ao!==eo.name)[0]}ro&&(io.indexes=ro),io.schema={...io.schema,[eo.name]:fp$1.cloneDeep(eo)},await this.save(io)}async deleteField(ue){let eo=fp$1.cloneDeep(get_store_value(this.derivedStore).selected);delete eo.schema[ue.name],await this.save(eo)}replaceTable(ue,eo){if(!ue)return;if(!eo){this.store.update(ro=>({...ro,list:ro.list.filter(io=>io._id!==ue)}));return}const no=get_store_value(this.store).list.findIndex(ro=>ro._id===eo._id);no===-1?this.store.update(ro=>({...ro,list:[...ro.list,eo]})):eo&&this.store.update(ro=>(ro.list[no]={...eo,type:ro.list[no].type},ro))}removeDatasourceTables(ue){this.store.update(eo=>({...eo,list:eo.list.filter(no=>no.sourceId!==ue)}))}}const tables=new TableStore;class ViewV2Store extends DerivedBudiStore{constructor(){const ue=eo=>derived([eo,tables],([no,ro])=>{var oo;let io=[];return(oo=ro.list)==null||oo.forEach(ao=>{const so=Object.values((ao==null?void 0:ao.views)||{}).filter(isV2);io=io.concat(so)}),{...no,list:io,selected:io.find(ao=>ao.id===no.selectedViewId)}});super({selectedViewId:null},ue),this.select=this.select.bind(this)}select(ue){this.store.update(eo=>({...eo,selectedViewId:ue}))}async delete(ue){await API.viewV2.delete(ue.id),this.replaceView(ue.id,null)}async create(ue){const no=(await API.viewV2.create(ue)).data;return this.replaceView(no.id,no),no}async save(ue){const eo=await API.viewV2.update(ue),no=eo==null?void 0:eo.data;this.replaceView(ue.id,no)}replaceView(ue,eo){const no=get_store_value(this.derivedStore).list.find(io=>io.id===ue),ro=get_store_value(tables).list.findIndex(io=>io._id===(eo==null?void 0:eo.tableId)||io._id===(no==null?void 0:no.tableId));if(ro!==-1)if(!eo&&no){tables.update(io=>(delete io.list[ro].views[no.name],io));return}else!no&&eo?tables.update(io=>{var oo;return(oo=io.list[ro]).views??(oo.views={}),io.list[ro].views[eo.name]=eo,io}):no&&eo&&tables.update(io=>{var oo;return(oo=io.list[ro]).views??(oo.views={}),delete io.list[ro].views[no.name],io.list[ro].views[eo.name]=eo,io})}}const viewsV2=new ViewV2Store,initialState$1={};class RowActionStore extends BudiStore{constructor(){super(initialState$1),this.reset=()=>{this.set(initialState$1)},this.refreshRowActions=async ue=>{var io;if(!ue)return;let eo=(io=get_store_value(tables).list.find(oo=>oo._id===ue))==null?void 0:io._id;if(!eo){const oo=get_store_value(viewsV2).list.find(ao=>ao.id===ue);eo=oo==null?void 0:oo.tableId}if(!eo)return;const no=await API.rowActions.fetch(eo),ro=Object.values(no||{});this.update(oo=>({...oo,[eo]:ro}))},this.createRowAction=async(ue,eo,no)=>{if(!ue)return;if(!no){const io=get_store_value(this)[ue]||[];no=getSequentialName(io,"New row action ",{getName:oo=>oo.name})}if(!no)throw new Error("Failed to generate a unique name for the row action");const ro=await API.rowActions.create(ue,no);return eo?await Promise.all([this.enableView(ue,ro.id,eo),automationStore.actions.fetch()]):await Promise.all([this.refreshRowActions(ue),automationStore.actions.fetch()]),ro},this.enableView=async(ue,eo,no)=>{await API.rowActions.enableView(ue,eo,no),await this.refreshRowActions(ue)},this.disableView=async(ue,eo,no)=>{await API.rowActions.disableView(ue,eo,no),await this.refreshRowActions(ue)},this.delete=async(ue,eo)=>{await API.rowActions.delete(ue,eo),await this.refreshRowActions(ue)},this.trigger=async(ue,eo,no)=>{await API.rowActions.trigger(ue,eo,no)}}}const store=new RowActionStore,derivedStore=derived(store,to=>{const ue={};return Object.keys(to||{}).forEach(eo=>{ue[eo]=to[eo];for(let no of to[eo]){const ro=(no.allowedSources||[]).filter(io=>io!==eo);for(let io of ro)ue[io]??(ue[io]=[]),ue[io].push(no)}}),ue}),rowActions={...store,subscribe:derivedStore.subscribe},getNewStepName=(to,ue)=>{const eo=ue.name,no=io=>io.reduce((oo,ao)=>(ao.name&&ao.name.startsWith(eo)&&oo++,ao.stepId===AutomationActionStepId.BRANCH&&ao.inputs&&ao.inputs.children&&Object.values(ao.inputs.children).forEach(so=>{oo+=no(so)}),oo),0);let ro=0;return to!=null&&to.definition&&(ro=no(to.definition.steps)),ro===0?eo:`${eo} ${ro+1}`},initialAutomationState={automations:[],testResults:null,showTestPanel:!1,blockDefinitions:{TRIGGER:{},CREATABLE_TRIGGER:{},ACTION:{}},selectedAutomationId:null},getFinalDefinitions=(to,ue)=>{const eo={};return Object.entries(to).forEach(no=>{no[0]!==AutomationTriggerStepId.ROW_ACTION&&(eo[no[0]]=no[1])}),{TRIGGER:to,CREATABLE_TRIGGER:eo,ACTION:ue}},automationActions=to=>({moveBlock:async(ue,eo,no)=>{const ro=ue.at(-1),io=eo.at(-1),oo=(ro==null?void 0:ro.id)===(io==null?void 0:io.id),ao=(io==null?void 0:io.branchStepId)&&io.branchIdx===(ro==null?void 0:ro.branchIdx)&&(ro==null?void 0:ro.stepIdx)===0;if(oo||ao)return;const{deleted:so,newAutomation:lo}=to.actions.deleteBlock(ue,no),co={};to.actions.traverse(co,lo);let uo;io!=null&&io.branchStepId?(uo=co[io.branchStepId].pathTo,uo.push(io)):(io!=null&&io.id&&(uo=co[io.id].pathTo),uo.at(-1).stepIdx+=1);const fo=to.actions.updateStep(uo,lo,so,!0);try{await to.actions.save(fo)}catch(po){notifications.error("Error moving automation block"),console.error("Error moving automation block ",po)}},deleteBlock:(ue,eo)=>{let no=fp$1.cloneDeep(eo);const ro=[no.definition.trigger,...no.definition.steps];let io;return ue.forEach((oo,ao,so)=>{const lo=ao===so.length-1,{stepIdx:co,branchIdx:uo}=oo,fo=(po,ho)=>{const _o=po[ho],go=[_o.id],bo=[],vo={};po.forEach($o=>{const{blockToLoop:ko,id:So}=$o;ko&&(vo[ko]=So)});const yo=vo[_o.id];yo&&go.push(yo);for(let $o=po.length-1;$o>=0;$o--)if(go.includes(po[$o].id)){const[ko]=po.splice($o,1);bo.unshift(ko)}return{deleted:bo,newAutomation:no}};if(!io){lo?io=fo(no.definition.steps,co>0?co-1:0):io=ro[co];return}if(Number.isInteger(uo)){const po=io.inputs.branches[uo].id,ho=io.inputs.children[po],_o=ho[co];lo?io=fo(ho,co):io=_o}}),io},registerBlock:(ue,eo,no,ro)=>{ue[eo.id]={...ue[eo.id]||{},pathTo:no,terminating:ro||!1,...eo.blockToLoop?{blockToLoop:eo.blockToLoop}:{}},eo.blockToLoop&&(ue[eo.blockToLoop]={...ue[eo.blockToLoop]||{},looped:eo.id})},getPathSteps:(ue,eo)=>{const no=[eo.definition.trigger,...eo.definition.steps];let ro=[];return ue.forEach(io=>{var lo;const{stepIdx:oo,branchIdx:ao}=io;if(!ro.length){ro=no.slice(0,oo+1);return}let so=ro[ro.length-1];if(isBranchStep(so)&&Number.isInteger(ao)){const co=so.inputs.branches[ao].id,fo=(((lo=so.inputs.children)==null?void 0:lo[co])||[]).slice(0,oo+1);ro=ro.concat(fo)}}),ro},updateStep:(ue,eo,no,ro=!1)=>{let io=fp$1.cloneDeep(eo);const oo=(so,lo,co)=>{so.splice(lo,ro?0:Array.isArray(co)?co.length:1,...Array.isArray(co)?co:[co])};let ao=null;return ue.forEach((so,lo,co)=>{const{stepIdx:uo,branchIdx:fo}=so;let po=lo===co.length-1;if(!ao){let ho=Math.max(uo-1,0);if(po){oo(io.definition.steps,ho,no);return}ao=io.definition.steps[ho]}if(Number.isInteger(fo)){const ho=ao.inputs.branches[fo].id,_o=ao.inputs.children[ho];po?oo(_o,uo,no):ao=_o[uo]}}),io},buildEnvironmentBindings:()=>get_store_value(licensing).environmentVariablesEnabled?getEnvironmentBindings().map(ue=>({...ue,display:{...ue.display,rank:98}})):[],buildUserBindings:()=>getUserBindings().map(ue=>({...ue,category:"User",display:{...ue.display,rank:98}})),buildSettingBindings:()=>getSettingBindings().map(ue=>({...ue,display:{...ue.display,rank:98}})),getPathBindings:ue=>{var no,ro;const eo=(no=get_store_value(selectedAutomation))==null?void 0:no.blockRefs[ue];return to.actions.getAvailableBindings(eo,(ro=get_store_value(selectedAutomation))==null?void 0:ro.data)},traverse:(ue,eo)=>{var io;let no=[];if(!eo||!ue)return;(io=eo.definition)!=null&&io.trigger&&no.push(eo.definition.trigger),no=no.concat(eo.definition.steps||[]);const ro=(oo,ao,so,lo,co)=>{var fo,po;const uo=[...ao||[],{...Number.isInteger(lo)?{branchIdx:lo}:{},stepIdx:so,id:oo.id}];if(isBranchStep(oo)){const ho=((fo=oo.inputs)==null?void 0:fo.branches)||[],_o=((po=oo.inputs)==null?void 0:po.children)||{};ho.forEach((go,bo)=>{_o[go.id].forEach((vo,yo,$o)=>{const ko=$o.length-1===yo&&!ho.length;ro(vo,uo,yo,bo,ko)})}),co=co&&!ho.length}to.actions.registerBlock(ue,oo,uo,co)};return no.forEach((oo,ao,so)=>{ro(oo,null,ao,null,so.length-1===ao)}),ue},getAvailableBindings:(ue,eo)=>{var lo,co,uo,fo,po,ho,_o;if(!ue||!(eo!=null&&eo.definition))return[];const no=(lo=get_store_value(selectedAutomation))==null?void 0:lo.blockRefs,ro=to.actions.getPathSteps(ue.pathTo,eo).slice(0,-1),io=to.actions.getPathSteps(ue.pathTo,eo).at(-1);let oo=[];const ao=(go,bo,vo,yo,$o,ko)=>{if(!go)return;const So=to.actions.determineRuntimeBinding(go,yo,$o,ko,eo,io,ro),Ao=to.actions.determineCategoryName(yo,$o,ko,so);oo.push(to.actions.createBindingObject(go,bo,vo,yo,so,$o,So,Ao,ko))};let so=0;for(let go=0;go<ro.length;go++){const bo=ro[go],vo=((co=eo.definition.stepNames)==null?void 0:co[bo.id])||bo.name;let yo=fp$1.cloneDeep((fo=(uo=bo==null?void 0:bo.schema)==null?void 0:uo.outputs)==null?void 0:fo.properties)??{},$o=!1;bo.blockToLoop&&($o=bo.stepId===ActionStepID.LOOP&&bo.blockToLoop in no),$o&&so==0&&(yo={currentItem:{type:AutomationIOType.STRING,description:"the item currently being executed"}});const ko=isTrigger(bo)?bo.icon:$o?"Reuse":bo.icon;if(go===0&&isTrigger(bo))if(isRowUpdateTrigger(bo)||isRowSaveTrigger(bo)){let So=get_store_value(tables).list.find(Ao=>Ao._id===bo.inputs.tableId);for(const Ao in So==null?void 0:So.schema)yo[Ao]={type:So.schema[Ao].type,subtype:So.schema[Ao].subtype};delete yo.row}else isAppTrigger(bo)&&(yo=Object.fromEntries(Object.keys(bo.inputs.fields||[]).map(So=>[So,{type:bo.inputs.fields[So]}])));if((po=no[bo.id])!=null&&po.looped){so++;const So=no[bo.id].looped,Ao=ro.find(Mo=>Mo.id===So);Ao?yo=fp$1.cloneDeep((_o=(ho=Ao.schema)==null?void 0:ho.outputs)==null?void 0:_o.properties):console.error("Loop block missing.")}Object.entries(yo).forEach(([So,Ao])=>{ao(So,Ao,ko,go,$o,vo)})}return ue.looped||(oo=oo.filter(go=>!go.readableBinding.includes("loop"))),oo},determineRuntimeBinding:(ue,eo,no,ro,io,oo,ao)=>{var lo,co,uo;let so;if(eo===0&&((lo=io.definition.trigger)==null?void 0:lo.event)===AutomationEventType.APP_TRIGGER)return`trigger.fields.${ue}`;if(eo===0&&(((co=io.definition.trigger)==null?void 0:co.event)===AutomationEventType.ROW_UPDATE||((uo=io.definition.trigger)==null?void 0:uo.event)===AutomationEventType.ROW_SAVE)&&!["id","revision","oldRow"].includes(ue))return`trigger.row.${ue}`;if(no)so=`loop.${ue}`;else if(eo===0)so=`trigger.${ue}`;else if((oo==null?void 0:oo.stepId)===AutomationActionStepId.EXECUTE_SCRIPT){const fo=ao[eo].id;if(!fo)return notifications.error("Error generating binding: Step ID not found."),null;so=`steps["${fo}"].${ue}`}else{const fo=ao[eo].id;if(!fo)return notifications.error("Error generating binding: Step ID not found."),null;so=`steps.${fo}.${ue}`}return so},determineCategoryName:(ue,eo,no,ro)=>ue===0?"Trigger outputs":eo?"Loop Outputs":no?`${no} outputs`:`Step ${ue-ro} outputs`,createBindingObject:(ue,eo,no,ro,io,oo,ao,so,lo)=>{const co=Object.values(FIELDS).find(uo=>uo.type===eo.type&&("subtype"in uo?uo.subtype===eo.subtype:!0));return{readableBinding:lo&&!oo&&ro!==0?`steps.${lo}.${ue}`:ao,runtimeBinding:ao,type:eo.type,description:eo.description,icon:no,category:so,display:{type:(co==null?void 0:co.name)||eo.type,name:ue,rank:oo?ro+1:ro-io}}},processBlockInputs:async(ue,eo)=>{var oo;let no={...ue,inputs:{...ue.inputs,...eo}};Object.keys(no.inputs).forEach(ao=>{const so=no.inputs[ao];(so==null||so==="")&&delete no.inputs[ao]});const ro=(oo=get_store_value(selectedAutomation))==null?void 0:oo.data;if(!ro)return!1;const io=to.actions.getUpdatedDefinition(ro,no);return JSON.stringify(io)===JSON.stringify(ro)?!1:io},updateBlockInputs:async(ue,eo)=>{const no=await to.actions.processBlockInputs(ue,eo);no!==!1&&await to.actions.save(no)},test:async(ue,eo)=>{var ro,io;let no;try{no=await API.testAutomation(ue._id,eo)}catch(oo){throw`Automation test failed - ${oo.message||oo.status||JSON.stringify(oo)}`}if(!(no!=null&&no.trigger)&&!((ro=no==null?void 0:no.steps)!=null&&ro.length)&&!(no!=null&&no.message))throw((io=no==null?void 0:no.err)==null?void 0:io.code)==="usage_limit_exceeded"?"You have exceeded your automation quota":"Something went wrong testing your automation";to.update(oo=>(oo.testResults=no,oo))},getUpdatedDefinition:(ue,eo)=>{var ro;let no;if(((ro=ue.definition.trigger)==null?void 0:ro.id)===eo.id)no=fp$1.cloneDeep(ue),no.definition.trigger=eo;else{const io=get_store_value(selectedAutomation).blockRefs[eo.id].pathTo;no=to.actions.updateStep(io,ue,eo)}return no},getLogs:async({automationId:ue,startDate:eo,status:no,page:ro}={})=>await API.getAutomationLogs({automationId:ue,startDate:eo,status:no,page:ro}),clearLogErrors:async({automationId:ue,appId:eo})=>{if(!ue||!eo)throw new Error("automationId and appId are required");return await API.clearAutomationLogErrors(ue,eo)},addTestDataToAutomation:ue=>{var no;let eo=fp$1.cloneDeep((no=get_store_value(selectedAutomation))==null?void 0:no.data);return eo&&(eo.testData={...eo.testData,...ue},eo)},constructBlock:(ue,eo,no)=>{var oo;const ro={...no,inputs:no.inputs||{},stepId:eo,type:ue,id:shortid.generate()},io=getNewStepName((oo=get_store_value(selectedAutomation))==null?void 0:oo.data,ro);return ro.name=io,ro},generateBranchBlock:()=>{const ue=get_store_value(to).blockDefinitions.ACTION.BRANCH;return to.actions.constructBlock("ACTION","BRANCH",ue)},addBlockToAutomation:async(ue,eo)=>{var ao;const no=(ao=get_store_value(selectedAutomation))==null?void 0:ao.data;if(!no)return;let ro=fp$1.cloneDeep(no);const io=[ro.definition.trigger,...ro.definition.steps];let oo;eo.forEach((so,lo,co)=>{var _o;const{stepIdx:uo,branchIdx:fo}=so,po=lo===co.length-1,ho=(go,bo)=>{const vo=!Number.isInteger(bo),yo=ue.blockToLoop||vo?bo:bo+1;go.splice(yo,0,ue)};if(!oo){po?(ho(ro.definition.steps,uo-1),oo=ue):oo=io[uo];return}if(Number.isInteger(fo)&&!Array.isArray(oo)&&isBranchStep(oo)){const go=oo.inputs.branches[fo].id,bo=((_o=oo.inputs.children)==null?void 0:_o[go])||[];po?(ho(bo,uo),oo=bo):oo=bo[uo]}});try{await to.actions.save(ro)}catch(so){notifications.error("Error adding automation block"),console.error("Automation adding block ",so)}},generateDefaultConditions:()=>{const ue={logicalOperator:UILogicalOperator.ALL,onEmptyFilter:EmptyFilterOption.RETURN_NONE,groups:[]};return{condition:buildQuery$1(ue),conditionUI:ue}},branchAutomation:async(ue,eo)=>{var uo;const no=ue.at(-1);let ro=fp$1.cloneDeep(eo),io,oo=!1;const ao=fo=>({name:fo,...to.actions.generateDefaultConditions(),id:shortid.generate()});ue.forEach((fo,po,ho)=>{const{stepIdx:_o,branchIdx:go}=fo,bo=po===ho.length-1;if(io||(bo?(io=ro.definition.steps,oo=!0):io=ro.definition.steps[_o-1]),Number.isInteger(go)){const vo=io.inputs.branches[go].id,yo=io.inputs.children[vo];io=bo?yo:yo[_o]}});const so=Math.max(no.stepIdx-1,0),lo=oo?so:no.stepIdx;if(((uo=io[lo])==null?void 0:uo.stepId)=="BRANCH"){let fo=io[lo].inputs.branches;const po=ao(`Branch ${fo.length+1}`);fo.splice(fo.length,0,po),io[lo].inputs.children[po.id]=[];try{await to.actions.save(ro)}catch(ho){notifications.error("Error adding branch to automation"),console.error("Error adding automation branch",ho)}return}const co=to.actions.generateBranchBlock();co.inputs.branches=Array.from({length:2}).map((fo,po)=>ao(`Branch ${po+1}`)),co.inputs.children=co.inputs.branches.reduce((fo,po,ho)=>(fo[po.id]=ho==0?io.slice(lo+1):[],fo),{}),io.splice(lo+1),io.push(co);try{await to.actions.save(ro)}catch(fo){notifications.error("Error adding branch to automation"),console.error("Error adding automation branch",fo)}},branchLeft:async(ue,eo,no)=>{const ro=to.actions.shiftBranch(ue,no);if(ro){const io=to.actions.updateStep(ue.slice(0,-1),eo,ro);await to.actions.save(io)}},branchRight:async(ue,eo,no)=>{const ro=to.actions.shiftBranch(ue,no,1);if(ro){const io=to.actions.updateStep(ue.slice(0,-1),eo,ro);await to.actions.save(io)}},shiftBranch:(ue,eo,no=-1)=>{let ro=fp$1.cloneDeep(eo);const oo=ue.at(-1).branchIdx;if(!ro.inputs.branches[oo+no]){console.error("Invalid index");return}let[ao]=ro.inputs.branches.splice(oo+no,1);return ro.inputs.branches.splice(oo,0,ao),ro},deleteBranch:async(ue,eo)=>{let no=fp$1.cloneDeep(eo),ro=[];ue.forEach((io,oo,ao)=>{const{stepIdx:so,branchIdx:lo}=io,co=oo===ao.length-1;if(!ro.length){if(co){ro=no.definition.steps;return}ro=[{node:no.definition.steps[so-1],context:no.definition.steps}]}const uo=ro.at(-1);if(Number.isInteger(lo)){const fo=uo.node.inputs.branches[lo].id,po=uo.node.inputs.children[fo];if(co){const ho=uo.node.inputs.branches.length==2;if(uo.node.inputs.branches.splice(lo,1),delete uo.node.inputs.children[fo],ho){const _o=uo.node.inputs.branches[0].id,go=uo.node.inputs.children[_o],bo=ro.at(-1).context;bo.pop(),bo.splice(bo.length,0,...go)}return}ro.push({node:po[so],context:po})}});try{await to.actions.save(no)}catch(io){notifications.error("Error deleting automation branch"),console.error("Error deleting automation branch",io)}},saveAutomationName:async(ue,eo)=>{var oo;const no=(oo=get_store_value(selectedAutomation))==null?void 0:oo.data;let ro=fp$1.cloneDeep(no);if(!ro)return;const io=eo.trim();ro.definition.stepNames={...ro.definition.stepNames,[ue]:io},await to.actions.save(ro)},deleteAutomationName:async ue=>{var ro;const eo=(ro=get_store_value(selectedAutomation))==null?void 0:ro.data;let no=fp$1.cloneDeep(eo);!eo||!no||(no!=null&&no.definition.stepNames&&delete no.definition.stepNames[ue],await to.actions.save(no))},deleteAutomationBlock:async ue=>{var ro;const eo=(ro=get_store_value(selectedAutomation))==null?void 0:ro.data;if(!eo)return;const{newAutomation:no}=to.actions.deleteBlock(ue,eo);try{await to.actions.save(no)}catch(io){notifications.error("Error deleting automation block"),console.error("Automation deleting block ",io)}},replace:(ue,eo)=>{if(!eo)to.store.update(no=>{var ro;return no.automations=no.automations.filter(io=>io._id!==ue),ue===no.selectedAutomationId&&to.actions.select(((ro=no.automations[0])==null?void 0:ro._id)||null),no});else{const no=get_store_value(to.store).automations.findIndex(ro=>ro._id===eo._id);no===-1?to.store.update(ro=>({...ro,automations:[...ro.automations,eo]})):to.store.update(ro=>(ro.automations[no]=eo,ro))}},create:async(ue,eo)=>{const no={name:ue,type:"automation",appId:get_store_value(appStore).appId,definition:{steps:[],trigger:eo},disabled:!1};return await to.actions.save(no)},duplicate:async ue=>await to.actions.save({...ue,name:`${ue.name} - copy`,_id:void 0,_rev:void 0}),toggleDisabled:async ue=>{let eo;try{if(eo=to.actions.getDefinition(ue),!eo)return;eo.disabled=!eo.disabled,await to.actions.save(eo),notifications.success(`Automation ${eo.disabled?"disabled":"enabled"} successfully`)}catch{notifications.error(`Error ${eo!=null&&eo.disabled?"disabling":"enabling"} automation`)}},definitions:async()=>{const ue=await API.getAutomationDefinitions();return to.update(eo=>(eo.blockDefinitions=getFinalDefinitions(ue.trigger,ue.action),eo)),ue},fetch:async()=>{const[ue,eo]=await Promise.all([API.getAutomations(),API.getAutomationDefinitions()]);to.update(no=>(no.automations=ue.automations,no.automations.sort((ro,io)=>ro.name<io.name?-1:1),no.blockDefinitions=getFinalDefinitions(eo.trigger,eo.action),no))},select:ue=>{!ue||ue===get_store_value(to).selectedAutomationId||to.update(eo=>(eo.selectedAutomationId=ue,eo.testResults=null,eo.showTestPanel=!1,eo))},getDefinition:ue=>{var eo;return(eo=get_store_value(to.store).automations)==null?void 0:eo.find(no=>no._id===ue)},save:async ue=>{const eo=await API.updateAutomation(ue);return await to.actions.fetch(),to.actions.select(eo.automation._id),eo.automation},delete:async ue=>{isRowAction(ue)?await rowActions.delete(ue.definition.trigger.inputs.tableId,ue.definition.trigger.inputs.rowActionId):await API.deleteAutomation(ue._id,ue._rev),to.update(no=>{var ro;return no.automations=no.automations.filter(io=>io._id!==ue._id),ue._id===no.selectedAutomationId&&(no.selectedAutomationId=((ro=no.automations[0])==null?void 0:ro._id)||null),no})}});class AutomationStore extends BudiStore{constructor(){super(initialAutomationState),this.actions=automationActions(this),this.history=createHistoryStore({getDoc:this.actions.getDefinition.bind(this),selectDoc:this.actions.select.bind(this)});const ue=this.actions.save.bind(this.actions),eo=this.actions.delete.bind(this.actions);this.actions.save=this.history.wrapSaveDoc(ue),this.actions.delete=this.history.wrapDeleteDoc(eo)}}const automationStore=new AutomationStore,automationHistoryStore=automationStore.history;class SelectedAutomationStore extends DerivedBudiStore{constructor(ue){const eo=()=>derived(ue,no=>{var ao;if(!no.selectedAutomationId)return{data:null,blockRefs:{},...no};const ro=(ao=no.automations)==null?void 0:ao.find(so=>so._id===no.selectedAutomationId);if(!ro)return{data:null,blockRefs:{},...no};const io={},oo=fp$1.cloneDeep(ro);return oo&&(ue.actions.traverse(io,oo),Object.values(io).filter(so=>so.terminating).forEach(so=>{ue.actions.getPathSteps(so.pathTo,oo).forEach((lo,co,uo)=>{migrateReferencesInObject({obj:lo,originalIndex:co,steps:uo})})})),{data:oo,blockRefs:io,...no}});super(initialAutomationState,eo)}}const selectedAutomation=new SelectedAutomationStore(automationStore);class UserStore extends BudiStore{constructor(){super([])}init(ue){this.set(ue)}updateUser(ue){const eo=get_store_value(this);eo.some(no=>no.sessionId===ue.sessionId)?this.update(no=>{const ro=no.findIndex(io=>io.sessionId===ue.sessionId);return no[ro]=ue,no.slice()}):this.set([...eo,ue])}removeUser(ue){this.update(eo=>eo.filter(no=>no.sessionId!==ue))}reset(){this.set([])}}const userStore=new UserStore,userSelectedResourceMap=derived(userStore,to=>{let ue={};return to.forEach(eo=>{var ro;const no=(ro=eo.builderMetadata)==null?void 0:ro.selectedResourceId;no&&(ue[no]||(ue[no]=[]),ue[no].push(eo))}),ue}),isOnlyUser=derived(userStore,to=>to.length<2),createDeploymentStore=()=>{let to=writable([]);const ue=async()=>{try{to.set(await API.getAppDeployments())}catch{notifications.error("Error fetching deployments")}};return{subscribe:to.subscribe,load:ue}},deploymentStore=createDeploymentStore(),INITIAL_CONTEXT_MENU_STATE={id:null,items:[],position:{x:0,y:0},visible:!1};function createViewsStore(){const to=writable({...INITIAL_CONTEXT_MENU_STATE}),ue=(no,ro,io)=>{to.set({id:no,items:ro,position:io,visible:!0})},eo=()=>{to.set({...INITIAL_CONTEXT_MENU_STATE})};return{subscribe:to.subscribe,open:ue,close:eo}}const contextMenuStore=createViewsStore();class SnippetStore extends BudiStore{constructor(){super([]),this.syncMetadata=ue=>{this.set((ue==null?void 0:ue.snippets)||[])},this.saveSnippet=async ue=>{const eo=[...get_store_value(this).filter(ro=>ro.name!==ue.name),ue],no=await API.saveAppMetadata(get_store_value(appStore).appId,{snippets:eo});this.syncMetadata(no)},this.deleteSnippet=async ue=>{const eo=get_store_value(this).filter(ro=>ro.name!==ue),no=await API.saveAppMetadata(get_store_value(appStore).appId,{snippets:eo});this.syncMetadata(no)}}}const snippets$1=new SnippetStore;class TableImportError extends Error{constructor(ue){super(),this.name="TableImportError",this.errors=ue}get description(){let ue="";for(const eo in this.errors)ue+=`${eo}: ${this.errors[eo]}
|
|
519
|
+
making the process more digestible for your users.</p>`},m(eo,no){insert$2(eo,ue,no)},p:noop$7,i:noop$7,o:noop$7,d(eo){eo&&detach(ue)}}}class NewFormSteps extends SvelteComponent{constructor(ue){super(),init$3(this,ue,null,create_fragment$9h,safe_not_equal,{})}}const ONBOARDING_EVENT_PREFIX="onboarding",TOUR_STEP_KEYS={BUILDER_APP_PUBLISH:"builder-app-publish",BUILDER_DATA_SECTION:"builder-data-section",BUILDER_DESIGN_SECTION:"builder-design-section",BUILDER_USER_MANAGEMENT:"builder-user-management",BUILDER_AUTOMATION_SECTION:"builder-automation-section",FEATURE_USER_MANAGEMENT:"feature-user-management",BUILDER_FORM_CREATE_STEPS:"builder-form-create-steps",BUILDER_FORM_VIEW_UPDATE_STEPS:"builder-form-view-update-steps",BUILDER_FORM_ROW_ID:"builder-form-row-id"},TOUR_KEYS={TOUR_BUILDER_ONBOARDING:"builder-onboarding",FEATURE_ONBOARDING:"feature-onboarding",BUILDER_FORM_CREATE:"builder-form-create",BUILDER_FORM_VIEW_UPDATE:"builder-form-view-update"},getCurrentStepIdx=(to,ue)=>{if(to!=null&&to.length)return to!=null&&to.length&&!ue?0:to.findIndex(eo=>eo.id===ue)},endUserOnboarding=async({skipped:to=!1}={})=>{if(get_store_value(auth).user){try{await API.updateSelf({onboardedAt:new Date().toISOString()}),to&&tourEvent("skipped"),await auth.getSelf(),builderStore.endBuilderOnboarding(),builderStore.setTour()}catch(ue){return console.error("Onboarding failed",ue),!1}return!0}},endTour=async({key:to,skipped:ue=!1}={})=>{const{tours:eo={}}=get_store_value(auth).user;eo[to]=new Date().toISOString(),await API.updateSelf({tours:eo}),ue&&tourEvent(to,ue),await auth.getSelf(),builderStore.setTour()},tourEvent=(to,ue)=>{analytics.captureEvent(`${ONBOARDING_EVENT_PREFIX}:${to}`,{eventSource:EventSource.PORTAL,skipped:ue})},getTours=()=>({[TOUR_KEYS.TOUR_BUILDER_ONBOARDING]:{steps:[{id:TOUR_STEP_KEYS.BUILDER_DATA_SECTION,title:"Data",route:"/builder/app/:application/data",layout:OnboardingData,query:".topleftnav .spectrum-Tabs-item#builder-data-tab",onLoad:async()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_DATA_SECTION)},align:"left"},{id:TOUR_STEP_KEYS.BUILDER_DESIGN_SECTION,title:"Design",route:"/builder/app/:application/design",layout:OnboardingDesign,query:".topleftnav .spectrum-Tabs-item#builder-design-tab",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_DESIGN_SECTION)},align:"left"},{id:TOUR_STEP_KEYS.BUILDER_AUTOMATION_SECTION,title:"Automations",route:"/builder/app/:application/automation",query:".topleftnav .spectrum-Tabs-item#builder-automation-tab",body:"Once you have your app screens made, you can set up automations to fit in with your current workflow",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_AUTOMATION_SECTION)},align:"left"},{id:TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT,title:"Users",query:".toprightnav #builder-app-users-button",body:"Add users to your app and control what level of access they have.",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_USER_MANAGEMENT)}},{id:TOUR_STEP_KEYS.BUILDER_APP_PUBLISH,title:"Publish",layout:OnboardingPublish,route:"/builder/app/:application/design",query:".toprightnav #builder-app-publish-button",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_APP_PUBLISH)},onComplete:endUserOnboarding}],onSkip:async()=>{await endUserOnboarding({skipped:!0})},endRoute:"/builder/app/:application/data"},[TOUR_KEYS.FEATURE_ONBOARDING]:{steps:[{id:TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT,title:"Users",query:".toprightnav #builder-app-users-button",body:"Add users to your app and control what level of access they have.",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.FEATURE_USER_MANAGEMENT)},onComplete:endUserOnboarding}]},[TOUR_KEYS.BUILDER_FORM_CREATE]:{steps:[{id:TOUR_STEP_KEYS.BUILDER_FORM_CREATE_STEPS,title:"Add multiple steps",layout:NewFormSteps,query:"#steps-prop-control-wrap",onComplete:()=>{builderStore.highlightSetting(),endTour({key:TOUR_KEYS.BUILDER_FORM_CREATE})},onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_FORM_CREATE_STEPS),builderStore.highlightSetting("steps","info")},align:"left-outside"}]},[TOUR_KEYS.BUILDER_FORM_VIEW_UPDATE]:{steps:[{id:TOUR_STEP_KEYS.BUILDER_FORM_ROW_ID,title:"Add row ID to update a row",layout:NewViewUpdateFormRowId,query:"#rowId-prop-control-wrap",onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_FORM_ROW_ID),builderStore.highlightSetting("rowId","info")},align:"left-outside"},{id:TOUR_STEP_KEYS.BUILDER_FORM_VIEW_UPDATE_STEPS,title:"Add multiple steps",layout:NewFormSteps,query:"#steps-prop-control-wrap",onComplete:()=>{builderStore.highlightSetting(),endTour({key:TOUR_KEYS.BUILDER_FORM_VIEW_UPDATE})},onLoad:()=>{tourEvent(TOUR_STEP_KEYS.BUILDER_FORM_VIEW_UPDATE_STEPS),builderStore.highlightSetting("steps","info")},align:"left-outside",scrollIntoView:!0}],onSkip:async()=>{builderStore.highlightSetting(),endTour({key:TOUR_KEYS.BUILDER_FORM_VIEW_UPDATE,skipped:!0})}}}),TOURS=getTours(),TOURSBYSTEP=Object.keys(TOURS).reduce((to,ue)=>(TOURS[ue].steps.forEach(eo=>{to[eo.id]=eo,to[eo.id].tour=ue}),to),{}),INITIAL_BUILDER_STATE={previousTopNavPath:{},highlightedSetting:null,propertyFocus:null,builderSidePanel:!1,onboarding:!1,tourNodes:null,tourKey:null,tourStepKey:null,hoveredComponentId:null};class BuilderStore extends BudiStore{constructor(){super({...INITIAL_BUILDER_STATE}),this.init=this.init.bind(this),this.refresh=this.refresh.bind(this),this.reset=this.reset.bind(this),this.highlightSetting=this.highlightSetting.bind(this),this.propertyFocus=this.propertyFocus.bind(this),this.hideBuilderSidePanel=this.hideBuilderSidePanel.bind(this),this.showBuilderSidePanel=this.showBuilderSidePanel.bind(this),this.setPreviousTopNavPath=this.setPreviousTopNavPath.bind(this),this.selectResource=this.selectResource.bind(this),this.registerTourNode=this.registerTourNode.bind(this),this.destroyTourNode=this.destroyTourNode.bind(this),this.startBuilderOnboarding=this.startBuilderOnboarding.bind(this)}init(ue){if(!(ue!=null&&ue.appId)){console.error("BuilderStore: No appId supplied for websocket");return}this.websocket||(this.websocket=createBuilderWebsocket(ue.appId))}refresh(){const ue=get_store_value(this.store);this.store.set(ue)}reset(){var ue;this.store.set({...INITIAL_BUILDER_STATE}),(ue=this.websocket)==null||ue.disconnect(),this.websocket=void 0}highlightSetting(ue,eo){this.update(no=>({...no,highlightedSetting:ue?{key:ue,type:eo||"info"}:null}))}propertyFocus(ue){this.update(eo=>({...eo,propertyFocus:ue}))}showBuilderSidePanel(){this.update(ue=>({...ue,builderSidePanel:!0}))}hideBuilderSidePanel(){this.update(ue=>({...ue,builderSidePanel:!1}))}setPreviousTopNavPath(ue,eo){this.update(no=>({...no,previousTopNavPath:{...no.previousTopNavPath||{},[ue]:eo}}))}selectResource(ue){var eo;(eo=this.websocket)==null||eo.emit(BuilderSocketEvent.SelectResource,{resourceId:ue})}registerTourNode(ue,eo){this.update(no=>({...no,tourNodes:{...no.tourNodes,[ue]:eo}}))}destroyTourNode(ue){var no;const eo=get_store_value(this.store);if((no=eo.tourNodes)!=null&&no[ue]){const ro={...eo.tourNodes};delete ro[ue],this.update(io=>({...io,tourNodes:ro}))}}startBuilderOnboarding(){this.update(ue=>({...ue,onboarding:!0,tourKey:TOUR_KEYS.TOUR_BUILDER_ONBOARDING}))}endBuilderOnboarding(){this.update(ue=>({...ue,onboarding:!1}))}setTour(ue){this.update(eo=>({...eo,tourStepKey:null,tourNodes:null,tourKey:ue||null}))}}const builderStore=new BuilderStore,INITIAL_HOVER_STATE={componentId:null};class HoverStore extends BudiStore{constructor(){super({...INITIAL_HOVER_STATE}),this.hover=this.hover.bind(this)}hover(ue,eo=!0){clearTimeout(this.hoverTimeout),ue?this.processHover(ue,eo):this.hoverTimeout=setTimeout(()=>{this.processHover(ue,eo)},10)}processHover(ue,eo){ue!==get_store_value(this.store).componentId&&(this.update(no=>(no.componentId=ue,no)),eo&&previewStore.sendEvent("hover-component",ue))}}const hoverStore=new HoverStore,INITIAL_PREVIEW_STATE={previewDevice:"desktop",previewEventHandler:null,showPreview:!1,selectedComponentContext:null};class PreviewStore extends BudiStore{constructor(){super(INITIAL_PREVIEW_STATE),this.setDevice=this.setDevice.bind(this),this.sendEvent=this.sendEvent.bind(this),this.registerEventHandler=this.registerEventHandler.bind(this),this.startDrag=this.startDrag.bind(this),this.stopDrag=this.stopDrag.bind(this),this.showPreview=this.showPreview.bind(this),this.setSelectedComponentContext=this.setSelectedComponentContext.bind(this),this.requestComponentContext=this.requestComponentContext.bind(this)}setDevice(ue){this.update(eo=>({...eo,previewDevice:ue}))}sendEvent(ue,eo){const{previewEventHandler:no}=get_store_value(this.store);no==null||no(ue,eo)}registerEventHandler(ue){this.update(eo=>({...eo,previewEventHandler:ue}))}async startDrag(ue){this.sendEvent("dragging-new-component",{dragging:!0,component:ue})}stopDrag(){this.sendEvent("dragging-new-component",{dragging:!1})}showPreview(ue){this.update(eo=>({...eo,showPreview:ue}))}setSelectedComponentContext(ue){this.update(eo=>({...eo,selectedComponentContext:ue}))}updateState(ue){this.sendEvent("builder-state",ue)}setUrlTestData(ue){this.sendEvent("builder-url-test-data",ue)}requestComponentContext(){this.sendEvent("request-context")}}const previewStore=new PreviewStore,TriggerStepID={ROW_SAVED:"ROW_SAVED",ROW_UPDATED:"ROW_UPDATED",ROW_DELETED:"ROW_DELETED",ROW_ACTION:"ROW_ACTION",WEBHOOK:"WEBHOOK",APP:"APP",CRON:"CRON"},ActionStepID={SEND_EMAIL_SMTP:"SEND_EMAIL_SMTP",CREATE_ROW:"CREATE_ROW",UPDATE_ROW:"UPDATE_ROW",DELETE_ROW:"DELETE_ROW",OUTGOING_WEBHOOK:"OUTGOING_WEBHOOK",EXECUTE_SCRIPT:"EXECUTE_SCRIPT",EXECUTE_QUERY:"EXECUTE_QUERY",SERVER_LOG:"SERVER_LOG",DELAY:"DELAY",FILTER:"FILTER",QUERY_ROWS:"QUERY_ROWS",LOOP:"LOOP",COLLECT:"COLLECT",TRIGGER_AUTOMATION_RUN:"TRIGGER_AUTOMATION_RUN",discord:"discord",slack:"slack",zapier:"zapier",integromat:"integromat",n8n:"n8n"},Features={LOOPING:"LOOPING"};class TableStore extends DerivedBudiStore{constructor(){const ue=eo=>derived(eo,no=>{var ro;return{...no,selected:(ro=no.list)==null?void 0:ro.find(io=>io._id===no.selectedTableId)}});super({list:[],selectedTableId:void 0},ue),this.select=this.select.bind(this)}async init(){return this.fetch()}async fetch(){const ue=await API.getTables();this.store.update(eo=>({...eo,list:ue}))}async singleFetch(ue){const eo=await API.getTable(ue);this.store.update(no=>{const ro=[];for(let io of no.list)eo._id===io._id?ro.push(eo):ro.push(io);return no.list=ro,no})}select(ue){this.store.update(eo=>({...eo,selectedTableId:ue}))}async save(ue){var lo;const eo=fp$1.cloneDeep(ue),no=get_store_value(this.store).list.filter(co=>co._id===ue._id)[0],ro=[];for(let co of Object.keys(eo.schema)){if(ro.indexOf(co.toLowerCase())!==-1){delete eo.schema[co];continue}const uo=eo.schema[co],fo=no==null?void 0:no.schema[co];fo!=null&&(fo==null?void 0:fo.type)!==uo.type&&!((lo=SWITCHABLE_TYPES[fo==null?void 0:fo.type])!=null&&lo.includes(uo.type))&&(eo.schema[co]=fo),uo.name&&uo.name!==co&&(eo.schema[uo.name]=uo,eo._rename={old:co,updated:uo.name},delete eo.schema[co]),ro.push(co.toLowerCase())}const io=await API.saveTable(eo);this.replaceTable(io._id,io),this.select(io._id);let oo=[];for(let co of Object.values((eo==null?void 0:eo.schema)||{}))co.type===FieldType.LINK&&oo.push(co.tableId);let ao=[];for(let co of Object.values((no==null?void 0:no.schema)||{}))co.type===FieldType.LINK&&ao.push(co.tableId);const so=[...new Set([...oo,...ao])];return so.length>3?await this.fetch():await Promise.all(so.map(co=>this.singleFetch(co))),io}async delete(ue){await API.deleteTable(ue._id,ue._rev),this.replaceTable(ue._id,null)}async saveField({originalName:ue,field:eo,primaryDisplay:no=!1,indexes:ro}){const io=fp$1.cloneDeep(get_store_value(this.derivedStore).selected);if(ue!=null&&ue!==eo.name&&(delete io.schema[ue],io._rename={old:ue,updated:eo.name}),no)io.primaryDisplay=eo.name;else if(io.primaryDisplay===ue){const oo=Object.keys(io.schema);io.primaryDisplay=oo.filter(ao=>ao!==ue||ao!==eo.name)[0]}ro&&(io.indexes=ro),io.schema={...io.schema,[eo.name]:fp$1.cloneDeep(eo)},await this.save(io)}async deleteField(ue){let eo=fp$1.cloneDeep(get_store_value(this.derivedStore).selected);delete eo.schema[ue.name],await this.save(eo)}replaceTable(ue,eo){if(!ue)return;if(!eo){this.store.update(ro=>({...ro,list:ro.list.filter(io=>io._id!==ue)}));return}const no=get_store_value(this.store).list.findIndex(ro=>ro._id===eo._id);no===-1?this.store.update(ro=>({...ro,list:[...ro.list,eo]})):eo&&this.store.update(ro=>(ro.list[no]={...eo,type:ro.list[no].type},ro))}removeDatasourceTables(ue){this.store.update(eo=>({...eo,list:eo.list.filter(no=>no.sourceId!==ue)}))}}const tables=new TableStore;class ViewV2Store extends DerivedBudiStore{constructor(){const ue=eo=>derived([eo,tables],([no,ro])=>{var oo;let io=[];return(oo=ro.list)==null||oo.forEach(ao=>{const so=Object.values((ao==null?void 0:ao.views)||{}).filter(isV2);io=io.concat(so)}),{...no,list:io,selected:io.find(ao=>ao.id===no.selectedViewId)}});super({selectedViewId:null},ue),this.select=this.select.bind(this)}select(ue){this.store.update(eo=>({...eo,selectedViewId:ue}))}async delete(ue){await API.viewV2.delete(ue.id),this.replaceView(ue.id,null)}async create(ue){const no=(await API.viewV2.create(ue)).data;return this.replaceView(no.id,no),no}async save(ue){const eo=await API.viewV2.update(ue),no=eo==null?void 0:eo.data;this.replaceView(ue.id,no)}replaceView(ue,eo){const no=get_store_value(this.derivedStore).list.find(io=>io.id===ue),ro=get_store_value(tables).list.findIndex(io=>io._id===(eo==null?void 0:eo.tableId)||io._id===(no==null?void 0:no.tableId));if(ro!==-1)if(!eo&&no){tables.update(io=>(delete io.list[ro].views[no.name],io));return}else!no&&eo?tables.update(io=>{var oo;return(oo=io.list[ro]).views??(oo.views={}),io.list[ro].views[eo.name]=eo,io}):no&&eo&&tables.update(io=>{var oo;return(oo=io.list[ro]).views??(oo.views={}),delete io.list[ro].views[no.name],io.list[ro].views[eo.name]=eo,io})}}const viewsV2=new ViewV2Store,initialState$1={};class RowActionStore extends BudiStore{constructor(){super(initialState$1),this.reset=()=>{this.set(initialState$1)},this.refreshRowActions=async ue=>{var io;if(!ue)return;let eo=(io=get_store_value(tables).list.find(oo=>oo._id===ue))==null?void 0:io._id;if(!eo){const oo=get_store_value(viewsV2).list.find(ao=>ao.id===ue);eo=oo==null?void 0:oo.tableId}if(!eo)return;const no=await API.rowActions.fetch(eo),ro=Object.values(no||{});this.update(oo=>({...oo,[eo]:ro}))},this.createRowAction=async(ue,eo,no)=>{if(!ue)return;if(!no){const io=get_store_value(this)[ue]||[];no=getSequentialName(io,"New row action ",{getName:oo=>oo.name})}if(!no)throw new Error("Failed to generate a unique name for the row action");const ro=await API.rowActions.create(ue,no);return eo?await Promise.all([this.enableView(ue,ro.id,eo),automationStore.actions.fetch()]):await Promise.all([this.refreshRowActions(ue),automationStore.actions.fetch()]),ro},this.enableView=async(ue,eo,no)=>{await API.rowActions.enableView(ue,eo,no),await this.refreshRowActions(ue)},this.disableView=async(ue,eo,no)=>{await API.rowActions.disableView(ue,eo,no),await this.refreshRowActions(ue)},this.delete=async(ue,eo)=>{await API.rowActions.delete(ue,eo),await this.refreshRowActions(ue)},this.trigger=async(ue,eo,no)=>{await API.rowActions.trigger(ue,eo,no)}}}const store=new RowActionStore,derivedStore=derived(store,to=>{const ue={};return Object.keys(to||{}).forEach(eo=>{ue[eo]=to[eo];for(let no of to[eo]){const ro=(no.allowedSources||[]).filter(io=>io!==eo);for(let io of ro)ue[io]??(ue[io]=[]),ue[io].push(no)}}),ue}),rowActions={...store,subscribe:derivedStore.subscribe},getNewStepName=(to,ue)=>{const eo=ue.name,no=io=>io.reduce((oo,ao)=>(ao.name&&ao.name.startsWith(eo)&&oo++,ao.stepId===AutomationActionStepId.BRANCH&&ao.inputs&&ao.inputs.children&&Object.values(ao.inputs.children).forEach(so=>{oo+=no(so)}),oo),0);let ro=0;return to!=null&&to.definition&&(ro=no(to.definition.steps)),ro===0?eo:`${eo} ${ro+1}`},initialAutomationState={automations:[],testResults:null,showTestPanel:!1,blockDefinitions:{TRIGGER:{},CREATABLE_TRIGGER:{},ACTION:{}},selectedAutomationId:null},getFinalDefinitions=(to,ue)=>{const eo={};return Object.entries(to).forEach(no=>{no[0]!==AutomationTriggerStepId.ROW_ACTION&&(eo[no[0]]=no[1])}),{TRIGGER:to,CREATABLE_TRIGGER:eo,ACTION:ue}},automationActions=to=>({moveBlock:async(ue,eo,no)=>{const ro=ue.at(-1),io=eo.at(-1),oo=(ro==null?void 0:ro.id)===(io==null?void 0:io.id),ao=(io==null?void 0:io.branchStepId)&&io.branchIdx===(ro==null?void 0:ro.branchIdx)&&(ro==null?void 0:ro.stepIdx)===0;if(oo||ao)return;const{deleted:so,newAutomation:lo}=to.actions.deleteBlock(ue,no),co={};to.actions.traverse(co,lo);let uo;io!=null&&io.branchStepId?(uo=co[io.branchStepId].pathTo,uo.push(io)):(io!=null&&io.id&&(uo=co[io.id].pathTo),uo.at(-1).stepIdx+=1);const fo=to.actions.updateStep(uo,lo,so,!0);try{await to.actions.save(fo)}catch(po){notifications.error("Error moving automation block"),console.error("Error moving automation block ",po)}},deleteBlock:(ue,eo)=>{let no=fp$1.cloneDeep(eo);const ro=[no.definition.trigger,...no.definition.steps];let io;return ue.forEach((oo,ao,so)=>{const lo=ao===so.length-1,{stepIdx:co,branchIdx:uo}=oo,fo=(po,ho)=>{const _o=po[ho],go=[_o.id],bo=[],vo={};po.forEach($o=>{const{blockToLoop:ko,id:So}=$o;ko&&(vo[ko]=So)});const yo=vo[_o.id];yo&&go.push(yo);for(let $o=po.length-1;$o>=0;$o--)if(go.includes(po[$o].id)){const[ko]=po.splice($o,1);bo.unshift(ko)}return{deleted:bo,newAutomation:no}};if(!io){lo?io=fo(no.definition.steps,co>0?co-1:0):io=ro[co];return}if(Number.isInteger(uo)){const po=io.inputs.branches[uo].id,ho=io.inputs.children[po],_o=ho[co];lo?io=fo(ho,co):io=_o}}),io},registerBlock:(ue,eo,no,ro)=>{ue[eo.id]={...ue[eo.id]||{},pathTo:no,terminating:ro||!1,...eo.blockToLoop?{blockToLoop:eo.blockToLoop}:{}},eo.blockToLoop&&(ue[eo.blockToLoop]={...ue[eo.blockToLoop]||{},looped:eo.id})},getPathSteps:(ue,eo)=>{const no=[eo.definition.trigger,...eo.definition.steps];let ro=[];return ue.forEach(io=>{var lo;const{stepIdx:oo,branchIdx:ao}=io;if(!ro.length){ro=no.slice(0,oo+1);return}let so=ro[ro.length-1];if(isBranchStep(so)&&Number.isInteger(ao)){const co=so.inputs.branches[ao].id,fo=(((lo=so.inputs.children)==null?void 0:lo[co])||[]).slice(0,oo+1);ro=ro.concat(fo)}}),ro},updateStep:(ue,eo,no,ro=!1)=>{let io=fp$1.cloneDeep(eo);const oo=(so,lo,co)=>{so.splice(lo,ro?0:Array.isArray(co)?co.length:1,...Array.isArray(co)?co:[co])};let ao=null;return ue.forEach((so,lo,co)=>{const{stepIdx:uo,branchIdx:fo}=so;let po=lo===co.length-1;if(!ao){let ho=Math.max(uo-1,0);if(po){oo(io.definition.steps,ho,no);return}ao=io.definition.steps[ho]}if(Number.isInteger(fo)){const ho=ao.inputs.branches[fo].id,_o=ao.inputs.children[ho];po?oo(_o,uo,no):ao=_o[uo]}}),io},buildEnvironmentBindings:()=>get_store_value(licensing).environmentVariablesEnabled?getEnvironmentBindings().map(ue=>({...ue,display:{...ue.display,rank:98}})):[],buildUserBindings:()=>getUserBindings().map(ue=>({...ue,category:"User",display:{...ue.display,rank:98}})),buildSettingBindings:()=>getSettingBindings().map(ue=>({...ue,display:{...ue.display,rank:98}})),getPathBindings:ue=>{var no,ro;const eo=(no=get_store_value(selectedAutomation))==null?void 0:no.blockRefs[ue];return to.actions.getAvailableBindings(eo,(ro=get_store_value(selectedAutomation))==null?void 0:ro.data)},traverse:(ue,eo)=>{var io;let no=[];if(!eo||!ue)return;(io=eo.definition)!=null&&io.trigger&&no.push(eo.definition.trigger),no=no.concat(eo.definition.steps||[]);const ro=(oo,ao,so,lo,co)=>{var fo,po;const uo=[...ao||[],{...Number.isInteger(lo)?{branchIdx:lo}:{},stepIdx:so,id:oo.id}];if(isBranchStep(oo)){const ho=((fo=oo.inputs)==null?void 0:fo.branches)||[],_o=((po=oo.inputs)==null?void 0:po.children)||{};ho.forEach((go,bo)=>{_o[go.id].forEach((vo,yo,$o)=>{const ko=$o.length-1===yo;ro(vo,uo,yo,bo,ko)})}),co=co&&!ho.length}to.actions.registerBlock(ue,oo,uo,co)};return no.forEach((oo,ao,so)=>{ro(oo,null,ao,null,so.length-1===ao)}),ue},getAvailableBindings:(ue,eo)=>{var lo,co,uo,fo,po,ho,_o;if(!ue||!(eo!=null&&eo.definition))return[];const no=(lo=get_store_value(selectedAutomation))==null?void 0:lo.blockRefs,ro=to.actions.getPathSteps(ue.pathTo,eo).slice(0,-1),io=to.actions.getPathSteps(ue.pathTo,eo).at(-1);let oo=[];const ao=(go,bo,vo,yo,$o,ko)=>{if(!go)return;const So=to.actions.determineRuntimeBinding(go,yo,$o,ko,eo,io,ro),Ao=to.actions.determineCategoryName(yo,$o,ko,so);oo.push(to.actions.createBindingObject(go,bo,vo,yo,so,$o,So,Ao,ko))};let so=0;for(let go=0;go<ro.length;go++){const bo=ro[go],vo=((co=eo.definition.stepNames)==null?void 0:co[bo.id])||bo.name;let yo=fp$1.cloneDeep((fo=(uo=bo==null?void 0:bo.schema)==null?void 0:uo.outputs)==null?void 0:fo.properties)??{},$o=!1;bo.blockToLoop&&($o=bo.stepId===ActionStepID.LOOP&&bo.blockToLoop in no),$o&&so==0&&(yo={currentItem:{type:AutomationIOType.STRING,description:"the item currently being executed"}});const ko=isTrigger(bo)?bo.icon:$o?"Reuse":bo.icon;if(go===0&&isTrigger(bo))if(isRowUpdateTrigger(bo)||isRowSaveTrigger(bo)){let So=get_store_value(tables).list.find(Ao=>Ao._id===bo.inputs.tableId);for(const Ao in So==null?void 0:So.schema)yo[Ao]={type:So.schema[Ao].type,subtype:So.schema[Ao].subtype};delete yo.row}else isAppTrigger(bo)&&(yo=Object.fromEntries(Object.keys(bo.inputs.fields||[]).map(So=>[So,{type:bo.inputs.fields[So]}])));if((po=no[bo.id])!=null&&po.looped){so++;const So=no[bo.id].looped,Ao=ro.find(Mo=>Mo.id===So);Ao?yo=fp$1.cloneDeep((_o=(ho=Ao.schema)==null?void 0:ho.outputs)==null?void 0:_o.properties):console.error("Loop block missing.")}Object.entries(yo).forEach(([So,Ao])=>{ao(So,Ao,ko,go,$o,vo)})}return ue.looped||(oo=oo.filter(go=>!go.readableBinding.includes("loop"))),oo},determineRuntimeBinding:(ue,eo,no,ro,io,oo,ao)=>{var lo,co,uo;let so;if(eo===0&&((lo=io.definition.trigger)==null?void 0:lo.event)===AutomationEventType.APP_TRIGGER)return`trigger.fields.${ue}`;if(eo===0&&(((co=io.definition.trigger)==null?void 0:co.event)===AutomationEventType.ROW_UPDATE||((uo=io.definition.trigger)==null?void 0:uo.event)===AutomationEventType.ROW_SAVE)&&!["id","revision","oldRow"].includes(ue))return`trigger.row.${ue}`;if(no)so=`loop.${ue}`;else if(eo===0)so=`trigger.${ue}`;else if((oo==null?void 0:oo.stepId)===AutomationActionStepId.EXECUTE_SCRIPT){const fo=ao[eo].id;if(!fo)return notifications.error("Error generating binding: Step ID not found."),null;so=`steps["${fo}"].${ue}`}else{const fo=ao[eo].id;if(!fo)return notifications.error("Error generating binding: Step ID not found."),null;so=`steps.${fo}.${ue}`}return so},determineCategoryName:(ue,eo,no,ro)=>ue===0?"Trigger outputs":eo?"Loop Outputs":no?`${no} outputs`:`Step ${ue-ro} outputs`,createBindingObject:(ue,eo,no,ro,io,oo,ao,so,lo)=>{const co=Object.values(FIELDS).find(uo=>uo.type===eo.type&&("subtype"in uo?uo.subtype===eo.subtype:!0));return{readableBinding:lo&&!oo&&ro!==0?`steps.${lo}.${ue}`:ao,runtimeBinding:ao,type:eo.type,description:eo.description,icon:no,category:so,display:{type:(co==null?void 0:co.name)||eo.type,name:ue,rank:oo?ro+1:ro-io}}},processBlockInputs:async(ue,eo)=>{var oo;let no={...ue,inputs:{...ue.inputs,...eo}};Object.keys(no.inputs).forEach(ao=>{const so=no.inputs[ao];(so==null||so==="")&&delete no.inputs[ao]});const ro=(oo=get_store_value(selectedAutomation))==null?void 0:oo.data;if(!ro)return!1;const io=to.actions.getUpdatedDefinition(ro,no);return JSON.stringify(io)===JSON.stringify(ro)?!1:io},updateBlockInputs:async(ue,eo)=>{const no=await to.actions.processBlockInputs(ue,eo);no!==!1&&await to.actions.save(no)},test:async(ue,eo)=>{var ro,io;let no;try{no=await API.testAutomation(ue._id,eo)}catch(oo){throw`Automation test failed - ${oo.message||oo.status||JSON.stringify(oo)}`}if(!(no!=null&&no.trigger)&&!((ro=no==null?void 0:no.steps)!=null&&ro.length)&&!(no!=null&&no.message))throw((io=no==null?void 0:no.err)==null?void 0:io.code)==="usage_limit_exceeded"?"You have exceeded your automation quota":"Something went wrong testing your automation";to.update(oo=>(oo.testResults=no,oo))},getUpdatedDefinition:(ue,eo)=>{var ro;let no;if(((ro=ue.definition.trigger)==null?void 0:ro.id)===eo.id)no=fp$1.cloneDeep(ue),no.definition.trigger=eo;else{const io=get_store_value(selectedAutomation).blockRefs[eo.id].pathTo;no=to.actions.updateStep(io,ue,eo)}return no},getLogs:async({automationId:ue,startDate:eo,status:no,page:ro}={})=>await API.getAutomationLogs({automationId:ue,startDate:eo,status:no,page:ro}),clearLogErrors:async({automationId:ue,appId:eo})=>{if(!ue||!eo)throw new Error("automationId and appId are required");return await API.clearAutomationLogErrors(ue,eo)},addTestDataToAutomation:ue=>{var no;let eo=fp$1.cloneDeep((no=get_store_value(selectedAutomation))==null?void 0:no.data);return eo&&(eo.testData={...eo.testData,...ue},eo)},constructBlock:(ue,eo,no)=>{var oo;const ro={...no,inputs:no.inputs||{},stepId:eo,type:ue,id:shortid.generate()},io=getNewStepName((oo=get_store_value(selectedAutomation))==null?void 0:oo.data,ro);return ro.name=io,ro},generateBranchBlock:()=>{const ue=get_store_value(to).blockDefinitions.ACTION.BRANCH;return to.actions.constructBlock("ACTION","BRANCH",ue)},addBlockToAutomation:async(ue,eo)=>{var ao;const no=(ao=get_store_value(selectedAutomation))==null?void 0:ao.data;if(!no)return;let ro=fp$1.cloneDeep(no);const io=[ro.definition.trigger,...ro.definition.steps];let oo;eo.forEach((so,lo,co)=>{var _o;const{stepIdx:uo,branchIdx:fo}=so,po=lo===co.length-1,ho=(go,bo)=>{const vo=!Number.isInteger(bo),yo=ue.blockToLoop||vo?bo:bo+1;go.splice(yo,0,ue)};if(!oo){po?(ho(ro.definition.steps,uo-1),oo=ue):oo=io[uo];return}if(Number.isInteger(fo)&&!Array.isArray(oo)&&isBranchStep(oo)){const go=oo.inputs.branches[fo].id,bo=((_o=oo.inputs.children)==null?void 0:_o[go])||[];po?(ho(bo,uo),oo=bo):oo=bo[uo]}});try{await to.actions.save(ro)}catch(so){notifications.error("Error adding automation block"),console.error("Automation adding block ",so)}},generateDefaultConditions:()=>{const ue={logicalOperator:UILogicalOperator.ALL,onEmptyFilter:EmptyFilterOption.RETURN_NONE,groups:[]};return{condition:buildQuery$1(ue),conditionUI:ue}},branchAutomation:async(ue,eo)=>{var uo;const no=ue.at(-1);let ro=fp$1.cloneDeep(eo),io,oo=!1;const ao=fo=>({name:fo,...to.actions.generateDefaultConditions(),id:shortid.generate()});ue.forEach((fo,po,ho)=>{const{stepIdx:_o,branchIdx:go}=fo,bo=po===ho.length-1;if(io||(bo?(io=ro.definition.steps,oo=!0):io=ro.definition.steps[_o-1]),Number.isInteger(go)){const vo=io.inputs.branches[go].id,yo=io.inputs.children[vo];io=bo?yo:yo[_o]}});const so=Math.max(no.stepIdx-1,0),lo=oo?so:no.stepIdx;if(((uo=io[lo])==null?void 0:uo.stepId)=="BRANCH"){let fo=io[lo].inputs.branches;const po=ao(`Branch ${fo.length+1}`);fo.splice(fo.length,0,po),io[lo].inputs.children[po.id]=[];try{await to.actions.save(ro)}catch(ho){notifications.error("Error adding branch to automation"),console.error("Error adding automation branch",ho)}return}const co=to.actions.generateBranchBlock();co.inputs.branches=Array.from({length:2}).map((fo,po)=>ao(`Branch ${po+1}`)),co.inputs.children=co.inputs.branches.reduce((fo,po,ho)=>(fo[po.id]=ho==0?io.slice(lo+1):[],fo),{}),io.splice(lo+1),io.push(co);try{await to.actions.save(ro)}catch(fo){notifications.error("Error adding branch to automation"),console.error("Error adding automation branch",fo)}},branchLeft:async(ue,eo,no)=>{const ro=to.actions.shiftBranch(ue,no);if(ro){const io=to.actions.updateStep(ue.slice(0,-1),eo,ro);await to.actions.save(io)}},branchRight:async(ue,eo,no)=>{const ro=to.actions.shiftBranch(ue,no,1);if(ro){const io=to.actions.updateStep(ue.slice(0,-1),eo,ro);await to.actions.save(io)}},shiftBranch:(ue,eo,no=-1)=>{let ro=fp$1.cloneDeep(eo);const oo=ue.at(-1).branchIdx;if(!ro.inputs.branches[oo+no]){console.error("Invalid index");return}let[ao]=ro.inputs.branches.splice(oo+no,1);return ro.inputs.branches.splice(oo,0,ao),ro},deleteBranch:async(ue,eo)=>{let no=fp$1.cloneDeep(eo),ro=[];ue.forEach((io,oo,ao)=>{const{stepIdx:so,branchIdx:lo}=io,co=oo===ao.length-1;if(!ro.length){if(co){ro=no.definition.steps;return}ro=[{node:no.definition.steps[so-1],context:no.definition.steps}]}const uo=ro.at(-1);if(Number.isInteger(lo)){const fo=uo.node.inputs.branches[lo].id,po=uo.node.inputs.children[fo];if(co){const ho=uo.node.inputs.branches.length==2;if(uo.node.inputs.branches.splice(lo,1),delete uo.node.inputs.children[fo],ho){const _o=uo.node.inputs.branches[0].id,go=uo.node.inputs.children[_o],bo=ro.at(-1).context;bo.pop(),bo.splice(bo.length,0,...go)}return}ro.push({node:po[so],context:po})}});try{await to.actions.save(no)}catch(io){notifications.error("Error deleting automation branch"),console.error("Error deleting automation branch",io)}},saveAutomationName:async(ue,eo)=>{var oo;const no=(oo=get_store_value(selectedAutomation))==null?void 0:oo.data;let ro=fp$1.cloneDeep(no);if(!ro)return;const io=eo.trim();ro.definition.stepNames={...ro.definition.stepNames,[ue]:io},await to.actions.save(ro)},deleteAutomationName:async ue=>{var ro;const eo=(ro=get_store_value(selectedAutomation))==null?void 0:ro.data;let no=fp$1.cloneDeep(eo);!eo||!no||(no!=null&&no.definition.stepNames&&delete no.definition.stepNames[ue],await to.actions.save(no))},deleteAutomationBlock:async ue=>{var ro;const eo=(ro=get_store_value(selectedAutomation))==null?void 0:ro.data;if(!eo)return;const{newAutomation:no}=to.actions.deleteBlock(ue,eo);try{await to.actions.save(no)}catch(io){notifications.error("Error deleting automation block"),console.error("Automation deleting block ",io)}},replace:(ue,eo)=>{if(!eo)to.store.update(no=>{var ro;return no.automations=no.automations.filter(io=>io._id!==ue),ue===no.selectedAutomationId&&to.actions.select(((ro=no.automations[0])==null?void 0:ro._id)||null),no});else{const no=get_store_value(to.store).automations.findIndex(ro=>ro._id===eo._id);no===-1?to.store.update(ro=>({...ro,automations:[...ro.automations,eo]})):to.store.update(ro=>(ro.automations[no]=eo,ro))}},create:async(ue,eo)=>{const no={name:ue,type:"automation",appId:get_store_value(appStore).appId,definition:{steps:[],trigger:eo},disabled:!1};return await to.actions.save(no)},duplicate:async ue=>await to.actions.save({...ue,name:`${ue.name} - copy`,_id:void 0,_rev:void 0}),toggleDisabled:async ue=>{let eo;try{if(eo=to.actions.getDefinition(ue),!eo)return;eo.disabled=!eo.disabled,await to.actions.save(eo),notifications.success(`Automation ${eo.disabled?"disabled":"enabled"} successfully`)}catch{notifications.error(`Error ${eo!=null&&eo.disabled?"disabling":"enabling"} automation`)}},definitions:async()=>{const ue=await API.getAutomationDefinitions();return to.update(eo=>(eo.blockDefinitions=getFinalDefinitions(ue.trigger,ue.action),eo)),ue},fetch:async()=>{const[ue,eo]=await Promise.all([API.getAutomations(),API.getAutomationDefinitions()]);to.update(no=>(no.automations=ue.automations,no.automations.sort((ro,io)=>ro.name<io.name?-1:1),no.blockDefinitions=getFinalDefinitions(eo.trigger,eo.action),no))},select:ue=>{!ue||ue===get_store_value(to).selectedAutomationId||to.update(eo=>(eo.selectedAutomationId=ue,eo.testResults=null,eo.showTestPanel=!1,eo))},getDefinition:ue=>{var eo;return(eo=get_store_value(to.store).automations)==null?void 0:eo.find(no=>no._id===ue)},save:async ue=>{const eo=await API.updateAutomation(ue);return await to.actions.fetch(),to.actions.select(eo.automation._id),eo.automation},delete:async ue=>{isRowAction(ue)?await rowActions.delete(ue.definition.trigger.inputs.tableId,ue.definition.trigger.inputs.rowActionId):await API.deleteAutomation(ue._id,ue._rev),to.update(no=>{var ro;return no.automations=no.automations.filter(io=>io._id!==ue._id),ue._id===no.selectedAutomationId&&(no.selectedAutomationId=((ro=no.automations[0])==null?void 0:ro._id)||null),no})}});class AutomationStore extends BudiStore{constructor(){super(initialAutomationState),this.actions=automationActions(this),this.history=createHistoryStore({getDoc:this.actions.getDefinition.bind(this),selectDoc:this.actions.select.bind(this)});const ue=this.actions.save.bind(this.actions),eo=this.actions.delete.bind(this.actions);this.actions.save=this.history.wrapSaveDoc(ue),this.actions.delete=this.history.wrapDeleteDoc(eo)}}const automationStore=new AutomationStore,automationHistoryStore=automationStore.history;class SelectedAutomationStore extends DerivedBudiStore{constructor(ue){const eo=()=>derived(ue,no=>{var ao;if(!no.selectedAutomationId)return{data:null,blockRefs:{},...no};const ro=(ao=no.automations)==null?void 0:ao.find(so=>so._id===no.selectedAutomationId);if(!ro)return{data:null,blockRefs:{},...no};const io={},oo=fp$1.cloneDeep(ro);return oo&&(ue.actions.traverse(io,oo),Object.values(io).filter(so=>so.terminating).forEach(so=>{ue.actions.getPathSteps(so.pathTo,oo).forEach((lo,co,uo)=>{migrateReferencesInObject({obj:lo,originalIndex:co,steps:uo})})})),{data:oo,blockRefs:io,...no}});super(initialAutomationState,eo)}}const selectedAutomation=new SelectedAutomationStore(automationStore);class UserStore extends BudiStore{constructor(){super([])}init(ue){this.set(ue)}updateUser(ue){const eo=get_store_value(this);eo.some(no=>no.sessionId===ue.sessionId)?this.update(no=>{const ro=no.findIndex(io=>io.sessionId===ue.sessionId);return no[ro]=ue,no.slice()}):this.set([...eo,ue])}removeUser(ue){this.update(eo=>eo.filter(no=>no.sessionId!==ue))}reset(){this.set([])}}const userStore=new UserStore,userSelectedResourceMap=derived(userStore,to=>{let ue={};return to.forEach(eo=>{var ro;const no=(ro=eo.builderMetadata)==null?void 0:ro.selectedResourceId;no&&(ue[no]||(ue[no]=[]),ue[no].push(eo))}),ue}),isOnlyUser=derived(userStore,to=>to.length<2),createDeploymentStore=()=>{let to=writable([]);const ue=async()=>{try{to.set(await API.getAppDeployments())}catch{notifications.error("Error fetching deployments")}};return{subscribe:to.subscribe,load:ue}},deploymentStore=createDeploymentStore(),INITIAL_CONTEXT_MENU_STATE={id:null,items:[],position:{x:0,y:0},visible:!1};function createViewsStore(){const to=writable({...INITIAL_CONTEXT_MENU_STATE}),ue=(no,ro,io)=>{to.set({id:no,items:ro,position:io,visible:!0})},eo=()=>{to.set({...INITIAL_CONTEXT_MENU_STATE})};return{subscribe:to.subscribe,open:ue,close:eo}}const contextMenuStore=createViewsStore();class SnippetStore extends BudiStore{constructor(){super([]),this.syncMetadata=ue=>{this.set((ue==null?void 0:ue.snippets)||[])},this.saveSnippet=async ue=>{const eo=[...get_store_value(this).filter(ro=>ro.name!==ue.name),ue],no=await API.saveAppMetadata(get_store_value(appStore).appId,{snippets:eo});this.syncMetadata(no)},this.deleteSnippet=async ue=>{const eo=get_store_value(this).filter(ro=>ro.name!==ue),no=await API.saveAppMetadata(get_store_value(appStore).appId,{snippets:eo});this.syncMetadata(no)}}}const snippets$1=new SnippetStore;class TableImportError extends Error{constructor(ue){super(),this.name="TableImportError",this.errors=ue}get description(){let ue="";for(const eo in this.errors)ue+=`${eo}: ${this.errors[eo]}
|
|
520
520
|
`;return ue}}class DatasourceStore extends DerivedBudiStore{constructor(){const ue=eo=>derived([eo,tables],([no,ro])=>{var so,lo,co,uo;let io=(so=no.rawList)==null?void 0:so.find(fo=>fo._id===BUDIBASE_INTERNAL_DB_ID),oo=(lo=no.rawList)==null?void 0:lo.filter(fo=>fo._id!==BUDIBASE_INTERNAL_DB_ID);if(io){const fo=(co=ro.list)==null?void 0:co.filter(po=>po.sourceId===BUDIBASE_INTERNAL_DB_ID&&po._id!==TableNames.USERS);io={...io,entities:fo}}let ao=[];return(uo=io==null?void 0:io.entities)!=null&&uo.length&&ao.push(io),ao=ao.concat(oo||[]),{...no,list:ao,selected:ao==null?void 0:ao.find(fo=>fo._id===no.selectedDatasourceId),hasDefaultData:ao==null?void 0:ao.some(fo=>fo._id===DEFAULT_BB_DATASOURCE_ID),hasData:(ao==null?void 0:ao.length)>0}});super({rawList:[],selectedDatasourceId:null},ue),this.fetch=this.fetch.bind(this),this.init=this.fetch.bind(this),this.select=this.select.bind(this),this.updateSchema=this.updateSchema.bind(this),this.create=this.create.bind(this),this.delete=this.deleteDatasource.bind(this),this.save=this.save.bind(this),this.replaceDatasource=this.replaceDatasource.bind(this),this.getTableNames=this.getTableNames.bind(this)}async fetch(){const ue=await API.getDatasources();this.store.update(eo=>({...eo,rawList:ue}))}async init(){return this.fetch()}select(ue){this.store.update(eo=>({...eo,selectedDatasourceId:ue}))}updateDatasourceInStore(ue,{ignoreErrors:eo}={}){const{datasource:no,errors:ro}=ue;if(!eo&&ro&&Object.keys(ro).length>0)throw new TableImportError(ro);return this.replaceDatasource(no._id,no),this.select(no._id),no}async updateSchema(ue,eo){const no=await API.buildDatasourceSchema(ue==null?void 0:ue._id,eo);this.updateDatasourceInStore(no)}sourceCount(ue){return get_store_value(this.store).rawList.filter(eo=>eo.source===ue).length}async checkDatasourceValidity(ue,eo){var no;if((no=ue.features)!=null&&no[DatasourceFeature.CONNECTION_CHECKING]){const{connected:ro,error:io}=await API.validateDatasource(eo);return ro?{valid:!0}:{valid:!1,error:io}}return{valid:!0}}async create({integration:ue,config:eo}){const no=this.sourceCount(ue.name),ro=no===0?"":` ${no+1}`,io={type:"datasource",source:ue.name,config:eo,name:`${ue.friendlyName}${ro}`,plus:ue.plus&&ue.name!==IntegrationTypes.REST,isSQL:ue.isSQL},{valid:oo,error:ao}=await this.checkDatasourceValidity(ue,io);if(!oo)throw new Error(`Unable to connect - ${ao}`);const so=await API.createDatasource({datasource:io,fetchSchema:ue.plus});return this.updateDatasourceInStore(so,{ignoreErrors:!0})}async save({integration:ue,datasource:eo}){if(!(await this.checkDatasourceValidity(ue,eo)).valid)throw new Error("Unable to connect");const no=await API.updateDatasource(eo);return this.updateDatasourceInStore(no)}async deleteDatasource(ue){!(ue!=null&&ue._id)||!(ue!=null&&ue._rev)||(await API.deleteDatasource(ue._id,ue._rev),this.replaceDatasource(ue._id))}async delete(ue){return this.deleteDatasource(ue)}replaceDatasource(ue,eo){if(!ue)return;if(!eo){this.store.update(ro=>({...ro,rawList:ro.rawList.filter(io=>io._id!==ue)})),tables.removeDatasourceTables(ue),queries.removeDatasourceQueries(ue);return}const no=get_store_value(this.store).rawList.findIndex(ro=>ro._id===eo._id);no===-1?(this.store.update(ro=>({...ro,rawList:[...ro.rawList,eo]})),tables.fetch()):eo&&this.store.update(ro=>(ro.rawList[no]=eo,ro))}async getTableNames(ue){return(await API.fetchInfoForDatasource(ue)).tableNames||[]}}const datasources=new DatasourceStore,INITIAL_STATE={},createIntegrationsStore=()=>{const to=writable(INITIAL_STATE);return{...to,init:async()=>{const eo=await API.getIntegrations(),no=Object.entries(eo).reduce((ro,[io,oo])=>(oo&&(ro[io]=oo),ro),{});to.set(no)}}},integrations=createIntegrationsStore(),sortQueries=to=>{to.sort((ue,eo)=>ue.name.localeCompare(eo.name))};class QueryStore extends DerivedBudiStore{constructor(){const ue=eo=>derived(eo,no=>{var ro;return{list:no.list,selectedQueryId:no.selectedQueryId,selected:(ro=no.list)==null?void 0:ro.find(io=>io._id===no.selectedQueryId)}});super({list:[],selectedQueryId:null},ue),this.init=this.fetch,this.select=this.select.bind(this)}async fetch(){const ue=await API.getQueries();sortQueries(ue),this.store.update(eo=>({...eo,list:ue}))}async save(ue,eo){const no=get_store_value(integrations),ro=get_store_value(datasources).list.filter(oo=>oo._id===ue);if(ro.length!==0){const ao=no[ro[0].source].query[eo.queryVerb].readable;ao&&(eo.readable=ao)}eo.datasourceId=ue;const io=await API.saveQuery(eo);return this.store.update(oo=>{const ao=oo.list.findIndex(lo=>lo._id===io._id),so=oo.list;return ao>=0?so.splice(ao,1,io):so.push(io),sortQueries(so),{list:so,selectedQueryId:io._id||null}}),io}async importQueries(ue){return await API.importQueries(ue)}select(ue){this.store.update(eo=>({...eo,selectedQueryId:ue}))}async preview(ue){const eo=await API.previewQuery(ue),no={};for(let[ro,io]of Object.entries(eo.schema))no[ro]=io||{type:"string"};return{...eo,schema:no,rows:eo.rows||[]}}async delete(ue){if(!ue._id||!ue._rev)throw new Error("Query ID or Revision is missing");await API.deleteQuery(ue._id,ue._rev),this.store.update(eo=>({...eo,list:eo.list.filter(no=>no._id!==ue._id)}))}async duplicate(ue){let eo=get_store_value(this.store).list;const no={...ue},ro=ue.datasourceId;return delete no._id,delete no._rev,no.name=duplicateName(ue.name,eo.map(io=>io.name)),await this.save(ro,no)}removeDatasourceQueries(ue){this.store.update(eo=>({...eo,list:eo.list.filter(no=>no.datasourceId!==ue)}))}}const queries=new QueryStore;class ViewsStore extends DerivedBudiStore{constructor(){const ue=eo=>derived([eo,tables],([no,ro])=>{var oo;let io=[];return(oo=ro.list)==null||oo.forEach(ao=>{const so=Object.values((ao==null?void 0:ao.views)||{}).filter(lo=>!isV2(lo));io=io.concat(so)}),{selectedViewName:no.selectedViewName,list:io,selected:io.find(ao=>ao.name===no.selectedViewName)}});super({selectedViewName:null},ue),this.select=eo=>{this.store.update(no=>({...no,selectedViewName:eo}))},this.delete=async eo=>{if(!eo.name)throw new Error("View name is required");await API.deleteView(eo.name),tables.update(no=>{const ro=no.list.find(io=>io._id===eo.tableId);return ro!=null&&ro.views&&eo.name&&delete ro.views[eo.name],{...no}})},this.save=async eo=>{if(!eo.name)throw new Error("View name is required");const no=await API.saveView(eo);this.select(eo.name),tables.update(ro=>{const io=ro.list.find(oo=>oo._id===eo.tableId);return io!=null&&io.views&&eo.name&&(eo.originalName&&delete io.views[eo.originalName],io.views[eo.name]=no),{...ro}})},this.select=this.select.bind(this)}}const views=new ViewsStore;function reduceBy(to,ue){return ue.reduce((eo,no)=>(eo[no[to]]=no,eo),{})}const friendlyNameByType={viewV2:"view"},validationKeyByType={table:"tableId",view:"name",viewV2:"id",query:"_id",custom:null,link:"rowId",field:"value",jsonarray:"value"},screenComponentsList=derived([selectedScreen],([to])=>to?findAllComponents(to.props):[]),screenComponentErrorList=derived([selectedScreen,tables,views,viewsV2,queries,componentStore],([to,ue,eo,no,ro,io])=>{if(!to)return[];const oo=to,ao={...reduceBy("_id",ue.list),...reduceBy("name",eo.list),...reduceBy("id",no.list),...reduceBy("_id",ro.list)},{components:so}=io,lo=[];function co(uo,fo){lo.push(...getInvalidDatasources(oo,uo,ao,so)),lo.push(...getMissingRequiredSettings(uo,so)),lo.push(...getMissingAncestors(uo,so,fo));for(const po of uo._children||[])co(po,[...fo,uo._component])}return co(to==null?void 0:to.props,[]),lo});function getInvalidDatasources(to,ue,eo,no){var ao,so;const ro=[],io=["table","dataSource"],oo=(so=(ao=no[ue._component])==null?void 0:ao.settings)==null?void 0:so.filter(lo=>io.includes(lo.type));if(oo)for(const lo of oo){const co=ue[lo.key];if(!co)continue;const{label:uo}=co,fo=co.type,po=validationKeyByType[fo];if(!po)continue;const ho=getBindableProperties(to,ue._id),_o={...reduceBy("rowId",extractRelationships(ho)),...reduceBy("value",extractFields(ho)),...reduceBy("value",extractJSONArrayFields(ho))},go=co[po];if(!{...eo,..._o}[go]){const bo=friendlyNameByType[fo]??fo;ro.push({componentId:ue._id,key:lo.key,label:lo.label||lo.key,message:`The ${bo} named "${uo}" could not be found`,errorType:"setting",cause:"invalid"})}}return ro}function parseDependsOn(to){return to===void 0?{}:typeof to=="string"?{key:to}:{key:to.setting,value:to.value}}function getMissingRequiredSettings(to,ue){const eo=[],no=ue[to._component],io=getSettingsDefinition(no).filter(oo=>{let ao=to[oo.key]==null||to[oo.key]==="",so=oo.required&&ao;if(oo.dependsOn){const{key:lo,value:co}=parseDependsOn(oo.dependsOn),uo=to[lo],{key:fo,value:po}=parseDependsOn(oo.sectionDependsOn),ho=to[fo];if(co==null&&uo==null||co!=null&&co!==uo||po!=null&&po!==ho)return!1}return so});return io!=null&&io.length&&eo.push(...io.map(oo=>({componentId:to._id,key:oo.key,label:oo.label||oo.key,message:`Add the <mark>${oo.label}</mark> setting to start using your component`,errorType:"setting",cause:"missing"}))),eo}const BudibasePrefix="@budibase/standard-components/";function getMissingAncestors(to,ue,eo){var oo;const no=ue[to._component];if(!((oo=no==null?void 0:no.requiredAncestors)!=null&&oo.length))return[];const ro=[],io=no.requiredAncestors.filter(ao=>!eo.includes(`${BudibasePrefix}${ao}`));if(io.length){const ao=so=>so.endsWith("s")?`${so}'`:`${so}s`;ro.push(...io.map(so=>{const lo=ue[`${BudibasePrefix}${so}`];return{componentId:to._id,message:`${ao(no.name)} need to be inside a
|
|
521
521
|
<mark>${lo.name}</mark>`,errorType:"ancestor-setting",ancestor:{name:lo.name,fullType:`${BudibasePrefix}${so}`}}}))}return ro}const screenComponentErrors=derived([screenComponentErrorList],([to])=>to.reduce((ue,eo)=>{var no;return ue[no=eo.componentId]??(ue[no]=[]),ue[eo.componentId].push(eo),ue},{}));class PermissionStore extends BudiStore{constructor(){super([]),this.save=async ue=>{const{level:eo,role:no,resource:ro}=ue;return await API.updatePermissionForResource(ro,no,eo)},this.remove=async ue=>{const{level:eo,role:no,resource:ro}=ue;return await API.removePermissionFromResource(ro,no,eo)},this.forResource=async ue=>(await API.getPermissionForResource(ue)).permissions,this.forResourceDetailed=async ue=>await API.getPermissionForResource(ue),this.getDependantsInfo=async ue=>await API.getDependants(ue)}}const permissions=new PermissionStore;class RoleStore extends DerivedBudiStore{constructor(){const ue=eo=>derived(eo,no=>no.map(ro=>{var io,oo,ao;return{...ro,uiMetadata:{displayName:((io=ro.uiMetadata)==null?void 0:io.displayName)||ro.name,color:((oo=ro.uiMetadata)==null?void 0:oo.color)||"var(--spectrum-global-color-magenta-400)",description:((ao=ro.uiMetadata)==null?void 0:ao.description)||"Custom role"}}}));super([],ue),this.setRoles=eo=>{this.set(eo.sort((no,ro)=>{var lo,co;const io=getRolePriority(no._id),oo=getRolePriority(ro._id);if(io!==oo)return io>oo?-1:1;const ao=((lo=no.uiMetadata)==null?void 0:lo.displayName)||no.name,so=((co=ro.uiMetadata)==null?void 0:co.displayName)||ro.name;return ao<so?-1:1}))},this.fetch=async()=>{const eo=await API.getRoles();this.setRoles(eo)},this.fetchByAppId=async eo=>{const{roles:no}=await API.getRolesForApp(eo);this.setRoles(no)},this.delete=async eo=>{!eo._id||!eo._rev||(await API.deleteRole(eo._id,eo._rev),await this.fetch())},this.save=async eo=>{const no=await API.saveRole(eo);return await this.fetch(),no},this.replace=(eo,no)=>{if(!eo)return;if(!no){this.update(io=>io.filter(oo=>oo._id!==eo));return}const ro=get_store_value(this).findIndex(io=>io._id===no._id);ro===-1?this.update(io=>[...io,no]):no&&this.update(io=>(io[ro]=no,[...io]))}}}const roles=new RoleStore,getIntegrationOrder=to=>to?to===DatasourceTypes.API?1:to===DatasourceTypes.RELATIONAL?2:to===DatasourceTypes.NON_RELATIONAL?3:to.charCodeAt(0)+4:Number.MAX_SAFE_INTEGER;class SortedIntegrationStore extends BudiStore{constructor(){super([]);const ue=derived(integrations,eo=>Object.entries(eo).map(([io,oo])=>({name:io,...oo})).sort((io,oo)=>{const ao=getIntegrationOrder(io.type),so=getIntegrationOrder(oo.type);return ao===so?io.friendlyName.localeCompare(oo.friendlyName):ao<so?-1:1}));this.subscribe=ue.subscribe}}const sortedIntegrations=new SortedIntegrationStore,INITIAL_FLAGS_STATE={flags:{}};class FlagsStore extends BudiStore{constructor(){super(INITIAL_FLAGS_STATE),this.fetch=this.fetch.bind(this),this.updateFlag=this.updateFlag.bind(this),this.toggleUiFeature=this.toggleUiFeature.bind(this)}async fetch(){const ue=await API.getFlags();this.update(eo=>({...eo,flags:ue}))}async updateFlag(ue,eo){await API.updateFlag(ue,eo),await this.fetch()}async toggleUiFeature(ue){await API.toggleUiFeature(ue)}}const flags=new FlagsStore;class ComponentTreeNodesStore extends BudiStore{constructor(){super({},{persistence:{type:PersistenceType.SESSION,key:"openNodes"}})}toggleNode(ue){this.update(eo=>(eo[`nodeOpen-${ue}`]=!eo[`nodeOpen-${ue}`],eo))}expandNodes(ue){this.update(eo=>{const no=Object.fromEntries(ue.map(ro=>[`nodeOpen-${ro}`,!0]));return{...eo,...no}})}collapseNodes(ue){this.update(eo=>{const no=Object.fromEntries(ue.map(ro=>[`nodeOpen-${ro}`,!1]));return{...eo,...no}})}makeNodeVisible(ue){const eo=get_store_value(selectedScreen);if(!eo)return console.error("Invalid node "+ue),{};const ro=findComponentPath(eo.props,ue).map(io=>io._id);this.update(io=>{const oo=Object.fromEntries(ro.map(ao=>[`nodeOpen-${ao}`,!0]));return{...io,...oo}})}isNodeExpanded(ue){return!!get_store_value(this)[`nodeOpen-${ue}`]}}const componentTreeNodesStore=new ComponentTreeNodesStore,appPublished=derived([appStore,appsStore,deploymentStore],([to,ue,eo])=>{const no=ue.apps.find(io=>io.devId===to.appId),ro=eo.filter(io=>io.status===DeploymentStatus.SUCCESS);return(no==null?void 0:no.status)==="published"&&ro.length>0}),reset=()=>{appStore.reset(),builderStore.reset(),screenStore.reset(),componentStore.reset(),layoutStore.reset(),navigationStore.reset(),rowActions.reset()},refreshBuilderData=async()=>{await Promise.all([automationStore.actions.fetch(),datasources.init(),integrations.init(),queries.init(),tables.init(),roles.fetch(),flags.fetch()])},resetBuilderHistory=()=>{screenStore.history.reset(),automationHistoryStore.reset()},initialise=async to=>{const{application:ue}=to;appStore.syncAppPackage(to),await Promise.all([appStore.syncAppRoutes(),componentStore.refreshDefinitions(ue==null?void 0:ue.appId)]),builderStore.init(ue),navigationStore.syncAppNavigation(ue==null?void 0:ue.navigation),themeStore.syncAppTheme(ue),snippets$1.syncMetadata(ue),screenStore.syncAppScreens(to),layoutStore.syncAppLayouts(to),resetBuilderHistory(),await refreshBuilderData()},API=createAPIClient({attachHeaders:to=>{let ue=get_store_value(appStore).appId;ue&&(to["x-budibase-app-id"]=ue);const eo=get_store_value(auth).user;eo!=null&&eo.csrfToken&&(to["x-csrf-token"]=eo.csrfToken)},onError:to=>{const{url:ue,message:eo,status:no,method:ro,handled:io}=to||{};if(!io){console.error("Unhandled error from API client",to);return}console.warn(`[Builder] HTTP ${no} on ${ro}:${ue}
|
|
522
522
|
${eo}`),no===403&&(removeCookie(Cookies.Auth),!ue.includes("self")&&!ue.includes("login")&&location.reload())},onMigrationDetected:to=>{var eo;const ue=`/builder/app/updating/${to}`;window.location.pathname!==ue&&((eo=get_store_value(navigation))==null||eo.goto(`${ue}?returnUrl=${encodeURIComponent(window.location.pathname)}`))}}),Logo$2="/builder/assets/bb-emblem-5d011fde.svg",handleError=to=>{let ue={...to};return Object.keys(ue).reduce((eo,no)=>(ue[no]&&(eo[no]=ue[no]),eo),{})},passwordsMatch=(to,ue)=>{let eo=ue==null?void 0:ue.trim(),no=to==null?void 0:to.trim();return typeof eo=="string"&&typeof no=="string"&&eo==no},index_svelte_svelte_type_style_lang$w="";function create_default_slot_8$F(to){let ue;return{c(){ue=text("Create an admin user")},m(eo,no){insert$2(eo,ue,no)},d(eo){eo&&detach(ue)}}}function create_default_slot_7$Q(to){let ue;return{c(){ue=text("The admin user has access to everything in Budibase.")},m(eo,no){insert$2(eo,ue,no)},d(eo){eo&&detach(ue)}}}function create_default_slot_6$10(to){let ue,eo,no,ro,io,oo,ao;return ro=new Heading({props:{size:"M",$$slots:{default:[create_default_slot_8$F]},$$scope:{ctx:to}}}),oo=new Body({props:{$$slots:{default:[create_default_slot_7$Q]},$$scope:{ctx:to}}}),{c(){ue=element("img"),no=space$1(),create_component(ro.$$.fragment),io=space$1(),create_component(oo.$$.fragment),attr(ue,"alt","logo"),src_url_equal(ue.src,eo=Logo$2)||attr(ue,"src",eo),attr(ue,"class","svelte-1rej6a3")},m(so,lo){insert$2(so,ue,lo),insert$2(so,no,lo),mount_component(ro,so,lo),insert$2(so,io,lo),mount_component(oo,so,lo),ao=!0},p(so,lo){const co={};lo&262144&&(co.$$scope={dirty:lo,ctx:so}),ro.$set(co);const uo={};lo&262144&&(uo.$$scope={dirty:lo,ctx:so}),oo.$set(uo)},i(so){ao||(transition_in(ro.$$.fragment,so),transition_in(oo.$$.fragment,so),ao=!0)},o(so){transition_out(ro.$$.fragment,so),transition_out(oo.$$.fragment,so),ao=!1},d(so){so&&(detach(ue),detach(no),detach(io)),destroy_component(ro,so),destroy_component(oo,so)}}}function create_default_slot_5$1i(to){let ue,eo,no,ro,io,oo;return ue=new FancyInput({props:{label:"Email",value:to[2].email,validate:to[9],disabled:to[3],error:to[1].email}}),ue.$on("change",to[10]),no=new FancyInput({props:{label:"Password",value:to[2].password,type:"password",validate:to[11],error:to[1].password,disabled:to[3]}}),no.$on("change",to[12]),io=new FancyInput({props:{label:"Repeat Password",value:to[2].confirmationPassword,type:"password",validate:to[13],error:to[1].confirmationPassword,disabled:to[3]}}),io.$on("change",to[14]),{c(){create_component(ue.$$.fragment),eo=space$1(),create_component(no.$$.fragment),ro=space$1(),create_component(io.$$.fragment)},m(ao,so){mount_component(ue,ao,so),insert$2(ao,eo,so),mount_component(no,ao,so),insert$2(ao,ro,so),mount_component(io,ao,so),oo=!0},p(ao,so){const lo={};so&4&&(lo.value=ao[2].email),so&6&&(lo.validate=ao[9]),so&8&&(lo.disabled=ao[3]),so&2&&(lo.error=ao[1].email),ue.$set(lo);const co={};so&4&&(co.value=ao[2].password),so&22&&(co.validate=ao[11]),so&2&&(co.error=ao[1].password),so&8&&(co.disabled=ao[3]),no.$set(co);const uo={};so&4&&(uo.value=ao[2].confirmationPassword),so&6&&(uo.validate=ao[13]),so&2&&(uo.error=ao[1].confirmationPassword),so&8&&(uo.disabled=ao[3]),io.$set(uo)},i(ao){oo||(transition_in(ue.$$.fragment,ao),transition_in(no.$$.fragment,ao),transition_in(io.$$.fragment,ao),oo=!0)},o(ao){transition_out(ue.$$.fragment,ao),transition_out(no.$$.fragment,ao),transition_out(io.$$.fragment,ao),oo=!1},d(ao){ao&&(detach(eo),detach(ro)),destroy_component(ue,ao),destroy_component(no,ao),destroy_component(io,ao)}}}function create_default_slot_4$1H(to){let ue,eo,no={$$slots:{default:[create_default_slot_5$1i]},$$scope:{ctx:to}};return ue=new FancyForm({props:no}),to[15](ue),{c(){create_component(ue.$$.fragment)},m(ro,io){mount_component(ue,ro,io),eo=!0},p(ro,io){const oo={};io&262174&&(oo.$$scope={dirty:io,ctx:ro}),ue.$set(oo)},i(ro){eo||(transition_in(ue.$$.fragment,ro),eo=!0)},o(ro){transition_out(ue.$$.fragment,ro),eo=!1},d(ro){to[15](null),destroy_component(ue,ro)}}}function create_default_slot_3$2e(to){let ue;return{c(){ue=text("Create super admin user")},m(eo,no){insert$2(eo,ue,no)},d(eo){eo&&detach(ue)}}}function create_default_slot_2$2T(to){let ue,eo;return ue=new Button({props:{cta:!0,size:"L",disabled:Object.keys(to[1]).length>0||to[3],$$slots:{default:[create_default_slot_3$2e]},$$scope:{ctx:to}}}),ue.$on("click",to[5]),{c(){create_component(ue.$$.fragment)},m(no,ro){mount_component(ue,no,ro),eo=!0},p(no,ro){const io={};ro&10&&(io.disabled=Object.keys(no[1]).length>0||no[3]),ro&262144&&(io.$$scope={dirty:ro,ctx:no}),ue.$set(io)},i(no){eo||(transition_in(ue.$$.fragment,no),eo=!0)},o(no){transition_out(ue.$$.fragment,no),eo=!1},d(no){destroy_component(ue,no)}}}function create_default_slot_1$41(to){let ue,eo,no,ro,io,oo;return ue=new Layout$n({props:{justifyItems:"center",noPadding:!0,$$slots:{default:[create_default_slot_6$10]},$$scope:{ctx:to}}}),no=new Layout$n({props:{gap:"S",noPadding:!0,$$slots:{default:[create_default_slot_4$1H]},$$scope:{ctx:to}}}),io=new Layout$n({props:{gap:"XS",noPadding:!0,justifyItems:"center",$$slots:{default:[create_default_slot_2$2T]},$$scope:{ctx:to}}}),{c(){create_component(ue.$$.fragment),eo=space$1(),create_component(no.$$.fragment),ro=space$1(),create_component(io.$$.fragment)},m(ao,so){mount_component(ue,ao,so),insert$2(ao,eo,so),mount_component(no,ao,so),insert$2(ao,ro,so),mount_component(io,ao,so),oo=!0},p(ao,so){const lo={};so&262144&&(lo.$$scope={dirty:so,ctx:ao}),ue.$set(lo);const co={};so&262175&&(co.$$scope={dirty:so,ctx:ao}),no.$set(co);const uo={};so&262154&&(uo.$$scope={dirty:so,ctx:ao}),io.$set(uo)},i(ao){oo||(transition_in(ue.$$.fragment,ao),transition_in(no.$$.fragment,ao),transition_in(io.$$.fragment,ao),oo=!0)},o(ao){transition_out(ue.$$.fragment,ao),transition_out(no.$$.fragment,ao),transition_out(io.$$.fragment,ao),oo=!1},d(ao){ao&&(detach(eo),detach(ro)),destroy_component(ue,ao),destroy_component(no,ao),destroy_component(io,ao)}}}function create_default_slot$5N(to){let ue,eo;return ue=new Layout$n({props:{gap:"M",noPadding:!0,$$slots:{default:[create_default_slot_1$41]},$$scope:{ctx:to}}}),{c(){create_component(ue.$$.fragment)},m(no,ro){mount_component(ue,no,ro),eo=!0},p(no,ro){const io={};ro&262175&&(io.$$scope={dirty:ro,ctx:no}),ue.$set(io)},i(no){eo||(transition_in(ue.$$.fragment,no),eo=!0)},o(no){transition_out(ue.$$.fragment,no),eo=!1},d(no){destroy_component(ue,no)}}}function create_fragment$9g(to){let ue,eo,no,ro;return ue=new TestimonialPage({props:{$$slots:{default:[create_default_slot$5N]},$$scope:{ctx:to}}}),{c(){create_component(ue.$$.fragment)},m(io,oo){mount_component(ue,io,oo),eo=!0,no||(ro=listen(window,"keydown",to[6]),no=!0)},p(io,[oo]){const ao={};oo&262175&&(ao.$$scope={dirty:oo,ctx:io}),ue.$set(ao)},i(io){eo||(transition_in(ue.$$.fragment,io),eo=!0)},o(io){transition_out(ue.$$.fragment,io),eo=!1},d(io){destroy_component(ue,io),no=!1,ro()}}}function instance$9i(to,ue,eo){let no,ro,io,oo,ao;component_subscribe(to,goto,ko=>eo(17,io=ko)),component_subscribe(to,admin,ko=>eo(7,oo=ko)),component_subscribe(to,auth,ko=>eo(8,ao=ko));let so,lo={},co={},uo=!1;async function fo(){if(so.validate(),!(Object.keys(lo).length>0)){eo(3,uo=!0);try{let ko={...co,tenantId:no};delete ko.confirmationPassword,await API.createAdminUser(ko),notifications.success("Admin user created"),await admin.init(),await auth.login(co==null?void 0:co.email.trim(),co==null?void 0:co.password),io("../portal")}catch(ko){eo(3,uo=!1),notifications.error(ko.message||"Failed to create admin user")}}}const po=ko=>{ko.key==="Enter"&&fo()},ho=()=>{let ko={email:co.email?void 0:"Please enter a valid email"};eo(1,lo=handleError({...lo,...ko}))},_o=ko=>{eo(2,co={...co,email:ko.detail})},go=()=>{let ko={};co.password?co.password.length<ro?ko.password=`Password must be at least ${ro} characters`:ko.password=void 0:ko.password="Please enter a password",ko.confirmationPassword=!passwordsMatch(co.password,co.confirmationPassword)&&co.confirmationPassword?"Passwords must match":void 0,eo(1,lo=handleError({...lo,...ko}))},bo=ko=>{eo(2,co={...co,password:ko.detail})},vo=()=>{let ko={confirmationPassword:!passwordsMatch(co.password,co.confirmationPassword)&&co.password?"Passwords must match":void 0};eo(1,lo=handleError({...lo,...ko}))},yo=ko=>{eo(2,co={...co,confirmationPassword:ko.detail})};function $o(ko){binding_callbacks[ko?"unshift":"push"](()=>{so=ko,eo(0,so)})}return to.$$.update=()=>{to.$$.dirty&256&&(no=ao.tenantId),to.$$.dirty&128&&eo(4,ro=oo.passwordMinLength??12)},[so,lo,co,uo,ro,fo,po,oo,ao,ho,_o,go,bo,vo,yo,$o]}class Admin extends SvelteComponent{constructor(ue){super(),init$3(this,ue,instance$9i,create_fragment$9g,safe_not_equal,{})}}function create_if_block$4h(to){let ue;const eo=to[4].default,no=create_slot(eo,to,to[3],null);return{c(){no&&no.c()},m(ro,io){no&&no.m(ro,io),ue=!0},p(ro,io){no&&no.p&&(!ue||io&8)&&update_slot_base(no,eo,ro,ro[3],ue?get_slot_changes(eo,ro[3],io,null):get_all_dirty_from_scope(ro[3]),null)},i(ro){ue||(transition_in(no,ro),ue=!0)},o(ro){transition_out(no,ro),ue=!1},d(ro){no&&no.d(ro)}}}function create_fragment$9f(to){let ue,eo,no=to[0]&&create_if_block$4h(to);return{c(){no&&no.c(),ue=empty$4()},m(ro,io){no&&no.m(ro,io),insert$2(ro,ue,io),eo=!0},p(ro,[io]){ro[0]?no?(no.p(ro,io),io&1&&transition_in(no,1)):(no=create_if_block$4h(ro),no.c(),transition_in(no,1),no.m(ue.parentNode,ue)):no&&(group_outros(),transition_out(no,1,1,()=>{no=null}),check_outros())},i(ro){eo||(transition_in(no),eo=!0)},o(ro){transition_out(no),eo=!1},d(ro){ro&&detach(ue),no&&no.d(ro)}}}function instance$9h(to,ue,eo){let no,ro,io,oo;component_subscribe(to,redirect,co=>eo(6,io=co)),component_subscribe(to,admin,co=>eo(2,oo=co));let{$$slots:ao={},$$scope:so}=ue,lo=!1;return onMount(()=>{var co,uo;(uo=(co=oo==null?void 0:oo.checklist)==null?void 0:co.adminUser)!=null&&uo.checked||ro?io("../"):eo(0,lo=!0)}),to.$$set=co=>{"$$scope"in co&&eo(3,so=co.$$scope)},to.$$.update=()=>{to.$$.dirty&4&&eo(1,no=oo.cloud),to.$$.dirty&6&&(ro=no&&!oo.disableAccountPortal)},[lo,no,oo,so,ao]}let Layout$m=class extends SvelteComponent{constructor(ue){super(),init$3(this,ue,instance$9h,create_fragment$9f,safe_not_equal,{})}};function instance$9g(to,ue,eo){let no;return component_subscribe(to,redirect,ro=>eo(0,no=ro)),no("../design"),[]}class Fallback extends SvelteComponent{constructor(ue){super(),init$3(this,ue,instance$9g,null,safe_not_equal,{})}}function instance$9f(to,ue,eo){let no;return component_subscribe(to,redirect,ro=>eo(0,no=ro)),no("./data"),[]}let U5Bapplicationu5D$1=class extends SvelteComponent{constructor(ue){super(),init$3(this,ue,instance$9f,null,safe_not_equal,{})}};function create_fragment$9e(to){let ue,eo,no,ro,io,oo;return{c(){ue=svg_element("svg"),eo=svg_element("path"),no=svg_element("path"),ro=svg_element("path"),io=svg_element("path"),oo=svg_element("path"),attr(eo,"d",`M169.341 104.792C168.322 101.71 165.652 99.5637 162.199 99.0487C160.57
|
package/builder/index.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<link href="/builder/fonts/source-sans-pro/600.css" rel="stylesheet" />
|
|
10
10
|
<link href="/builder/fonts/source-sans-pro/700.css" rel="stylesheet" />
|
|
11
11
|
<link href="/builder/fonts/remixicon.css" rel="stylesheet" />
|
|
12
|
-
<script type="module" crossorigin src="/builder/assets/index-
|
|
12
|
+
<script type="module" crossorigin src="/builder/assets/index-6d226d86.js"></script>
|
|
13
13
|
<link rel="stylesheet" href="/builder/assets/index-8a7e067c.css">
|
|
14
14
|
</head>
|
|
15
15
|
|
package/dist/yarn.lock
CHANGED
|
@@ -2695,6 +2695,13 @@
|
|
|
2695
2695
|
dependencies:
|
|
2696
2696
|
regenerator-runtime "^0.14.0"
|
|
2697
2697
|
|
|
2698
|
+
"@babel/runtime@^7.8.3":
|
|
2699
|
+
version "7.26.9"
|
|
2700
|
+
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433"
|
|
2701
|
+
integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==
|
|
2702
|
+
dependencies:
|
|
2703
|
+
regenerator-runtime "^0.14.0"
|
|
2704
|
+
|
|
2698
2705
|
"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.25.9", "@babel/template@^7.3.3":
|
|
2699
2706
|
version "7.25.9"
|
|
2700
2707
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016"
|
|
@@ -9035,7 +9042,14 @@ co-body@^5.1.1:
|
|
|
9035
9042
|
raw-body "^2.2.0"
|
|
9036
9043
|
type-is "^1.6.14"
|
|
9037
9044
|
|
|
9038
|
-
co@^
|
|
9045
|
+
co-wrap-all@^1.0.0:
|
|
9046
|
+
version "1.0.0"
|
|
9047
|
+
resolved "https://registry.yarnpkg.com/co-wrap-all/-/co-wrap-all-1.0.0.tgz#370ae3e8333510a53f6b2f7fdfbe4568a11b7ecf"
|
|
9048
|
+
integrity sha512-aru6gLi2vTUazr+MxVm3Rv6ST7/EKtFj9BrfkcOrbCO2Qv6LqJdE71m88HhHiBEviKw/ucVrwoGLrq2xHpOsJA==
|
|
9049
|
+
dependencies:
|
|
9050
|
+
co "^4.0.0"
|
|
9051
|
+
|
|
9052
|
+
co@^4.0.0, co@^4.6.0:
|
|
9039
9053
|
version "4.6.0"
|
|
9040
9054
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
|
9041
9055
|
integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
|
|
@@ -13188,7 +13202,7 @@ ioredis@5.3.2:
|
|
|
13188
13202
|
redis-parser "^3.0.0"
|
|
13189
13203
|
standard-as-callback "^2.1.0"
|
|
13190
13204
|
|
|
13191
|
-
ioredis@^4.28.5:
|
|
13205
|
+
ioredis@^4.14.1, ioredis@^4.28.5:
|
|
13192
13206
|
version "4.28.5"
|
|
13193
13207
|
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f"
|
|
13194
13208
|
integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==
|
|
@@ -14695,6 +14709,16 @@ koa-pino-logger@4.0.0:
|
|
|
14695
14709
|
dependencies:
|
|
14696
14710
|
pino-http "^6.5.0"
|
|
14697
14711
|
|
|
14712
|
+
koa-redis@^4.0.1:
|
|
14713
|
+
version "4.0.1"
|
|
14714
|
+
resolved "https://registry.yarnpkg.com/koa-redis/-/koa-redis-4.0.1.tgz#57ac1b46d9ab851221a9f4952c1e8d4bf289db40"
|
|
14715
|
+
integrity sha512-o2eTVNo1NBnloeUGhHed5Q2ZvJSLpUEj/+E1/7oH5EmH8WuQ+QLdl/VawkshxdFQ47W1p6V09lM3hCTu7D0YnQ==
|
|
14716
|
+
dependencies:
|
|
14717
|
+
"@babel/runtime" "^7.8.3"
|
|
14718
|
+
co-wrap-all "^1.0.0"
|
|
14719
|
+
debug "^4.1.1"
|
|
14720
|
+
ioredis "^4.14.1"
|
|
14721
|
+
|
|
14698
14722
|
koa-router@^10.0.0:
|
|
14699
14723
|
version "10.1.1"
|
|
14700
14724
|
resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-10.1.1.tgz#20809f82648518b84726cd445037813cd99f17ff"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "3.4.
|
|
4
|
+
"version": "3.4.17",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -216,5 +216,5 @@
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
},
|
|
219
|
-
"gitHead": "
|
|
219
|
+
"gitHead": "b11920670c98e8e400c9c3a665c539d63cb7b8fa"
|
|
220
220
|
}
|
|
@@ -1,511 +1,532 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AIOperationEnum,
|
|
3
3
|
CalculationType,
|
|
4
|
+
Datasource,
|
|
4
5
|
FieldType,
|
|
5
6
|
RelationshipType,
|
|
6
|
-
SourceName,
|
|
7
7
|
Table,
|
|
8
8
|
ViewV2,
|
|
9
9
|
ViewV2Type,
|
|
10
10
|
} from "@budibase/types"
|
|
11
11
|
import { buildSqlFieldList } from "../sqlUtils"
|
|
12
12
|
import { structures } from "../../../../routes/tests/utilities"
|
|
13
|
-
import { sql } from "@budibase/backend-core"
|
|
14
13
|
import { generator } from "@budibase/backend-core/tests"
|
|
15
14
|
import { generateViewID } from "../../../../../db/utils"
|
|
16
15
|
|
|
17
|
-
import sdk from "../../../../../sdk"
|
|
18
|
-
import { cloneDeep } from "lodash"
|
|
19
16
|
import { utils } from "@budibase/shared-core"
|
|
17
|
+
import {
|
|
18
|
+
DatabaseName,
|
|
19
|
+
datasourceDescribe,
|
|
20
|
+
} from "../../../../../integrations/tests/utils"
|
|
21
|
+
import { context } from "@budibase/backend-core"
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}))
|
|
25
|
-
const getTableMock = sdk.views.getTable as jest.MockedFunction<
|
|
26
|
-
typeof sdk.views.getTable
|
|
27
|
-
>
|
|
28
|
-
|
|
29
|
-
describe("buildSqlFieldList", () => {
|
|
30
|
-
let allTables: Record<string, Table>
|
|
31
|
-
|
|
32
|
-
class TableConfig {
|
|
33
|
-
private _table: Table & { _id: string }
|
|
34
|
-
|
|
35
|
-
constructor(name: string) {
|
|
36
|
-
this._table = {
|
|
37
|
-
...structures.tableForDatasource({
|
|
38
|
-
type: "datasource",
|
|
39
|
-
source: SourceName.POSTGRES,
|
|
40
|
-
}),
|
|
41
|
-
name,
|
|
42
|
-
_id: sql.utils.buildExternalTableId("ds_id", name),
|
|
43
|
-
schema: {
|
|
44
|
-
name: {
|
|
45
|
-
name: "name",
|
|
46
|
-
type: FieldType.STRING,
|
|
47
|
-
},
|
|
48
|
-
description: {
|
|
49
|
-
name: "description",
|
|
50
|
-
type: FieldType.STRING,
|
|
51
|
-
},
|
|
52
|
-
amount: {
|
|
53
|
-
name: "amount",
|
|
54
|
-
type: FieldType.NUMBER,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
}
|
|
23
|
+
const descriptions = datasourceDescribe({
|
|
24
|
+
only: [DatabaseName.POSTGRES],
|
|
25
|
+
})
|
|
58
26
|
|
|
59
|
-
|
|
60
|
-
|
|
27
|
+
if (descriptions.length) {
|
|
28
|
+
describe.each(descriptions)(
|
|
29
|
+
"buildSqlFieldList ($dbName)",
|
|
30
|
+
({ config, dsProvider }) => {
|
|
31
|
+
let allTables: Record<string, Table>
|
|
32
|
+
let datasource: Datasource
|
|
33
|
+
|
|
34
|
+
beforeEach(async () => {
|
|
35
|
+
const ds = await dsProvider()
|
|
36
|
+
datasource = ds.datasource!
|
|
37
|
+
allTables = {}
|
|
38
|
+
})
|
|
61
39
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return this
|
|
65
|
-
}
|
|
40
|
+
class TableConfig {
|
|
41
|
+
private _table: Table
|
|
66
42
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
| FieldType.STRING
|
|
71
|
-
| FieldType.NUMBER
|
|
72
|
-
| FieldType.FORMULA
|
|
73
|
-
| FieldType.AI,
|
|
74
|
-
options?: { visible: boolean }
|
|
75
|
-
) {
|
|
76
|
-
switch (type) {
|
|
77
|
-
case FieldType.NUMBER:
|
|
78
|
-
case FieldType.STRING:
|
|
79
|
-
this._table.schema[name] = {
|
|
43
|
+
constructor(name: string) {
|
|
44
|
+
this._table = {
|
|
45
|
+
...structures.tableForDatasource(datasource),
|
|
80
46
|
name,
|
|
81
|
-
|
|
82
|
-
|
|
47
|
+
schema: {
|
|
48
|
+
name: {
|
|
49
|
+
name: "name",
|
|
50
|
+
type: FieldType.STRING,
|
|
51
|
+
},
|
|
52
|
+
description: {
|
|
53
|
+
name: "description",
|
|
54
|
+
type: FieldType.STRING,
|
|
55
|
+
},
|
|
56
|
+
amount: {
|
|
57
|
+
name: "amount",
|
|
58
|
+
type: FieldType.NUMBER,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
83
61
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
withHiddenField(field: string) {
|
|
65
|
+
this._table.schema[field].visible = false
|
|
66
|
+
return this
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
withField(
|
|
70
|
+
name: string,
|
|
71
|
+
type:
|
|
72
|
+
| FieldType.STRING
|
|
73
|
+
| FieldType.NUMBER
|
|
74
|
+
| FieldType.FORMULA
|
|
75
|
+
| FieldType.AI,
|
|
76
|
+
options?: { visible: boolean }
|
|
77
|
+
) {
|
|
78
|
+
switch (type) {
|
|
79
|
+
case FieldType.NUMBER:
|
|
80
|
+
case FieldType.STRING:
|
|
81
|
+
this._table.schema[name] = {
|
|
82
|
+
name,
|
|
83
|
+
type,
|
|
84
|
+
...options,
|
|
85
|
+
}
|
|
86
|
+
break
|
|
87
|
+
case FieldType.FORMULA:
|
|
88
|
+
this._table.schema[name] = {
|
|
89
|
+
name,
|
|
90
|
+
type,
|
|
91
|
+
formula: "any",
|
|
92
|
+
...options,
|
|
93
|
+
}
|
|
94
|
+
break
|
|
95
|
+
case FieldType.AI:
|
|
96
|
+
this._table.schema[name] = {
|
|
97
|
+
name,
|
|
98
|
+
type,
|
|
99
|
+
operation: AIOperationEnum.PROMPT,
|
|
100
|
+
...options,
|
|
101
|
+
}
|
|
102
|
+
break
|
|
103
|
+
default:
|
|
104
|
+
utils.unreachable(type)
|
|
91
105
|
}
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
return this
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
withRelation(name: string, toTableId: string) {
|
|
94
110
|
this._table.schema[name] = {
|
|
95
111
|
name,
|
|
96
|
-
type,
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
type: FieldType.LINK,
|
|
113
|
+
relationshipType: RelationshipType.ONE_TO_MANY,
|
|
114
|
+
fieldName: "link",
|
|
115
|
+
foreignKey: "link",
|
|
116
|
+
tableId: toTableId,
|
|
99
117
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
return this
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
withPrimary(field: string) {
|
|
122
|
+
this._table.primary = [field]
|
|
123
|
+
return this
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
withDisplay(field: string) {
|
|
127
|
+
this._table.primaryDisplay = field
|
|
128
|
+
return this
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async create() {
|
|
132
|
+
const table = await config.api.table.save(this._table)
|
|
133
|
+
allTables[table.name] = table
|
|
134
|
+
return table
|
|
135
|
+
}
|
|
103
136
|
}
|
|
104
|
-
return this
|
|
105
|
-
}
|
|
106
137
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
name,
|
|
110
|
-
type: FieldType.LINK,
|
|
111
|
-
relationshipType: RelationshipType.ONE_TO_MANY,
|
|
112
|
-
fieldName: "link",
|
|
113
|
-
tableId: toTableId,
|
|
114
|
-
}
|
|
115
|
-
return this
|
|
116
|
-
}
|
|
138
|
+
class ViewConfig {
|
|
139
|
+
private _view: ViewV2
|
|
117
140
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
141
|
+
constructor(table: Table) {
|
|
142
|
+
this._view = {
|
|
143
|
+
version: 2,
|
|
144
|
+
id: generateViewID(table._id!),
|
|
145
|
+
name: generator.word(),
|
|
146
|
+
tableId: table._id!,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
withVisible(field: string) {
|
|
151
|
+
this._view.schema ??= {}
|
|
152
|
+
this._view.schema[field] ??= {}
|
|
153
|
+
this._view.schema[field].visible = true
|
|
154
|
+
return this
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
withHidden(field: string) {
|
|
158
|
+
this._view.schema ??= {}
|
|
159
|
+
this._view.schema[field] ??= {}
|
|
160
|
+
this._view.schema[field].visible = false
|
|
161
|
+
return this
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
withRelationshipColumns(
|
|
165
|
+
field: string,
|
|
166
|
+
columns: Record<string, { visible: boolean }>
|
|
167
|
+
) {
|
|
168
|
+
this._view.schema ??= {}
|
|
169
|
+
this._view.schema[field] ??= {}
|
|
170
|
+
this._view.schema[field].columns = columns
|
|
171
|
+
return this
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
withCalculation(
|
|
175
|
+
name: string,
|
|
176
|
+
field: string,
|
|
177
|
+
calculationType: CalculationType
|
|
178
|
+
) {
|
|
179
|
+
this._view.type = ViewV2Type.CALCULATION
|
|
180
|
+
this._view.schema ??= {}
|
|
181
|
+
this._view.schema[name] = {
|
|
182
|
+
field,
|
|
183
|
+
calculationType,
|
|
184
|
+
visible: true,
|
|
185
|
+
}
|
|
186
|
+
return this
|
|
187
|
+
}
|
|
122
188
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
189
|
+
async create() {
|
|
190
|
+
return await config.api.viewV2.create(this._view)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
127
193
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
constructor(table: Table) {
|
|
138
|
-
this._table = table
|
|
139
|
-
this._view = {
|
|
140
|
-
version: 2,
|
|
141
|
-
id: generateViewID(table._id!),
|
|
142
|
-
name: generator.word(),
|
|
143
|
-
tableId: table._id!,
|
|
194
|
+
const buildSqlFieldListInApp: typeof buildSqlFieldList = async (
|
|
195
|
+
table,
|
|
196
|
+
allTables,
|
|
197
|
+
opts
|
|
198
|
+
) => {
|
|
199
|
+
return context.doInAppContext(config.getAppId(), () =>
|
|
200
|
+
buildSqlFieldList(table, allTables, opts)
|
|
201
|
+
)
|
|
144
202
|
}
|
|
145
|
-
}
|
|
146
203
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
204
|
+
describe("table", () => {
|
|
205
|
+
it("extracts fields from table schema", async () => {
|
|
206
|
+
const table = await new TableConfig("table").create()
|
|
207
|
+
const result = await buildSqlFieldListInApp(table, {})
|
|
208
|
+
expect(result).toEqual([
|
|
209
|
+
"table.name",
|
|
210
|
+
"table.description",
|
|
211
|
+
"table.amount",
|
|
212
|
+
"table.id",
|
|
213
|
+
])
|
|
214
|
+
})
|
|
153
215
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
216
|
+
it("excludes hidden fields", async () => {
|
|
217
|
+
const table = await new TableConfig("table")
|
|
218
|
+
.withHiddenField("description")
|
|
219
|
+
.create()
|
|
220
|
+
const result = await buildSqlFieldListInApp(table, {})
|
|
221
|
+
expect(result).toEqual(["table.name", "table.amount", "table.id"])
|
|
222
|
+
})
|
|
160
223
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
224
|
+
it("excludes non-sql fields fields", async () => {
|
|
225
|
+
const table = await new TableConfig("table")
|
|
226
|
+
.withField("formula", FieldType.FORMULA)
|
|
227
|
+
.withField("ai", FieldType.AI)
|
|
228
|
+
.create()
|
|
229
|
+
|
|
230
|
+
const result = await buildSqlFieldListInApp(table, {})
|
|
231
|
+
expect(result).toEqual([
|
|
232
|
+
"table.name",
|
|
233
|
+
"table.description",
|
|
234
|
+
"table.amount",
|
|
235
|
+
"table.id",
|
|
236
|
+
])
|
|
237
|
+
})
|
|
170
238
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
239
|
+
it("includes hidden fields if there is a formula column", async () => {
|
|
240
|
+
const table = await new TableConfig("table")
|
|
241
|
+
.withHiddenField("description")
|
|
242
|
+
.withField("formula", FieldType.FORMULA)
|
|
243
|
+
.create()
|
|
244
|
+
|
|
245
|
+
const result = await buildSqlFieldListInApp(table, {})
|
|
246
|
+
expect(result).toEqual([
|
|
247
|
+
"table.name",
|
|
248
|
+
"table.description",
|
|
249
|
+
"table.amount",
|
|
250
|
+
"table.id",
|
|
251
|
+
])
|
|
252
|
+
})
|
|
185
253
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
it("excludes hidden fields", async () => {
|
|
209
|
-
const table = new TableConfig("table")
|
|
210
|
-
.withHiddenField("description")
|
|
211
|
-
.create()
|
|
212
|
-
const result = await buildSqlFieldList(table, {})
|
|
213
|
-
expect(result).toEqual(["table.name", "table.amount"])
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
it("excludes non-sql fields fields", async () => {
|
|
217
|
-
const table = new TableConfig("table")
|
|
218
|
-
.withField("formula", FieldType.FORMULA)
|
|
219
|
-
.withField("ai", FieldType.AI)
|
|
220
|
-
.withRelation("link", "otherTableId")
|
|
221
|
-
.create()
|
|
222
|
-
|
|
223
|
-
const result = await buildSqlFieldList(table, {})
|
|
224
|
-
expect(result).toEqual([
|
|
225
|
-
"table.name",
|
|
226
|
-
"table.description",
|
|
227
|
-
"table.amount",
|
|
228
|
-
])
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
it("includes hidden fields if there is a formula column", async () => {
|
|
232
|
-
const table = new TableConfig("table")
|
|
233
|
-
.withHiddenField("description")
|
|
234
|
-
.withField("formula", FieldType.FORMULA)
|
|
235
|
-
.create()
|
|
236
|
-
|
|
237
|
-
const result = await buildSqlFieldList(table, {})
|
|
238
|
-
expect(result).toEqual([
|
|
239
|
-
"table.name",
|
|
240
|
-
"table.description",
|
|
241
|
-
"table.amount",
|
|
242
|
-
])
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
it("includes relationships fields when flagged", async () => {
|
|
246
|
-
const otherTable = new TableConfig("linkedTable")
|
|
247
|
-
.withField("id", FieldType.NUMBER)
|
|
248
|
-
.withPrimary("id")
|
|
249
|
-
.withDisplay("name")
|
|
250
|
-
.create()
|
|
251
|
-
|
|
252
|
-
const table = new TableConfig("table")
|
|
253
|
-
.withRelation("link", otherTable._id)
|
|
254
|
-
.create()
|
|
255
|
-
|
|
256
|
-
const result = await buildSqlFieldList(table, allTables, {
|
|
257
|
-
relationships: true,
|
|
258
|
-
})
|
|
259
|
-
expect(result).toEqual([
|
|
260
|
-
"table.name",
|
|
261
|
-
"table.description",
|
|
262
|
-
"table.amount",
|
|
263
|
-
"linkedTable.id",
|
|
264
|
-
"linkedTable.name",
|
|
265
|
-
])
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
it("includes all relationship fields if there is a formula column", async () => {
|
|
269
|
-
const otherTable = new TableConfig("linkedTable")
|
|
270
|
-
.withField("hidden", FieldType.STRING, { visible: false })
|
|
271
|
-
.create()
|
|
272
|
-
|
|
273
|
-
const table = new TableConfig("table")
|
|
274
|
-
.withRelation("link", otherTable._id)
|
|
275
|
-
.withField("formula", FieldType.FORMULA)
|
|
276
|
-
.create()
|
|
277
|
-
|
|
278
|
-
const result = await buildSqlFieldList(table, allTables, {
|
|
279
|
-
relationships: true,
|
|
280
|
-
})
|
|
281
|
-
expect(result).toEqual([
|
|
282
|
-
"table.name",
|
|
283
|
-
"table.description",
|
|
284
|
-
"table.amount",
|
|
285
|
-
"linkedTable.name",
|
|
286
|
-
"linkedTable.description",
|
|
287
|
-
"linkedTable.amount",
|
|
288
|
-
"linkedTable.hidden",
|
|
289
|
-
])
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
it("never includes non-sql columns from relationships", async () => {
|
|
293
|
-
const otherTable = new TableConfig("linkedTable")
|
|
294
|
-
.withField("id", FieldType.NUMBER)
|
|
295
|
-
.withField("hidden", FieldType.STRING, { visible: false })
|
|
296
|
-
.withField("formula", FieldType.FORMULA)
|
|
297
|
-
.withField("ai", FieldType.AI)
|
|
298
|
-
.withRelation("link", "otherTableId")
|
|
299
|
-
.create()
|
|
300
|
-
|
|
301
|
-
const table = new TableConfig("table")
|
|
302
|
-
.withRelation("link", otherTable._id)
|
|
303
|
-
.withField("formula", FieldType.FORMULA)
|
|
304
|
-
.create()
|
|
305
|
-
|
|
306
|
-
const result = await buildSqlFieldList(table, allTables, {
|
|
307
|
-
relationships: true,
|
|
308
|
-
})
|
|
309
|
-
expect(result).toEqual([
|
|
310
|
-
"table.name",
|
|
311
|
-
"table.description",
|
|
312
|
-
"table.amount",
|
|
313
|
-
"linkedTable.name",
|
|
314
|
-
"linkedTable.description",
|
|
315
|
-
"linkedTable.amount",
|
|
316
|
-
"linkedTable.id",
|
|
317
|
-
"linkedTable.hidden",
|
|
318
|
-
])
|
|
319
|
-
})
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
describe("view", () => {
|
|
323
|
-
it("extracts fields from table schema", async () => {
|
|
324
|
-
const view = new ViewConfig(new TableConfig("table").create())
|
|
325
|
-
.withVisible("amount")
|
|
326
|
-
.withHidden("name")
|
|
327
|
-
.create()
|
|
328
|
-
|
|
329
|
-
const result = await buildSqlFieldList(view, {})
|
|
330
|
-
expect(result).toEqual(["table.amount"])
|
|
331
|
-
})
|
|
332
|
-
|
|
333
|
-
it("includes all fields if there is a formula column", async () => {
|
|
334
|
-
const table = new TableConfig("table")
|
|
335
|
-
.withField("formula", FieldType.FORMULA)
|
|
336
|
-
.create()
|
|
337
|
-
const view = new ViewConfig(table)
|
|
338
|
-
.withHidden("name")
|
|
339
|
-
.withVisible("amount")
|
|
340
|
-
.withVisible("formula")
|
|
341
|
-
.create()
|
|
342
|
-
|
|
343
|
-
const result = await buildSqlFieldList(view, {})
|
|
344
|
-
expect(result).toEqual([
|
|
345
|
-
"table.name",
|
|
346
|
-
"table.description",
|
|
347
|
-
"table.amount",
|
|
348
|
-
])
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
it("does not includes all fields if the formula column is not included", async () => {
|
|
352
|
-
const table = new TableConfig("table")
|
|
353
|
-
.withField("formula", FieldType.FORMULA)
|
|
354
|
-
.create()
|
|
355
|
-
const view = new ViewConfig(table)
|
|
356
|
-
.withHidden("name")
|
|
357
|
-
.withVisible("amount")
|
|
358
|
-
.withHidden("formula")
|
|
359
|
-
.create()
|
|
360
|
-
|
|
361
|
-
const result = await buildSqlFieldList(view, {})
|
|
362
|
-
expect(result).toEqual(["table.amount"])
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
it("includes relationships columns", async () => {
|
|
366
|
-
const otherTable = new TableConfig("linkedTable")
|
|
367
|
-
.withField("id", FieldType.NUMBER)
|
|
368
|
-
.withField("formula", FieldType.FORMULA)
|
|
369
|
-
.withPrimary("id")
|
|
370
|
-
.create()
|
|
371
|
-
|
|
372
|
-
const table = new TableConfig("table")
|
|
373
|
-
.withRelation("link", otherTable._id)
|
|
374
|
-
.create()
|
|
375
|
-
|
|
376
|
-
const view = new ViewConfig(table)
|
|
377
|
-
.withVisible("name")
|
|
378
|
-
.withVisible("link")
|
|
379
|
-
.withRelationshipColumns("link", {
|
|
380
|
-
name: { visible: false },
|
|
381
|
-
amount: { visible: true },
|
|
382
|
-
formula: { visible: false },
|
|
254
|
+
it("includes relationships fields when flagged", async () => {
|
|
255
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
256
|
+
.withField("id", FieldType.NUMBER)
|
|
257
|
+
.withPrimary("id")
|
|
258
|
+
.withDisplay("name")
|
|
259
|
+
.create()
|
|
260
|
+
|
|
261
|
+
const table = await new TableConfig("table")
|
|
262
|
+
.withRelation("link", otherTable._id!)
|
|
263
|
+
.create()
|
|
264
|
+
|
|
265
|
+
const result = await buildSqlFieldListInApp(table, allTables, {
|
|
266
|
+
relationships: true,
|
|
267
|
+
})
|
|
268
|
+
expect(result).toEqual([
|
|
269
|
+
"table.name",
|
|
270
|
+
"table.description",
|
|
271
|
+
"table.amount",
|
|
272
|
+
"table.id",
|
|
273
|
+
"linkedTable.id",
|
|
274
|
+
"linkedTable.name",
|
|
275
|
+
])
|
|
383
276
|
})
|
|
384
|
-
.create()
|
|
385
277
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
278
|
+
it("includes all relationship fields if there is a formula column", async () => {
|
|
279
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
280
|
+
.withField("hidden", FieldType.STRING, { visible: false })
|
|
281
|
+
.create()
|
|
282
|
+
|
|
283
|
+
const table = await new TableConfig("table")
|
|
284
|
+
.withRelation("link", otherTable._id!)
|
|
285
|
+
.withField("formula", FieldType.FORMULA)
|
|
286
|
+
.create()
|
|
287
|
+
|
|
288
|
+
const result = await buildSqlFieldListInApp(table, allTables, {
|
|
289
|
+
relationships: true,
|
|
290
|
+
})
|
|
291
|
+
expect(result).toEqual([
|
|
292
|
+
"table.name",
|
|
293
|
+
"table.description",
|
|
294
|
+
"table.amount",
|
|
295
|
+
"table.id",
|
|
296
|
+
"linkedTable.name",
|
|
297
|
+
"linkedTable.description",
|
|
298
|
+
"linkedTable.amount",
|
|
299
|
+
"linkedTable.hidden",
|
|
300
|
+
"linkedTable.id",
|
|
301
|
+
])
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it("never includes non-sql columns from relationships", async () => {
|
|
305
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
306
|
+
.withField("hidden", FieldType.STRING, { visible: false })
|
|
307
|
+
.withField("formula", FieldType.FORMULA)
|
|
308
|
+
.withField("ai", FieldType.AI)
|
|
309
|
+
.create()
|
|
310
|
+
|
|
311
|
+
const table = await new TableConfig("table")
|
|
312
|
+
.withRelation("link", otherTable._id!)
|
|
313
|
+
.withField("formula", FieldType.FORMULA)
|
|
314
|
+
.create()
|
|
315
|
+
|
|
316
|
+
const result = await buildSqlFieldListInApp(table, allTables, {
|
|
317
|
+
relationships: true,
|
|
318
|
+
})
|
|
319
|
+
expect(result).toEqual([
|
|
320
|
+
"table.name",
|
|
321
|
+
"table.description",
|
|
322
|
+
"table.amount",
|
|
323
|
+
"table.id",
|
|
324
|
+
"linkedTable.name",
|
|
325
|
+
"linkedTable.description",
|
|
326
|
+
"linkedTable.amount",
|
|
327
|
+
"linkedTable.hidden",
|
|
328
|
+
"linkedTable.id",
|
|
329
|
+
])
|
|
330
|
+
})
|
|
415
331
|
})
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
332
|
+
|
|
333
|
+
describe("view", () => {
|
|
334
|
+
it("extracts fields from table schema", async () => {
|
|
335
|
+
const view = await new ViewConfig(
|
|
336
|
+
await new TableConfig("table").create()
|
|
337
|
+
)
|
|
338
|
+
.withVisible("amount")
|
|
339
|
+
.withHidden("name")
|
|
340
|
+
.create()
|
|
341
|
+
|
|
342
|
+
const result = await buildSqlFieldListInApp(view, {})
|
|
343
|
+
expect(result).toEqual(["table.amount", "table.id"])
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
it("includes all fields if there is a formula column", async () => {
|
|
347
|
+
const table = await new TableConfig("table")
|
|
348
|
+
.withField("formula", FieldType.FORMULA)
|
|
349
|
+
.create()
|
|
350
|
+
const view = await new ViewConfig(table)
|
|
351
|
+
.withHidden("name")
|
|
352
|
+
.withVisible("amount")
|
|
353
|
+
.withVisible("formula")
|
|
354
|
+
.create()
|
|
355
|
+
|
|
356
|
+
const result = await buildSqlFieldListInApp(view, {})
|
|
357
|
+
expect(result).toEqual([
|
|
358
|
+
"table.name",
|
|
359
|
+
"table.description",
|
|
360
|
+
"table.amount",
|
|
361
|
+
"table.id",
|
|
362
|
+
])
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
it("does not includes all fields if the formula column is not included", async () => {
|
|
366
|
+
const table = await new TableConfig("table")
|
|
367
|
+
.withField("formula", FieldType.FORMULA)
|
|
368
|
+
.create()
|
|
369
|
+
const view = await new ViewConfig(table)
|
|
370
|
+
.withHidden("name")
|
|
371
|
+
.withVisible("amount")
|
|
372
|
+
.withHidden("formula")
|
|
373
|
+
.create()
|
|
374
|
+
|
|
375
|
+
const result = await buildSqlFieldListInApp(view, {})
|
|
376
|
+
expect(result).toEqual(["table.amount", "table.id"])
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
it("includes relationships columns", async () => {
|
|
380
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
381
|
+
.withField("id", FieldType.NUMBER)
|
|
382
|
+
.withField("formula", FieldType.FORMULA)
|
|
383
|
+
.withPrimary("id")
|
|
384
|
+
.create()
|
|
385
|
+
|
|
386
|
+
const table = await new TableConfig("table")
|
|
387
|
+
.withRelation("link", otherTable._id!)
|
|
388
|
+
.create()
|
|
389
|
+
|
|
390
|
+
const view = await new ViewConfig(table)
|
|
391
|
+
.withVisible("name")
|
|
392
|
+
.withVisible("link")
|
|
393
|
+
.withRelationshipColumns("link", {
|
|
394
|
+
name: { visible: false },
|
|
395
|
+
amount: { visible: true },
|
|
396
|
+
formula: { visible: false },
|
|
397
|
+
})
|
|
398
|
+
.create()
|
|
399
|
+
|
|
400
|
+
const result = await buildSqlFieldListInApp(view, allTables, {
|
|
401
|
+
relationships: true,
|
|
402
|
+
})
|
|
403
|
+
expect(result).toEqual([
|
|
404
|
+
"table.name",
|
|
405
|
+
"table.id",
|
|
406
|
+
"linkedTable.id",
|
|
407
|
+
"linkedTable.amount",
|
|
408
|
+
])
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
it("excludes relationships fields when view is not included in the view", async () => {
|
|
412
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
413
|
+
.withField("id", FieldType.NUMBER)
|
|
414
|
+
.withPrimary("id")
|
|
415
|
+
.withDisplay("name")
|
|
416
|
+
.create()
|
|
417
|
+
|
|
418
|
+
const table = await new TableConfig("table")
|
|
419
|
+
.withRelation("link", otherTable._id!)
|
|
420
|
+
.withField("formula", FieldType.FORMULA)
|
|
421
|
+
.create()
|
|
422
|
+
|
|
423
|
+
const view = await new ViewConfig(table)
|
|
424
|
+
.withVisible("name")
|
|
425
|
+
.withHidden("amount")
|
|
426
|
+
.create()
|
|
427
|
+
|
|
428
|
+
const result = await buildSqlFieldListInApp(view, allTables, {
|
|
429
|
+
relationships: true,
|
|
430
|
+
})
|
|
431
|
+
expect(result).toEqual(["table.name", "table.id"])
|
|
437
432
|
})
|
|
438
|
-
.create()
|
|
439
433
|
|
|
440
|
-
|
|
441
|
-
|
|
434
|
+
it("does not include relationships columns for hidden links", async () => {
|
|
435
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
436
|
+
.withField("id", FieldType.NUMBER)
|
|
437
|
+
.withField("formula", FieldType.FORMULA)
|
|
438
|
+
.withPrimary("id")
|
|
439
|
+
.create()
|
|
440
|
+
|
|
441
|
+
const table = await new TableConfig("table")
|
|
442
|
+
.withRelation("link", otherTable._id!)
|
|
443
|
+
.create()
|
|
444
|
+
|
|
445
|
+
const view = await new ViewConfig(table)
|
|
446
|
+
.withVisible("name")
|
|
447
|
+
.withHidden("link")
|
|
448
|
+
.withRelationshipColumns("link", {
|
|
449
|
+
name: { visible: false },
|
|
450
|
+
amount: { visible: true },
|
|
451
|
+
formula: { visible: false },
|
|
452
|
+
})
|
|
453
|
+
.create()
|
|
454
|
+
|
|
455
|
+
const result = await buildSqlFieldListInApp(view, allTables, {
|
|
456
|
+
relationships: true,
|
|
457
|
+
})
|
|
458
|
+
expect(result).toEqual(["table.name", "table.id"])
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
it("includes all relationship fields if there is a formula column", async () => {
|
|
462
|
+
const otherTable = await new TableConfig("linkedTable")
|
|
463
|
+
.withField("id", FieldType.NUMBER)
|
|
464
|
+
.withField("hidden", FieldType.STRING, { visible: false })
|
|
465
|
+
.withField("formula", FieldType.FORMULA)
|
|
466
|
+
.withField("ai", FieldType.AI)
|
|
467
|
+
.withPrimary("id")
|
|
468
|
+
.create()
|
|
469
|
+
|
|
470
|
+
const table = await new TableConfig("table")
|
|
471
|
+
.withRelation("link", otherTable._id!)
|
|
472
|
+
.withField("formula", FieldType.FORMULA)
|
|
473
|
+
.create()
|
|
474
|
+
|
|
475
|
+
const view = await new ViewConfig(table)
|
|
476
|
+
.withVisible("name")
|
|
477
|
+
.withVisible("formula")
|
|
478
|
+
.withHidden("link")
|
|
479
|
+
.withRelationshipColumns("link", {
|
|
480
|
+
name: { visible: false },
|
|
481
|
+
amount: { visible: true },
|
|
482
|
+
formula: { visible: false },
|
|
483
|
+
})
|
|
484
|
+
.create()
|
|
485
|
+
|
|
486
|
+
const result = await buildSqlFieldListInApp(view, allTables, {
|
|
487
|
+
relationships: true,
|
|
488
|
+
})
|
|
489
|
+
expect(result).toEqual([
|
|
490
|
+
"table.name",
|
|
491
|
+
"table.description",
|
|
492
|
+
"table.amount",
|
|
493
|
+
"table.id",
|
|
494
|
+
"linkedTable.name",
|
|
495
|
+
"linkedTable.description",
|
|
496
|
+
"linkedTable.amount",
|
|
497
|
+
"linkedTable.id",
|
|
498
|
+
"linkedTable.hidden",
|
|
499
|
+
])
|
|
500
|
+
})
|
|
442
501
|
})
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const table = new TableConfig("table")
|
|
457
|
-
.withRelation("link", otherTable._id)
|
|
458
|
-
.withField("formula", FieldType.FORMULA)
|
|
459
|
-
.create()
|
|
460
|
-
|
|
461
|
-
const view = new ViewConfig(table)
|
|
462
|
-
.withVisible("name")
|
|
463
|
-
.withVisible("formula")
|
|
464
|
-
.withHidden("link")
|
|
465
|
-
.withRelationshipColumns("link", {
|
|
466
|
-
name: { visible: false },
|
|
467
|
-
amount: { visible: true },
|
|
468
|
-
formula: { visible: false },
|
|
502
|
+
|
|
503
|
+
describe("calculation view", () => {
|
|
504
|
+
it("does not include calculation fields", async () => {
|
|
505
|
+
const view = await new ViewConfig(
|
|
506
|
+
await new TableConfig("table").create()
|
|
507
|
+
)
|
|
508
|
+
.withCalculation("average", "amount", CalculationType.AVG)
|
|
509
|
+
|
|
510
|
+
.create()
|
|
511
|
+
|
|
512
|
+
const result = await buildSqlFieldListInApp(view, {})
|
|
513
|
+
expect(result).toEqual([])
|
|
469
514
|
})
|
|
470
|
-
.create()
|
|
471
515
|
|
|
472
|
-
|
|
473
|
-
|
|
516
|
+
it("includes visible fields calculation fields", async () => {
|
|
517
|
+
const view = await new ViewConfig(
|
|
518
|
+
await new TableConfig("table").create()
|
|
519
|
+
)
|
|
520
|
+
.withCalculation("average", "amount", CalculationType.AVG)
|
|
521
|
+
.withHidden("name")
|
|
522
|
+
.withVisible("amount")
|
|
523
|
+
|
|
524
|
+
.create()
|
|
525
|
+
|
|
526
|
+
const result = await buildSqlFieldListInApp(view, {})
|
|
527
|
+
expect(result).toEqual(["table.amount"])
|
|
528
|
+
})
|
|
474
529
|
})
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
"table.amount",
|
|
479
|
-
"linkedTable.name",
|
|
480
|
-
"linkedTable.description",
|
|
481
|
-
"linkedTable.amount",
|
|
482
|
-
"linkedTable.id",
|
|
483
|
-
"linkedTable.hidden",
|
|
484
|
-
])
|
|
485
|
-
})
|
|
486
|
-
})
|
|
487
|
-
|
|
488
|
-
describe("calculation view", () => {
|
|
489
|
-
it("does not include calculation fields", async () => {
|
|
490
|
-
const view = new ViewConfig(new TableConfig("table").create())
|
|
491
|
-
.withCalculation("average", "amount", CalculationType.AVG)
|
|
492
|
-
|
|
493
|
-
.create()
|
|
494
|
-
|
|
495
|
-
const result = await buildSqlFieldList(view, {})
|
|
496
|
-
expect(result).toEqual([])
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
it("includes visible fields calculation fields", async () => {
|
|
500
|
-
const view = new ViewConfig(new TableConfig("table").create())
|
|
501
|
-
.withCalculation("average", "amount", CalculationType.AVG)
|
|
502
|
-
.withHidden("name")
|
|
503
|
-
.withVisible("amount")
|
|
504
|
-
|
|
505
|
-
.create()
|
|
506
|
-
|
|
507
|
-
const result = await buildSqlFieldList(view, {})
|
|
508
|
-
expect(result).toEqual(["table.amount"])
|
|
509
|
-
})
|
|
510
|
-
})
|
|
511
|
-
})
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
}
|