From 1984952e4eeb2e95ebc2a1946e8697e4d30316df Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Sun, 6 Sep 2026 17:13:06 +0300 Subject: [PATCH] fixed multiline index column and utrigger index validations if failing to parse all columns --- tools/dbutils/index.go | 9 +++++++-- tools/dbutils/index_test.go | 8 ++++---- ui/dist/assets/{index-Cr4q2t8U.js => index-DjhEaS_B.js} | 4 ++-- ...ge-CAkJEeUl.js => pageConfirmEmailChange-DnQm0RLl.js} | 2 +- ...-BpBFn0WV.js => pageConfirmPasswordReset-BQ8SRN4r.js} | 2 +- ...n-BZgVXICb.js => pageConfirmVerification-ctYHuWr_.js} | 2 +- ...geInstaller-CUhmKhWk.js => pageInstaller-DMVWU1zE.js} | 2 +- ui/dist/index.html | 2 +- ui/src/utils.js | 8 ++++---- 9 files changed, 22 insertions(+), 17 deletions(-) rename ui/dist/assets/{index-Cr4q2t8U.js => index-DjhEaS_B.js} (99%) rename ui/dist/assets/{pageConfirmEmailChange-CAkJEeUl.js => pageConfirmEmailChange-DnQm0RLl.js} (97%) rename ui/dist/assets/{pageConfirmPasswordReset-BpBFn0WV.js => pageConfirmPasswordReset-BQ8SRN4r.js} (97%) rename ui/dist/assets/{pageConfirmVerification-BZgVXICb.js => pageConfirmVerification-ctYHuWr_.js} (96%) rename ui/dist/assets/{pageInstaller-CUhmKhWk.js => pageInstaller-DMVWU1zE.js} (98%) diff --git a/tools/dbutils/index.go b/tools/dbutils/index.go index 90b45ea0..40dc4a77 100644 --- a/tools/dbutils/index.go +++ b/tools/dbutils/index.go @@ -8,8 +8,8 @@ import ( ) var ( - indexRegex = regexp.MustCompile(`(?im)\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s+where\s+([\s\S]*?))?\s*$`) - indexColumnRegex = regexp.MustCompile(`(?im)^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?$`) + indexRegex = regexp.MustCompile(`(?i)\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s+where\s+([\s\S]*?))?\s*$`) + indexColumnRegex = regexp.MustCompile(`(?i)^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?\s*$`) ) // IndexColumn represents a single parsed SQL index column. @@ -187,6 +187,11 @@ func ParseIndex(createIndexExpr string) Index { }) } + if len(rawColumns) != len(result.Columns) { + // unset to trigger validation error + result.Columns = []IndexColumn{} + } + // WHERE expression // --- result.Where = strings.TrimSpace(matches[6]) diff --git a/tools/dbutils/index_test.go b/tools/dbutils/index_test.go index b1674be8..74692353 100644 --- a/tools/dbutils/index_test.go +++ b/tools/dbutils/index_test.go @@ -57,10 +57,10 @@ func TestParseIndex(t *testing.T) { `CREATE UNIQUE INDEX IF NOT EXISTS "schemaname".[indexname] on 'tablename' ( col0, ` + "`" + `col1` + "`" + `, - json_extract("col2", "$.a") asc, + json_extract("col2_multiline",` + "\n" + ` "$.a") asc, "col3" collate NOCASE, "col4" collate RTRIM desc - ) where cast(test1 as int) = 1 and test2 != ''`, + ) where cast(test1 as ` + "\n" + `int) = 1 and test2 != ''`, dbutils.Index{ Unique: true, Optional: true, @@ -70,11 +70,11 @@ func TestParseIndex(t *testing.T) { Columns: []dbutils.IndexColumn{ {Name: "col0"}, {Name: "col1"}, - {Name: `json_extract("col2", "$.a")`, Sort: "ASC"}, + {Name: `json_extract("col2_multiline",` + "\n" + ` "$.a")`, Sort: "ASC"}, {Name: `col3`, Collate: "NOCASE"}, {Name: `col4`, Collate: "RTRIM", Sort: "DESC"}, }, - Where: "cast(test1 as int) = 1 and test2 != ''", + Where: "cast(test1 as \nint) = 1 and test2 != ''", }, }, } diff --git a/ui/dist/assets/index-Cr4q2t8U.js b/ui/dist/assets/index-DjhEaS_B.js similarity index 99% rename from ui/dist/assets/index-Cr4q2t8U.js rename to ui/dist/assets/index-DjhEaS_B.js index 04492633..b8d78e57 100644 --- a/ui/dist/assets/index-Cr4q2t8U.js +++ b/ui/dist/assets/index-DjhEaS_B.js @@ -1,6 +1,6 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./docsList-DsIHfo2q.js","./expandInfo-CJ9aeAaN.js","./fieldsInfo-CiLcXgNq.js","./docsView-oyuvqZP8.js","./docsCreate-Ap21j9FE.js","./docsUpdate-DAnNYWFv.js","./docsListAuthMethods-CYETXzX7.js","./docsAuthWithPassword-NXiq7pZI.js","./docsAuthWithOAuth2-qI6si9uJ.js","./docsAuthWithOTP-75iz1Xmg.js","./docsAuthRefresh-Cq3xTY6M.js"])))=>i.map(i=>d[i]); var e=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,n)=>()=>(n||(e((n={exports:{}}).exports,n),e=null),n.exports),c=(e,a,s,c)=>{if(a&&typeof a==`object`||typeof a==`function`)for(var l=i(a),u=0,d=l.length,f;ua[e]).bind(null,f),enumerable:!(c=r(a,f))||c.enumerable});return e},l=(r,i,s)=>(s=r==null?{}:e(a(r)),c(i||!r||!r.__esModule||!o.call(r,`default`)?n(s,`default`,{value:r,enumerable:!0}):s,r));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))r(e);new MutationObserver(e=>{for(let n of e)if(n.type===`childList`)for(let e of n.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&r(e)}).observe(document,{childList:!0,subtree:!0});function n(e){let n={};return e.integrity&&(n.integrity=e.integrity),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),n.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,n}function r(e){if(e.ep)return;e.ep=!0;let r=n(e);fetch(e.href,r)}})();var u=`abcdefghijklmnopqrstuvwxyz0123456789`,d=store({hash:window.location.hash});window.addEventListener(`hashchange`,()=>{d.hash=window.location.hash}),Prism.languages.pbrule={string:Prism.languages.js.string,number:Prism.languages.js.number,function:Prism.languages.js.function,boolean:/\b(?:true|false)\b/i,constant:/\b(?:null)\b/i,comment:{pattern:/\/\/.*/,greedy:!0},italic:/_via_|\:\w+/,keyword:/&&|\|\||\??(?:!~|!=|>=|<=|=|~|>|>|<)(?=[@\w\s]|$)/};var f={isObject(e){return typeof e==`object`&&!!e&&e.constructor===Object},isEmpty(e){return e==null||e===``||Array.isArray(e)&&e.length===0||typeof e==`object`&&app.utils.isEmptyObject(e)},isEmptyObject(e){for(let n in e)return!1;return!0},toArray(e,n=!1){return Array.isArray(e)?e.slice():(n||!f.isEmpty(e))&&e!==void 0?[e]:[]},removeByValue(e,n){if(!Array.isArray(e)){console.warn(`[removeByValue] not an array:`,e);return}for(let r=e.length-1;r>=0;r--)if(e[r]==n){e.splice(r,1);break}},removeByKey(e,n,r){if(!Array.isArray(e)){console.warn(`[removeByKey] not an array:`,e);return}for(let i in e)if(e[i][n]==r){e.splice(i,1);break}},pushUnique(e,n){if(!Array.isArray(e)){console.warn(`[pushUnique] not an array:`,e);return}e.includes(n)||e.push(n)},mergeUnique(e,n){for(let r of n)app.utils.pushUnique(e,r);return e},pushOrReplaceObject(e,n,r=`id`){for(let i=e.length-1;i>=0;i--)if(e[i][r]==n[r]){e[i]=n;return}e.push(n)},filterDuplicatesByKey(e,n=`id`){e=Array.isArray(e)?e:[];let r={};for(let i of e)r[i[n]]=i;return Object.values(r)},filterRedactedProps(e,n=`******`){let r=JSON.parse(JSON.stringify(e||{}));for(let e in r)typeof r[e]==`object`&&r[e]!==null?r[e]=f.filterRedactedProps(r[e],n):r[e]===n&&delete r[e];return r},getByPath(e,n,r=null,i=`.`){let a=e||{},o=(n||``).split(i);for(let e of o){if(!f.isObject(a)&&!Array.isArray(a)||a[e]===void 0)return r;a=a[e]}return a},setByPath(e,n,r,i=`.`){if(typeof e!=`object`||!e){console.warn(`setByPath: data not an object or array.`);return}let a=e,o=n.split(i),s=o.pop();for(let e of o)(!f.isObject(a)&&!Array.isArray(a)||!f.isObject(a[e])&&!Array.isArray(a[e]))&&(a[e]={}),a=a[e];a[s]=r},deleteByPath(e,n,r=`.`){let i=e||{},a=(n||``).split(r),o=a.pop();for(let e of a)(!f.isObject(i)&&!Array.isArray(i)||!f.isObject(i[e])&&!Array.isArray(i[e]))&&(i[e]={}),i=i[e];Array.isArray(i)?i.splice(o,1):f.isObject(i)&&delete i[o],a.length>0&&(Array.isArray(i)&&!i.length||f.isObject(i)&&!Object.keys(i).length)&&(Array.isArray(e)&&e.length>0||f.isObject(e)&&Object.keys(e).length>0)&&f.deleteByPath(e,a.join(r),r)},emptyClone(e,n=[]){let r=JSON.parse(JSON.stringify(e));for(let e in r)n.includes(e)||(typeof r[e]==`string`?r[e]=``:typeof r[e]==`number`?r[e]=0:typeof r[e]==`boolean`?r[e]=!1:Array.isArray(r[e])?r[e]=[]:app.utils.isObject(r[e])&&(r[e]={}));return r},randomString(e=8,n=u){let r=``;for(let i=0;i`u`)return app.utils.randomString(e);let n=new Uint8Array(e);crypto.getRandomValues(n);let r=``;for(let i=0;i`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`):``},plainText(e){return e?(new DOMParser().parseFromString(e,`text/html`).body.textContent||``).trim():``},truncate(e,n=150,r=!0){if(e=``+e,e.length<=n)return e;if(e=e.slice(0,n),r){for(;e.endsWith(`.`);)e=e.slice(0,-1);e+=`...`}return e},truncateObject(e,n=150,r=!0){let i=Array.isArray(e)?[]:{};for(let a in e){let o=e[a];typeof o==`string`?o=app.utils.truncate(o,n,r):(Array.isArray(o)||app.utils.isObject(o))&&(o=app.utils.truncateObject(o,n,r)),i[a]=o}return i},displayValue(e,n=150,r=`N/A`){if(f.isEmpty(e))return r;if(typeof e!=`string`){if(typeof e==`boolean`)e=e?`True`:`False`;else if(Array.isArray(e)&&typeof e[0]!=`object`)e=e.map(e=>f.displayValue(e,n,r)).join(`, `);else try{e=JSON.stringify(e)||``}catch{e=``+e}}return e?f.truncate(e,n):r},splitNonEmpty(e,n=`,`){let r=(e||``).split(n),i=[];for(let e of r)e=e.trim(),f.isEmpty(e)||i.push(e);return i},joinNonEmpty(e,n=`, `){e||=[];let r=[];for(let n of e)n=typeof n==`string`?n.trim():n,f.isEmpty(n)||r.push(``+n);return r.join(n)},formattedFileSize(e){let n=e?Math.floor(Math.log(e)/Math.log(1024)):0;return(e/1024**n).toFixed(2)*1+` `+[`B`,`KB`,`MB`,`GB`,`TB`][n]},toRFC3339Datetime(e){if(!e)return``;let n;return n=e instanceof Date?e:typeof e==`string`?new Date(e.replace(` `,`T`)):new Date(e),n.toISOString().replace(`T`,` `)},toLocalDatetime(e){if(!e)return``;let n;n=e instanceof Date?e:typeof e==`string`?new Date(e.replace(` `,`T`)):new Date(e);let r=n.getFullYear();return isNaN(r)?``:`${r}-${(n.getMonth()+1).toString().padStart(2,`0`)}-${n.getDate().toString().padStart(2,`0`)} ${n.getHours().toString().padStart(2,`0`)}:${n.getMinutes().toString().padStart(2,`0`)}:${n.getSeconds().toString().padStart(2,`0`)}.${n.getMilliseconds().toString().padStart(3,`0`)}`},toDatetimeLocalInputValue(e){if(!e)return``;let n;n=e instanceof Date?e:typeof e==`string`?new Date(e.replaceAll(` `,`T`)):new Date(e);let r=n.getFullYear();return isNaN(r)?``:`${r}-${(n.getMonth()+1).toString().padStart(2,`0`)}-${n.getDate().toString().padStart(2,`0`)}T${n.getHours().toString().padStart(2,`0`)}:${n.getMinutes().toString().padStart(2,`0`)}:${n.getSeconds().toString().padStart(2,`0`)}`},async copyToClipboard(e){if(e=e==null?``:e instanceof Date?e.toISOString():typeof e==`object`?JSON.stringify(e):``+e,!(!e.length||!window.navigator?.clipboard))return window.navigator.clipboard.writeText(e).catch(e=>{console.warn(`Failed to copy.`,e)})},download(e,n){let r=document.createElement(`a`);r.setAttribute(`href`,e),r.setAttribute(`download`,n),r.setAttribute(`target`,`_blank`),r.setAttribute(`rel`,`noopener noreferrer`),r.click(),r=null},downloadJSON(e,n){n=n.endsWith(`.json`)?n:n+`.json`;let r=new Blob([JSON.stringify(e,null,2)],{type:`application/json`}),i=window.URL.createObjectURL(r);f.download(i,n)},downloadCSV(e,n){n=n.endsWith(`.csv`)?n:n+`.csv`;let r=e.map(e=>e.map(e=>`"`+(``+e).replaceAll(`"`,`""`)+`"`).join(`,`)).join(` -`),i=new Blob([r],{type:`text/csv;charset=utf-8;`}),a=window.URL.createObjectURL(i);f.download(a,n)},getApiExampleURL(){let e;if(app.pb.baseURL.startsWith(`http://`)||app.pb.baseURL.startsWith(`https://`))e=app.pb.baseURL;else{e=window.location.href;let n=e.indexOf(`/_/`);e=n>=0?e.substring(0,n):window.location.origin}return e.replace(`//localhost`,`//127.0.0.1`)},isActivePath(e,n=!0,r=``){r||=d.hash;let i;return i=RegExp(n?`^`+RegExp.escape(e)+`\\/?.*$`:`^`+RegExp.escape(e)+`\\/?(?:\\?.+)?$`),i.test(r)},getHashQueryParams(e=``){e||=d.hash;let n=``,r=e.indexOf(`?`);return r>-1&&(n=window.location.hash.substring(r+1)),Object.fromEntries(new URLSearchParams(n))},replaceHashQueryParams(e,n=null){e||={};let r=``,i=window.location.hash,a=i.indexOf(`?`);a>-1&&(r=i.substring(a+1),i=i.substring(0,a));let o=new URLSearchParams(r);for(let n in e){let r=e[n];f.isEmpty(r)?o.delete(n):o.set(n,r)}r=o.toString(),r!=``&&(i+=`?`+r);let s=window.location.href,c=s.indexOf(`#`);c>-1&&(s=s.substring(0,c));let l=s+i;return n===!1||(n===!0?window.history.pushState(null,``,l):window.history.replaceState(null,``,l)),l},getLocalHistory(e,n=null){try{let r=window.localStorage.getItem(e);if(r)return JSON.parse(r)||n}catch(n){console.log(`failed to load local history:`,e,n)}return n},saveLocalHistory(e,n){try{app.utils.isEmpty(n)?window.localStorage.removeItem(e):typeof n==`string`?window.localStorage.setItem(e,n):window.localStorage.setItem(e,JSON.stringify(n))}catch(n){console.log(`failed to save local history:`,e,n)}},generateThumb(e,n=100,r=100){return new Promise(i=>{let a=new FileReader;a.onload=function(a){let o=new Image;o.onload=function(){let a=document.createElement(`canvas`),s=a.getContext(`2d`),c=o.width,l=o.height;return a.width=n,a.height=r,s.drawImage(o,c>l?(c-l)/2:0,0,c>l?l:c,c>l?l:c,0,0,n,r),i(a.toDataURL(e.type))},o.src=a.target.result},a.readAsDataURL(e)})},normalizeSearchFilter(e,n=[]){if(e=(e||``).trim(),!e||!n.length)return e;for(let n of[`=`,`~`,`>`,`<`])if(e.includes(n))return e;return e=isNaN(e)&&e!=`true`&&e!=`false`?e.replace(/^[\"\'\`]|[\"\'\`]$/gm,``):e,n.map(n=>app.pb.filter(`${n}?~{:searchTerm}`,{searchTerm:e})).join(`||`)},logLevels:{[-4]:{label:`DEBUG`,class:``},0:{label:`INFO`,class:`success`},4:{label:`WARN`,class:`warning`},8:{label:`ERROR`,class:`danger`}},logDataFormatters:{execTime:function(e){return e?.data?.execTime===void 0?`N/A`:e.data.execTime+`ms`}},extendStore(e,n={},...r){let i=[];for(let a in n){let o=n[a];typeof e.__raw?.[a]==`function`||typeof o!=`function`||a.length>2&&a.startsWith(`on`)||r.includes(a)?e[a]=o:i.push(watch(o,n=>{e[a]=n}))}return i},cssTimeToMs(e){return e?(e=e.toLowerCase(),e.endsWith(`ms`)?Number(e.substring(0,e.length-2)):e.endsWith(`s`)?Number(e.substring(0,e.length-1)):Number(e)||0):0},isDarkEnoughForWhiteText(e){if(e=e?.startsWith(`#`)?e.substring(1):e,e?.length!=6)return!1;let n=parseInt(e.substring(0,2),16),r=parseInt(e.substring(2,4),16),i=parseInt(e.substring(4,6),16);return(n*299+r*587+i*114)/1e3<128},bulkSelectRange(e,n,r,i){let a=e.findIndex(e=>e.id==r.id);if(a==-1)return;let o=Object.keys(n),s=o[o.length-1],c=e.findIndex(e=>e.id==s);if(c==-1)return;let l=c,u=a;l>u&&([l,u]=[u,l]);for(let r=l;r<=u;r++)i?n[e[r].id]=e[r]:delete n[e[r].id]},imageExtensions:[`.jpg`,`.jpeg`,`.png`,`.svg`,`.gif`,`.jfif`,`.webp`,`.avif`],videoExtensions:[`.mp4`,`.avi`,`.mov`,`.3gp`,`.wmv`],audioExtensions:[`.aa`,`.aac`,`.m4v`,`.mp3`,`.ogg`,`.oga`,`.mogg`,`.amr`],documentExtensions:[`.pdf`,`.doc`,`.docx`,`.xls`,`.xlsx`,`.ppt`,`.pptx`,`.odp`,`.odt`,`.ods`,`.txt`],archiveExtensions:[`.zip`,`.gz`,`.tar`,`.rar`,`.7z`],hasExtension(e,n){return typeof n==`string`&&(n=n.toLowerCase(),!!e?.find(e=>n.endsWith(e)))},hasImageExtension(e){return app.utils.hasExtension(app.utils.imageExtensions,e)},hasVideoExtension(e){return app.utils.hasExtension(app.utils.videoExtensions,e)},hasAudioExtension(e){return app.utils.hasExtension(app.utils.audioExtensions,e)},hasDocumentExtension(e){return app.utils.hasExtension(app.utils.documentExtensions,e)},hasArchiveExtension(e){return app.utils.hasExtension(app.utils.archiveExtensions,e)},getFileType(e){return app.utils.hasImageExtension(e)?`image`:app.utils.hasVideoExtension(e)?`video`:app.utils.hasAudioExtension(e)?`audio`:app.utils.hasDocumentExtension(e)?`document`:app.utils.hasArchiveExtension(e)?`archive`:`file`},fileTypeIcons:{image:`ri-image-line`,video:`ri-movie-line`,audio:`ri-music-2-line`,document:`ri-file-line`,archive:`ri-file-zip-line`,file:`ri-file-line`},fallbackFieldIcon:`ri-puzzle-line`,fallbackCollectionIcon:`ri-puzzle-line`,fallbackProviderIcon:`ri-puzzle-line`,fallbackPresentableProps:[`title`,`name`,`slug`,`email`,`username`,`nickname`,`displayName`,`label`,`subject`,`topic`,`message`,`heading`,`headline`,`header`,`caption`,`key`,`identifier`,`id`],sortedCollections(e=[]){let n,r;function i(e,i){return n=e.name.startsWith(`_`),r=i.name.startsWith(`_`),n&&!r?1:!n&&r?-1:e.name>i.name?1:e.namee?.id&&!a.find(n=>n.id==e.id)),s=a.filter(e=>e?.id&&!i.find(n=>n.id==e.id)),c=a.filter(e=>{let n=app.utils.isObject(e)&&i.find(n=>n.id==e.id);if(!n)return!1;for(let r in n)if(JSON.stringify(e[r])!=JSON.stringify(n[r]))return!0;return!1});return!!(s.length||c.length||r&&o.length)},extractColumnsFromQuery(e){let n=`__PBGROUP__`;e=(e||``).replace(/\([\s\S]+?\)/gm,n).replace(/[\t\r\n]|(?:\s\s)+/g,` `);let r=e.match(/select\s+([\s\S]+)\s+from/)?.[1]?.split(`,`)||[],i=[];for(let e of r){let r=e.trim().split(` `).pop();r!=``&&r!=n&&i.push(r.replace(/[\'\"\`\[\]\s]/g,``))}return i},getAllCollectionIdentifiers(e,n=``){if(!e)return[];let r=[n+`id`],i=e.type==`auth`;if(e.type===`view`)for(let i of app.utils.extractColumnsFromQuery(e.viewQuery))app.utils.pushUnique(r,n+i);let a=e.fields||[];for(let e of a)if(!(e.type==`password`||i&&e.name==`tokenKey`)){if(app.fieldTypes[e.type]?.identifierExtractor){let i=app.utils.toArray(app.fieldTypes[e.type]?.identifierExtractor(e,n));for(let e of i)app.utils.pushUnique(r,e)}else app.utils.pushUnique(r,n+e.name)}return r},getDummyFieldsData(e,n=!1){let r=e?.fields||[],i={};for(let e of r)if(!e.hidden){if(app.fieldTypes[e.type]?.dummyData){let r=app.fieldTypes[e.type].dummyData(e,n);r!==void 0&&(i[e.name]=r)}else i[e.name]=`[[DATA]]`}return i},parseIndex(e){let n={unique:!1,optional:!1,schemaName:``,indexName:``,tableName:``,columns:[],where:``},r=/\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s*where\s+([\s\S]*?))?\s*$/gim.exec((e||``).trim());if(r?.length!=7)return n;let i=/^[\"\'\`\[\{}]|[\"\'\`\]\}]$/gm;n.unique=r[1]?.trim().toLowerCase()===`unique`,n.optional=!app.utils.isEmpty(r[2]?.trim());let a=(r[3]||``).split(`.`);a.length==2?(n.schemaName=a[0].replace(i,``),n.indexName=a[1].replace(i,``)):(n.schemaName=``,n.indexName=a[0].replace(i,``)),n.tableName=(r[4]||``).replace(i,``);let o=(r[5]||``).replace(/,(?=[^\(]*\))/gim,`{PB_TEMP}`).split(`,`);for(let e of o){e=e.trim().replaceAll(`{PB_TEMP}`,`,`);let r=/^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?$/gim.exec(e);if(r?.length!=4)continue;let a=r[1]?.trim()?.replace(i,``);a&&n.columns.push({name:a,collate:r[2]||``,sort:r[3]?.toUpperCase()||``})}return n.where=r[6]||``,n},buildIndex(e){let n=`CREATE `;e.unique&&(n+=`UNIQUE `),n+=`INDEX `,e.optional&&(n+=`IF NOT EXISTS `),e.schemaName&&(n+=`\`${e.schemaName}\`.`),n+=`\`${e.indexName||`idx_`+app.utils.randomString(10)}\` `,n+=`ON \`${e.tableName}\` (`;let r=e.columns.filter(e=>!!e?.name);return r.length>1&&(n+=` +`),i=new Blob([r],{type:`text/csv;charset=utf-8;`}),a=window.URL.createObjectURL(i);f.download(a,n)},getApiExampleURL(){let e;if(app.pb.baseURL.startsWith(`http://`)||app.pb.baseURL.startsWith(`https://`))e=app.pb.baseURL;else{e=window.location.href;let n=e.indexOf(`/_/`);e=n>=0?e.substring(0,n):window.location.origin}return e.replace(`//localhost`,`//127.0.0.1`)},isActivePath(e,n=!0,r=``){r||=d.hash;let i;return i=RegExp(n?`^`+RegExp.escape(e)+`\\/?.*$`:`^`+RegExp.escape(e)+`\\/?(?:\\?.+)?$`),i.test(r)},getHashQueryParams(e=``){e||=d.hash;let n=``,r=e.indexOf(`?`);return r>-1&&(n=window.location.hash.substring(r+1)),Object.fromEntries(new URLSearchParams(n))},replaceHashQueryParams(e,n=null){e||={};let r=``,i=window.location.hash,a=i.indexOf(`?`);a>-1&&(r=i.substring(a+1),i=i.substring(0,a));let o=new URLSearchParams(r);for(let n in e){let r=e[n];f.isEmpty(r)?o.delete(n):o.set(n,r)}r=o.toString(),r!=``&&(i+=`?`+r);let s=window.location.href,c=s.indexOf(`#`);c>-1&&(s=s.substring(0,c));let l=s+i;return n===!1||(n===!0?window.history.pushState(null,``,l):window.history.replaceState(null,``,l)),l},getLocalHistory(e,n=null){try{let r=window.localStorage.getItem(e);if(r)return JSON.parse(r)||n}catch(n){console.log(`failed to load local history:`,e,n)}return n},saveLocalHistory(e,n){try{app.utils.isEmpty(n)?window.localStorage.removeItem(e):typeof n==`string`?window.localStorage.setItem(e,n):window.localStorage.setItem(e,JSON.stringify(n))}catch(n){console.log(`failed to save local history:`,e,n)}},generateThumb(e,n=100,r=100){return new Promise(i=>{let a=new FileReader;a.onload=function(a){let o=new Image;o.onload=function(){let a=document.createElement(`canvas`),s=a.getContext(`2d`),c=o.width,l=o.height;return a.width=n,a.height=r,s.drawImage(o,c>l?(c-l)/2:0,0,c>l?l:c,c>l?l:c,0,0,n,r),i(a.toDataURL(e.type))},o.src=a.target.result},a.readAsDataURL(e)})},normalizeSearchFilter(e,n=[]){if(e=(e||``).trim(),!e||!n.length)return e;for(let n of[`=`,`~`,`>`,`<`])if(e.includes(n))return e;return e=isNaN(e)&&e!=`true`&&e!=`false`?e.replace(/^[\"\'\`]|[\"\'\`]$/gm,``):e,n.map(n=>app.pb.filter(`${n}?~{:searchTerm}`,{searchTerm:e})).join(`||`)},logLevels:{[-4]:{label:`DEBUG`,class:``},0:{label:`INFO`,class:`success`},4:{label:`WARN`,class:`warning`},8:{label:`ERROR`,class:`danger`}},logDataFormatters:{execTime:function(e){return e?.data?.execTime===void 0?`N/A`:e.data.execTime+`ms`}},extendStore(e,n={},...r){let i=[];for(let a in n){let o=n[a];typeof e.__raw?.[a]==`function`||typeof o!=`function`||a.length>2&&a.startsWith(`on`)||r.includes(a)?e[a]=o:i.push(watch(o,n=>{e[a]=n}))}return i},cssTimeToMs(e){return e?(e=e.toLowerCase(),e.endsWith(`ms`)?Number(e.substring(0,e.length-2)):e.endsWith(`s`)?Number(e.substring(0,e.length-1)):Number(e)||0):0},isDarkEnoughForWhiteText(e){if(e=e?.startsWith(`#`)?e.substring(1):e,e?.length!=6)return!1;let n=parseInt(e.substring(0,2),16),r=parseInt(e.substring(2,4),16),i=parseInt(e.substring(4,6),16);return(n*299+r*587+i*114)/1e3<128},bulkSelectRange(e,n,r,i){let a=e.findIndex(e=>e.id==r.id);if(a==-1)return;let o=Object.keys(n),s=o[o.length-1],c=e.findIndex(e=>e.id==s);if(c==-1)return;let l=c,u=a;l>u&&([l,u]=[u,l]);for(let r=l;r<=u;r++)i?n[e[r].id]=e[r]:delete n[e[r].id]},imageExtensions:[`.jpg`,`.jpeg`,`.png`,`.svg`,`.gif`,`.jfif`,`.webp`,`.avif`],videoExtensions:[`.mp4`,`.avi`,`.mov`,`.3gp`,`.wmv`],audioExtensions:[`.aa`,`.aac`,`.m4v`,`.mp3`,`.ogg`,`.oga`,`.mogg`,`.amr`],documentExtensions:[`.pdf`,`.doc`,`.docx`,`.xls`,`.xlsx`,`.ppt`,`.pptx`,`.odp`,`.odt`,`.ods`,`.txt`],archiveExtensions:[`.zip`,`.gz`,`.tar`,`.rar`,`.7z`],hasExtension(e,n){return typeof n==`string`&&(n=n.toLowerCase(),!!e?.find(e=>n.endsWith(e)))},hasImageExtension(e){return app.utils.hasExtension(app.utils.imageExtensions,e)},hasVideoExtension(e){return app.utils.hasExtension(app.utils.videoExtensions,e)},hasAudioExtension(e){return app.utils.hasExtension(app.utils.audioExtensions,e)},hasDocumentExtension(e){return app.utils.hasExtension(app.utils.documentExtensions,e)},hasArchiveExtension(e){return app.utils.hasExtension(app.utils.archiveExtensions,e)},getFileType(e){return app.utils.hasImageExtension(e)?`image`:app.utils.hasVideoExtension(e)?`video`:app.utils.hasAudioExtension(e)?`audio`:app.utils.hasDocumentExtension(e)?`document`:app.utils.hasArchiveExtension(e)?`archive`:`file`},fileTypeIcons:{image:`ri-image-line`,video:`ri-movie-line`,audio:`ri-music-2-line`,document:`ri-file-line`,archive:`ri-file-zip-line`,file:`ri-file-line`},fallbackFieldIcon:`ri-puzzle-line`,fallbackCollectionIcon:`ri-puzzle-line`,fallbackProviderIcon:`ri-puzzle-line`,fallbackPresentableProps:[`title`,`name`,`slug`,`email`,`username`,`nickname`,`displayName`,`label`,`subject`,`topic`,`message`,`heading`,`headline`,`header`,`caption`,`key`,`identifier`,`id`],sortedCollections(e=[]){let n,r;function i(e,i){return n=e.name.startsWith(`_`),r=i.name.startsWith(`_`),n&&!r?1:!n&&r?-1:e.name>i.name?1:e.namee?.id&&!a.find(n=>n.id==e.id)),s=a.filter(e=>e?.id&&!i.find(n=>n.id==e.id)),c=a.filter(e=>{let n=app.utils.isObject(e)&&i.find(n=>n.id==e.id);if(!n)return!1;for(let r in n)if(JSON.stringify(e[r])!=JSON.stringify(n[r]))return!0;return!1});return!!(s.length||c.length||r&&o.length)},extractColumnsFromQuery(e){let n=`__PBGROUP__`;e=(e||``).replace(/\([\s\S]+?\)/gm,n).replace(/[\t\r\n]|(?:\s\s)+/g,` `);let r=e.match(/select\s+([\s\S]+)\s+from/)?.[1]?.split(`,`)||[],i=[];for(let e of r){let r=e.trim().split(` `).pop();r!=``&&r!=n&&i.push(r.replace(/[\'\"\`\[\]\s]/g,``))}return i},getAllCollectionIdentifiers(e,n=``){if(!e)return[];let r=[n+`id`],i=e.type==`auth`;if(e.type===`view`)for(let i of app.utils.extractColumnsFromQuery(e.viewQuery))app.utils.pushUnique(r,n+i);let a=e.fields||[];for(let e of a)if(!(e.type==`password`||i&&e.name==`tokenKey`)){if(app.fieldTypes[e.type]?.identifierExtractor){let i=app.utils.toArray(app.fieldTypes[e.type]?.identifierExtractor(e,n));for(let e of i)app.utils.pushUnique(r,e)}else app.utils.pushUnique(r,n+e.name)}return r},getDummyFieldsData(e,n=!1){let r=e?.fields||[],i={};for(let e of r)if(!e.hidden){if(app.fieldTypes[e.type]?.dummyData){let r=app.fieldTypes[e.type].dummyData(e,n);r!==void 0&&(i[e.name]=r)}else i[e.name]=`[[DATA]]`}return i},parseIndex(e){let n={unique:!1,optional:!1,schemaName:``,indexName:``,tableName:``,columns:[],where:``},r=/\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s*where\s+([\s\S]*?))?\s*$/gi.exec((e||``).trim());if(r?.length!=7)return n;let i=/^[\"\'\`\[\{}]|[\"\'\`\]\}]$/g;n.unique=r[1]?.trim().toLowerCase()===`unique`,n.optional=!app.utils.isEmpty(r[2]?.trim());let a=(r[3]||``).split(`.`);a.length==2?(n.schemaName=a[0].replace(i,``),n.indexName=a[1].replace(i,``)):(n.schemaName=``,n.indexName=a[0].replace(i,``)),n.tableName=(r[4]||``).replace(i,``);let o=(r[5]||``).replace(/,(?=[^\(]*\))/gi,`{PB_TEMP}`).split(`,`);for(let e of o){e=e.trim().replaceAll(`{PB_TEMP}`,`,`);let r=/^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?\s*$/gi.exec(e);if(r?.length!=4)continue;let a=r[1]?.trim()?.replace(i,``);a&&n.columns.push({name:a,collate:r[2]||``,sort:r[3]?.toUpperCase()||``})}return n.where=r[6]||``,n},buildIndex(e){let n=`CREATE `;e.unique&&(n+=`UNIQUE `),n+=`INDEX `,e.optional&&(n+=`IF NOT EXISTS `),e.schemaName&&(n+=`\`${e.schemaName}\`.`),n+=`\`${e.indexName||`idx_`+app.utils.randomString(10)}\` `,n+=`ON \`${e.tableName}\` (`;let r=e.columns.filter(e=>!!e?.name);return r.length>1&&(n+=` `),n+=r.map(e=>{let n=``;return e.name.includes(`(`)||e.name.includes(` `)?n+=e.name:n+="`"+e.name+"`",e.collate&&(n+=` COLLATE `+e.collate),e.sort&&(n+=` `+e.sort.toUpperCase()),n}).join(`, `),r.length>1&&(n+=` `),n+=`)`,e.where&&(n+=` WHERE ${e.where}`),n},replaceIndexFields(e,n){let r=app.utils.parseIndex(e);return typeof n==`function`?Object.assign(r,n(r)||{}):Object.assign(r,n||{}),app.utils.buildIndex(r)},replaceIndexColumn(e,n,r){if(n===r)return e;let i=app.utils.parseIndex(e),a=!1;for(let e of i.columns)e.name===n&&(e.name=r,a=!0);return a?app.utils.buildIndex(i):e}};window.app=window.app||{},window.app.utils=f,window.app=window.app||{},window.app.utils=window.app.utils||{},window.app.utils.mimeTypes=[{ext:``,mimeType:`application/octet-stream`},{ext:`.xpm`,mimeType:`image/x-xpixmap`},{ext:`.7z`,mimeType:`application/x-7z-compressed`},{ext:`.zip`,mimeType:`application/zip`},{ext:`.xlsx`,mimeType:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`},{ext:`.docx`,mimeType:`application/vnd.openxmlformats-officedocument.wordprocessingml.document`},{ext:`.pptx`,mimeType:`application/vnd.openxmlformats-officedocument.presentationml.presentation`},{ext:`.epub`,mimeType:`application/epub+zip`},{ext:`.apk`,mimeType:`application/vnd.android.package-archive`},{ext:`.jar`,mimeType:`application/jar`},{ext:`.odt`,mimeType:`application/vnd.oasis.opendocument.text`},{ext:`.ott`,mimeType:`application/vnd.oasis.opendocument.text-template`},{ext:`.ods`,mimeType:`application/vnd.oasis.opendocument.spreadsheet`},{ext:`.ots`,mimeType:`application/vnd.oasis.opendocument.spreadsheet-template`},{ext:`.odp`,mimeType:`application/vnd.oasis.opendocument.presentation`},{ext:`.otp`,mimeType:`application/vnd.oasis.opendocument.presentation-template`},{ext:`.odg`,mimeType:`application/vnd.oasis.opendocument.graphics`},{ext:`.otg`,mimeType:`application/vnd.oasis.opendocument.graphics-template`},{ext:`.odf`,mimeType:`application/vnd.oasis.opendocument.formula`},{ext:`.odc`,mimeType:`application/vnd.oasis.opendocument.chart`},{ext:`.sxc`,mimeType:`application/vnd.sun.xml.calc`},{ext:`.pdf`,mimeType:`application/pdf`},{ext:`.fdf`,mimeType:`application/vnd.fdf`},{ext:``,mimeType:`application/x-ole-storage`},{ext:`.msi`,mimeType:`application/x-ms-installer`},{ext:`.aaf`,mimeType:`application/octet-stream`},{ext:`.msg`,mimeType:`application/vnd.ms-outlook`},{ext:`.xls`,mimeType:`application/vnd.ms-excel`},{ext:`.pub`,mimeType:`application/vnd.ms-publisher`},{ext:`.ppt`,mimeType:`application/vnd.ms-powerpoint`},{ext:`.doc`,mimeType:`application/msword`},{ext:`.ps`,mimeType:`application/postscript`},{ext:`.psd`,mimeType:`image/vnd.adobe.photoshop`},{ext:`.p7s`,mimeType:`application/pkcs7-signature`},{ext:`.ogg`,mimeType:`application/ogg`},{ext:`.oga`,mimeType:`audio/ogg`},{ext:`.ogv`,mimeType:`video/ogg`},{ext:`.png`,mimeType:`image/png`},{ext:`.png`,mimeType:`image/vnd.mozilla.apng`},{ext:`.jpg`,mimeType:`image/jpeg`},{ext:`.jxl`,mimeType:`image/jxl`},{ext:`.jp2`,mimeType:`image/jp2`},{ext:`.jpf`,mimeType:`image/jpx`},{ext:`.jpm`,mimeType:`image/jpm`},{ext:`.jxs`,mimeType:`image/jxs`},{ext:`.gif`,mimeType:`image/gif`},{ext:`.webp`,mimeType:`image/webp`},{ext:`.exe`,mimeType:`application/vnd.microsoft.portable-executable`},{ext:``,mimeType:`application/x-elf`},{ext:``,mimeType:`application/x-object`},{ext:``,mimeType:`application/x-executable`},{ext:`.so`,mimeType:`application/x-sharedlib`},{ext:``,mimeType:`application/x-coredump`},{ext:`.a`,mimeType:`application/x-archive`},{ext:`.deb`,mimeType:`application/vnd.debian.binary-package`},{ext:`.tar`,mimeType:`application/x-tar`},{ext:`.xar`,mimeType:`application/x-xar`},{ext:`.bz2`,mimeType:`application/x-bzip2`},{ext:`.fits`,mimeType:`application/fits`},{ext:`.tiff`,mimeType:`image/tiff`},{ext:`.bmp`,mimeType:`image/bmp`},{ext:`.ico`,mimeType:`image/x-icon`},{ext:`.mp3`,mimeType:`audio/mpeg`},{ext:`.flac`,mimeType:`audio/flac`},{ext:`.midi`,mimeType:`audio/midi`},{ext:`.ape`,mimeType:`audio/ape`},{ext:`.mpc`,mimeType:`audio/musepack`},{ext:`.amr`,mimeType:`audio/amr`},{ext:`.wav`,mimeType:`audio/wav`},{ext:`.aiff`,mimeType:`audio/aiff`},{ext:`.au`,mimeType:`audio/basic`},{ext:`.mpeg`,mimeType:`video/mpeg`},{ext:`.mov`,mimeType:`video/quicktime`},{ext:`.mp4`,mimeType:`video/mp4`},{ext:`.avif`,mimeType:`image/avif`},{ext:`.3gp`,mimeType:`video/3gpp`},{ext:`.3g2`,mimeType:`video/3gpp2`},{ext:`.mp4`,mimeType:`audio/mp4`},{ext:`.mqv`,mimeType:`video/quicktime`},{ext:`.m4a`,mimeType:`audio/x-m4a`},{ext:`.m4v`,mimeType:`video/x-m4v`},{ext:`.heic`,mimeType:`image/heic`},{ext:`.heic`,mimeType:`image/heic-sequence`},{ext:`.heif`,mimeType:`image/heif`},{ext:`.heif`,mimeType:`image/heif-sequence`},{ext:`.mj2`,mimeType:`video/mj2`},{ext:`.dvb`,mimeType:`video/vnd.dvb.file`},{ext:`.webm`,mimeType:`video/webm`},{ext:`.avi`,mimeType:`video/x-msvideo`},{ext:`.flv`,mimeType:`video/x-flv`},{ext:`.mkv`,mimeType:`video/x-matroska`},{ext:`.asf`,mimeType:`video/x-ms-asf`},{ext:`.asf`,mimeType:`video/x-ms-wmv`},{ext:`.asf`,mimeType:`video/asf`},{ext:`.aac`,mimeType:`audio/aac`},{ext:`.voc`,mimeType:`audio/x-unknown`},{ext:`.m3u`,mimeType:`application/vnd.apple.mpegurl`},{ext:`.rmvb`,mimeType:`application/vnd.rn-realmedia-vbr`},{ext:`.gz`,mimeType:`application/gzip`},{ext:`.class`,mimeType:`application/x-java-applet`},{ext:`.swf`,mimeType:`application/x-shockwave-flash`},{ext:`.crx`,mimeType:`application/x-chrome-extension`},{ext:`.ttf`,mimeType:`font/ttf`},{ext:`.woff`,mimeType:`font/woff`},{ext:`.woff2`,mimeType:`font/woff2`},{ext:`.otf`,mimeType:`font/otf`},{ext:`.ttc`,mimeType:`font/collection`},{ext:`.eot`,mimeType:`application/vnd.ms-fontobject`},{ext:`.wasm`,mimeType:`application/wasm`},{ext:`.shx`,mimeType:`application/vnd.shx`},{ext:`.shp`,mimeType:`application/vnd.shp`},{ext:`.dbf`,mimeType:`application/x-dbf`},{ext:`.dcm`,mimeType:`application/dicom`},{ext:`.rar`,mimeType:`application/x-rar-compressed`},{ext:`.djvu`,mimeType:`image/vnd.djvu`},{ext:`.mobi`,mimeType:`application/x-mobipocket-ebook`},{ext:`.lit`,mimeType:`application/x-ms-reader`},{ext:`.bpg`,mimeType:`image/bpg`},{ext:`.cbor`,mimeType:`application/cbor`},{ext:`.sqlite`,mimeType:`application/vnd.sqlite3`},{ext:`.dwg`,mimeType:`image/vnd.dwg`},{ext:`.nes`,mimeType:`application/vnd.nintendo.snes.rom`},{ext:`.lnk`,mimeType:`application/x-ms-shortcut`},{ext:`.macho`,mimeType:`application/x-mach-binary`},{ext:`.qcp`,mimeType:`audio/qcelp`},{ext:`.icns`,mimeType:`image/x-icns`},{ext:`.hdr`,mimeType:`image/vnd.radiance`},{ext:`.mrc`,mimeType:`application/marc`},{ext:`.mdb`,mimeType:`application/x-msaccess`},{ext:`.accdb`,mimeType:`application/x-msaccess`},{ext:`.zst`,mimeType:`application/zstd`},{ext:`.cab`,mimeType:`application/vnd.ms-cab-compressed`},{ext:`.rpm`,mimeType:`application/x-rpm`},{ext:`.xz`,mimeType:`application/x-xz`},{ext:`.lz`,mimeType:`application/lzip`},{ext:`.torrent`,mimeType:`application/x-bittorrent`},{ext:`.cpio`,mimeType:`application/x-cpio`},{ext:``,mimeType:`application/tzif`},{ext:`.xcf`,mimeType:`image/x-xcf`},{ext:`.pat`,mimeType:`image/x-gimp-pat`},{ext:`.gbr`,mimeType:`image/x-gimp-gbr`},{ext:`.glb`,mimeType:`model/gltf-binary`},{ext:`.cab`,mimeType:`application/x-installshield`},{ext:`.jxr`,mimeType:`image/jxr`},{ext:`.parquet`,mimeType:`application/vnd.apache.parquet`},{ext:`.txt`,mimeType:`text/plain`},{ext:`.html`,mimeType:`text/html`},{ext:`.svg`,mimeType:`image/svg+xml`},{ext:`.xml`,mimeType:`text/xml`},{ext:`.rss`,mimeType:`application/rss+xml`},{ext:`.atom`,mimeType:`application/atom+xml`},{ext:`.x3d`,mimeType:`model/x3d+xml`},{ext:`.kml`,mimeType:`application/vnd.google-earth.kml+xml`},{ext:`.xlf`,mimeType:`application/x-xliff+xml`},{ext:`.dae`,mimeType:`model/vnd.collada+xml`},{ext:`.gml`,mimeType:`application/gml+xml`},{ext:`.gpx`,mimeType:`application/gpx+xml`},{ext:`.tcx`,mimeType:`application/vnd.garmin.tcx+xml`},{ext:`.amf`,mimeType:`application/x-amf`},{ext:`.3mf`,mimeType:`application/vnd.ms-package.3dmanufacturing-3dmodel+xml`},{ext:`.xfdf`,mimeType:`application/vnd.adobe.xfdf`},{ext:`.owl`,mimeType:`application/owl+xml`},{ext:`.php`,mimeType:`text/x-php`},{ext:`.js`,mimeType:`text/javascript`},{ext:`.lua`,mimeType:`text/x-lua`},{ext:`.pl`,mimeType:`text/x-perl`},{ext:`.py`,mimeType:`text/x-python`},{ext:`.json`,mimeType:`application/json`},{ext:`.geojson`,mimeType:`application/geo+json`},{ext:`.har`,mimeType:`application/json`},{ext:`.ndjson`,mimeType:`application/x-ndjson`},{ext:`.rtf`,mimeType:`text/rtf`},{ext:`.srt`,mimeType:`application/x-subrip`},{ext:`.tcl`,mimeType:`text/x-tcl`},{ext:`.csv`,mimeType:`text/csv`},{ext:`.tsv`,mimeType:`text/tab-separated-values`},{ext:`.vcf`,mimeType:`text/vcard`},{ext:`.ics`,mimeType:`text/calendar`},{ext:`.warc`,mimeType:`application/warc`},{ext:`.vtt`,mimeType:`text/vtt`},{ext:`.pbm`,mimeType:`image/x-portable-bitmap`},{ext:`.pgm`,mimeType:`image/x-portable-graymap`},{ext:`.ppm`,mimeType:`image/x-portable-pixmap`},{ext:`.eml`,mimeType:`message/rfc822`}];var p=new BroadcastChannel(`tabsSync`),m=`pbSettings`,h=`pbColorScheme`;window.app=window.app||{},window.app.store=store({_ready:!1,superuser:null,showHeader:!0,page:t.div({className:`page`},()=>{if(!app.store._ready)return t.span({className:`loader lg m-auto`,title:`Loading plugins...`})}),mainLogo:`./images/logo.svg`,headerLogo:`./images/logo_white.svg`,favicon:``,title:``,_mediaColorScheme:``,userColorScheme:window.localStorage.getItem(h)||``,get activeColorScheme(){return app.store.userColorScheme?app.store.userColorScheme:app.store._mediaColorScheme||`light`},errors:null,creditLinks:[{href:`https://pocketbase.io/docs`,icon:`ri-book-open-line`,label:`Docs`},{href:`https://github.com/pocketbase/pocketbase/releases`,icon:`ri-github-line`,label:`PocketBase v0.40.3-dev`}],headerLinks:[{href:`#/collections`,icon:`ri-database-2-line`,label:`Collections`},{href:`#/logs`,icon:`ri-bar-chart-box-line`,label:`Logs`},{href:`#/settings`,icon:`ri-settings-3-line`,label:`Settings`}],settingsNavGroups:{System:[{href:`#/settings`,icon:`ri-home-gear-line`,label:`Application`},{href:`#/settings/mail`,icon:`ri-send-plane-2-line`,label:`Mail settings`},{href:`#/settings/storage`,icon:`ri-archive-drawer-line`,label:`Files storage`},{href:`#/settings/backups`,icon:`ri-archive-line`,label:`Backups`},{href:`#/settings/crons`,icon:`ri-time-line`,label:`Crons`}],Sync:[{href:`#/settings/export-collections`,icon:`ri-uninstall-line`,label:`Export collections`},{href:`#/settings/import-collections`,icon:`ri-install-line`,label:`Import collections`}],Debug:[{href:`#/settings/sql`,icon:`ri-terminal-box-line`,label:`SQL console`}]},predefinedAccentColors:[`#1055c9`,`#a3142a`,`#096d5c`,`#e6620a`,`#007d9c`,`#3f3da9`],settings:app.utils.getLocalHistory(m,{}),isLoadingSettings:!1,async loadSettings(){app.store.isLoadingSettings=!0;try{let e=await app.pb.settings.getAll({requestKey:`appStore.loadSettings`});app.store.settings=e,app.store.isLoadingSettings=!1}catch(e){e.isAbort||(app.store.isLoadingSettings=!1,app.checkApiError(e))}},collections:[],collectionScaffolds:{},isLoadingCollections:!1,_activeCollectionIdOrName:``,get activeCollection(){let e=app.store._activeCollectionIdOrName;return app.store.collections.find(n=>n.id==e||n.name==e)||app.store.collections[0]},set activeCollection(e){typeof e==`string`?app.store._activeCollectionIdOrName=e:app.store._activeCollectionIdOrName=e?.id},async silentlyReloadCollections(){try{let e=await app.pb.collections.getFullList({requestKey:`appStore.silentlyReloadCollections`});e=app.utils.sortedCollectionsByType(e),JSON.stringify(e)!=JSON.stringify(app.store.collections)&&(app.store.collections=e)}catch(e){e.isAbort||console.warn(`failed to reload app store collections:`,e)}},async loadCollections(e=null){app.store.isLoadingCollections=!0;try{let[n,r]=await Promise.all([app.pb.collections.getScaffolds({requestKey:`appStore.loadCollections.getScaffolds`}),app.pb.collections.getFullList({requestKey:`appStore.loadCollections.getFullList`})]);r=app.utils.sortedCollectionsByType(r),JSON.stringify(app.store.collections)!=JSON.stringify(r)&&(app.store.collections=r),app.store.collectionScaffolds=n,app.store._activeCollectionIdOrName=e||app.store._activeCollectionIdOrName||app.store.collections[0]?.id||``,app.store.isLoadingCollections=!1}catch(e){e.isAbort||(app.store.isLoadingCollections=!1,app.checkApiError(e))}},addOrUpdateCollection(e){let n=app.store.collections.findIndex(n=>n.id==e.id);n>=0?(app.store.activeCollection?.id==e.id&&(app.store._activeCollectionIdOrName=e.id),app.store.collections[n]=e):app.store.collections.push(e),app.store.collections=app.utils.sortedCollectionsByType(app.store.collections)},oauth2Providers:[],isLoadingOAuth2Providers:!1,async loadOAuth2Providers(){app.store.isLoadingOAuth2Providers=!0;try{app.store.oauth2Providers=await app.pb.collections.getAllOAuth2Providers(),app.store.isLoadingOAuth2Providers=!1}catch(e){e.isAbort||(app.checkApiError(e),app.store.isLoadingOAuth2Providers=!1)}}}),window.addEventListener(`hashchange`,()=>{app.store.title=``,app.store.errors=null}),watch(()=>{let e=app.utils.toArray(app.store.title),n=app.store.settings?.meta?.appName||``;n&&e.push(n),document.title=e.join(` - `)});var g;watch(()=>app.store.settings?.meta?.accentColor,e=>{g||(g=t.meta({name:`theme-color`}),document.head.appendChild(g)),e?(g?.setAttribute(`content`,e),document.documentElement.style.setProperty(`--accentColor`,e)):(g?.removeAttribute(`content`),document.documentElement.style.removeProperty(`--accentColor`))});var _;watch(()=>app.store.favicon,e=>{_||(_=t.link({rel:`icon`}),document.head.appendChild(_)),e?_.href=e:_.href=window.location.href.startsWith(`https://`)?`./images/favicon_prod.png`:`./images/favicon.png`});var v=window.matchMedia(`(prefers-color-scheme: dark)`);app.store._mediaColorScheme=v.matches?`dark`:`light`,v.addEventListener(`change`,({matches:e})=>{app.store._mediaColorScheme=e?`dark`:`light`}),watch(()=>app.store.userColorScheme,e=>{e?window.localStorage.setItem(h,e):window.localStorage.removeItem(h),p?.postMessage({colorScheme:e})});var ee;watch(()=>app.store.activeColorScheme,e=>{clearTimeout(ee),document.documentElement.style.setProperty(`--animationSpeed`,`0`),document.documentElement.setAttribute(`data-color-scheme`,e),ee=setTimeout(()=>{document.documentElement.style.removeProperty(`--animationSpeed`)},100)});function te(e,n){e.__errListener&&=(e.removeEventListener(`input`,e.__errListener),e.removeEventListener(`change`,e.__errListener),null),e.setCustomValidity&&(e.setCustomValidity(``),e._oldTitle?e.setAttribute(`title`,e._oldTitle):e.removeAttribute(`title`)),e.removeAttribute(`data-error`);let r=n.nextSibling;r&&r.classList?.contains(`generated-error`)&&r.getAttribute(`data-input-name`)==e.getAttribute(`name`)&&r.remove(),n.querySelector(`[data-error]`)||n.classList.remove(`error`)}watch(()=>JSON.stringify(app.store.errors)&&app.store.errors,e=>{let n=document.querySelectorAll(`[name]`);for(let r of n){if(r.classList.contains(`no-error`))continue;let n=r.closest(`.field-list`)||r.closest(`.fields`)||r.closest(`.field`);if(!n)continue;let i=r.getAttribute(`name`);te(r,n);let a=app.utils.getByPath(e,i),o=a?.message||``;if(!o&&!app.utils.isEmpty(a)){let e=[];for(let n in a)a[n]?.message&&e.push(`${n}: ${a[n]?.message}`);o=e.join(` @@ -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 zi(e={oncreated:null}){let n=Bi(e);n&&(document.body.appendChild(n),app.modals.open(n))}function Bi(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 the performance could be slightly degraded and some queries may take longer to complete than usual.`),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 Vi(e){let n=Hi(e);document.body.appendChild(n),app.modals.open(n)}function Hi(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 Ui(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:()=>Vi(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:()=>{zi({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 Wi(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 Gi(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`},Di(),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}),Wi(r)),Ui({reset:()=>n.resetList})),t.div({className:`col-lg-12`},Ri({onsave:()=>r()})))),t.footer({className:`page-footer`},app.components.credits())))}function Ki(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 qi(e){app.store.title=`Crons`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageCronsSettings`,className:`page`},Di(),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})),Ki({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 Ji(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`},Di(),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 Yi=`pbSQLConsoleHistory`;function Xi(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(Yi,[]),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(Yi,e)})];return t.div({pbEvent:`pageSQLConsole`,className:`page`,onunmount:()=>{app.pb.cancelRequest(i),p.forEach(e=>e?.unwatch())}},Di(),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 Zi(){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`},Di(),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 Qi(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}return t.div({pbEvent:`pageExportCollections`,className:`page page-export-collections`},Di(),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:n=>{let i=Object.assign({},r.bulkSelected);n.target.__shiftKey&&(n.target.__shiftKey=!1,app.utils.bulkSelectRange(r.collections,i,e,n.target.checked)),n.target.checked?i[e.id]=e:delete i[e.id],r.bulkSelected=i}}),t.label({htmlFor:i,textContent:()=>e.name,onclick:e=>{e.preventDefault();let n=document.getElementById(e.target.htmlFor);n&&(n.__shiftKey=e.shiftKey,n.click())}})))})),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 $i(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())}},Di(),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`);ea[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`);ea[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`);ea[e]=async e=>{app.store.showHeader=!1,app.store.page=await n(e)}};var ea={},ta;function na(){ta&&ta(),ta=router(ea,{fallbackPath:app.routes.fallbackPath})}app.routes.guestOnly(`#/pbinstall/{token}`,async e=>{let{pageInstaller:n}=await G(async()=>{let{pageInstaller:e}=await import(`./pageInstaller-CUhmKhWk.js`);return{pageInstaller:e}},[],import.meta.url);return n(e)}),app.routes.guestOnly(`#/login`,e=>$r(e)),app.routes.guestOnly(`#/request-password-reset`,async e=>{let{pageRequestSuperuserPasswordReset:n}=await G(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 G(async()=>{let{pageConfirmPasswordReset:e}=await import(`./pageConfirmPasswordReset-BpBFn0WV.js`);return{pageConfirmPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-verification/{token}`,async e=>{let{pageConfirmVerification:n}=await G(async()=>{let{pageConfirmVerification:e}=await import(`./pageConfirmVerification-BZgVXICb.js`);return{pageConfirmVerification:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-email-change/{token}`,async e=>{let{pageConfirmEmailChange:n}=await G(async()=>{let{pageConfirmEmailChange:e}=await import(`./pageConfirmEmailChange-CAkJEeUl.js`);return{pageConfirmEmailChange:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-success`,async e=>{let{pageOAuth2RedirectSuccess:n}=await G(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 G(async()=>{let{pageOAuth2RedirectFailure:e}=await import(`./pageOAuth2RedirectFailure-CRvz4PXa.js`);return{pageOAuth2RedirectFailure:e}},[],import.meta.url);return n(e)}),app.routes.superuserOnly(`#/collections`,hi),app.routes.superuserOnly(`#/logs`,Ei),app.routes.superuserOnly(`#/settings`,Ii),app.routes.superuserOnly(`#/settings/mail`,Ji),app.routes.superuserOnly(`#/settings/storage`,Zi),app.routes.superuserOnly(`#/settings/backups`,Gi),app.routes.superuserOnly(`#/settings/crons`,qi),app.routes.superuserOnly(`#/settings/export-collections`,Qi),app.routes.superuserOnly(`#/settings/import-collections`,$i),app.routes.superuserOnly(`#/settings/sql`,Xi);var ra=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 ra[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&&na()}),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 zi(e={oncreated:null}){let n=Bi(e);n&&(document.body.appendChild(n),app.modals.open(n))}function Bi(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 the performance could be slightly degraded and some queries may take longer to complete than usual.`),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 Vi(e){let n=Hi(e);document.body.appendChild(n),app.modals.open(n)}function Hi(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 Ui(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:()=>Vi(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:()=>{zi({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 Wi(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 Gi(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`},Di(),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}),Wi(r)),Ui({reset:()=>n.resetList})),t.div({className:`col-lg-12`},Ri({onsave:()=>r()})))),t.footer({className:`page-footer`},app.components.credits())))}function Ki(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 qi(e){app.store.title=`Crons`;let n=store({resetList:null});function r(){n.resetList=Date.now()}return t.div({pbEvent:`pageCronsSettings`,className:`page`},Di(),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})),Ki({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 Ji(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`},Di(),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 Yi=`pbSQLConsoleHistory`;function Xi(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(Yi,[]),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(Yi,e)})];return t.div({pbEvent:`pageSQLConsole`,className:`page`,onunmount:()=>{app.pb.cancelRequest(i),p.forEach(e=>e?.unwatch())}},Di(),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 Zi(){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`},Di(),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 Qi(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}return t.div({pbEvent:`pageExportCollections`,className:`page page-export-collections`},Di(),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:n=>{let i=Object.assign({},r.bulkSelected);n.target.__shiftKey&&(n.target.__shiftKey=!1,app.utils.bulkSelectRange(r.collections,i,e,n.target.checked)),n.target.checked?i[e.id]=e:delete i[e.id],r.bulkSelected=i}}),t.label({htmlFor:i,textContent:()=>e.name,onclick:e=>{e.preventDefault();let n=document.getElementById(e.target.htmlFor);n&&(n.__shiftKey=e.shiftKey,n.click())}})))})),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 $i(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())}},Di(),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`);ea[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`);ea[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`);ea[e]=async e=>{app.store.showHeader=!1,app.store.page=await n(e)}};var ea={},ta;function na(){ta&&ta(),ta=router(ea,{fallbackPath:app.routes.fallbackPath})}app.routes.guestOnly(`#/pbinstall/{token}`,async e=>{let{pageInstaller:n}=await G(async()=>{let{pageInstaller:e}=await import(`./pageInstaller-DMVWU1zE.js`);return{pageInstaller:e}},[],import.meta.url);return n(e)}),app.routes.guestOnly(`#/login`,e=>$r(e)),app.routes.guestOnly(`#/request-password-reset`,async e=>{let{pageRequestSuperuserPasswordReset:n}=await G(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 G(async()=>{let{pageConfirmPasswordReset:e}=await import(`./pageConfirmPasswordReset-BQ8SRN4r.js`);return{pageConfirmPasswordReset:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-verification/{token}`,async e=>{let{pageConfirmVerification:n}=await G(async()=>{let{pageConfirmVerification:e}=await import(`./pageConfirmVerification-ctYHuWr_.js`);return{pageConfirmVerification:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/confirm-email-change/{token}`,async e=>{let{pageConfirmEmailChange:n}=await G(async()=>{let{pageConfirmEmailChange:e}=await import(`./pageConfirmEmailChange-DnQm0RLl.js`);return{pageConfirmEmailChange:e}},[],import.meta.url);return n(e)}),app.routes.blank(`#/auth/oauth2-redirect-success`,async e=>{let{pageOAuth2RedirectSuccess:n}=await G(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 G(async()=>{let{pageOAuth2RedirectFailure:e}=await import(`./pageOAuth2RedirectFailure-CRvz4PXa.js`);return{pageOAuth2RedirectFailure:e}},[],import.meta.url);return n(e)}),app.routes.superuserOnly(`#/collections`,hi),app.routes.superuserOnly(`#/logs`,Ei),app.routes.superuserOnly(`#/settings`,Ii),app.routes.superuserOnly(`#/settings/mail`,Ji),app.routes.superuserOnly(`#/settings/storage`,Zi),app.routes.superuserOnly(`#/settings/backups`,Gi),app.routes.superuserOnly(`#/settings/crons`,qi),app.routes.superuserOnly(`#/settings/export-collections`,Qi),app.routes.superuserOnly(`#/settings/import-collections`,$i),app.routes.superuserOnly(`#/settings/sql`,Xi);var ra=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 ra[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&&na()}),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-CAkJEeUl.js b/ui/dist/assets/pageConfirmEmailChange-DnQm0RLl.js similarity index 97% rename from ui/dist/assets/pageConfirmEmailChange-CAkJEeUl.js rename to ui/dist/assets/pageConfirmEmailChange-DnQm0RLl.js index dd566c5b..4c91b533 100644 --- a/ui/dist/assets/pageConfirmEmailChange-CAkJEeUl.js +++ b/ui/dist/assets/pageConfirmEmailChange-DnQm0RLl.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-Cr4q2t8U.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-DjhEaS_B.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-BpBFn0WV.js b/ui/dist/assets/pageConfirmPasswordReset-BQ8SRN4r.js similarity index 97% rename from ui/dist/assets/pageConfirmPasswordReset-BpBFn0WV.js rename to ui/dist/assets/pageConfirmPasswordReset-BQ8SRN4r.js index 414bf831..6ecc4a5f 100644 --- a/ui/dist/assets/pageConfirmPasswordReset-BpBFn0WV.js +++ b/ui/dist/assets/pageConfirmPasswordReset-BQ8SRN4r.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-Cr4q2t8U.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-DjhEaS_B.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-BZgVXICb.js b/ui/dist/assets/pageConfirmVerification-ctYHuWr_.js similarity index 96% rename from ui/dist/assets/pageConfirmVerification-BZgVXICb.js rename to ui/dist/assets/pageConfirmVerification-ctYHuWr_.js index 7669794c..c2584581 100644 --- a/ui/dist/assets/pageConfirmVerification-BZgVXICb.js +++ b/ui/dist/assets/pageConfirmVerification-ctYHuWr_.js @@ -1 +1 @@ -import{n as e,t as n}from"./index-Cr4q2t8U.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-DjhEaS_B.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-CUhmKhWk.js b/ui/dist/assets/pageInstaller-DMVWU1zE.js similarity index 98% rename from ui/dist/assets/pageInstaller-CUhmKhWk.js rename to ui/dist/assets/pageInstaller-DMVWU1zE.js index 882ee2d9..613f7956 100644 --- a/ui/dist/assets/pageInstaller-CUhmKhWk.js +++ b/ui/dist/assets/pageInstaller-DMVWU1zE.js @@ -1 +1 @@ -import{n as e,r as n}from"./index-Cr4q2t8U.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-DjhEaS_B.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 c5b42df2..bc8a2e06 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -13,7 +13,7 @@ - + diff --git a/ui/src/utils.js b/ui/src/utils.js index 73f14f27..c5c8d7f3 100644 --- a/ui/src/utils.js +++ b/ui/src/utils.js @@ -1667,14 +1667,14 @@ const utils = { }; const indexRegex = - /\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s*where\s+([\s\S]*?))?\s*$/gim; + /\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s*where\s+([\s\S]*?))?\s*$/gi; const matches = indexRegex.exec((idx || "").trim()); if (matches?.length != 7) { return result; } - const sqlQuoteRegex = /^[\"\'\`\[\{}]|[\"\'\`\]\}]$/gm; + const sqlQuoteRegex = /^[\"\'\`\[\{}]|[\"\'\`\]\}]$/g; // unique result.unique = matches[1]?.trim().toLowerCase() === "unique"; @@ -1697,13 +1697,13 @@ const utils = { // columns const rawColumns = (matches[5] || "") - .replace(/,(?=[^\(]*\))/gim, "{PB_TEMP}") // temporary replace comma within expressions for easier splitting + .replace(/,(?=[^\(]*\))/gi, "{PB_TEMP}") // temporary replace comma within expressions for easier splitting .split(","); // split columns for (let col of rawColumns) { col = col.trim().replaceAll("{PB_TEMP}", ","); // revert temp replacement - const colRegex = /^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?$/gim; + const colRegex = /^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?\s*$/gi; const colMatches = colRegex.exec(col); if (colMatches?.length != 4) { continue;