UNPKG

@isdk/kvsqlite

Version:

SQlite(>=3.45.0) key/value Document store

1 lines 34.1 kB
"use strict";var t,e=Object.create,s=Object.defineProperty,i=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,r=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,E=(t,e,r,E)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let c of n(e))o.call(t,c)||c===r||s(t,c,{get:()=>e[c],enumerable:!(E=i(e,c))||E.enumerable});return t},c=(t,i,n)=>(n=null!=t?e(r(t)):{},E(!i&&t&&t.__esModule?n:s(n,"default",{value:t,enumerable:!0}),t)),a={};((t,e)=>{for(var i in e)s(t,i,{get:e[i],enumerable:!0})})(a,{DefaultKVCollection:()=>h,KVFileCurrentVer:()=>l,KVSqlite:()=>it,KVSqliteAttachments:()=>rt,KVSqliteCollection:()=>nt,KV_CREATEDAT_FIELD_NAME:()=>R,KV_FIELD_SYMBOL_MAP:()=>_,KV_FIELD_SYMBOL_MAP_REVERSE:()=>I,KV_FILE_VER_NAME:()=>u,KV_NAME_FIELD_NAME:()=>p,KV_NAME_SYMBOL:()=>S,KV_TYPE_FIELD_NAME:()=>A,KV_TYPE_SYMBOL:()=>d,KV_UPDATEDAT_FIELD_NAME:()=>N,KV_VALUE_FIELD_NAME:()=>O,KV_VALUE_SYMBOL:()=>$,SYS_KV_COLLECTION:()=>T,updateKVFieldSymbol:()=>k}),module.exports=(t=a,E(s({},"__esModule",{value:!0}),t));var f=(()=>"undefined"==typeof document?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href)(),l=5,u="ver",h="kv",T="_sys_kv",$="值",d="型",O="value",A="type",R="createdAt",N="updatedAt",_={[$]:O},I=Object.fromEntries(Object.entries(_).map((([t,e])=>[e,t]))),S="名",p="name",L=c(require("path/posix")),b=c(require("path")),y=c(require("fs")),m=require("url"),F=require("mime-type/with-db"),C=c(require("better-sqlite3")),D=require("lodash-es");function M(t,e){void 0===e&&(e={});for(const s in t)t.hasOwnProperty(s)&&(null!==t[s]&&"object"==typeof t[s]?(("object"!=typeof e[s]||Array.isArray(e[s]))&&(e[s]=Array.isArray(t[s])?[]:{}),M(t[s],e[s])):void 0!==t[s]&&(e[s]=t[s]));return e}function g(t,e){return t?`'${e}'`:String(e)}function j(t,e){return t.map((t=>x(t,e))).join(" AND ")}function w(t,e){return t.map((t=>x(t,e))).join(" OR ")}function v(t,e,s){const i=[];return Object.keys(e).forEach((n=>{const r=e[n];let o="string"==typeof e[n];switch(n){case"$lt":case"<":i.push(`${t} < ${g(o,r)}`);break;case"<=":case"$lte":i.push(`${t} <= ${g(o,r)}`);break;case"$gt":case">":i.push(`${t} > ${g(o,r)}`);break;case"$gte":case">=":i.push(`${t} >= ${g(o,r)}`);break;case"$ne":case"!=":i.push(`${t} != ${g(o,r)}`);break;case"=":case"$eq":i.push(`${t} = ${g(o,r)}`);break;case"$in":i.push(`${t} IN (${r.map((t=>g(!0,t))).join(", ")})`);break;case"$nin":i.push(`${t} NOT IN (${r.map((t=>g(!0,t))).join(", ")})`);break;case"$regex":i.push(`${t} REGEXP '${r.source}'`);break;case"$like":i.push(`${t} LIKE '${r}'`);break;case"$nlike":i.push(`${t} NOT LIKE '${r}'`);break;case"$glob":i.push(`${t} GLOB '${r}'`);break;case"$nglob":i.push(`${t} NOT GLOB '${r}'`);break;case"$or":if(Array.isArray(r)){n=n.slice(1).toUpperCase();const e=e=>"string"==typeof e?`${t}='${g(o,e)}'`:v(t,e,s);i.push(`(${r.map((t=>e(t))).join(` ${n} `)})`);break}throw new Error(`${n} is not an array for ${t}`);default:throw new Error(`Unsupported condition operator: ${n} for ${t}`)}})),i.join(" AND ")}function x(t,e){const s=[];let i=e?.wrapKey;if(e||(e={}),"function"!=typeof i&&(e.wrapKey=i=t=>t),Array.isArray(t))s.push(j(t,e));else for(const[n,r]of Object.entries(t))if("$and"===n)s.push(`(${j(t[n],e)})`);else if("$or"===n)s.push(`(${w(t[n],e)})`);else{const t=typeof r;if(null==r)s.push(`${i(n)} IS NULL`);else if("object"!==t||Array.isArray(r))if("string"===t)s.push(`${i(n)}='${r}'`);else{if("number"!==t&&"boolean"!==t)throw new Error(`Unsupported value type for key ${n}`);s.push(`${i(n)}=${r}`)}else s.push(v(i(n),r,e))}return s.length>1?s.join(" AND "):s[0]}function U(t,e){let s="";if(Array.isArray(t))s="string"==typeof e?"("+t.map((t=>U(t,e))).join(") || (")+")":"("+t.map((t=>U(t,e))).join(") (")+")";else if("object"==typeof t&&null!==t){const i=Object.keys(t);if(1!==i.length)throw new Error("Unsupported JSON object structure for FTS5 query.");const n=i[0],r=t[n];if("$or"===n)s=e?r.map((t=>U(t,e))).join(" || ' OR ' || "):r.map((t=>U(t,e))).join(" OR ");else if("$and"===n)s=e?r.map((t=>U(t,e))).join(" || "):r.map((t=>U(t,e))).join(" ");else{if("$near"!==n)throw new Error(`Unsupported operator: ${n}`);if(Array.isArray(r))s="string"==typeof e?"'NEAR(' || "+r.map((t=>U(t,e))).join(" || ")+" || ')'":"NEAR("+r.map((t=>U(t,e))).join(" ")+")";else{if(!r||!Array.isArray(r.items))throw new Error(`Invalid value for $near operator: ${r}`);{const t=r.items;s="string"==typeof e?"'NEAR(' || "+t.map((t=>U(t,e))).join(" || "):"NEAR("+t.map((t=>U(t,e))).join(" "),r.distance&&(s+="string"==typeof e?` || ', ${r.distance}`:`, ${r.distance}`),s+="string"==typeof e?")'":")"}}}}else s=e?"string"==typeof e?(e=e.trim()).endsWith(")")?e:`${e}('${t}')`:`'${t}'`:`"${t}"`;return s}function B(t,e){let s;return"string"==typeof e?((e=e.trim()).endsWith(")")||(e+="(?)"),t=e,s=!0):!0!==e&&(t="?",s=!0),{query:t,hasParam:s}}var W=c(require("better-sqlite3"));var X=(0,m.fileURLToPath)(f),H=b.default.dirname(X);function k(t,e){_[t]=e,I[e]=t}var G=(0,D.template)("CASE WHEN strftime('%Y', NEW.${field}) IS NOT NULL THEN NEW.${field} ELSE ${fallback} END"),q=(0,D.template)("${field} != NEW.${field}"),P="schema",K={zh:{name:"zh",plugin:{path:"zh",jiebaDict:"dict",load(t,e){if(e?.jiebaDict){const s=b.default.isAbsolute(e.jiebaDict)?e.jiebaDict:b.default.resolve(H,"..","plugins",e.jiebaDict);t.prepare("select jieba_dict(?)").run(s)}}},tokenize:"simple"},en:{name:"en",tokenize:"porter unicode61"}};function V(t,e){if(null==t)return"NULL";if("string"==typeof t)return t.startsWith("?=")?t=t.slice(2):ot(t)?t:`'${t}'`;if("number"==typeof t)return`${t}`;if("boolean"==typeof t)return t?"1":"0";if("object"==typeof t){return`${e&&!1===e.usingJsonb?"json":"jsonb"}('${(e?.serialize||JSON.stringify)(t)}')`}}function J(t,e,s){if(null==t)return null;switch(e=e.toUpperCase(),["DATE","TIME"].some((t=>e.startsWith(t)))&&(e="TEXT"),e){case"INTEGER":{const e=typeof t;if("boolean"===e)t=t?1:0;else if("string"===e){const e=parseInt(t);if(isNaN(e))throw new Error(`${t} is not a number`);t=e}return t}case"REAL":{const e=typeof t;if("boolean"===e)t=t?1:0;else if("string"===e){const e=parseFloat(t);if(isNaN(e))throw new Error(`${t} is not a number`);t=e}return t}case"BLOB":if(!Buffer.isBuffer(t)){if("string"===typeof t)t=Buffer.from(t,"utf8");else{if(!(Array.isArray(t)||t.length>=0))throw new Error(`${t} can not convert to a buffer`);t=Buffer.from(t)}}return t;case"TEXT":return""+t;case"JSON":case"JSONB":return(s?.serialize??JSON.stringify)(t)}}function z(t){for(const[e,s]of Object.entries(t)){const i=_[e];i&&(t[i]=s,delete t[e])}return t}function Y(t){for(const[e,s]of Object.entries(t)){const i=I[e];i&&(t[i]=s,delete t[e])}return t}function Z(t){if("string"==typeof t)return ot(t)?t.slice(1,-1):this.prepare(`SELECT ${t}`).pluck().get()}function Q(t,e,s){const i={};for(let n in t){const r=t[n],o=_[n];if(e){const t=e[n]??e[o]??Z.call(this,r.default);if(null==t&&r.notNull)throw new Error(`field ${n} is not nullable`);o&&(n=o),i[n]=J(t,r.type,s)}else{o&&(n=o);let t="@"+n;switch(r.type){case"JSON":t=`json(${t})`;break;case"JSONB":t=`jsonb(${t})`}i[n]=t}}return i}function tt(t){const e=[];for(let s in t){const i=t[s];_[s]&&(s=_[s]),"JSON"!==i.type&&"JSONB"!==i.type||(s=`json(${s}) as ${s}`),e.push(s)}return e}function et(t,e,s){const i=s?.deserialize??JSON.parse;for(let s in e){const n=I[s],r=e[s],o=t[s];"string"!=typeof o||"JSON"!==r.type&&"JSONB"!==r.type||(t[s]=i(o)),n&&void 0!==o&&(t[n]=o,delete t[s])}return t}function st(t,e){const s=e?.foreignKeys;let i=t.name;if(!i)throw new Error("fieldName is required");_[i]&&(i=_[i]);const n=(t.type||"TEXT")+" ";let r=t.constraint||"";t.notNull&&!r.toUpperCase().includes("NOT NULL")&&(r+="NOT NULL "),t.primary&&!r.toUpperCase().includes("PRIMARY KEY")&&(r+="PRIMARY KEY "),t.unique&&!r.toUpperCase().includes("UNIQUE")&&(r+="UNIQUE ");const o=`${i} ${n}${r}${null!=t.default?`DEFAULT ${V(t.default,e)}`:""}`.trim();if(s){const e=t.foreignKey;if(e){const{reference:t,isJson:n,onUpdate:r,onDelete:o}=e;let E=e.referenceField;if(!t)throw new Error("foreignKey.referenceTable is required");E||(E="_id"),n&&(E=`val->>'$.${E}'`);let c=`FOREIGN KEY (${i}) REFERENCES ${t}(${E})`;c+=` ON UPDATE ${r||"CASCADE"}`,c+=` ON DELETE ${o||"CASCADE"}`,s.add(c)}}return o}var it=class extends C.default{constructor(t,e){if("string"==typeof t&&":"!=t[0]){const e=b.default.dirname(t);e&&!y.default.existsSync(e)&&y.default.mkdirSync(e,{recursive:!0})}super(t,e),this.ftsLoaded={},this.collections={},this.serdeOptions={};const s=0===this.prepare("SELECT COUNT(*) FROM sqlite_master").pluck().get();if(this.preIsExists=this.prepare("SELECT COUNT(*) FROM sqlite_master WHERE type = ? AND name= ?").pluck(),e?.serialize&&(this.serdeOptions.serialize=e.serialize),e?.deserialize&&(this.serdeOptions.deserialize=e.deserialize),e?.id&&(this.id=e.id),this.readonly){const t=this.sqlSchema({type:"table"}).map((t=>t.tbl_name));t.length&&this.createCollections(t)}else{const t=e?.collections||[],i=t.indexOf(T);let n;if(i>=0){const e=t.splice(i,1);"string"!=typeof e&&(n=e)}if(this.create(T,n),t.includes(h)||t.push(h),e?.collection&&!t.includes(e.collection)&&t.push(e.collection),t.length&&this.createCollections(t,e),!s){const t=this.getSysConfig(u,T);t!==l&&this.tryUpgradeVer(t)}}}static dump(t){return function(t){let e=!1;if("string"==typeof t){const s={};":memory:"!==t&&(s.readonly=!0),t=new W.default(t,s),e=!0}if(!(t instanceof W.default))throw new Error("db must be a string or a Database instance");let s="";try{s+="PRAGMA foreign_keys=OFF;\n",s+="BEGIN TRANSACTION;\n";const e=t.prepare("SELECT type, name, sql FROM sqlite_master WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite_%'").all(),i=e.filter((t=>"table"===t.type&&"sqlite_sequence"!==t.name)),n=e.filter((t=>"trigger"===t.type)),r=e.filter((t=>"view"===t.type)),o=e.filter((t=>"index"===t.type));for(const t of i)s+=`${t.sql.replace(/^CREATE TABLE/,"CREATE TABLE IF NOT EXISTS")};\n`;for(const e of i){const i=t.prepare(`SELECT * FROM "${e.name}"`).all();for(const t of i){const i=Object.keys(t).map((t=>`"${t}"`)).join(", "),n=Object.values(t).map((t=>null===t?"NULL":"string"==typeof t?`'${t.replace(/'/g,"''")}'`:"boolean"==typeof t?t?"1":"0":Buffer.isBuffer(t)?`x'${t.toString("hex")}'`:t)).join(", ");s+=`INSERT OR IGNORE INTO "${e.name}" (${i}) VALUES (${n});\n`}}for(const t of n)s+=`${t.sql.replace(/^CREATE TRIGGER/,"CREATE TRIGGER IF NOT EXISTS")};\n`;for(const t of r)s+=`${t.sql.replace(/^CREATE VIEW/,"CREATE VIEW IF NOT EXISTS")};\n`;for(const t of o)s+=`${t.sql.replace(/^CREATE INDEX/,"CREATE INDEX IF NOT EXISTS")};\n`;s+="COMMIT;\n"}catch(t){throw t}finally{e&&t.close()}return s}(t)}createCollections(t,e){t.forEach((t=>{let s;"string"==typeof t?(s=t,t=e):s=t.name,s&&!this.collections[s]&&this.create(s,t)}))}tryUpgradeVer(t){const e=this.collections[T];if(null==t&&e&&(t=e.getExtend(T,u)),t||(t=0),t<1){const t=this.tableInfo(h);t?.key&&this.exec(`ALTER TABLE ${h} RENAME COLUMN "key" TO "_id"`)}if(t<5)for(const e of Object.values(this.collections)){const s=e.tableInfo({mapped:!1}),i=e.name;t<4?(this.exec(`DROP TRIGGER IF EXISTS tr_${i}_createdAt;`),this.exec(`DROP TRIGGER IF EXISTS tr_${i}_updatedAt;`)):4===t&&(this.exec(`DROP TRIGGER IF EXISTS tr_${i}_auto_timestamp_insert;`),this.exec(`DROP TRIGGER IF EXISTS tr_${i}_auto_timestamp_update;`)),e.createIndexAndTriggerForAutoTimestamp(s)}t!==l&&e.setExtend(T,u,l)}usingJsonb(t){let e;t||(t=h);const s=this.collections[T];if(s&&(e=s.getExtend(t,"usingJsonb")),void 0===e){const s=this.tableInfo(t);s?.val&&(e="JSONB"===s.val.type||"BLOB"===s.val.type)}return e}getSysConfig(t,e){const s=this.collections[T];if(s)return e||(e=h),s.getExtend(e,t)}setSysConfig(t,e,s){const i=this.collections[T];if(i)return s||(s=h),i.setExtend(s,t,e)}getSerdeOptions(t){const e={};return t?.serialize?e.serialize=t.serialize:this.serdeOptions.serialize&&(e.serialize=this.serdeOptions.serialize),t?.deserialize?e.deserialize=t.deserialize:this.serdeOptions.deserialize&&(e.deserialize=this.serdeOptions.deserialize),e}create(t,e){if(!this.collections[t])return this.collections[t]=new nt(t,this,e)}getCollection(t){let e=this.collections[t];return!e&&this.isCollectionExists(t)&&(e=this.collections[t]=new nt(t,this)),e}drop(t){if(this.collections[t]){if(t===T||t===h)throw new Error("Cannot drop system collection");this.exec(`DROP TABLE IF EXISTS ${t}_fts`),this.exec(`DROP TABLE IF EXISTS ${t}`);const e=this.collections[T];e&&(e.delExtend(t,"%"),e.del(t)),delete this.collections[t]}}set(t,e,s){const i=("object"===typeof t?e?.collection:s?.collection)||h;return this.collections[i]?.set(t,e,s)}setExtend(t,e,s,i){const n=i?.collection||h;return this.collections[n]?.setExtend(t,e,s,i)}setExtends(t,e,s){const i=s?.collection||h;return this.collections[i]?.setExtends(t,e,s)}bulkDocs(t,e){const s=e?.collection||h;return this.collections[s]?.bulkDocs(t,e)}get(t,e){const s=e?.collection||h;return this.collections[s]?.get(t)}getExtend(t,e,s){const i=s?.collection||h;return this.collections[i]?.getExtend(t,e)}getExtends(t,e,s){const i=s?.collection||h;return this.collections[i]?.getExtends(t,e,s)}del(t,e){const s=e?.collection||h;return this.collections[s]?.del(t)}isExists(t,e){const s=e?.collection||h;return this.collections[s]?.isExists(t)}count(t,e){const s=e?.collection||h;return this.collections[s]?.count(t)}list(t,e){t&&"object"==typeof t&&(t=(e=t).query);const s=e?.collection||h;return this.collections[s]?.list(t,e)}createJsonIndex(t,e,s){const i=s?.collection||h;return this.collections[i]?.createJsonIndex(t,e)}createIndex(t,e,s){const i=s?.collection||h;return this.collections[i]?.createTableIndex(t,e)}searchEx(t,e){const s=e?.collection||h;return this.collections[s]?.searchEx(t,e)}search(t,e){const s=e?.collection||h;return this.collections[s]?.search(t,e)}buildWhereClause(t,e){const s=e?.collection||h;return this.collections[s]?.buildWhereClause(t,e)}isTypeExists(t,e){return this.preIsExists.get(t,e)}isCollectionExists(t){return this.isTypeExists("table",t)}loadFtsLanguage(t){const e=t?.language||"en",s=e&&"object"==typeof e?e.name:e;if(!this.ftsLoaded[s]){const t="object"==typeof e?(0,D.defaultsDeep)({},e,K[s]):K[s];if(t&&t.plugin){const e=t.plugin;if(e.path){const t=b.default.isAbsolute(e.path)?e.path:b.default.resolve(H,"..","plugins",e.path);this.loadExtension(t,"sqlite3_simple_init")}"function"==typeof e.load&&e.load(this,e)}this.ftsLoaded[s]=!0}}tableInfo(t,e){return"string"==typeof t?(e||(e={}),e.collection=t):t&&"object"==typeof t&&(e=t),this._tableInfo(e)}_tableInfo(t){const e=t?.collection||h,s=t?.mapped??!0,i=this.prepare(`PRAGMA table_info(${e})`).all();if(i){const t={};i.forEach((e=>{let i=e.name;s&&I[i]&&(i=I[i]);const n=t[i]={name:i,type:e.type,notNull:!!e.notnull,primary:!!e.pk};null!==e.dflt_value&&(n.default=e.dflt_value)}));const n=this.prepare(`PRAGMA index_list(${e})`).all();return n?.length&&n.forEach((e=>{const i=this.prepare(`PRAGMA index_xinfo(${e.name})`).all().map((t=>t.name)).filter((t=>t));i.length&&i.forEach((i=>{s&&I[i]&&(i=I[i]),t[i].index={name:e.name,unique:!!e.unique,partial:!!e.partial}}))})),t}}sqlSchema(t,e){let s,i,n="",r=!0;t&&"object"==typeof t&&(t=(e=t).name),t&&(n+=`name = '${t}'`),e&&(null!=e.excludeUnmanaged&&(r=e.excludeUnmanaged),i=e.type,i&&(s="virtual_table"===i,s&&(i="table"),n&&(n+=" AND "),n+=`type = '${i}'`)),n&&(n=` WHERE ${n}`),n="SELECT * FROM sqlite_master"+n;let o=this.prepare(n).all();return"table"===i&&(o=o.filter((t=>{if(r&&!this.isManagedTable(t.tbl_name))return!1;let e=t.sql.startsWith("CREATE VIRTUAL TABLE");return s?t.type="virtual_table":e=!e,e}))),t&&o.length<=1?o[0]:o}dump(){return this.constructor.dump(this)}isManagedTable(t){const e=this.tableInfo(t,{mapped:!1});if(!e)throw new Error(`Table ${t} not found`);return e._id&&e._id.primary&&e.val}enableFts(t,e){return t=t||h,this.collections[t]?.enableFts(e)}searchFts(t,e){const s=e?.collection||h;return this.collections[s]?.searchFts(t,e)}},nt=class{constructor(t,e,s={}){this.name=t,this.db=e;const i=e.usingJsonb(t)??s.usingJsonb??e.usingJsonb(T)??!0,n=i?"jsonb":"json";let r;this.jsonb=n,s=(0,D.cloneDeep)(s);e.isCollectionExists(t)?(r=this.tableInfo({collection:t,mapped:!1}),s.fields=r):(s.fields?s.fields=function(t){return Array.isArray(t)?t=t.reduce(((t,e)=>{let s;if("string"==typeof e)s=e,e={};else{if(!e||"object"!=typeof e)throw new Error(`${e} is not a valid field name`);s=e.name}const i=_[s];return i&&(s=i),t[s]=e,t}),{}):z(t),t}(s.fields):s.fields={},r=s.fields,r._id&&r._id.type?r._id.primary=!0:r._id={name:"_id",type:"TEXT",primary:!0},r.val?r.val.type=i?"JSONB":"JSON":r.val={name:"val",type:i?"JSONB":"JSON"},!0===s.fts&&(s.fts={unIndexed:["_id"]}));const o=Q.call(e,r,void 0,e.getSerdeOptions(s)),E=tt(r);e.readonly||this.createTable(t,s),this.preExists=e.prepare("SELECT 1 FROM "+t+" WHERE _id = ?").pluck(),this.preAdd=e.prepare(`INSERT INTO ${t} (${Object.keys(o).join(",")}) VALUES (${Object.values(o).join(",")})`),this.preUpdate=e.prepare(`UPDATE ${t} SET ${Object.entries(o).map((([t,e])=>`${t} = ${e}`)).join(",")} WHERE _id=@_id`),this.preGet=e.prepare(`SELECT ${E.join(",")} FROM ${t} WHERE _id = ?`),this.preDel=e.prepare("DELETE FROM "+t+" WHERE _id = ?"),this.preDelAll=e.prepare("DELETE FROM "+t),this.preCount=e.prepare("SELECT Count(*) as count FROM "+t).pluck(),this.preCountW=e.prepare("SELECT Count(*) as count FROM "+t+" WHERE _id LIKE ?").pluck(),this.preSearchKey=e.prepare(`SELECT ${E.join(",")} FROM ${t} WHERE _id LIKE @query LIMIT @size OFFSET @offset`),this.preSearchKeyAll=e.prepare(`SELECT ${E.join(",")} FROM ${t} WHERE _id LIKE @query`),this.preAll=e.prepare(`SELECT ${E.join(",")} FROM ${t}`),this.preAllLimit=e.prepare(`SELECT ${E.join(",")} FROM ${t} LIMIT @size OFFSET @offset`)}createIndexAndTriggerForAutoTimestamp(t){const e=t.val?"JSONB"===t.val.type||"BLOB"===t.val.type?"jsonb":"json":"";t.createdAt?this.createTableIndex("createdAt","createdAt"):e&&this.createJsonIndex("createdAt","createdAt"),t.updatedAt?this.createTableIndex("updatedAt","updatedAt"):e&&this.createJsonIndex("updatedAt","updatedAt");const s=t.createdAt?"createdAt":e?"val->>'$.createdAt'":void 0,i=t.updatedAt?"updatedAt":e?"val->>'$.updatedAt'":void 0,n=t.createdAt?"createdAt = (":e?`val = ${e}_set(New.val, '$.createdAt',`:"",r=t.updatedAt?"updatedAt = (":e?`val = ${e}_set(New.val, '$.updatedAt', `:"";let o="";(s||i)&&(!e||t.createdAt||t.updatedAt?(s&&(o+=`${n} strftime('%FT%H:%M:%fZ', ${G({field:s,fallback:"'now'"})}))`),i&&(o&&(o+=", "),o+=`${r} strftime('%FT%H:%M:%fZ', ${G({field:i,fallback:"'now'"})}))`)):o=`val = ${e}_set(New.val, '$.createdAt', strftime('%FT%H:%M:%fZ', ${G({field:s,fallback:"'now'"})}), '$.updatedAt', strftime('%FT%H:%M:%fZ', ${G({field:i,fallback:"'now'"})}))`,o+=" WHERE _id = NEW._id;",this.createTrigger({name:"auto_timestamp_insert",triggerTiming:"AFTER",event:"INSERT",condition:"FOR EACH ROW",action:`UPDATE ${this.name} SET `+o})),o="",!e||t.createdAt||t.updatedAt?(s&&(o+=`${n} strftime('%FT%H:%M:%fZ', ${G({field:s,fallback:`IFNULL(OLD.${s}, 'now')`})}))`),i&&(o&&(o+=", "),o+=`${r} strftime('%FT%H:%M:%fZ', ${G({field:i,fallback:"'now'"})}))`)):o=`val = ${e}_set(New.val, '$.createdAt', strftime('%FT%H:%M:%fZ', ${G({field:s,fallback:`IFNULL(OLD.${s}, 'now')`})}), '$.updatedAt', strftime('%FT%H:%M:%fZ', ${G({field:i,fallback:"'now'"})}))`,o+=` WHERE _id = NEW._id AND (${i} IS NULL OR ${q({name:this.name,field:i})} OR strftime('%Y', NEW.${i}) IS NULL);`,this.createTrigger({name:"auto_timestamp_update",triggerTiming:"AFTER",event:"UPDATE",condition:"FOR EACH ROW",action:`UPDATE ${this.name} SET `+o})}_set(t,e){const s=t._id;t={...t};let i,n=this.get(s);if(n){if(e?.ignoreExists)return{changes:0,lastInsertRowid:-1};const s=!e||!1!==e.overwrite;i=this.preUpdate,s?n=t:t&&"object"==typeof t&&n&&"object"==typeof n?(delete n.createdAt,delete n.updatedAt,M(t,n)):n=t}else i=this.preAdd,n=t;const r=this.tableInfo(),o=[...Object.keys(r),...Object.keys((0,D.omit)(I,[O]))];let E=(0,D.omit)(n,o);1===Object.keys(E).length&&null!=E[$]&&"object"!=typeof E[$]&&(E=E[$]);const c=(0,D.pick)(n,o);null!=E&&("object"==typeof E&&z(E),c.val=E);const a=Q.call(this.db,r,c,this.db.getSerdeOptions(e));return i.run(a)}set(t,e,s){const i=typeof t;return"object"===i?(s=e,e=t):"string"!==i&&"number"!==i||(e._id=t),this.db.transaction((()=>this._set(e,s)))()}_setExtend(t,e,s,i){e.startsWith(".")||(e="."+e);const n={_id:t=L.default.join(""+t,e),[$]:s};return i?.[d]&&(n[d]=i[d]),this._set(n,i)}setExtend(t,e,s,i){return this.db.transaction((()=>this._setExtend(t,e,s,i)))()}setExtends(t,e,s){return this.db.transaction((()=>Object.keys(e).map((i=>this._setExtend(t,i,e[i],s)))))()}bulkDocs(t,e){return this.db.transaction((()=>t.map((t=>this._set(t,e)))))()}get(t){let e=this.getEx(t);return e&&"object"==typeof e?e._id=t:void 0!==e&&(e={[$]:e,_id:t}),e}getEx(t){let e=this.preGet.get(t+"");if(e){et(e,this.tableInfo({mapped:!1}),this.db.getSerdeOptions());const t=e.val;t&&"object"==typeof t?(delete e.val,e={...e,...Y(t)}):2===Object.keys(e).length?e=t:(delete e.val,void 0!==t&&(e[$]=t))}return e}getExtend(t,e){e&&(t=Et(t,e));const s=this.get(t);return s?.[$]}isExistsExtend(t,e){return e&&(t=Et(t,e)),this.isExists(t)}delExtend(t,e){return e&&(t=Et(t,e)),this.del(t)}getExtends(t,e,s){const i=s?.singleValue;e?"string"==typeof e&&(e=[e]):e=["%"];const n=(e=e.map((e=>Et(t,e)))).map((t=>t.lastIndexOf("%")>=0?this.list(t):this.get(t))).flat();let r=n.reduce(((t,e)=>{if(e){const s=e[$];t[L.default.basename(e._id+"").slice(1)]=s}return t}),{_id:t});return i&&(r=1===n.length?n[0][$]:r),r}del(t){if(Array.isArray(t))return this.db.transaction((()=>t.map((t=>this.preDel.run(t)))))();if(t&&"object"==typeof t){let e=x(t);return e="DELETE FROM "+this.name+" WHERE "+e,this.db.prepare(e).run()}return t?this.preDel.run(t):this.preDelAll.run()}isExists(t){return this.preExists.get(t+"")}count(t){let e;if(t){"object"==typeof t&&(t=this.buildWhereClause(t));const s="SELECT Count(*) as count FROM "+this.name+" WHERE "+t;e=this.db.prepare(s).pluck()}else e=this.preCount;return e.get()}list(t,e){t&&"object"==typeof t&&(t=(e=t).query);const s=this.tableInfo({mapped:!1}),i=e?.size,n=e?.page||0;let r,o=e?.sort;if(o){const E=tt(s),c=e?.order;Array.isArray(o)||(o=[o]),o=o.map((t=>`val->>'$.${t}'`)),"DESC"===c&&(o=o.map((t=>`${t} DESC`))),o=" ORDER BY "+o.join(", ");const a=i?` LIMIT ${i} OFFSET ${n*i}`:"";t=t?` WHERE _id LIKE ${t}`:"",r=this.db.prepare(`SELECT ${E.join(",")} FROM ${this.name}`+t+o+a).all()}else r=t?i?this.preSearchKey.all({query:t,size:i,offset:n*i}):this.preSearchKeyAll.all({query:t}):i?this.preAllLimit.all({size:i,offset:n*i}):this.preAll.all();const E=this.db.getSerdeOptions(e).deserialize??JSON.parse;return r.map((t=>{const i=E(t.val);return delete t.val,i&&"object"==typeof i?{...et((0,D.omit)(t,["val"]),s,this.db.getSerdeOptions(e)),...Y(i)}:{...et((0,D.omit)(t,["val"]),s,this.db.getSerdeOptions(e)),[$]:i}}))}getSchema(){const t=this.db.collections[T];return t?.getExtend(this.name,P)}createSchema(t){const e=this.db;if(t.name&&t.fields&&t.name!==T){const s=e.collections[T];if(s){const e=t.overwrite;delete t.overwrite,e?s.setExtend(t.name,P,t,{overwrite:e}):s.isExistsExtend(t.name,P)||s.setExtend(t.name,P,t)}}}createTable(t,e){const s=this.db,i=e.fields,n=e.fts;s.prepare(function(t,e){const s=e.fields,i=new Set,n=Object.keys(s).map((t=>{const n=s[t];return n.name||(n.name=t),st(n,{...e,foreignKeys:i})}));i.size&&n.push(...i);let r=`CREATE TABLE IF NOT EXISTS ${t} (`;return r+=n.join(", "),r+=");",r}(t,{...e,...s.getSerdeOptions(e)})).run(),this.createIndexAndTriggerForAutoTimestamp(i),e.indexes&&this.createIndexes(e),n&&this.enableFts(n);const r=e.triggers;Array.isArray(r)?r.forEach((t=>{this.createTrigger(t,e)})):"object"==typeof r&&this.createTrigger(r,e),e.name=t,this.createSchema(e)}createJsonIndex(t,e){return t.startsWith("ix_"+this.name+"_")||(t="ix_"+this.name+"_"+t),Array.isArray(e)||(e=[e]),e=e.map((t=>`val->>'$.${t}'`)),this.db.prepare("CREATE INDEX IF NOT EXISTS "+t+" ON "+this.name+" ("+e.join(",")+")").run()}createTableIndex(t,e){return t.startsWith("ix_"+this.name+"_")||(t="ix_"+this.name+"_"+t),Array.isArray(e)||(e=[e]),e=e.map((t=>{const e=t.trim().split(" ");return _[e[0]]&&(e[0]=_[e[0]],t=e.join(" ")),t})),this.db.prepare("CREATE INDEX IF NOT EXISTS "+t+" ON "+this.name+" ("+e.join(",")+")").run()}createIndex(t,e){let s=t.fields;if(!s)throw new Error("index fields is required");const i=e?.fields||this.tableInfo({mapped:!1});let n=t.name;n.startsWith("ix_"+this.name+"_")||(n="ix_"+this.name+"_"+n),s=s.map((t=>{const e=t.trim().split(" "),s=_[e[0]]??e[0];return i[s]||(e[0]=`val->>'$.${s}'`,t=e.join(" ")),t}));let r="CREATE "+(t.unique?"UNIQUE ":"")+"INDEX IF NOT EXISTS "+n+" ON "+this.name+" ("+s.join(",")+")";return t.partial&&(r+=" WHERE "+t.partial),this.db.prepare(r).run()}createIndexes(t){let e=t.indexes;if(!e)throw new Error("indexes is required");return Array.isArray(e)||(e=[e]),this.db.transaction((()=>e.map((e=>this.createIndex(e,t)))))()}createTrigger(t,e){const s=t.condition||"";let i=t.name;i?.startsWith("tr_"+this.name+"_")||(i="tr_"+this.name+"_"+i);const n=`\n CREATE TRIGGER IF NOT EXISTS ${i} ${t.triggerTiming} ${t.event} ON ${this.name}\n ${s}\n BEGIN\n ${t.action}\n END;`;return this.db.prepare(n).run()}renameField(t,e,s){const i=this.db;if("string"==typeof e){const s=`ALTER TABLE ${this.name} RENAME COLUMN ${t} TO ${e}`;return i.prepare(s).run()}if(e?.name){const n=s?.fieldInfos??this.tableInfo({mapped:!1});i.transaction((()=>{let r=`__${t}_OlD`,o=0;for(;n?.[r];)r+=o++;i.exec(`ALTER TABLE ${this.name} RENAME COLUMN ${t} TO ${r}`),i.exec(`ALTER TABLE ${this.name} ADD COLUMN ${e.name} ${st(e,s)}`),i.exec(`UPDATE ${this.name} SET ${e.name} = ${r} WHERE ${r} IS NOT NULL`),i.exec(`ALTER TABLE ${this.name} DROP COLUMN ${r}`)})).immediate()}}searchEx(t,e){const s=e?.fieldInfos??this.tableInfo({mapped:!1});"string"!=typeof t&&(t=Object.entries(t).map((([t,i])=>(_[t]&&(t=_[t]),(void 0===s[t]?`val->>'$.${t}'`:t)+`=${V(i,{...e,...this.db.getSerdeOptions(e)})}`))).join(" AND "));let i=e?.sort;const n=e?.order,r=e?.size,o=e?.page||0;i?(Array.isArray(i)||(i=[i]),i=i.map((t=>(_[t]&&(t=_[t]),void 0===s[t]&&(t=`val->>'$.${t}'`),t))),"DESC"===n&&(i=i.map((t=>`${t} DESC`))),i=" ORDER BY "+i.join(", ")):i="";const E=`SELECT ${tt(e?.fieldNames?(0,D.pick)(s,["_id","val",...e.fieldNames]):s).join(",")} FROM `+this.name+" WHERE "+t+i,c=this.db.prepare(E+" LIMIT @size OFFSET @offset"),a=this.db.prepare(E),f=r?c.all({size:r,offset:o*r}):a.all(),l=this.db.getSerdeOptions(e).deserialize??JSON.parse;return f.map((t=>{let i=l(t.val);return delete t.val,i&&"object"==typeof i?Y(i):i={[$]:i},{...et(t,s,this.db.getSerdeOptions(e)),...i}}))}search(t,e){const s=e?.fieldInfos??this.tableInfo({mapped:!1}),i=this.buildWhereClause(t,{...e,fieldInfos:s});return this.searchEx(i,{...e,fieldInfos:s})}buildWhereClause(t,e){const s=e?.fieldInfos??this.tableInfo({mapped:!1});return x(t,{wrapKey:t=>{const e=_[t];return e&&(t=e),void 0===s[t]?`val->>'$.${t}'`:t}})}tableInfo(t){const e=this.name;return this.db._tableInfo({...t,collection:e})}enableFts(t={}){const e=this.db,s=this.name,i=this.tableInfo({mapped:!1});let n=t.fields;if(!n){const i=e.getSysConfig("fts",s);i?.fields&&(t.fields=n=i.fields)}if(i&&n?.length&&Object.keys(i).forEach((t=>{n.includes(t)||delete i[t]})),!i||0===Object.keys(i).length)throw new Error(`Missing fields to add fts for collection ${s}`);const r=t.exclude?new Set(t.exclude):void 0,o=t.include?new Set(t.include):void 0;let E=t.language;"string"==typeof E?E=K[E]??K.en:E&&E.name&&K[E.name]?(0,D.defaultsDeep)(E,K[E.name]):E&&"object"==typeof E||(E=K.en),t.language=E,e.loadFtsLanguage(t);const c=[],a=[],f=(t.unIndexed??["_id"]).map((t=>_[t]??t));if(Object.keys(i).forEach((e=>{r&&r.has(e)||(a.push(e),(f.includes(e)||!1!==t.skipIndexed&&i[e]?.index&&!o?.has(e))&&(e+=" UNINDEXED"),c.push(e))})),0===c.length)throw new Error("fts fields is empty");if(E.tokenize){let t=E.options||"";t&&(t=" "+t),c.push(`tokenize="${E.tokenize}${t}"`)}c.push(`content='${s}'`),e.transaction((()=>{const n=(t,e)=>"jsonb"===i[t].type?`json(${e})`:e;e.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS ${s}_fts USING fts5(${c.join(",")})`),e.exec(`\n CREATE TRIGGER IF NOT EXISTS tr_${s}_fts_ai AFTER INSERT ON ${s}\n BEGIN\n INSERT INTO ${s}_fts(${a.join(",")}) VALUES (${a.map((t=>n(t,"NEW."+t))).join(",")});\n END;\n `),e.exec(`\n CREATE TRIGGER IF NOT EXISTS tr_${s}_fts_au AFTER UPDATE ON ${s}\n BEGIN\n INSERT INTO ${s}_fts (${s}_fts, oid, ${a.join(",")}) VALUES ('delete', OLD.oid, ${a.map((t=>"OLD."+t)).join(",")});\n INSERT INTO ${s}_fts (oid, ${a.join(",")}) VALUES (NEW.oid, ${a.map((t=>n(t,"NEW."+t))).join(",")});\n END;\n `),e.exec(`\n CREATE TRIGGER IF NOT EXISTS tr_${s}_fts_ad AFTER DELETE ON ${s}\n BEGIN\n INSERT INTO ${s}_fts (${s}_fts, oid, ${a.join(",")}) VALUES ('delete', OLD.oid, ${a.map((t=>"OLD."+t)).join(",")});\n END;\n `),e.setSysConfig("fts",{...t,language:E.name,fields:a,unIndexed:f},s)}))()}searchFts(t,e){const s=e?.collection||this.name,i=this.db;i.loadFtsLanguage(e);const n=e?.fieldInfos??this.tableInfo({mapped:!1});let r=e?.fieldNames;if(!r){const t=i.getSysConfig("fts",s);r=tt(t?.fields?(0,D.pick)(n,t.fields):n)}r.includes("_id")||r.push("_id");let o=e?.sort;const E=e?.order,c=e?.size,a="number"==typeof c&&c>0?`LIMIT ${c} OFFSET ${(e?.page||0)*c}`:"";o?(Array.isArray(o)||(o=[o]),o.unshift("rank"),"DESC"===E&&(o=o.map((t=>`${t} DESC`))),o=" ORDER BY "+o.join(", ")):(o="ORDER BY rank","DESC"===E&&(o+=" DESC"));let f,l,u="",h=e?.query;if("string"==typeof t){const i=B(t,e?.ftsQueryStyle);u+=`${s}_fts MATCH ${i.query}`,l=i.hasParam}else if(t&&"object"==typeof t){let i=e?.ftsQueryStyle,n=t;if(!(Array.isArray(n)||1===Object.keys(n).length&&null==n.$match)){const e=(0,D.omit)(n,["$match"]),s=(0,D.pick)(n,["$match"]);if(Object.keys(e).length&&(h=(0,D.defaultsDeep)(e,h)),s.$match&&(n=s.$match,"string"==typeof n)){t=n;const e=B(n,i);n=e.query,l=e.hasParam}}"object"==typeof n&&(n=U(n,i),i||(n=`'${n}'`)),u+=`${s}_fts MATCH ${n}`}if(h){let t=h;"object"==typeof t&&(t=this.buildWhereClause(t,{...e,fieldInfos:n})),t&&(u&&(u+=" AND "),u+=t)}if(u&&(u=`WHERE ${u}`),u=`SELECT ${r} FROM ${s}_fts ${u} ${o} ${a}`,f=l?i.prepare(u).all(t):i.prepare(u).all(),f){const t=e?.retrieveFull,s=this.db.getSerdeOptions(e).deserialize??JSON.parse;f=f.map((e=>{const i=e._id;if(t)return this.get(i);const n=e.val?s(e.val):e;let r;return null!=n?"object"==typeof n?(r=n,r._id=i):r={_id:i,[$]:n}:r={_id:i},Object.entries(e).forEach((([t,e])=>{"_id"!==t&&"val"!==t&&(I[t]&&(t=I[t]),r[t]=e)})),r}))}return f}drop(){this.db.drop(this.name)}},rt=class{constructor(t,e){this.name=t,this.db=e,t+="_attach",e.readonly||(e.prepare("CREATE TABLE IF NOT EXISTS "+t+" (_id TEXT PRIMARY KEY,filename TEXT, isText BOOLEAN, size INTEGER, mime TEXT, content BLOB, createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP)").run(),e.prepare(`CREATE INDEX IF NOT EXISTS ix_${t}_createdAt ON ${t} (createdAt)`).run(),e.prepare(`CREATE INDEX IF NOT EXISTS ix_${t}_updatedAt ON ${t} (updatedAt)`).run(),e.prepare(`CREATE INDEX IF NOT EXISTS ix_${t}_filename ON ${t} (filename)`).run(),e.prepare(`CREATE INDEX IF NOT EXISTS ix_${t}_isText ON ${t} (isText)`).run(),e.prepare(`CREATE INDEX IF NOT EXISTS ix_${t}_size ON ${t} (size)`).run(),e.prepare(`CREATE TRIGGER IF NOT EXISTS tr_${t}_updatedAt AFTER UPDATE ON ${t} BEGIN UPDATE ${t} SET updatedAt = CURRENT_TIMESTAMP WHERE key = NEW.key; END`).run()),this.preAdd=e.prepare("INSERT INTO "+t+" (_id, filename, isText, mime, content) VALUES (@_id, @filename, @isText, @mime, @content))"),this.preUpdate=e.prepare("UPDATE "+t+" SET _id = @_id, content = @content WHERE _id=@_id"),this.preExists=e.prepare("SELECT 1 FROM "+t+" WHERE _id = ?").pluck(),this.preGet=e.prepare("SELECT filename, content FROM "+t+" WHERE _id = ?").pluck(),this.preDel=e.prepare("DELETE FROM "+t+" WHERE _id = ?"),this.preDelAll=e.prepare("DELETE FROM "+t+" WHERE _id like ?"),this.preCount=e.prepare("SELECT Count(*) as count FROM "+t).pluck(),this.preCountW=e.prepare("SELECT Count(*) as count FROM "+t+" WHERE _id LIKE ?").pluck(),this.preSearchKey=e.prepare("SELECT _id, filename, isText, mime, size, createdAt, updatedAt FROM "+t+" WHERE _id LIKE @query LIMIT @size OFFSET @offset"),this.preSearchKeyAll=e.prepare("SELECT _id, filename, isText, mime, size, createdAt, updatedAt FROM "+t+" WHERE _id LIKE @query"),this.preAll=e.prepare("SELECT _id, filename, isText, mime, size, createdAt, updatedAt FROM "+t),this.preAllLimit=e.prepare("SELECT _id, filename, isText, mime, size, createdAt, updatedAt FROM "+t+" LIMIT @size OFFSET @offset"),this.preCalcSize=e.prepare("SELECT length(content) FROM "+t+" WHERE _id = ?").pluck()}get(t,e){const s=t+"/"+e;return this.preGet.get(s)}list(t,e=""){return this.preSearchKeyAll.all({query:t+`/${e}%`})}add(t,e,s,i={}){const n=t+"/"+e;if(!i.mime){const t=F.mimeType.lookup(e);if(t&&(i.mime=t,void 0===i.isText)){const e=t.includes("text")||t.includes("xml")||t.includes("json")||t.includes("script");e&&(i.isText=e)}}return this.preAdd.run({...i,_id:n,filename:e,content:s})}update(t,e,s,i={}){const n=t+"/"+e;if(!i.mime){const t=F.mimeType.lookup(e);if(t&&(i.mime=t,void 0===i.isText)){const e=t.includes("text")||t.includes("xml")||t.includes("json")||t.includes("script");e&&(i.isText=e)}}let r=["_id = @_id","content = @content",`filename = '${e}'`];void 0!==i.isText&&r.push("isText = "+(i.isText?"true":"false")),i.mime&&r.push(`mime = '${i.mime}'`);let o="UPDATE "+this.name+" SET "+r.join(", ")+"WHERE _id = @_id";return this.db.prepare(o).run({_id:n,content:s})}del(t,e){return String(t).endsWith("/")||(t+="/"),e?Array.isArray(e)?this.db.transaction((()=>e.map((e=>this.preDel.run(t+e)))))():this.preDel.run(t+e):this.preDelAll.run(t+"%")}};function ot(t){return('"'===t[0]||"'"===t[0])&&t[t.length-1]===t[0]}function Et(t,e){return e&&(e.startsWith(".")||(e="."+e),t=L.default.join(""+t,e)),t}