diff --git a/apis/sql.go b/apis/sql.go index 8cdd52ad..082eabb7 100644 --- a/apis/sql.go +++ b/apis/sql.go @@ -73,7 +73,10 @@ type runSQLResult struct { Rows [][]any `json:"rows"` } -var knownWriteQueryPrefixes = []string{"INSERT", "CREATE", "UPDATE", "DELETE", "DROP", "DETACH"} +var knownWriteQueryPrefixes = []string{ + "INSERT", "CREATE", "UPDATE", "DELETE", + "DROP", "DETACH", "ALTER", "REPLACE", +} func executeQuery(app core.App, query string, maxRows int) (*runSQLResult, error) { query = strings.TrimSpace(query) diff --git a/ui/dist/assets/index-BbAer_sj.js b/ui/dist/assets/index-gZx3-mqo.js similarity index 96% rename from ui/dist/assets/index-BbAer_sj.js rename to ui/dist/assets/index-gZx3-mqo.js index 5bd6b16f..c24fdfcc 100644 --- a/ui/dist/assets/index-BbAer_sj.js +++ b/ui/dist/assets/index-gZx3-mqo.js @@ -83,4 +83,4 @@ Records update will also require an extra unlock step before save.`)})))),t.div( @weekly @daily @midnight -@hourly`)},`macros`),`.`,t.br(),`By default the timezone is in UTC.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`backups.cronMaxKeep`},`Max @auto backups to keep`),t.input({id:`backups.cronMaxKeep`,name:`backups.cronMaxKeep`,type:`number`,required:()=>a.enableAutoBackups,min:1,value:()=>a.formSettings.backups.cronMaxKeep,oninput:e=>{a.formSettings.backups.cronMaxKeep=parseInt(e.target.value,10)}})))))),t.div({className:`col-lg-12`},app.components.s3ConfigFields({toggleLabel:`Store backups in S3 storage`,testFilesystem:`backups`,config:()=>a.formSettings.backups.s3})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!a.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:l},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${a.isSaving?`loading`:``}`,disabled:()=>!a.hasChanges||a.isSaving},t.span({className:`txt`},`Save changes`))))])))}function Fi(e={oncreated:null}){let n=Ii(e);n&&(document.body.appendChild(n),app.modals.open(n))}function Ii(e){let n,r=`backup_create_`+app.utils.randomString(),i=store({name:``,isSubmitting:!1}),a;async function o(){if(!i.isSubmitting){i.isSubmitting=!0,clearTimeout(a),a=setTimeout(()=>{app.modals.close(n)},1500);try{await app.pb.backups.create(i.name,{requestKey:r}),i.isSubmitting=!1,e.oncreated&&e.oncreated(i.name),app.toasts.success(`Successfully generated new backup.`),app.modals.close(n)}catch(e){e.isAbort||(clearTimeout(a),i.isSubmitting=!1,app.checkApiError(e))}}}return n=t.div({pbEvent:`backupCreateModal`,className:`modal popup backup-create-modal`,onbeforeclose:()=>{i.isSubmitting&&app.toasts.info(`The backup was started but may take a while to complete. You can come back later.`)},onafterclose:e=>{clearTimeout(a),e?.remove()}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Initialize new backup`)),t.form({id:r,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Please note that during the backup other concurrent write requests may fail since the database will be temporary "locked" (this usually happens only during the ZIP generation).`),t.p({className:`txt-bold`},`If you are using S3 storage for the collections file upload, you'll have to backup them separately since they are not locally stored and they will not be included in the generated backup!`)))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:r+`_name`},`Backup name`),t.input({id:r+`_name`,name:`name`,type:`text`,pattern:`^[a-z0-9_-]+.zip$`,placeholder:`Leave empty to autogenerate`,value:()=>i.name,oninput:e=>i.name=e.target.value})),t.div({className:`field-help`},`Must be in the format [a-z0-9_-].zip`)))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,disabled:()=>i.isSubmitting,onclick:()=>app.modals.close(n)},t.span({className:`txt`},`Cancel`)),t.button({"html-form":r,type:`submit`,className:()=>`btn ${i.isSubmitting?`loading`:``}`,disabled:()=>i.isSubmitting},t.span({className:`txt`},`Start backup`)))),n}function Li(e){let n=Ri(e);document.body.appendChild(n),app.modals.open(n)}function Ri(e){let n=`backup_restore_`+app.utils.randomString(),r=store({key:e,keyConfirm:``,isSubmitting:!1,get canSubmit(){return r.key&&r.key==r.keyConfirm}}),i;async function a(){if(!(r.isSubmitting||!r.canSubmit)){clearTimeout(i),r.isSubmitting=!0;try{await app.pb.backups.restore(r.keyConfirm),i=setTimeout(()=>{window.location.reload(),r.isSubmitting=!1},2e3)}catch(e){clearTimeout(i),e?.isAbort||(r.isSubmitting=!1,app.checkApiError(e))}}}return t.div({pbEvent:`backupRestoreModal`,className:`modal popup backup-restore-modal`,onbeforeclose:()=>!r.isSubmitting,onafterclose:e=>{e?.remove()},onunmount:()=>{clearTimeout(i)}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Restore `,t.strong(null,()=>r.key))),t.form({id:n,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),a()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert danger`},t.div({className:`content`},t.p({className:`txt-bold`},`Please proceed with extreme caution and use it only with trusted backups!`),t.p(null,`Backup restore currently works only on UNIX based systems.`),t.p(null,`The restore operation will attempt to replace your existing `,t.code(null,`pb_data`),` with the one from the backup and will restart the application process.`),t.p(null,`This means that on success all of your data (including app settings, users, superusers, etc.) will be replaced with the ones from the backup.`),t.p(null,`The operation will be reverted if the backup is invalid (ex. missing `,t.code(null,`data.db`),` file).`),t.p(null,`Below is an oversimplified version of the restore flow:`),t.ol(null,t.li(null,`Replaces the current `,t.code(null,`pb_data`),` with the content from the backup.`),t.li(null,`Triggers app restart.`),t.li(null,`Applies all migrations that are missing in the restored `,t.code(null,`pb_data`),`.`),t.li(null,`Initializes the app server as usual.`))))),t.div({className:`col-lg-12`},t.div({className:`confirm-key-label m-b-sm`},`Type the backup name `,t.div({className:`label`},()=>r.key,app.components.copyButton(()=>r.key)),` to confirm:`),t.div({className:`field`},t.label({htmlFor:n+`_key`},`Backup name`),t.input({id:n+`_key`,name:`key`,type:`text`,required:!0,value:()=>r.keyConfirm,oninput:e=>r.keyConfirm=e.target.value}))))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(),disabled:()=>r.isSubmitting},t.span({className:`txt`},`Cancel`)),t.button({"html-form":n,type:`submit`,className:()=>`btn ${r.isSubmitting?`loading`:``}`,disabled:()=>r.isSubmitting||!r.canSubmit},t.span({className:`txt`},`Restore backup`))))}function zi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({canBackup:!0,isLoading:!1,isDownloading:{},isDeleting:{},backups:[]});async function a(){i.isLoading=!0;try{i.backups=await app.pb.backups.getFullList(),i.backups.sort((e,n)=>e.modifiedn.modified?-1:0),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){app.modals.confirm(`Do you really want to delete ${e}?`,()=>s(e))}async function s(e){if(!i.isDeleting[e]){i.isDeleting[e]=!0;try{await app.pb.backups.delete(e),a(),app.toasts.success(`Successfully deleted ${e}.`)}catch(e){app.checkApiError(e)}delete i.isDeleting[e]}}async function c(){try{let e=await app.pb.health.check({requestKey:null}),n=i.canBackup;i.canBackup=e?.data?.canBackup||!1,i.canBackup&&n!=i.canBackup&&a()}catch(e){console.warn(`failed to load canBackup checks`,e)}}async function l(e){if(!i.isDownloading[e]){i.isDownloading[e]=!0;try{let n=await app.pb.files.getToken({requestKey:null});app.utils.download(app.pb.backups.getDownloadURL(n,e))}catch(e){app.checkApiError(e)}delete i.isDownloading[e]}}return t.div({pbEvent:`backupsList`,className:`list backups-list`,onmount:e=>{r.push(watch(()=>n.reset,()=>{a()})),e._canBackupIntervalId=setInterval(()=>{c()},3500)},onunmount:e=>{clearInterval(e._canBackupIntervalId),r.forEach(e=>e?.unwatch())}},t.div({className:`list-content`},t.div({hidden:()=>!i.isLoading||i.backups.length,className:`list-item`},t.div({className:`skeleton-loader`})),t.div({hidden:()=>i.isLoading||i.backups.length,className:()=>`list-item`},t.div({className:`content block txt-hint`},`No backups found.`)),()=>i.backups.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.i({className:`ri-folder-zip-line`,ariaHidden:!0}),t.div({className:`content`},t.span({className:`backup-name txt-ellipsis`,title:()=>e.key,textContent:()=>e.key}),t.small({className:`backup-size txt-hint txt-nowrap`},`(`,()=>app.utils.formattedFileSize(e.size),`)`)),t.nav({hidden:()=>i.isLoading,className:`actions autohide`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Download`),className:()=>`btn sm circle secondary transparent ${i.isDownloading[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>l(e.key)},t.i({className:`ri-download-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Restore`),className:()=>`btn sm circle secondary transparent`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>Li(e.key)},t.i({className:`ri-restart-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Delete`),className:()=>`btn sm circle secondary transparent ${i.isDeleting[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>o(e.key)},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0})))))),t.div({className:`list-item`},t.button({type:`button`,className:()=>`btn secondary block ${i.isLoading?`loading`:``}`,disabled:()=>!i.canBackup||i.isLoading,onclick:()=>{Fi({oncreated:()=>a()})}},()=>i.canBackup?[t.i({className:`ri-play-circle-line`,ariaHidden:!0}),t.span({className:`txt`},`Initialize new backup`)]:[t.span({className:`loader sm`}),t.span({className:`txt`},`Backup/restore operation is in process`)])))}function Bi(e=null){let n=`backup_upload_`+app.utils.randomString(),r=store({isUploading:!1});function i(e){e&&app.modals.confirm(`Note that we don't perform validations for the uploaded backup files. Proceed with extreme caution and only if you trust the source.\n\nDo you really want to upload "${e.name}"?`,()=>{a(e)},()=>{o()})}async function a(i){if(!(!i||r.isUploading)){r.isUploading=!0;try{let a=new FormData;a.set(`file`,i),await app.pb.backups.upload(a,{requestKey:n}),r.isUploading=!1,e(i),app.toasts.success(`Successfully uploaded a new backup.`)}catch(e){e.isAbort||(r.isUploading=!1,e.response?.formData?.file?.message?app.toasts.error(e.response.formData.file.message):app.checkApiError(e))}o()}}function o(){s&&(s.value=``)}let s=t.input({type:`file`,accept:`application/zip`,className:`hidden`,onchange:e=>{i(e.target?.files?.[0])}});return t.div(null,t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Upload backup`),className:()=>`btn sm transparent secondary circle ${r.isUploading?`loading`:``}`,disabled:()=>r.isUploading,onclick:()=>s?.click(),onunmount:()=>{app.pb.cancelRequest(n)}},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0})),s)}function Vi(e){app.store.title=`Backups`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageBackupsSettings`,className:`page page-backups-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Backup and restore your PocketBase data`),app.components.refreshButton({className:`btn sm transparent secondary circle tooltip-bottom`,onclick:r}),Bi(r)),zi({reset:()=>n.resetList})),t.div({className:`col-lg-12`},Pi({onsave:()=>r()})))),t.footer({className:`page-footer`},app.components.credits())))}function Hi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({isLoading:!1,isRunning:{},crons:[]});async function a(){i.isLoading=!0;try{i.crons=await app.pb.crons.getFullList(),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){if(!(!e||i.isRunning[e])){i.isRunning[e]=!0;try{await app.pb.crons.run(e),app.toasts.success(`Successfully triggered "${e}".`),i.isRunning[e]=!1}catch(n){n.isAbort||(ApiClient.error(n),i.isRunning[e]=!1)}}}return t.div({pbEvent:`cronsList`,className:`list`,onmount:()=>{r.push(watch(()=>n.reset,()=>{a()}))},onunmount:()=>{r.forEach(e=>e?.unwatch())}},()=>{if(!i.isLoading||i.crons.length)return;let e=[];for(let n=0;n<4;n++)e.push(t.div({rid:`skeleton_`+n,className:`list-item`},t.div({className:`skeleton-loader`})));return e},t.div({hidden:()=>i.isLoading||i.crons.length,className:`list-item`},t.div({className:`content block txt-hint`},`No registered crons found.`)),()=>i.crons.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.div({className:`content`},t.span({className:`cron-id txt-code txt-ellipsis`,title:()=>e.id,textContent:()=>e.id})),t.small({className:`cron-expression txt-hint txt-nowrap txt-code`},()=>e.expression),t.nav({hidden:()=>i.isLoading,className:`actions`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Run`),className:()=>`btn sm circle secondary transparent ${i.isRunning[e.id]?`loading`:``}`,disabled:()=>i.isRunning[e.id],onclick:()=>o(e.id)},t.i({className:`ri-play-large-line`,ariaHidden:!0}))))))}function Ui(e){app.store.title=`Crons`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageCronsSettings`,className:`page`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Registered app cron jobs`),app.components.refreshButton({className:`btn sm transparent secondary circle`,onclick:r})),Hi({reset:()=>n.resetList}),t.div({className:`txt-sm txt-hint m-t-sm`},`App cron jobs can be registered only programmatically with `,t.a({href:`https://pocketbase.io/docs/go-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JavaScript`}),`.`)),t.footer({className:`page-footer`},app.components.credits())))}function Wi(e){app.store.title=`Mail settings`;let n=[{label:`Auto (StartTLS)`,value:!1},{label:`Always`,value:!0}],r=[{label:`PLAIN (default)`,value:`PLAIN`},{label:`LOGIN`,value:`LOGIN`}],i=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,showMoreOptions:!1,get hasChanges(){return i.initSerialized!=JSON.stringify(i.formSettings)}});a();async function a(){i.isLoading=!0;try{s(await app.pb.settings.getAll()),i.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function o(){if(!(i.isSaving||!i.hasChanges)){i.isSaving=!0;try{let e=app.utils.filterRedactedProps(i.formSettings);s(await app.pb.settings.update(e)),app.toasts.success(`Successfully saved mail settings.`)}catch(e){app.checkApiError(e)}i.isSaving=!1}}function s(e={}){app.store.settings=JSON.parse(JSON.stringify(e)),i.formSettings={meta:e?.meta||{},smtp:e?.smtp||{}},i.formSettings.smtp.authMethod||(i.formSettings.smtp.authMethod=r[0].value),i.initSerialized=JSON.stringify(i.formSettings)}function c(){i.formSettings=JSON.parse(i.initSerialized)}return t.div({pbEvent:`pageMailSettings`,className:`page page-mail-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`mailSettingsForm`,className:`grid mail-settings-form`,inert:()=>i.isSaving,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`Configure common settings for sending emails.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderName`},`Sender name`),t.input({id:`meta.senderName`,name:`meta.senderName`,type:`text`,required:!0,value:()=>i.formSettings.meta.senderName||``,oninput:e=>i.formSettings.meta.senderName=e.target.value}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderAddress`},`Sender address`),t.input({id:`meta.senderAddress`,name:`meta.senderAddress`,type:`email`,required:!0,value:()=>i.formSettings.meta.senderAddress||``,oninput:e=>i.formSettings.meta.senderAddress=e.target.value}))),t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`smtp.enabled`,name:`smtp.enabled`,type:`checkbox`,className:`switch`,checked:()=>!!i.formSettings.smtp.enabled,onchange:e=>i.formSettings.smtp.enabled=e.target.checked}),t.label({htmlFor:`smtp.enabled`},t.span({className:`txt`},`Use SMTP mail server `,t.strong(null,`(recommended)`)),t.i({className:`ri-information-line link-faded`,ariaDescription:app.attrs.tooltip(`By default PocketBase uses the unix "sendmail" command for sending emails. For better emails deliverability it is recommended to use a SMTP mail server.`)}))),app.components.slide(()=>i.formSettings.smtp.enabled,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-4`},t.div({className:`field`},t.label({htmlFor:`smtp.host`},`SMTP server host`),t.input({id:`smtp.host`,name:`smtp.host`,type:`text`,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.host||``,oninput:e=>i.formSettings.smtp.host=e.target.value}))),t.div({className:`col-lg-2`},t.div({className:`field`},t.label({htmlFor:`smtp.port`},`Port`),t.input({id:`smtp.port`,name:`smtp.port`,type:`number`,min:0,step:1,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.port||``,oninput:e=>i.formSettings.smtp.port=parseInt(e.target.value,10)}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.username`},`Username`),t.input({id:`smtp.username`,name:`smtp.username`,type:`text`,autocomplete:`off`,value:()=>i.formSettings.smtp.username||``,oninput:e=>i.formSettings.smtp.username=e.target.value}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.password`},`Password`),t.input({id:`smtp.password`,name:`smtp.password`,type:`password`,autocomplete:`new-password`,value:()=>i.formSettings.smtp.password||``,oninput:e=>i.formSettings.smtp.password=e.target.value,onkeyup:e=>{e.key==`Backspace`&&i.formSettings.smtp.password===void 0&&(i.formSettings.smtp.password=``)},placeholder:()=>i.formSettings.smtp.password===void 0?`* * * * * *`:``})))),t.button({type:`button`,className:`btn secondary sm m-t-sm`,onclick:()=>i.showMoreOptions=!i.showMoreOptions},t.span({className:`txt`},()=>i.showMoreOptions?`Hide more options`:`Show more options`),t.i({className:()=>i.showMoreOptions?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`})),app.components.slide(()=>i.showMoreOptions,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.tls`},`TLS encryption`),app.components.select({id:`smtp.tls`,name:`smtp.tls`,required:!0,options:n,value:()=>i.formSettings.smtp.tls||!1,onchange:e=>{i.formSettings.smtp.tls=e?.[0]?.value}}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.authMethod`},`AUTH method`),app.components.select({id:`smtp.authMethod`,name:`smtp.authMethod`,required:!0,options:r,value:()=>i.formSettings.smtp.authMethod||r[0].value,onchange:e=>{i.formSettings.smtp.authMethod=e?.[0]?.value}}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`smtp.localName`},t.span({className:`txt`},`EHLO/HELO domain`),t.i({className:`ri-information-line link-hint tooltip-top`,ariaDescription:app.attrs.tooltip(`Some SMTP servers, such as the Gmail SMTP-relay, requires a proper domain name in the inital EHLO/HELO exchange and will reject attempts to use localhost.`)})),t.input({id:`smtp.localName`,name:`smtp.localName`,type:`text`,placeholder:`Default to localhost`,value:()=>i.formSettings.smtp.localName||``,oninput:e=>i.formSettings.smtp.localName=e.target.value}))))))),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),()=>i.hasChanges?[t.button({type:`button`,className:`btn transparent secondary`,onclick:c},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${i.isSaving?`loading`:``}`,disabled:()=>!i.hasChanges||i.isSaving},t.span({className:`txt`},`Save changes`))]:t.button({type:`button`,className:()=>`btn expanded-lg outline`,onclick:()=>app.modals.openMailTest()},t.i({className:`ri-mail-check-line`,ariaHidden:!0}),t.span({className:`txt`},`Send test email`)))))),t.footer({className:`page-footer`},app.components.credits())))}var Gi=`pbSQLConsoleHistory`;function Ki(e){app.store.title=`SQL console`;let n=`sql_console_`+app.utils.randomString(),r=n+`editor`,i=n+`executeSQL`,a=store({askedForConfirmationAtLeastOnce:!1,isExecuting:!1,maxRows:250,query:``,result:{},sort:{},errorMsg:``,executedHistory:app.utils.getLocalHistory(Gi,[]),get sortedResultRows(){if(a.sort?.index===void 0){let e=a.result?.rows||[];return a.maxRows>=e.length?e:e.slice(0,a.maxRows)}let e=!!a.sort?.asc,n=a.result?.rows?.toSorted((n,r)=>{let i=n[a.sort.index],o=r[a.sort.index];return e||(i=r[a.sort.index],o=n[a.sort.index]),i==o?0:i==null?-1:o==null?1:i.localeCompare(o)})||[];return a.maxRows>=n.length?n:n.slice(0,a.maxRows)},get totalRemainingRows(){return(a.result?.rows?.length<<0)-a.sortedResultRows.length}});function o(e){return e?.trim()?!a.askedForConfirmationAtLeastOnce&&app.store.settings?.meta?.hideControls?!0:(e=e?.replace(/[\s\;]/gm,` `).toUpperCase()+` `,!![`INSERT `,`CREATE `,`UPDATE `,`DELETE `,`DROP `,`DETACH `,`PRAGMA `].find(n=>e.includes(n))):!1}async function s(){return o(a.query)?(a.askedForConfirmationAtLeastOnce=!0,app.modals.confirm(t.div({className:`txt-center`},t.h6(null,`Be careful and continue only if you really know what you are doing because, depending on the query, the operation could break your application and may not be reversible.`)),()=>c(),null,{yesButton:`Execute`,noButton:`Cancel`})):c()}async function c(){a.isExecuting=!0,a.maxRows=250,a.result={},a.sort={},a.errorMsg=``;let e=a.query.trim();if(!e){app.pb.cancelRequest(i),a.isExecuting=!1;return}try{a.result=await app.pb.sql.run(e,{requestKey:i}),u(e),a.isExecuting=!1}catch(e){e?.isAbort||(a.isExecuting=!1,a.errorMsg=e?.response?.message||e?.message||`Failed to execute query.`)}}function l(e){function n(e){return e.replace(/[\s\;]/gm,``).toUpperCase()}let r=n(e);for(let i=a.executedHistory.length-1;i>=0;i--)(a.executedHistory[i]==e||n(a.executedHistory[i])==r)&&a.executedHistory.splice(i,1)}function u(e){l(e),a.executedHistory.unshift(a.query),a.executedHistory.length>10&&a.executedHistory.splice(10)}function d(){if(!a.sortedResultRows.length)return;let e=[a.result.columns.map(e=>e.name)].concat(a.sortedResultRows),n=`export_`+new Date().toISOString().replace(/[\-\:\.]/g,``)+`.csv`;app.utils.downloadCSV(e,n)}function f(e){a.sort?.index==e?a.sort={index:e,asc:!a.sort.asc}:a.sort={index:e,asc:!0}}let p=[watch(()=>JSON.stringify(a.executedHistory),(e,n)=>{n!==void 0&&window.localStorage.setItem(Gi,e)})];return t.div({pbEvent:`pageSQLConsole`,className:`page`,onunmount:()=>{app.pb.cancelRequest(i),p.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title)),t.div({className:`page-header-secondary-btns`},t.button({type:`button`,className:`btn circle transparent secondary`,ariaDescription:app.attrs.tooltip(`Recently executed queries`,`right`),"html-popovertarget":`sql-console-history-dropdown`},t.i({className:`ri-history-line`,ariaHidden:!0})),t.div({id:`sql-console-history-dropdown`,className:()=>`dropdown left sql-console-history-dropdown ${a.executedHistory.length?``:`no-items`}`,popover:`auto`},()=>a.executedHistory.length?a.executedHistory.map(e=>t.button({role:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),a.query=e,document.getElementById(r)?.click()}},t.span({className:`query`},()=>app.utils.truncate(e,500)),t.small({role:`button`,className:`remove-btn link-hint m-l-auto p-l-5 p-r-5`,title:`Clear`,onauxclick:e=>(e.stopPropagation(),!1),onclick:n=>(n.stopPropagation(),l(e),!1)},t.i({className:`ri-close-line`,ariaHidden:!0})))):t.span({className:`txt txt-hint p-5`},`No recently executed queries.`))),t.div({className:`page-header-primary-btns`},t.button({type:`button`,className:()=>`btn expanded-lg ${a.isExecuting?`loading`:``}`,disabled:()=>a.isExecuting,onclick:()=>s()},t.i({className:`ri-play-large-line`,ariaHidden:!0}),t.span({className:`txt`},`Execute`)))),t.div({className:`field sql-console-field`},app.components.codeEditor({id:r,language:`sql`,required:!0,name:`query`,placeholder:`e.g. EXPLAIN QUERY PLAN SELECT * from users WHERE verified=true`,value:()=>a.query,oninput:e=>a.query=e,onblur:e=>a.query=e.trim()})),t.div({className:`flex field-help m-b-sm`},t.button({type:`button`,className:`link-hint m-l-auto`,"html-popovertarget":n+`caveats_dropdown`},()=>`SQL console caveats`),t.div({id:n+`caveats_dropdown`,className:`dropdown sm query-caveats-dropdown`,popover:`auto`},t.ul(null,t.li(null,`The returned rows are limited up to 1000.`),t.li(null,`The executed queries have a max timeout of 3 minutes.`),t.li(null,`The data is returned as byte strings without any additional formatting.`),t.li(null,`Multiple queries are supported but only the result of the last one is returned.`)))),t.div({hidden:()=>a.isExecuting||!a.errorMsg,className:`alert danger m-b-sm`},t.pre(null,()=>a.errorMsg)),t.div({hidden:()=>a.isExecuting||a.errorMsg||a.result?.columns?.length||app.utils.isEmpty(a.result),className:`alert success m-b-sm`},t.p({className:`txt-bold`},`Query executed successfully!`),t.p(null,`Affected rows: `,()=>a.result?.affectedRows||0)),t.div({hidden:()=>a.isExecuting||!a.result?.columns?.length,className:`page-table-wrapper`},t.table({className:`sql-console-table responsive-table optimize`},t.thead({className:`sticky`},t.tr(null,()=>a.result?.columns?.map((e,n)=>t.th({textContent:e.name,className:()=>{let e=`sort-handle`;return a.sort?.index==n&&(e+=a.sort.asc?` asc`:` desc`),e},onclick:()=>f(n)})))),t.tbody(null,()=>a.sortedResultRows.length?a.sortedResultRows.map(e=>t.tr(null,()=>a.result?.columns?.map((n,r)=>{let i=e[r];return t.td({"html-data-name":n.name},i==null?`NULL`:app.utils.truncate(i,2e3))}))):t.tr(null,t.td({colSpan:a.result?.columns?.length||1,className:`txt-center`},t.span({className:`txt-hint`},`No rows found.`))),t.tr({hidden:()=>a.isExecuting||!a.result?.rows?.length||a.result.rows.length<=a.sortedResultRows.length},t.td({colSpan:99},t.button({type:`button`,className:`btn lg secondary load-more-btn`,onclick:()=>{a.maxRows=a.result?.rows?.length||250}},t.span({className:`txt`,textContent:()=>`Load remaining (${a.totalRemainingRows})`}))))))),t.footer({className:`page-footer`},t.span({className:()=>`exec-time ${a.isExecuting?`faded`:``}`},`Time: `,()=>(a.result?.execTime||0)+`ms`),t.span({hidden:()=>!a.result?.columns?.length,className:()=>`total-count ${a.isExecuting?`faded`:``}`},`Rows: `,()=>a.result?.rows?.length||0,()=>{if(a.result?.rows?.length)return[` (`,t.span({role:`button`,className:`link-hint`,textContent:`Export as CSV`,onclick:d}),`)`]}),app.components.credits())))}function qi(){app.store.title=`File storage`;let e=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,originalFormSettings:null,get hasChanges(){return e.initSerialized!=JSON.stringify(e.formSettings)}});n();async function n(){e.isLoading=!0;try{i(await app.pb.settings.getAll()),e.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function r(){if(!(e.isSaving||!e.hasChanges)){e.isSaving=!0;try{let n=app.utils.filterRedactedProps(e.formSettings);i(await app.pb.settings.update(n)),app.toasts.success(`Successfully saved storage settings.`)}catch(e){app.checkApiError(e)}e.isSaving=!1}}function i(n={}){app.store.settings=JSON.parse(JSON.stringify(n)),e.formSettings={s3:n?.s3||{}},e.initSerialized=JSON.stringify(e.formSettings),e.originalFormSettings=JSON.parse(e.initSerialized)}function a(){e.formSettings=JSON.parse(e.initSerialized)}return t.div({pbEvent:`pageStorageSettings`,className:`page page-storage-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>e.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`storageSettingsForm`,className:`grid storage-settings-form`,inert:()=>e.isSaving,onsubmit:e=>{e.preventDefault(),r()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`By default PocketBase uses and recommends the local file system to store uploaded files because it is more performant, easier to manage and backup.`),t.p(null,`Alternatively, if you have limited disk space available, you could opt to an S3 compatible external storage.`)),t.div({className:`col-lg-12`},app.components.s3ConfigFields({config:()=>e.formSettings.s3,before:()=>{let n=e.originalFormSettings.s3?.enabled;if(n!=e.formSettings.s3?.enabled)return t.div({className:`alert info m-t-sm`},`If you have existing uploaded files, you'll have to migrate them manually from the `,t.strong(null,n?`S3 storage`:`local file system`),` to the `,t.strong(null,e.formSettings.s3?.enabled?`S3 storage`:`local file system`),`.`,t.br(),`There are several command line tools that can help you, such as: `,t.a({href:`https://github.com/rclone/rclone`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`rclone`}),`, `,t.a({href:`https://github.com/peak/s5cmd`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`s5cmd`}),`, etc.`)}})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!e.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:a},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${e.isSaving?`loading`:``}`,disabled:()=>!e.hasChanges||e.isSaving},t.span({className:`txt`},`Save changes`)))))),t.footer({className:`page-footer`},app.components.credits())))}function Ji(e){app.store.title=`Export collections`;let n=`export_`+app.utils.randomString(),r=store({isLoading:!1,collections:[],bulkSelected:{},get bulkSelectStr(){return JSON.stringify(app.utils.sortedCollectionsByType(Object.values(r.bulkSelected)),null,2)},get totalSelected(){return Object.keys(r.bulkSelected).length},get areAllSelected(){return r.collections.length&&r.collections.length==r.totalSelected}});i();async function i(){r.isLoading=!0;try{let e=await app.pb.collections.getFullList({requestKey:n});for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;r.collections=app.utils.sortedCollectionsByType(e),c(),r.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),r.isLoading=!1)}}function a(){let e=app.utils.sortedCollectionsByType(Object.values(r.bulkSelected));app.utils.downloadJSON(e,`pb_schema`)}function o(){r.areAllSelected?s():c()}function s(){r.bulkSelected={}}function c(){r.bulkSelected={};for(let e of r.collections)r.bulkSelected[e.id]=e}function l(e){let n=JSON.parse(JSON.stringify(r.bulkSelected));r.bulkSelected[e.id]?delete n[e.id]:n[e.id]=e,r.bulkSelected=n}return t.div({pbEvent:`pageExportCollections`,className:`page page-export-collections`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>r.isLoading?t.div({className:`txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`txt-lg`},`Below you'll find your current collections configuration that you could import in another PocketBase environment.`)),t.div({className:`col-lg-12`},t.div({className:`export-panel`},t.aside({className:`export-list`},t.div({className:`list-item`},t.div({className:`field`},t.input({id:n+`.select_all`,type:`checkbox`,checked:()=>r.areAllSelected,onchange:()=>o()}),t.label({htmlFor:n+`.select_all`},`Select all`))),()=>r.collections.map(e=>{let i=n+`_c_`+e.id;return t.div({className:`list-item`},t.div({className:`field`},t.input({id:i,type:`checkbox`,checked:()=>!!r.bulkSelected[e.id],onchange:()=>{l(e)}}),t.label({htmlFor:i},e.name)))})),t.output({className:`export-preview`},app.components.codeBlock({value:()=>r.bulkSelectStr,language:`plain`}),t.nav({className:`ctrls`},app.components.copyButton(()=>r.bulkSelectStr))))),t.div({className:`col-lg-12 txt-right`},t.button({className:`btn`,onclick:a},t.i({className:`ri-download-line`,ariaHidden:!0}),t.span({className:`txt`},`Download as JSON`))))),t.footer({className:`page-footer`},app.components.credits())))}function Yi(e){app.store.title=`Import collections`;let n=`import_`+app.utils.randomString(),r=[],i=store({rawNewCollections:``,oldCollections:[],newCollections:[],collectionsToUpdate:[],deleteMissing:!0,isLoadingFile:!1,isLoadingOldCollections:!1,mergeWithOldCollections:!1,get isRawValid(){return!!i.rawNewCollections&&i.newCollections?.length>0&&i.newCollections.length==i.newCollections.filter(e=>!!e.id&&!!e.name).length},get collectionsToDelete(){return i.oldCollections.filter(e=>i.isRawValid&&!i.mergeWithOldCollections&&i.deleteMissing&&!i.newCollections.find(n=>n.id==e.id))},get collectionsToAdd(){return i.newCollections.filter(e=>i.isRawValid&&!i.oldCollections.find(n=>n.id==e.id))},get idReplacableCollections(){return i.newCollections.filter(e=>{let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)return!1;if(n.id!=e.id)return!0;let r=Array.isArray(n.fields)?n.fields:[],a=Array.isArray(e.fields)?e.fields:[];for(let e of a){if(r.find(n=>n.id==e.id))continue;let n=r.find(n=>n.name==e.name);if(n&&e.id!=n.id)return!0}return!1})},get hasChanges(){return!!i.rawNewCollections&&!!(i.collectionsToDelete.length||i.collectionsToAdd.length||i.collectionsToUpdate.length)},get canReview(){return!i.isLoadingOldCollections&&i.isRawValid&&i.hasChanges}}),a=t.input({id:n+`_load_json`,type:`file`,className:`hidden`,accept:`.json`,onchange:()=>{d(a.files?.[0])}});o();async function o(){i.isLoadingOldCollections=!0;try{let e=await app.pb.collections.getFullList();for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;i.oldCollections=e,i.isLoadingOldCollections=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoadingOldCollections=!1)}}r.push(watch(()=>i.rawNewCollections,()=>{s()}));function s(){let e=[];try{e=JSON.parse(i.rawNewCollections),e=Array.isArray(e)?app.utils.filterDuplicatesByKey(e):[];for(let n of e)delete n.created,delete n.updated,n.fields&&=app.utils.filterDuplicatesByKey(n.fields)}catch{}i.newCollections=e}r.push(watch(()=>[i.newCollections,i.deleteMissing],()=>{c()}));function c(){if(i.collectionsToUpdate=[],i.isRawValid)for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.id==e.id);!n?.id||!app.utils.hasCollectionChanges(n,e,i.deleteMissing)||i.collectionsToUpdate.push({new:e,old:n})}}function l(){for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)continue;let r=e.id,a=n.id;e.id=a;let o=Array.isArray(n.fields)?n.fields:[],s=Array.isArray(e.fields)?e.fields:[];for(let e of s){let n=o.find(n=>n.name==e.name);n&&n.id&&(e.id=n.id)}for(let e of i.newCollections)if(Array.isArray(e.fields))for(let n of e.fields)n.collectionId&&n.collectionId===r&&(n.collectionId=a);for(let n=0;ne.replace(r,a))}i.rawNewCollections=JSON.stringify(i.newCollections,null,2)}function u(){i.rawNewCollections=``,a.value=``,app.store.errors=null}function d(e){i.isLoadingFile=!0;let n=new FileReader;n.onload=async e=>{i.isLoadingFile=!1,a.value=``,i.rawNewCollections=e.target.result,await new Promise(e=>setTimeout(e,0)),i.newCollections.length||(app.toasts.error(`Invalid collections configuration.`),u())},n.onerror=e=>{app.toasts.error(`Failed to load the imported JSON.`),console.warn(e),i.isLoadingFile=!1,a.value=``},n.readAsText(e)}function f(){let e=i.mergeWithOldCollections?app.utils.filterDuplicatesByKey(i.oldCollections.concat(i.newCollections)):i.newCollections;app.modals.openImportCollectionsReview(i.oldCollections,e,{deleteMissing:i.deleteMissing,onsubmit:()=>{u(),o()}})}return t.div({pbEvent:`pageImportCollections`,className:`page page-import-collections`,onunmount:()=>{r.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoadingOldCollections?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.span({className:`txt-lg m-r-5`},`Paste below the collections configuration you want to import or`),t.label({htmlFor:a.id,className:()=>`btn sm outline ${i.isLoadingFile?`loading`:``}`},t.span({className:`txt`},`Load from JSON file`)),a,t.p({className:`txt-hint`},t.em(null,`You can use the `,t.a({href:`https://pocketbase.io/docs/go-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JS`}),` migrations to manage your collections programmatically in more granular and version controlled manner.`))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:n+`_collections_field`},`Collections`),t.textarea({id:n+`_collections_field`,name:`collections`,rows:12,className:`txt-code`,spellcheck:!1,autocorrect:!1,autocomplete:`off`,autocapitalize:`off`,value:()=>i.rawNewCollections,oninput:e=>i.rawNewCollections=e.target.value})),t.div({className:()=>`field-help error ${i.rawNewCollections&&!i.isRawValid?``:`hidden`}`},`Invalid collections configuration.`)),t.div({className:()=>`col-lg-12 ${i.isRawValid?``:`hidden`}`},t.div({className:`field`},t.input({id:n+`_merge_checkbox`,type:`checkbox`,className:`switch`,checked:()=>i.mergeWithOldCollections,onchange:e=>i.mergeWithOldCollections=e.target.checked}),t.label({htmlFor:n+`_merge_checkbox`},`Merge with the existing collections`))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&!i.hasChanges?``:`hidden`}`},t.div({className:`alert info`},t.div({className:`content`},t.p(null,`Your collections configuration is already up-to-date!`)))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&i.hasChanges?``:`hidden`}`},t.p({className:`txt-hint txt-bold`},`Detected changes`),t.div({className:`list`},()=>i.collectionsToDelete.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label danger`,textContent:`Deleted`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))),()=>i.collectionsToUpdate.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label warning`,textContent:`Changed`}),t.div({className:`inline-flex gap-5`},()=>{if(e.old.name!=e.new.name)return[t.span({className:`txt-strikethrough txt-hint`,textContent:e.old.name}),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0})]},t.strong({textContent:()=>e.new.name}),t.small({className:()=>`txt-hint ${e.new.id?``:`hidden`}`,textContent:()=>e.new.id})))),()=>i.collectionsToAdd.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label success`,textContent:`Added`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))))),t.div({className:()=>`col-lg-12 ${i.idReplacableCollections?.length?``:`hidden`}`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Some of the imported collections share the same name and/or fields but are imported with different IDs.`),t.p(null,`You can replace them in the import if you want to:`,t.button({type:`button`,className:`btn warning sm m-l-10`,textContent:`Replace with original IDs`,onclick:l}))))),t.div({className:`col-lg-12`},t.div({className:`flex`},t.button({type:`button`,className:()=>`btn secondary ${i.rawNewCollections?``:`hidden`}`,onclick:u},t.span({className:`txt`},`Clear`)),t.button({type:`button`,className:`btn expanded-lg m-l-auto`,disabled:()=>!i.canReview,onclick:f},t.span({className:`txt`},`Review`)))))),t.footer({className:`page-footer`},app.components.credits())))}window.app=window.app||{},window.app.routes=window.app.routes||{},window.app.routes.fallbackPath=`#/collections`,app.routes.guestOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(app.pb.authStore.isValid&&app.pb.authStore.record?.id){window.location.hash=`#/`;return}app.store.showHeader=!1,app.store.page=await n(e)}},app.routes.superuserOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(!app.pb.authStore.isValid||!app.pb.authStore.record?.id){window.location.hash=`#/login`;return}app.store.showHeader=!0,app.store.page=await n(e)}},app.routes.blank=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{app.store.showHeader=!1,app.store.page=await n(e)}};var Xi={},Zi;function Qi(){Zi&&Zi(),Zi=router(Xi,{fallbackPath:app.routes.fallbackPath})}app.routes.guestOnly(`#/pbinstall/{token}`,async e=>{let{pageInstaller:n}=await W(async()=>{let{pageInstaller:e}=await import(`./pageInstaller-BurRu8ai.js`);return{pageInstaller:e}},[],import.meta.url);return n(e)}),app.routes.guestOnly(`#/login`,e=>Yr(e)),app.routes.guestOnly(`#/request-password-reset`,async e=>{let{pageRequestSuperuserPasswordReset:n}=await W(async()=>{let{pageRequestSuperuserPasswordReset:e}=await import(`./pageRequestSuperuserPasswordReset-C39AMhGf.js`);return{pageRequestSuperuserPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-password-reset/{token}`,async e=>{let{pageConfirmPasswordReset:n}=await W(async()=>{let{pageConfirmPasswordReset:e}=await import(`./pageConfirmPasswordReset-D76h8E3Z.js`);return{pageConfirmPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-verification/{token}`,async e=>{let{pageConfirmVerification:n}=await W(async()=>{let{pageConfirmVerification:e}=await import(`./pageConfirmVerification-B8_4Ca-4.js`);return{pageConfirmVerification:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-email-change/{token}`,async e=>{let{pageConfirmEmailChange:n}=await W(async()=>{let{pageConfirmEmailChange:e}=await import(`./pageConfirmEmailChange-CmDy-gO9.js`);return{pageConfirmEmailChange:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-success`,async e=>{let{pageOAuth2RedirectSuccess:n}=await W(async()=>{let{pageOAuth2RedirectSuccess:e}=await import(`./pageOAuth2RedirectSuccess-DmZV1eyz.js`);return{pageOAuth2RedirectSuccess:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-failure`,async e=>{let{pageOAuth2RedirectFailure:n}=await W(async()=>{let{pageOAuth2RedirectFailure:e}=await import(`./pageOAuth2RedirectFailure-CRvz4PXa.js`);return{pageOAuth2RedirectFailure:e}},[],import.meta.url);return n(e)}),app.routes.superuserOnly(`#/collections`,di),app.routes.superuserOnly(`#/logs`,Si),app.routes.superuserOnly(`#/settings`,Mi),app.routes.superuserOnly(`#/settings/mail`,Wi),app.routes.superuserOnly(`#/settings/storage`,qi),app.routes.superuserOnly(`#/settings/backups`,Vi),app.routes.superuserOnly(`#/settings/crons`,Ui),app.routes.superuserOnly(`#/settings/export-collections`,Ji),app.routes.superuserOnly(`#/settings/import-collections`,Yi),app.routes.superuserOnly(`#/settings/sql`,Ki);var $i=t;t=new Proxy({},{get(e,n){return function(){let e=arguments?.[0];if(e&&e.pbEvent){let n=e.onmount;e.onmount=r=>{n?.(r),r.dataset.pb=e.pbEvent,document.dispatchEvent(new CustomEvent(`mount:`+e.pbEvent,{detail:r}))};let r=e.onunmount;e.onunmount=n=>{document.dispatchEvent(new CustomEvent(`unmount:`+e.pbEvent,{detail:n})),r?.(n)}}return $i[n](...arguments)}}}),document.body.prepend(t.main({"html-class":`app`,className:()=>`app ${app.store.settings?.meta?.hideControls?`hide-controls`:``}`},Fe(),e=>(typeof app.store.page==`function`&&app.store.page(e),app.store.page))),watch(()=>app.store._ready,e=>{e&&Qi()}),document.body.appendChild(t.script({type:`module`,src:app.pb.buildURL(`/_/extensions.js`),onload:()=>{app.store._ready=!0},onerror:e=>{console.warn(`Failed to load extensions:`,e),app.store._ready=!0}}));export{S as n,se as r,Ee as t}; \ No newline at end of file +@hourly`)},`macros`),`.`,t.br(),`By default the timezone is in UTC.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`backups.cronMaxKeep`},`Max @auto backups to keep`),t.input({id:`backups.cronMaxKeep`,name:`backups.cronMaxKeep`,type:`number`,required:()=>a.enableAutoBackups,min:1,value:()=>a.formSettings.backups.cronMaxKeep,oninput:e=>{a.formSettings.backups.cronMaxKeep=parseInt(e.target.value,10)}})))))),t.div({className:`col-lg-12`},app.components.s3ConfigFields({toggleLabel:`Store backups in S3 storage`,testFilesystem:`backups`,config:()=>a.formSettings.backups.s3})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!a.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:l},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${a.isSaving?`loading`:``}`,disabled:()=>!a.hasChanges||a.isSaving},t.span({className:`txt`},`Save changes`))))])))}function Fi(e={oncreated:null}){let n=Ii(e);n&&(document.body.appendChild(n),app.modals.open(n))}function Ii(e){let n,r=`backup_create_`+app.utils.randomString(),i=store({name:``,isSubmitting:!1}),a;async function o(){if(!i.isSubmitting){i.isSubmitting=!0,clearTimeout(a),a=setTimeout(()=>{app.modals.close(n)},1500);try{await app.pb.backups.create(i.name,{requestKey:r}),i.isSubmitting=!1,e.oncreated&&e.oncreated(i.name),app.toasts.success(`Successfully generated new backup.`),app.modals.close(n)}catch(e){e.isAbort||(clearTimeout(a),i.isSubmitting=!1,app.checkApiError(e))}}}return n=t.div({pbEvent:`backupCreateModal`,className:`modal popup backup-create-modal`,onbeforeclose:()=>{i.isSubmitting&&app.toasts.info(`The backup was started but may take a while to complete. You can come back later.`)},onafterclose:e=>{clearTimeout(a),e?.remove()}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Initialize new backup`)),t.form({id:r,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Please note that during the backup other concurrent write requests may fail since the database will be temporary "locked" (this usually happens only during the ZIP generation).`),t.p({className:`txt-bold`},`If you are using S3 storage for the collections file upload, you'll have to backup them separately since they are not locally stored and they will not be included in the generated backup!`)))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:r+`_name`},`Backup name`),t.input({id:r+`_name`,name:`name`,type:`text`,pattern:`^[a-z0-9_-]+.zip$`,placeholder:`Leave empty to autogenerate`,value:()=>i.name,oninput:e=>i.name=e.target.value})),t.div({className:`field-help`},`Must be in the format [a-z0-9_-].zip`)))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,disabled:()=>i.isSubmitting,onclick:()=>app.modals.close(n)},t.span({className:`txt`},`Cancel`)),t.button({"html-form":r,type:`submit`,className:()=>`btn ${i.isSubmitting?`loading`:``}`,disabled:()=>i.isSubmitting},t.span({className:`txt`},`Start backup`)))),n}function Li(e){let n=Ri(e);document.body.appendChild(n),app.modals.open(n)}function Ri(e){let n=`backup_restore_`+app.utils.randomString(),r=store({key:e,keyConfirm:``,isSubmitting:!1,get canSubmit(){return r.key&&r.key==r.keyConfirm}}),i;async function a(){if(!(r.isSubmitting||!r.canSubmit)){clearTimeout(i),r.isSubmitting=!0;try{await app.pb.backups.restore(r.keyConfirm),i=setTimeout(()=>{window.location.reload(),r.isSubmitting=!1},2e3)}catch(e){clearTimeout(i),e?.isAbort||(r.isSubmitting=!1,app.checkApiError(e))}}}return t.div({pbEvent:`backupRestoreModal`,className:`modal popup backup-restore-modal`,onbeforeclose:()=>!r.isSubmitting,onafterclose:e=>{e?.remove()},onunmount:()=>{clearTimeout(i)}},t.header({className:`modal-header`},t.h5({className:`m-auto txt-center`},`Restore `,t.strong(null,()=>r.key))),t.form({id:n,className:`modal-content backup-restore-form`,autocomplete:`off`,onsubmit:e=>{e.preventDefault(),a()}},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`alert danger`},t.div({className:`content`},t.p({className:`txt-bold`},`Please proceed with extreme caution and use it only with trusted backups!`),t.p(null,`Backup restore currently works only on UNIX based systems.`),t.p(null,`The restore operation will attempt to replace your existing `,t.code(null,`pb_data`),` with the one from the backup and will restart the application process.`),t.p(null,`This means that on success all of your data (including app settings, users, superusers, etc.) will be replaced with the ones from the backup.`),t.p(null,`The operation will be reverted if the backup is invalid (ex. missing `,t.code(null,`data.db`),` file).`),t.p(null,`Below is an oversimplified version of the restore flow:`),t.ol(null,t.li(null,`Replaces the current `,t.code(null,`pb_data`),` with the content from the backup.`),t.li(null,`Triggers app restart.`),t.li(null,`Applies all migrations that are missing in the restored `,t.code(null,`pb_data`),`.`),t.li(null,`Initializes the app server as usual.`))))),t.div({className:`col-lg-12`},t.div({className:`confirm-key-label m-b-sm`},`Type the backup name `,t.div({className:`label`},()=>r.key,app.components.copyButton(()=>r.key)),` to confirm:`),t.div({className:`field`},t.label({htmlFor:n+`_key`},`Backup name`),t.input({id:n+`_key`,name:`key`,type:`text`,required:!0,value:()=>r.keyConfirm,oninput:e=>r.keyConfirm=e.target.value}))))),t.footer({className:`modal-footer`},t.button({type:`button`,className:`btn transparent m-r-auto`,onclick:()=>app.modals.close(),disabled:()=>r.isSubmitting},t.span({className:`txt`},`Cancel`)),t.button({"html-form":n,type:`submit`,className:()=>`btn ${r.isSubmitting?`loading`:``}`,disabled:()=>r.isSubmitting||!r.canSubmit},t.span({className:`txt`},`Restore backup`))))}function zi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({canBackup:!0,isLoading:!1,isDownloading:{},isDeleting:{},backups:[]});async function a(){i.isLoading=!0;try{i.backups=await app.pb.backups.getFullList(),i.backups.sort((e,n)=>e.modifiedn.modified?-1:0),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){app.modals.confirm(`Do you really want to delete ${e}?`,()=>s(e))}async function s(e){if(!i.isDeleting[e]){i.isDeleting[e]=!0;try{await app.pb.backups.delete(e),a(),app.toasts.success(`Successfully deleted ${e}.`)}catch(e){app.checkApiError(e)}delete i.isDeleting[e]}}async function c(){try{let e=await app.pb.health.check({requestKey:null}),n=i.canBackup;i.canBackup=e?.data?.canBackup||!1,i.canBackup&&n!=i.canBackup&&a()}catch(e){console.warn(`failed to load canBackup checks`,e)}}async function l(e){if(!i.isDownloading[e]){i.isDownloading[e]=!0;try{let n=await app.pb.files.getToken({requestKey:null});app.utils.download(app.pb.backups.getDownloadURL(n,e))}catch(e){app.checkApiError(e)}delete i.isDownloading[e]}}return t.div({pbEvent:`backupsList`,className:`list backups-list`,onmount:e=>{r.push(watch(()=>n.reset,()=>{a()})),e._canBackupIntervalId=setInterval(()=>{c()},3500)},onunmount:e=>{clearInterval(e._canBackupIntervalId),r.forEach(e=>e?.unwatch())}},t.div({className:`list-content`},t.div({hidden:()=>!i.isLoading||i.backups.length,className:`list-item`},t.div({className:`skeleton-loader`})),t.div({hidden:()=>i.isLoading||i.backups.length,className:()=>`list-item`},t.div({className:`content block txt-hint`},`No backups found.`)),()=>i.backups.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.i({className:`ri-folder-zip-line`,ariaHidden:!0}),t.div({className:`content`},t.span({className:`backup-name txt-ellipsis`,title:()=>e.key,textContent:()=>e.key}),t.small({className:`backup-size txt-hint txt-nowrap`},`(`,()=>app.utils.formattedFileSize(e.size),`)`)),t.nav({hidden:()=>i.isLoading,className:`actions autohide`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Download`),className:()=>`btn sm circle secondary transparent ${i.isDownloading[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>l(e.key)},t.i({className:`ri-download-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Restore`),className:()=>`btn sm circle secondary transparent`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>Li(e.key)},t.i({className:`ri-restart-line`,ariaHidden:!0})),t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Delete`),className:()=>`btn sm circle secondary transparent ${i.isDeleting[e.key]?`loading`:``}`,disabled:()=>i.isDeleting[e.key]||i.isDownloading[e.key],onclick:()=>o(e.key)},t.i({className:`ri-delete-bin-7-line`,ariaHidden:!0})))))),t.div({className:`list-item`},t.button({type:`button`,className:()=>`btn secondary block ${i.isLoading?`loading`:``}`,disabled:()=>!i.canBackup||i.isLoading,onclick:()=>{Fi({oncreated:()=>a()})}},()=>i.canBackup?[t.i({className:`ri-play-circle-line`,ariaHidden:!0}),t.span({className:`txt`},`Initialize new backup`)]:[t.span({className:`loader sm`}),t.span({className:`txt`},`Backup/restore operation is in process`)])))}function Bi(e=null){let n=`backup_upload_`+app.utils.randomString(),r=store({isUploading:!1});function i(e){e&&app.modals.confirm(`Note that we don't perform validations for the uploaded backup files. Proceed with extreme caution and only if you trust the source.\n\nDo you really want to upload "${e.name}"?`,()=>{a(e)},()=>{o()})}async function a(i){if(!(!i||r.isUploading)){r.isUploading=!0;try{let a=new FormData;a.set(`file`,i),await app.pb.backups.upload(a,{requestKey:n}),r.isUploading=!1,e(i),app.toasts.success(`Successfully uploaded a new backup.`)}catch(e){e.isAbort||(r.isUploading=!1,e.response?.formData?.file?.message?app.toasts.error(e.response.formData.file.message):app.checkApiError(e))}o()}}function o(){s&&(s.value=``)}let s=t.input({type:`file`,accept:`application/zip`,className:`hidden`,onchange:e=>{i(e.target?.files?.[0])}});return t.div(null,t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Upload backup`),className:()=>`btn sm transparent secondary circle ${r.isUploading?`loading`:``}`,disabled:()=>r.isUploading,onclick:()=>s?.click(),onunmount:()=>{app.pb.cancelRequest(n)}},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0})),s)}function Vi(e){app.store.title=`Backups`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageBackupsSettings`,className:`page page-backups-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Backup and restore your PocketBase data`),app.components.refreshButton({className:`btn sm transparent secondary circle tooltip-bottom`,onclick:r}),Bi(r)),zi({reset:()=>n.resetList})),t.div({className:`col-lg-12`},Pi({onsave:()=>r()})))),t.footer({className:`page-footer`},app.components.credits())))}function Hi(e={}){let n=store({reset:null}),r=app.utils.extendStore(n,e),i=store({isLoading:!1,isRunning:{},crons:[]});async function a(){i.isLoading=!0;try{i.crons=await app.pb.crons.getFullList(),i.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoading=!1)}}async function o(e){if(!(!e||i.isRunning[e])){i.isRunning[e]=!0;try{await app.pb.crons.run(e),app.toasts.success(`Successfully triggered "${e}".`),i.isRunning[e]=!1}catch(n){n.isAbort||(ApiClient.error(n),i.isRunning[e]=!1)}}}return t.div({pbEvent:`cronsList`,className:`list`,onmount:()=>{r.push(watch(()=>n.reset,()=>{a()}))},onunmount:()=>{r.forEach(e=>e?.unwatch())}},()=>{if(!i.isLoading||i.crons.length)return;let e=[];for(let n=0;n<4;n++)e.push(t.div({rid:`skeleton_`+n,className:`list-item`},t.div({className:`skeleton-loader`})));return e},t.div({hidden:()=>i.isLoading||i.crons.length,className:`list-item`},t.div({className:`content block txt-hint`},`No registered crons found.`)),()=>i.crons.map(e=>t.div({className:()=>`list-item ${i.isLoading?`faded`:``}`},t.div({className:`content`},t.span({className:`cron-id txt-code txt-ellipsis`,title:()=>e.id,textContent:()=>e.id})),t.small({className:`cron-expression txt-hint txt-nowrap txt-code`},()=>e.expression),t.nav({hidden:()=>i.isLoading,className:`actions`},t.button({type:`button`,ariaLabel:app.attrs.tooltip(`Run`),className:()=>`btn sm circle secondary transparent ${i.isRunning[e.id]?`loading`:``}`,disabled:()=>i.isRunning[e.id],onclick:()=>o(e.id)},t.i({className:`ri-play-large-line`,ariaHidden:!0}))))))}function Ui(e){app.store.title=`Crons`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageCronsSettings`,className:`page`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},t.div({className:`flex gap-10 m-b-sm`},t.div({className:`txt-lg`},`Registered app cron jobs`),app.components.refreshButton({className:`btn sm transparent secondary circle`,onclick:r})),Hi({reset:()=>n.resetList}),t.div({className:`txt-sm txt-hint m-t-sm`},`App cron jobs can be registered only programmatically with `,t.a({href:`https://pocketbase.io/docs/go-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-jobs-scheduling/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JavaScript`}),`.`)),t.footer({className:`page-footer`},app.components.credits())))}function Wi(e){app.store.title=`Mail settings`;let n=[{label:`Auto (StartTLS)`,value:!1},{label:`Always`,value:!0}],r=[{label:`PLAIN (default)`,value:`PLAIN`},{label:`LOGIN`,value:`LOGIN`}],i=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,showMoreOptions:!1,get hasChanges(){return i.initSerialized!=JSON.stringify(i.formSettings)}});a();async function a(){i.isLoading=!0;try{s(await app.pb.settings.getAll()),i.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function o(){if(!(i.isSaving||!i.hasChanges)){i.isSaving=!0;try{let e=app.utils.filterRedactedProps(i.formSettings);s(await app.pb.settings.update(e)),app.toasts.success(`Successfully saved mail settings.`)}catch(e){app.checkApiError(e)}i.isSaving=!1}}function s(e={}){app.store.settings=JSON.parse(JSON.stringify(e)),i.formSettings={meta:e?.meta||{},smtp:e?.smtp||{}},i.formSettings.smtp.authMethod||(i.formSettings.smtp.authMethod=r[0].value),i.initSerialized=JSON.stringify(i.formSettings)}function c(){i.formSettings=JSON.parse(i.initSerialized)}return t.div({pbEvent:`pageMailSettings`,className:`page page-mail-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`mailSettingsForm`,className:`grid mail-settings-form`,inert:()=>i.isSaving,onsubmit:e=>{e.preventDefault(),o()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`Configure common settings for sending emails.`)),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderName`},`Sender name`),t.input({id:`meta.senderName`,name:`meta.senderName`,type:`text`,required:!0,value:()=>i.formSettings.meta.senderName||``,oninput:e=>i.formSettings.meta.senderName=e.target.value}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`meta.senderAddress`},`Sender address`),t.input({id:`meta.senderAddress`,name:`meta.senderAddress`,type:`email`,required:!0,value:()=>i.formSettings.meta.senderAddress||``,oninput:e=>i.formSettings.meta.senderAddress=e.target.value}))),t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`smtp.enabled`,name:`smtp.enabled`,type:`checkbox`,className:`switch`,checked:()=>!!i.formSettings.smtp.enabled,onchange:e=>i.formSettings.smtp.enabled=e.target.checked}),t.label({htmlFor:`smtp.enabled`},t.span({className:`txt`},`Use SMTP mail server `,t.strong(null,`(recommended)`)),t.i({className:`ri-information-line link-faded`,ariaDescription:app.attrs.tooltip(`By default PocketBase uses the unix "sendmail" command for sending emails. For better emails deliverability it is recommended to use a SMTP mail server.`)}))),app.components.slide(()=>i.formSettings.smtp.enabled,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-4`},t.div({className:`field`},t.label({htmlFor:`smtp.host`},`SMTP server host`),t.input({id:`smtp.host`,name:`smtp.host`,type:`text`,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.host||``,oninput:e=>i.formSettings.smtp.host=e.target.value}))),t.div({className:`col-lg-2`},t.div({className:`field`},t.label({htmlFor:`smtp.port`},`Port`),t.input({id:`smtp.port`,name:`smtp.port`,type:`number`,min:0,step:1,required:()=>i.formSettings.smtp.enabled,value:()=>i.formSettings.smtp.port||``,oninput:e=>i.formSettings.smtp.port=parseInt(e.target.value,10)}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.username`},`Username`),t.input({id:`smtp.username`,name:`smtp.username`,type:`text`,autocomplete:`off`,value:()=>i.formSettings.smtp.username||``,oninput:e=>i.formSettings.smtp.username=e.target.value}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.password`},`Password`),t.input({id:`smtp.password`,name:`smtp.password`,type:`password`,autocomplete:`new-password`,value:()=>i.formSettings.smtp.password||``,oninput:e=>i.formSettings.smtp.password=e.target.value,onkeyup:e=>{e.key==`Backspace`&&i.formSettings.smtp.password===void 0&&(i.formSettings.smtp.password=``)},placeholder:()=>i.formSettings.smtp.password===void 0?`* * * * * *`:``})))),t.button({type:`button`,className:`btn secondary sm m-t-sm`,onclick:()=>i.showMoreOptions=!i.showMoreOptions},t.span({className:`txt`},()=>i.showMoreOptions?`Hide more options`:`Show more options`),t.i({className:()=>i.showMoreOptions?`ri-arrow-drop-up-line`:`ri-arrow-drop-down-line`})),app.components.slide(()=>i.showMoreOptions,t.div({className:`grid m-t-sm`},t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.tls`},`TLS encryption`),app.components.select({id:`smtp.tls`,name:`smtp.tls`,required:!0,options:n,value:()=>i.formSettings.smtp.tls||!1,onchange:e=>{i.formSettings.smtp.tls=e?.[0]?.value}}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`smtp.authMethod`},`AUTH method`),app.components.select({id:`smtp.authMethod`,name:`smtp.authMethod`,required:!0,options:r,value:()=>i.formSettings.smtp.authMethod||r[0].value,onchange:e=>{i.formSettings.smtp.authMethod=e?.[0]?.value}}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:`smtp.localName`},t.span({className:`txt`},`EHLO/HELO domain`),t.i({className:`ri-information-line link-hint tooltip-top`,ariaDescription:app.attrs.tooltip(`Some SMTP servers, such as the Gmail SMTP-relay, requires a proper domain name in the inital EHLO/HELO exchange and will reject attempts to use localhost.`)})),t.input({id:`smtp.localName`,name:`smtp.localName`,type:`text`,placeholder:`Default to localhost`,value:()=>i.formSettings.smtp.localName||``,oninput:e=>i.formSettings.smtp.localName=e.target.value}))))))),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),()=>i.hasChanges?[t.button({type:`button`,className:`btn transparent secondary`,onclick:c},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${i.isSaving?`loading`:``}`,disabled:()=>!i.hasChanges||i.isSaving},t.span({className:`txt`},`Save changes`))]:t.button({type:`button`,className:()=>`btn expanded-lg outline`,onclick:()=>app.modals.openMailTest()},t.i({className:`ri-mail-check-line`,ariaHidden:!0}),t.span({className:`txt`},`Send test email`)))))),t.footer({className:`page-footer`},app.components.credits())))}var Gi=`pbSQLConsoleHistory`;function Ki(e){app.store.title=`SQL console`;let n=`sql_console_`+app.utils.randomString(),r=n+`editor`,i=n+`executeSQL`,a=store({askedForConfirmationAtLeastOnce:!1,isExecuting:!1,maxRows:250,query:``,result:{},sort:{},errorMsg:``,executedHistory:app.utils.getLocalHistory(Gi,[]),get sortedResultRows(){if(a.sort?.index===void 0){let e=a.result?.rows||[];return a.maxRows>=e.length?e:e.slice(0,a.maxRows)}let e=!!a.sort?.asc,n=a.result?.rows?.toSorted((n,r)=>{let i=n[a.sort.index],o=r[a.sort.index];return e||(i=r[a.sort.index],o=n[a.sort.index]),i==o?0:i==null?-1:o==null?1:i.localeCompare(o)})||[];return a.maxRows>=n.length?n:n.slice(0,a.maxRows)},get totalRemainingRows(){return(a.result?.rows?.length<<0)-a.sortedResultRows.length}});function o(e){return e?.trim()?!a.askedForConfirmationAtLeastOnce&&app.store.settings?.meta?.hideControls?!0:(e=e?.replace(/[\s\;]/gm,` `).toUpperCase()+` `,!![`ALTER `,`REPLACE `,`INSERT `,`CREATE `,`UPDATE `,`DELETE `,`DROP `,`DETACH `,`PRAGMA `].find(n=>e.includes(n))):!1}async function s(){return o(a.query)?(a.askedForConfirmationAtLeastOnce=!0,app.modals.confirm(t.div({className:`txt-center`},t.h6(null,`Be careful and continue only if you really know what you are doing because, depending on the query, the operation could break your application and may not be reversible.`)),()=>c(),null,{yesButton:`Execute`,noButton:`Cancel`})):c()}async function c(){a.isExecuting=!0,a.maxRows=250,a.result={},a.sort={},a.errorMsg=``;let e=a.query.trim();if(!e){app.pb.cancelRequest(i),a.isExecuting=!1;return}try{a.result=await app.pb.sql.run(e,{requestKey:i}),u(e),a.isExecuting=!1}catch(e){e?.isAbort||(a.isExecuting=!1,a.errorMsg=e?.response?.message||e?.message||`Failed to execute query.`)}}function l(e){function n(e){return e.replace(/[\s\;]/gm,``).toUpperCase()}let r=n(e);for(let i=a.executedHistory.length-1;i>=0;i--)(a.executedHistory[i]==e||n(a.executedHistory[i])==r)&&a.executedHistory.splice(i,1)}function u(e){l(e),a.executedHistory.unshift(a.query),a.executedHistory.length>10&&a.executedHistory.splice(10)}function d(){if(!a.sortedResultRows.length)return;let e=[a.result.columns.map(e=>e.name)].concat(a.sortedResultRows),n=`export_`+new Date().toISOString().replace(/[\-\:\.]/g,``)+`.csv`;app.utils.downloadCSV(e,n)}function f(e){a.sort?.index==e?a.sort={index:e,asc:!a.sort.asc}:a.sort={index:e,asc:!0}}let p=[watch(()=>JSON.stringify(a.executedHistory),(e,n)=>{n!==void 0&&window.localStorage.setItem(Gi,e)})];return t.div({pbEvent:`pageSQLConsole`,className:`page`,onunmount:()=>{app.pb.cancelRequest(i),p.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title)),t.div({className:`page-header-secondary-btns`},t.button({type:`button`,className:`btn circle transparent secondary`,ariaDescription:app.attrs.tooltip(`Recently executed queries`,`right`),"html-popovertarget":`sql-console-history-dropdown`},t.i({className:`ri-history-line`,ariaHidden:!0})),t.div({id:`sql-console-history-dropdown`,className:()=>`dropdown left sql-console-history-dropdown ${a.executedHistory.length?``:`no-items`}`,popover:`auto`},()=>a.executedHistory.length?a.executedHistory.map(e=>t.button({role:`button`,className:`dropdown-item`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),a.query=e,document.getElementById(r)?.click()}},t.span({className:`query`},()=>app.utils.truncate(e,500)),t.small({role:`button`,className:`remove-btn link-hint m-l-auto p-l-5 p-r-5`,title:`Clear`,onauxclick:e=>(e.stopPropagation(),!1),onclick:n=>(n.stopPropagation(),l(e),!1)},t.i({className:`ri-close-line`,ariaHidden:!0})))):t.span({className:`txt txt-hint p-5`},`No recently executed queries.`))),t.div({className:`page-header-primary-btns`},t.button({type:`button`,className:()=>`btn expanded-lg ${a.isExecuting?`loading`:``}`,disabled:()=>a.isExecuting,onclick:()=>s()},t.i({className:`ri-play-large-line`,ariaHidden:!0}),t.span({className:`txt`},`Execute`)))),t.div({className:`field sql-console-field`},app.components.codeEditor({id:r,language:`sql`,required:!0,name:`query`,placeholder:`e.g. EXPLAIN QUERY PLAN SELECT * from users WHERE verified=true`,value:()=>a.query,oninput:e=>a.query=e,onblur:e=>a.query=e.trim()})),t.div({className:`flex field-help m-b-sm`},t.button({type:`button`,className:`link-hint m-l-auto`,"html-popovertarget":n+`caveats_dropdown`},()=>`SQL console caveats`),t.div({id:n+`caveats_dropdown`,className:`dropdown sm query-caveats-dropdown`,popover:`auto`},t.ul(null,t.li(null,`The returned rows are limited up to 1000.`),t.li(null,`The executed queries have a max timeout of 3 minutes.`),t.li(null,`The data is returned as byte strings without any additional formatting.`),t.li(null,`Multiple queries are supported but only the result of the last one is returned.`)))),t.div({hidden:()=>a.isExecuting||!a.errorMsg,className:`alert danger m-b-sm`},t.pre(null,()=>a.errorMsg)),t.div({hidden:()=>a.isExecuting||a.errorMsg||a.result?.columns?.length||app.utils.isEmpty(a.result),className:`alert success m-b-sm`},t.p({className:`txt-bold`},`Query executed successfully!`),()=>{if(a.result?.affectedRows)return t.p(null,`Affected rows: `,a.result?.affectedRows)}),t.div({hidden:()=>a.isExecuting||!a.result?.columns?.length,className:`page-table-wrapper`},t.table({className:`sql-console-table responsive-table optimize`},t.thead({className:`sticky`},t.tr(null,()=>a.result?.columns?.map((e,n)=>t.th({textContent:e.name,className:()=>{let e=`sort-handle`;return a.sort?.index==n&&(e+=a.sort.asc?` asc`:` desc`),e},onclick:()=>f(n)})))),t.tbody(null,()=>a.sortedResultRows.length?a.sortedResultRows.map(e=>t.tr(null,()=>a.result?.columns?.map((n,r)=>{let i=e[r];return t.td({"html-data-name":n.name},i==null?`NULL`:app.utils.truncate(i,2e3))}))):t.tr(null,t.td({colSpan:a.result?.columns?.length||1,className:`txt-center`},t.span({className:`txt-hint`},`No rows found.`))),t.tr({hidden:()=>a.isExecuting||!a.result?.rows?.length||a.result.rows.length<=a.sortedResultRows.length},t.td({colSpan:99},t.button({type:`button`,className:`btn lg secondary load-more-btn`,onclick:()=>{a.maxRows=a.result?.rows?.length||250}},t.span({className:`txt`,textContent:()=>`Load remaining (${a.totalRemainingRows})`}))))))),t.footer({className:`page-footer`},t.span({className:()=>`exec-time ${a.isExecuting?`faded`:``}`},`Time: `,()=>(a.result?.execTime||0)+`ms`),t.span({hidden:()=>!a.result?.columns?.length,className:()=>`total-count ${a.isExecuting?`faded`:``}`},`Rows: `,()=>a.result?.rows?.length||0,()=>{if(a.result?.rows?.length)return[` (`,t.span({role:`button`,className:`link-hint`,textContent:`Export as CSV`,onclick:d}),`)`]}),app.components.credits())))}function qi(){app.store.title=`File storage`;let e=store({isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,originalFormSettings:null,get hasChanges(){return e.initSerialized!=JSON.stringify(e.formSettings)}});n();async function n(){e.isLoading=!0;try{i(await app.pb.settings.getAll()),e.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function r(){if(!(e.isSaving||!e.hasChanges)){e.isSaving=!0;try{let n=app.utils.filterRedactedProps(e.formSettings);i(await app.pb.settings.update(n)),app.toasts.success(`Successfully saved storage settings.`)}catch(e){app.checkApiError(e)}e.isSaving=!1}}function i(n={}){app.store.settings=JSON.parse(JSON.stringify(n)),e.formSettings={s3:n?.s3||{}},e.initSerialized=JSON.stringify(e.formSettings),e.originalFormSettings=JSON.parse(e.initSerialized)}function a(){e.formSettings=JSON.parse(e.initSerialized)}return t.div({pbEvent:`pageStorageSettings`,className:`page page-storage-settings`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>e.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`storageSettingsForm`,className:`grid storage-settings-form`,inert:()=>e.isSaving,onsubmit:e=>{e.preventDefault(),r()}},t.div({className:`col-lg-12 txt-lg`},t.p(null,`By default PocketBase uses and recommends the local file system to store uploaded files because it is more performant, easier to manage and backup.`),t.p(null,`Alternatively, if you have limited disk space available, you could opt to an S3 compatible external storage.`)),t.div({className:`col-lg-12`},app.components.s3ConfigFields({config:()=>e.formSettings.s3,before:()=>{let n=e.originalFormSettings.s3?.enabled;if(n!=e.formSettings.s3?.enabled)return t.div({className:`alert info m-t-sm`},`If you have existing uploaded files, you'll have to migrate them manually from the `,t.strong(null,n?`S3 storage`:`local file system`),` to the `,t.strong(null,e.formSettings.s3?.enabled?`S3 storage`:`local file system`),`.`,t.br(),`There are several command line tools that can help you, such as: `,t.a({href:`https://github.com/rclone/rclone`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`rclone`}),`, `,t.a({href:`https://github.com/peak/s5cmd`,target:`_blank`,rel:`noopener noreferrer`,className:`txt-bold`,textContent:`s5cmd`}),`, etc.`)}})),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({hidden:()=>!e.hasChanges,type:`button`,className:`btn transparent secondary`,onclick:a},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded-lg ${e.isSaving?`loading`:``}`,disabled:()=>!e.hasChanges||e.isSaving},t.span({className:`txt`},`Save changes`)))))),t.footer({className:`page-footer`},app.components.credits())))}function Ji(e){app.store.title=`Export collections`;let n=`export_`+app.utils.randomString(),r=store({isLoading:!1,collections:[],bulkSelected:{},get bulkSelectStr(){return JSON.stringify(app.utils.sortedCollectionsByType(Object.values(r.bulkSelected)),null,2)},get totalSelected(){return Object.keys(r.bulkSelected).length},get areAllSelected(){return r.collections.length&&r.collections.length==r.totalSelected}});i();async function i(){r.isLoading=!0;try{let e=await app.pb.collections.getFullList({requestKey:n});for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;r.collections=app.utils.sortedCollectionsByType(e),c(),r.isLoading=!1}catch(e){e.isAbort||(app.checkApiError(e),r.isLoading=!1)}}function a(){let e=app.utils.sortedCollectionsByType(Object.values(r.bulkSelected));app.utils.downloadJSON(e,`pb_schema`)}function o(){r.areAllSelected?s():c()}function s(){r.bulkSelected={}}function c(){r.bulkSelected={};for(let e of r.collections)r.bulkSelected[e.id]=e}function l(e){let n=JSON.parse(JSON.stringify(r.bulkSelected));r.bulkSelected[e.id]?delete n[e.id]:n[e.id]=e,r.bulkSelected=n}return t.div({pbEvent:`pageExportCollections`,className:`page page-export-collections`},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>r.isLoading?t.div({className:`txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.div({className:`txt-lg`},`Below you'll find your current collections configuration that you could import in another PocketBase environment.`)),t.div({className:`col-lg-12`},t.div({className:`export-panel`},t.aside({className:`export-list`},t.div({className:`list-item`},t.div({className:`field`},t.input({id:n+`.select_all`,type:`checkbox`,checked:()=>r.areAllSelected,onchange:()=>o()}),t.label({htmlFor:n+`.select_all`},`Select all`))),()=>r.collections.map(e=>{let i=n+`_c_`+e.id;return t.div({className:`list-item`},t.div({className:`field`},t.input({id:i,type:`checkbox`,checked:()=>!!r.bulkSelected[e.id],onchange:()=>{l(e)}}),t.label({htmlFor:i},e.name)))})),t.output({className:`export-preview`},app.components.codeBlock({value:()=>r.bulkSelectStr,language:`plain`}),t.nav({className:`ctrls`},app.components.copyButton(()=>r.bulkSelectStr))))),t.div({className:`col-lg-12 txt-right`},t.button({className:`btn`,onclick:a},t.i({className:`ri-download-line`,ariaHidden:!0}),t.span({className:`txt`},`Download as JSON`))))),t.footer({className:`page-footer`},app.components.credits())))}function Yi(e){app.store.title=`Import collections`;let n=`import_`+app.utils.randomString(),r=[],i=store({rawNewCollections:``,oldCollections:[],newCollections:[],collectionsToUpdate:[],deleteMissing:!0,isLoadingFile:!1,isLoadingOldCollections:!1,mergeWithOldCollections:!1,get isRawValid(){return!!i.rawNewCollections&&i.newCollections?.length>0&&i.newCollections.length==i.newCollections.filter(e=>!!e.id&&!!e.name).length},get collectionsToDelete(){return i.oldCollections.filter(e=>i.isRawValid&&!i.mergeWithOldCollections&&i.deleteMissing&&!i.newCollections.find(n=>n.id==e.id))},get collectionsToAdd(){return i.newCollections.filter(e=>i.isRawValid&&!i.oldCollections.find(n=>n.id==e.id))},get idReplacableCollections(){return i.newCollections.filter(e=>{let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)return!1;if(n.id!=e.id)return!0;let r=Array.isArray(n.fields)?n.fields:[],a=Array.isArray(e.fields)?e.fields:[];for(let e of a){if(r.find(n=>n.id==e.id))continue;let n=r.find(n=>n.name==e.name);if(n&&e.id!=n.id)return!0}return!1})},get hasChanges(){return!!i.rawNewCollections&&!!(i.collectionsToDelete.length||i.collectionsToAdd.length||i.collectionsToUpdate.length)},get canReview(){return!i.isLoadingOldCollections&&i.isRawValid&&i.hasChanges}}),a=t.input({id:n+`_load_json`,type:`file`,className:`hidden`,accept:`.json`,onchange:()=>{d(a.files?.[0])}});o();async function o(){i.isLoadingOldCollections=!0;try{let e=await app.pb.collections.getFullList();for(let n of e)delete n.created,delete n.updated,delete n.oauth2?.providers;i.oldCollections=e,i.isLoadingOldCollections=!1}catch(e){e.isAbort||(app.checkApiError(e),i.isLoadingOldCollections=!1)}}r.push(watch(()=>i.rawNewCollections,()=>{s()}));function s(){let e=[];try{e=JSON.parse(i.rawNewCollections),e=Array.isArray(e)?app.utils.filterDuplicatesByKey(e):[];for(let n of e)delete n.created,delete n.updated,n.fields&&=app.utils.filterDuplicatesByKey(n.fields)}catch{}i.newCollections=e}r.push(watch(()=>[i.newCollections,i.deleteMissing],()=>{c()}));function c(){if(i.collectionsToUpdate=[],i.isRawValid)for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.id==e.id);!n?.id||!app.utils.hasCollectionChanges(n,e,i.deleteMissing)||i.collectionsToUpdate.push({new:e,old:n})}}function l(){for(let e of i.newCollections){let n=i.oldCollections.find(n=>n.name==e.name||n.id==e.id);if(!n)continue;let r=e.id,a=n.id;e.id=a;let o=Array.isArray(n.fields)?n.fields:[],s=Array.isArray(e.fields)?e.fields:[];for(let e of s){let n=o.find(n=>n.name==e.name);n&&n.id&&(e.id=n.id)}for(let e of i.newCollections)if(Array.isArray(e.fields))for(let n of e.fields)n.collectionId&&n.collectionId===r&&(n.collectionId=a);for(let n=0;ne.replace(r,a))}i.rawNewCollections=JSON.stringify(i.newCollections,null,2)}function u(){i.rawNewCollections=``,a.value=``,app.store.errors=null}function d(e){i.isLoadingFile=!0;let n=new FileReader;n.onload=async e=>{i.isLoadingFile=!1,a.value=``,i.rawNewCollections=e.target.result,await new Promise(e=>setTimeout(e,0)),i.newCollections.length||(app.toasts.error(`Invalid collections configuration.`),u())},n.onerror=e=>{app.toasts.error(`Failed to load the imported JSON.`),console.warn(e),i.isLoadingFile=!1,a.value=``},n.readAsText(e)}function f(){let e=i.mergeWithOldCollections?app.utils.filterDuplicatesByKey(i.oldCollections.concat(i.newCollections)):i.newCollections;app.modals.openImportCollectionsReview(i.oldCollections,e,{deleteMissing:i.deleteMissing,onsubmit:()=>{u(),o()}})}return t.div({pbEvent:`pageImportCollections`,className:`page page-import-collections`,onunmount:()=>{r.forEach(e=>e?.unwatch())}},Ci(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},()=>app.store.title))),t.div({className:`wrapper m-b-base`},()=>i.isLoadingOldCollections?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.div({className:`grid`},t.div({className:`col-lg-12`},t.span({className:`txt-lg m-r-5`},`Paste below the collections configuration you want to import or`),t.label({htmlFor:a.id,className:()=>`btn sm outline ${i.isLoadingFile?`loading`:``}`},t.span({className:`txt`},`Load from JSON file`)),a,t.p({className:`txt-hint`},t.em(null,`You can use the `,t.a({href:`https://pocketbase.io/docs/go-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`Go`}),` or `,t.a({href:`https://pocketbase.io/docs/js-migrations/`,target:`_blank`,rel:`noopener noreferrer`,textContent:`JS`}),` migrations to manage your collections programmatically in more granular and version controlled manner.`))),t.div({className:`col-lg-12`},t.div({className:`field`},t.label({htmlFor:n+`_collections_field`},`Collections`),t.textarea({id:n+`_collections_field`,name:`collections`,rows:12,className:`txt-code`,spellcheck:!1,autocorrect:!1,autocomplete:`off`,autocapitalize:`off`,value:()=>i.rawNewCollections,oninput:e=>i.rawNewCollections=e.target.value})),t.div({className:()=>`field-help error ${i.rawNewCollections&&!i.isRawValid?``:`hidden`}`},`Invalid collections configuration.`)),t.div({className:()=>`col-lg-12 ${i.isRawValid?``:`hidden`}`},t.div({className:`field`},t.input({id:n+`_merge_checkbox`,type:`checkbox`,className:`switch`,checked:()=>i.mergeWithOldCollections,onchange:e=>i.mergeWithOldCollections=e.target.checked}),t.label({htmlFor:n+`_merge_checkbox`},`Merge with the existing collections`))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&!i.hasChanges?``:`hidden`}`},t.div({className:`alert info`},t.div({className:`content`},t.p(null,`Your collections configuration is already up-to-date!`)))),t.div({className:()=>`col-lg-12 ${i.isRawValid&&i.hasChanges?``:`hidden`}`},t.p({className:`txt-hint txt-bold`},`Detected changes`),t.div({className:`list`},()=>i.collectionsToDelete.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label danger`,textContent:`Deleted`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))),()=>i.collectionsToUpdate.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label warning`,textContent:`Changed`}),t.div({className:`inline-flex gap-5`},()=>{if(e.old.name!=e.new.name)return[t.span({className:`txt-strikethrough txt-hint`,textContent:e.old.name}),t.i({className:`ri-arrow-right-line txt-sm`,ariaHidden:!0})]},t.strong({textContent:()=>e.new.name}),t.small({className:()=>`txt-hint ${e.new.id?``:`hidden`}`,textContent:()=>e.new.id})))),()=>i.collectionsToAdd.map(e=>t.div({className:`list-item`},t.span({className:`label import-change-label success`,textContent:`Added`}),t.div({className:`inline-flex gap-5`},t.strong({textContent:()=>e.name}),t.small({className:()=>`txt-hint ${e.id?``:`hidden`}`,textContent:()=>e.id})))))),t.div({className:()=>`col-lg-12 ${i.idReplacableCollections?.length?``:`hidden`}`},t.div({className:`alert warning`},t.div({className:`content`},t.p(null,`Some of the imported collections share the same name and/or fields but are imported with different IDs.`),t.p(null,`You can replace them in the import if you want to:`,t.button({type:`button`,className:`btn warning sm m-l-10`,textContent:`Replace with original IDs`,onclick:l}))))),t.div({className:`col-lg-12`},t.div({className:`flex`},t.button({type:`button`,className:()=>`btn secondary ${i.rawNewCollections?``:`hidden`}`,onclick:u},t.span({className:`txt`},`Clear`)),t.button({type:`button`,className:`btn expanded-lg m-l-auto`,disabled:()=>!i.canReview,onclick:f},t.span({className:`txt`},`Review`)))))),t.footer({className:`page-footer`},app.components.credits())))}window.app=window.app||{},window.app.routes=window.app.routes||{},window.app.routes.fallbackPath=`#/collections`,app.routes.guestOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(app.pb.authStore.isValid&&app.pb.authStore.record?.id){window.location.hash=`#/`;return}app.store.showHeader=!1,app.store.page=await n(e)}},app.routes.superuserOnly=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{if(!app.pb.authStore.isValid||!app.pb.authStore.record?.id){window.location.hash=`#/login`;return}app.store.showHeader=!0,app.store.page=await n(e)}},app.routes.blank=function(e,n){if(app.store._ready)throw Error(`the router is already initialized`);Xi[e]=async e=>{app.store.showHeader=!1,app.store.page=await n(e)}};var Xi={},Zi;function Qi(){Zi&&Zi(),Zi=router(Xi,{fallbackPath:app.routes.fallbackPath})}app.routes.guestOnly(`#/pbinstall/{token}`,async e=>{let{pageInstaller:n}=await W(async()=>{let{pageInstaller:e}=await import(`./pageInstaller-DJdGfAhp.js`);return{pageInstaller:e}},[],import.meta.url);return n(e)}),app.routes.guestOnly(`#/login`,e=>Yr(e)),app.routes.guestOnly(`#/request-password-reset`,async e=>{let{pageRequestSuperuserPasswordReset:n}=await W(async()=>{let{pageRequestSuperuserPasswordReset:e}=await import(`./pageRequestSuperuserPasswordReset-C39AMhGf.js`);return{pageRequestSuperuserPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-password-reset/{token}`,async e=>{let{pageConfirmPasswordReset:n}=await W(async()=>{let{pageConfirmPasswordReset:e}=await import(`./pageConfirmPasswordReset-DE6sv7BF.js`);return{pageConfirmPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-verification/{token}`,async e=>{let{pageConfirmVerification:n}=await W(async()=>{let{pageConfirmVerification:e}=await import(`./pageConfirmVerification-CeyOBacX.js`);return{pageConfirmVerification:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-email-change/{token}`,async e=>{let{pageConfirmEmailChange:n}=await W(async()=>{let{pageConfirmEmailChange:e}=await import(`./pageConfirmEmailChange-87a5LVPe.js`);return{pageConfirmEmailChange:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-success`,async e=>{let{pageOAuth2RedirectSuccess:n}=await W(async()=>{let{pageOAuth2RedirectSuccess:e}=await import(`./pageOAuth2RedirectSuccess-DmZV1eyz.js`);return{pageOAuth2RedirectSuccess:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-failure`,async e=>{let{pageOAuth2RedirectFailure:n}=await W(async()=>{let{pageOAuth2RedirectFailure:e}=await import(`./pageOAuth2RedirectFailure-CRvz4PXa.js`);return{pageOAuth2RedirectFailure:e}},[],import.meta.url);return n(e)}),app.routes.superuserOnly(`#/collections`,di),app.routes.superuserOnly(`#/logs`,Si),app.routes.superuserOnly(`#/settings`,Mi),app.routes.superuserOnly(`#/settings/mail`,Wi),app.routes.superuserOnly(`#/settings/storage`,qi),app.routes.superuserOnly(`#/settings/backups`,Vi),app.routes.superuserOnly(`#/settings/crons`,Ui),app.routes.superuserOnly(`#/settings/export-collections`,Ji),app.routes.superuserOnly(`#/settings/import-collections`,Yi),app.routes.superuserOnly(`#/settings/sql`,Ki);var $i=t;t=new Proxy({},{get(e,n){return function(){let e=arguments?.[0];if(e&&e.pbEvent){let n=e.onmount;e.onmount=r=>{n?.(r),r.dataset.pb=e.pbEvent,document.dispatchEvent(new CustomEvent(`mount:`+e.pbEvent,{detail:r}))};let r=e.onunmount;e.onunmount=n=>{document.dispatchEvent(new CustomEvent(`unmount:`+e.pbEvent,{detail:n})),r?.(n)}}return $i[n](...arguments)}}}),document.body.prepend(t.main({"html-class":`app`,className:()=>`app ${app.store.settings?.meta?.hideControls?`hide-controls`:``}`},Fe(),e=>(typeof app.store.page==`function`&&app.store.page(e),app.store.page))),watch(()=>app.store._ready,e=>{e&&Qi()}),document.body.appendChild(t.script({type:`module`,src:app.pb.buildURL(`/_/extensions.js`),onload:()=>{app.store._ready=!0},onerror:e=>{console.warn(`Failed to load extensions:`,e),app.store._ready=!0}}));export{S as n,se as r,Ee as t}; \ No newline at end of file diff --git a/ui/dist/assets/pageConfirmEmailChange-CmDy-gO9.js b/ui/dist/assets/pageConfirmEmailChange-87a5LVPe.js similarity index 94% rename from ui/dist/assets/pageConfirmEmailChange-CmDy-gO9.js rename to ui/dist/assets/pageConfirmEmailChange-87a5LVPe.js index 3168f2bd..5bc90f82 100644 --- a/ui/dist/assets/pageConfirmEmailChange-CmDy-gO9.js +++ b/ui/dist/assets/pageConfirmEmailChange-87a5LVPe.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-BbAer_sj.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.newEmail||!a.collectionId){app.toasts.error(`Invalid or expired email change token.`),window.location.hash=`#/`;return}app.store.title=`Confirm email change`;let o=store({password:``,isSubmitting:!1,isSuccess:!1,showPassword:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmEmailChange(i,o.password),o.isSuccess=!0}catch(e){app.checkApiError(e),o.isSuccess=!1}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmEmailChange`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmEmailChangeAlert`,className:`alert success txt-center`},t.p(null,`The email was successfully changed.`),t.p(null,`You can go back and sign in with your new email address.`)):t.form({pbEvent:`confirmEmailChangeForm`,className:`grid confirm-email-change-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your password to confirm changing your email address to `,t.strong(null,a.newEmail),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`password_confirm`},`Password`),t.input({id:`password_confirm`,name:`password`,required:!0,autofocus:!0,type:()=>o.showPassword?`text`:`password`,value:()=>o.password,oninput:e=>o.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showPassword?`Hide password`:`Show password`),onclick:()=>o.showPassword=!o.showPassword},t.i({className:()=>o.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Confirm new email`)))))}export{r as pageConfirmEmailChange}; \ No newline at end of file +import{n as e,t as n}from"./index-gZx3-mqo.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.newEmail||!a.collectionId){app.toasts.error(`Invalid or expired email change token.`),window.location.hash=`#/`;return}app.store.title=`Confirm email change`;let o=store({password:``,isSubmitting:!1,isSuccess:!1,showPassword:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmEmailChange(i,o.password),o.isSuccess=!0}catch(e){app.checkApiError(e),o.isSuccess=!1}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmEmailChange`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmEmailChangeAlert`,className:`alert success txt-center`},t.p(null,`The email was successfully changed.`),t.p(null,`You can go back and sign in with your new email address.`)):t.form({pbEvent:`confirmEmailChangeForm`,className:`grid confirm-email-change-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your password to confirm changing your email address to `,t.strong(null,a.newEmail),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`password_confirm`},`Password`),t.input({id:`password_confirm`,name:`password`,required:!0,autofocus:!0,type:()=>o.showPassword?`text`:`password`,value:()=>o.password,oninput:e=>o.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showPassword?`Hide password`:`Show password`),onclick:()=>o.showPassword=!o.showPassword},t.i({className:()=>o.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Confirm new email`)))))}export{r as pageConfirmEmailChange}; \ No newline at end of file diff --git a/ui/dist/assets/pageConfirmPasswordReset-D76h8E3Z.js b/ui/dist/assets/pageConfirmPasswordReset-DE6sv7BF.js similarity index 96% rename from ui/dist/assets/pageConfirmPasswordReset-D76h8E3Z.js rename to ui/dist/assets/pageConfirmPasswordReset-DE6sv7BF.js index e35a50fd..1f921fc1 100644 --- a/ui/dist/assets/pageConfirmPasswordReset-D76h8E3Z.js +++ b/ui/dist/assets/pageConfirmPasswordReset-DE6sv7BF.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-BbAer_sj.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired password reset token.`),window.location.hash=`#/`;return}app.store.title=`Confirm password reset`;let o=store({newPassword:``,newPasswordConfirm:``,showNewPassword:!1,showNewPasswordConfirm:!1,isSubmitting:!1,isSuccess:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmPasswordReset(i,o.newPassword,o.newPasswordConfirm),o.isSuccess=!0}catch(e){app.checkApiError(e)}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmPasswordReset`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmPasswordResetAlert`,className:`alert success txt-center`},t.p(null,`The password was successfully changed.`),t.p(null,`You can go back to sign in with your new password.`)):t.form({pbEvent:`confirmPasswordResetForm`,className:`grid confirm-password-reset-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your new password for `,t.strong(null,a.email),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPassword`},`New password`),t.input({id:`newPassword`,name:`password`,required:!0,autofocus:!0,autocomplete:`new-password`,type:()=>o.showNewPassword?`text`:`password`,value:()=>o.newPassword,oninput:e=>o.newPassword=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPassword?`Hide password`:`Show password`),onclick:()=>o.showNewPassword=!o.showNewPassword},t.i({className:()=>o.showNewPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPasswordConfirm`},`New password confirm`),t.input({id:`newPasswordConfirm`,name:`passwordConfirm`,required:!0,autocomplete:`new-password`,type:()=>o.showNewPasswordConfirm?`text`:`password`,value:()=>o.newPasswordConfirm,oninput:e=>o.newPasswordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPasswordConfirm?`Hide password`:`Show password`),onclick:()=>o.showNewPasswordConfirm=!o.showNewPasswordConfirm},t.i({className:()=>o.showNewPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Set new password`)))))}export{r as pageConfirmPasswordReset}; \ No newline at end of file +import{n as e,t as n}from"./index-gZx3-mqo.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired password reset token.`),window.location.hash=`#/`;return}app.store.title=`Confirm password reset`;let o=store({newPassword:``,newPasswordConfirm:``,showNewPassword:!1,showNewPasswordConfirm:!1,isSubmitting:!1,isSuccess:!1});async function s(){if(o.isSubmitting)return;o.isSubmitting=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmPasswordReset(i,o.newPassword,o.newPasswordConfirm),o.isSuccess=!0}catch(e){app.checkApiError(e)}o.isSubmitting=!1}return t.div({pbEvent:`pageConfirmPasswordReset`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isSuccess?t.div({pbEvent:`confirmPasswordResetAlert`,className:`alert success txt-center`},t.p(null,`The password was successfully changed.`),t.p(null,`You can go back to sign in with your new password.`)):t.form({pbEvent:`confirmPasswordResetForm`,className:`grid confirm-password-reset-form`,onsubmit:e=>{e.preventDefault(),s()}},t.div({className:`col-12`},t.div({className:`content txt-center m-b-sm`},`Type your new password for `,t.strong(null,a.email),`:`),t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPassword`},`New password`),t.input({id:`newPassword`,name:`password`,required:!0,autofocus:!0,autocomplete:`new-password`,type:()=>o.showNewPassword?`text`:`password`,value:()=>o.newPassword,oninput:e=>o.newPassword=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPassword?`Hide password`:`Show password`),onclick:()=>o.showNewPassword=!o.showNewPassword},t.i({className:()=>o.showNewPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`newPasswordConfirm`},`New password confirm`),t.input({id:`newPasswordConfirm`,name:`passwordConfirm`,required:!0,autocomplete:`new-password`,type:()=>o.showNewPasswordConfirm?`text`:`password`,value:()=>o.newPasswordConfirm,oninput:e=>o.newPasswordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>o.showNewPasswordConfirm?`Hide password`:`Show password`),onclick:()=>o.showNewPasswordConfirm=!o.showNewPasswordConfirm},t.i({className:()=>o.showNewPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg block ${o.isSubmitting?`loading`:``}`,disabled:()=>o.isSubmitting},t.span({className:`txt`},`Set new password`)))))}export{r as pageConfirmPasswordReset}; \ No newline at end of file diff --git a/ui/dist/assets/pageConfirmVerification-B8_4Ca-4.js b/ui/dist/assets/pageConfirmVerification-CeyOBacX.js similarity index 95% rename from ui/dist/assets/pageConfirmVerification-B8_4Ca-4.js rename to ui/dist/assets/pageConfirmVerification-CeyOBacX.js index e06e4cd3..f485a2b3 100644 --- a/ui/dist/assets/pageConfirmVerification-B8_4Ca-4.js +++ b/ui/dist/assets/pageConfirmVerification-CeyOBacX.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-BbAer_sj.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired verification token.`),window.location.hash=`#/`;return}app.store.title=`Confirm verification`;let o=store({isConfirming:!1,isConfirmSuccess:!1,isResending:!1,isResendSuccess:!1});s();async function s(){if(o.isConfirming)return;o.isConfirming=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmVerification(i),o.isConfirmSuccess=!0}catch{o.isConfirmSuccess=!1}o.isConfirming=!1}async function c(){if(o.isResending)return;o.isResending=!0;let e=new n(`../`);try{await e.collection(a.collectionId).requestVerification(a.email),o.isResendSuccess=!0}catch(e){app.checkApiError(e),o.isResendSuccess=!1}o.isResending=!1}return t.div({pbEvent:`pageConfirmVerification`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isConfirming?t.div({className:`block txt-center`},t.span({className:`loader`},`Please wait...`)):o.isConfirmSuccess?t.div({pbEvent:`confirmVerificationSuccessAlert`,className:`alert success txt-center`},t.p(null,`Successfully verified `,t.strong(null,a.email),`.`)):o.isResendSuccess?t.div({pbEvent:`confirmVerificationResendAlert`,className:`alert success txt-center`},t.p(null,`Please check your email for the new verification link.`)):[t.div({pbEvent:`confirmVerificationErrorAlert`,className:`alert danger txt-center m-b-base`},t.p(null,`Invalid or expired verification token.`)),t.button({type:`button`,className:()=>`btn transparent lg block ${o.isResending?`loading`:``}`,disabled:()=>o.isResending,onclick:()=>c()},t.span({className:`txt`},`Resend`))])}export{r as pageConfirmVerification}; \ No newline at end of file +import{n as e,t as n}from"./index-gZx3-mqo.js";function r(r){let i=r.params?.token||``,a=e(i);if(!a.email||!a.collectionId){app.toasts.error(`Invalid or expired verification token.`),window.location.hash=`#/`;return}app.store.title=`Confirm verification`;let o=store({isConfirming:!1,isConfirmSuccess:!1,isResending:!1,isResendSuccess:!1});s();async function s(){if(o.isConfirming)return;o.isConfirming=!0;let e=new n(app.pb.baseURL);try{await e.collection(a.collectionId).confirmVerification(i),o.isConfirmSuccess=!0}catch{o.isConfirmSuccess=!1}o.isConfirming=!1}async function c(){if(o.isResending)return;o.isResending=!0;let e=new n(`../`);try{await e.collection(a.collectionId).requestVerification(a.email),o.isResendSuccess=!0}catch(e){app.checkApiError(e),o.isResendSuccess=!1}o.isResending=!1}return t.div({pbEvent:`pageConfirmVerification`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),()=>o.isConfirming?t.div({className:`block txt-center`},t.span({className:`loader`},`Please wait...`)):o.isConfirmSuccess?t.div({pbEvent:`confirmVerificationSuccessAlert`,className:`alert success txt-center`},t.p(null,`Successfully verified `,t.strong(null,a.email),`.`)):o.isResendSuccess?t.div({pbEvent:`confirmVerificationResendAlert`,className:`alert success txt-center`},t.p(null,`Please check your email for the new verification link.`)):[t.div({pbEvent:`confirmVerificationErrorAlert`,className:`alert danger txt-center m-b-base`},t.p(null,`Invalid or expired verification token.`)),t.button({type:`button`,className:()=>`btn transparent lg block ${o.isResending?`loading`:``}`,disabled:()=>o.isResending,onclick:()=>c()},t.span({className:`txt`},`Resend`))])}export{r as pageConfirmVerification}; \ No newline at end of file diff --git a/ui/dist/assets/pageInstaller-BurRu8ai.js b/ui/dist/assets/pageInstaller-DJdGfAhp.js similarity index 97% rename from ui/dist/assets/pageInstaller-BurRu8ai.js rename to ui/dist/assets/pageInstaller-DJdGfAhp.js index e559d295..c057d47d 100644 --- a/ui/dist/assets/pageInstaller-BurRu8ai.js +++ b/ui/dist/assets/pageInstaller-DJdGfAhp.js @@ -1 +1 @@ -import{n as e,r as n}from"./index-BbAer_sj.js";function r(r){let i=r.params?.token||``;if(e(i).type!=`auth`||n(i)){app.toasts.error(`The installer token is invalid or has expired.`),window.location.hash=`#/`;return}app.store.title=`Setup your PocketBase instance`;let a=store({email:``,password:``,passwordConfirm:``,showPassword:!1,showPasswordConfirm:!1,isSubmitting:!1,isUploading:!1,get isBusy(){return a.isSubmitting||a.isUploading}});async function o(){if(!a.isBusy){a.isSubmitting=!0;try{await app.pb.collection(`_superusers`).create({email:a.email,password:a.password,passwordConfirm:a.passwordConfirm},{headers:{Authorization:i}}),await app.pb.collection(`_superusers`).authWithPassword(a.email,a.password),window.location.hash=`#/`}catch(e){app.checkApiError(e)}a.isSubmitting=!1}}let s=`backupFileInput`;function c(){let e=document.getElementById(s);e&&(e.value=``)}function l(e){e&&app.modals.confirm(t.h6(null,`Note that we don't perform validations for the uploaded backup files. Proceed with caution and only if you trust the file source.\n\nDo you really want to upload and initialize "${e.name}"?`),()=>{u(e)},()=>{c()})}async function u(e){if(!(!e||a.isBusy)){a.isUploading=!0;try{await app.pb.backups.upload({file:e},{headers:{Authorization:i}}),await app.pb.backups.restore(e.name,{headers:{Authorization:i}}),app.toasts.info(`Please wait while extracting the uploaded archive!`),await new Promise(e=>setTimeout(e,3e3)),window.location.href=`#/`}catch(e){app.checkApiError(e)}c(),a.isUploading=!1}}return t.div({pbEvent:`pageInstaller`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),t.form({pbEvent:`installerForm`,className:`grid installer-form`,onsubmit:e=>{e.preventDefault(),o(a)}},t.div({className:`col-12 txt-center`},`Create your first superuser account in order to continue:`),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:`superuser_email`},`Email`),t.input({id:`superuser_email`,name:`email`,type:`email`,required:!0,autofocus:!0,autocomplete:`off`,disabled:()=>a.isBusy,value:()=>a.email,oninput:e=>a.email=e.target.value}))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password`},`Password`),t.input({id:`superuser_password`,name:`password`,min:10,required:!0,disabled:()=>a.isBusy,type:()=>a.showPassword?`text`:`password`,value:()=>a.password,oninput:e=>a.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPassword?`Hide password`:`Show password`),onclick:()=>a.showPassword=!a.showPassword},t.i({className:()=>a.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0})))),t.div({className:`field-help`},`Recommended at least 10 characters.`)),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password_confirm`},`Password confirm`),t.input({id:`superuser_password_confirm`,name:`passwordConfirm`,required:!0,disabled:()=>a.isBusy,type:()=>a.showPasswordConfirm?`text`:`password`,value:()=>a.passwordConfirm,oninput:e=>a.passwordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPasswordConfirm?`Hide password`:`Show password`),onclick:()=>a.showPasswordConfirm=!a.showPasswordConfirm},t.i({className:()=>a.showPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg next block ${a.isSubmitting?`loading`:``}`,disabled:()=>a.isBusy},t.span({className:`txt`},`Create superuser and login`),t.i({className:`ri-arrow-right-line`,ariaHidden:!0})))),t.hr(),t.label({htmlFor:s,className:()=>`btn secondary transparent lg block ${a.isBusy?`disabled`:``} ${a.isUploading?`loading`:``}`},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0}),t.span({className:`txt`},`Or initialize from backup`)),t.input({id:s,type:`file`,className:`hidden`,accept:`.zip`,onchange:e=>{l(e.target?.files?.[0])}}))}export{r as pageInstaller}; \ No newline at end of file +import{n as e,r as n}from"./index-gZx3-mqo.js";function r(r){let i=r.params?.token||``;if(e(i).type!=`auth`||n(i)){app.toasts.error(`The installer token is invalid or has expired.`),window.location.hash=`#/`;return}app.store.title=`Setup your PocketBase instance`;let a=store({email:``,password:``,passwordConfirm:``,showPassword:!1,showPasswordConfirm:!1,isSubmitting:!1,isUploading:!1,get isBusy(){return a.isSubmitting||a.isUploading}});async function o(){if(!a.isBusy){a.isSubmitting=!0;try{await app.pb.collection(`_superusers`).create({email:a.email,password:a.password,passwordConfirm:a.passwordConfirm},{headers:{Authorization:i}}),await app.pb.collection(`_superusers`).authWithPassword(a.email,a.password),window.location.hash=`#/`}catch(e){app.checkApiError(e)}a.isSubmitting=!1}}let s=`backupFileInput`;function c(){let e=document.getElementById(s);e&&(e.value=``)}function l(e){e&&app.modals.confirm(t.h6(null,`Note that we don't perform validations for the uploaded backup files. Proceed with caution and only if you trust the file source.\n\nDo you really want to upload and initialize "${e.name}"?`),()=>{u(e)},()=>{c()})}async function u(e){if(!(!e||a.isBusy)){a.isUploading=!0;try{await app.pb.backups.upload({file:e},{headers:{Authorization:i}}),await app.pb.backups.restore(e.name,{headers:{Authorization:i}}),app.toasts.info(`Please wait while extracting the uploaded archive!`),await new Promise(e=>setTimeout(e,3e3)),window.location.href=`#/`}catch(e){app.checkApiError(e)}c(),a.isUploading=!1}}return t.div({pbEvent:`pageInstaller`,className:`wrapper sm m-auto p-b-base`},t.header({className:`txt-center m-b-base`},t.img({className:`main-logo`,src:()=>app.store.mainLogo,ariaHidden:!0,alt:`App logo`}),t.h5({className:`m-t-10`},()=>app.store.title)),t.form({pbEvent:`installerForm`,className:`grid installer-form`,onsubmit:e=>{e.preventDefault(),o(a)}},t.div({className:`col-12 txt-center`},`Create your first superuser account in order to continue:`),t.div({className:`col-12`},t.div({className:`field`},t.label({htmlFor:`superuser_email`},`Email`),t.input({id:`superuser_email`,name:`email`,type:`email`,required:!0,autofocus:!0,autocomplete:`off`,disabled:()=>a.isBusy,value:()=>a.email,oninput:e=>a.email=e.target.value}))),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password`},`Password`),t.input({id:`superuser_password`,name:`password`,min:10,required:!0,disabled:()=>a.isBusy,type:()=>a.showPassword?`text`:`password`,value:()=>a.password,oninput:e=>a.password=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPassword?`Hide password`:`Show password`),onclick:()=>a.showPassword=!a.showPassword},t.i({className:()=>a.showPassword?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0})))),t.div({className:`field-help`},`Recommended at least 10 characters.`)),t.div({className:`col-12`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`superuser_password_confirm`},`Password confirm`),t.input({id:`superuser_password_confirm`,name:`passwordConfirm`,required:!0,disabled:()=>a.isBusy,type:()=>a.showPasswordConfirm?`text`:`password`,value:()=>a.passwordConfirm,oninput:e=>a.passwordConfirm=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,tabIndex:-1,className:`btn sm transparent secondary circle tooltip-right`,ariaLabel:app.attrs.tooltip(()=>a.showPasswordConfirm?`Hide password`:`Show password`),onclick:()=>a.showPasswordConfirm=!a.showPasswordConfirm},t.i({className:()=>a.showPasswordConfirm?`ri-eye-off-line`:`ri-eye-line`,ariaHidden:!0}))))),t.div({className:`col-12`},t.button({className:()=>`btn lg next block ${a.isSubmitting?`loading`:``}`,disabled:()=>a.isBusy},t.span({className:`txt`},`Create superuser and login`),t.i({className:`ri-arrow-right-line`,ariaHidden:!0})))),t.hr(),t.label({htmlFor:s,className:()=>`btn secondary transparent lg block ${a.isBusy?`disabled`:``} ${a.isUploading?`loading`:``}`},t.i({className:`ri-upload-cloud-line`,ariaHidden:!0}),t.span({className:`txt`},`Or initialize from backup`)),t.input({id:s,type:`file`,className:`hidden`,accept:`.zip`,onchange:e=>{l(e.target?.files?.[0])}}))}export{r as pageInstaller}; \ No newline at end of file diff --git a/ui/dist/index.html b/ui/dist/index.html index 21760929..0cb35626 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -13,7 +13,7 @@ - + diff --git a/ui/src/settings/sql/pageSQLConsole.js b/ui/src/settings/sql/pageSQLConsole.js index 2bf45c08..5acf7e83 100644 --- a/ui/src/settings/sql/pageSQLConsole.js +++ b/ui/src/settings/sql/pageSQLConsole.js @@ -75,6 +75,8 @@ export function pageSQLConsole(route) { query = query?.replace(/[\s\;]/gm, " ").toUpperCase() + " "; return !![ + "ALTER ", + "REPLACE ", "INSERT ", "CREATE ", "UPDATE ", @@ -349,7 +351,13 @@ export function pageSQLConsole(route) { className: "alert success m-b-sm", }, t.p({ className: "txt-bold" }, "Query executed successfully!"), - t.p(null, "Affected rows: ", () => pageData.result?.affectedRows || 0), + () => { + // show the affected rows only when a non empty value is returned + // to avoid ambiguity with drivers that don't support it + if (pageData.result?.affectedRows) { + return t.p(null, "Affected rows: ", pageData.result?.affectedRows); + } + }, ), // rows t.div(