diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h --- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h @@ -80,6 +80,11 @@ virtual void setMetadata(std::string entry_name, std::string data) const = 0; virtual void clearMetadata(std::string entry_name) const = 0; virtual std::string getMetadata(std::string entry_name) const = 0; + +#ifdef EMSCRIPTEN + virtual std::vector getAllThreadsWeb() const = 0; + virtual void replaceThreadWeb(const WebThread &thread) const = 0; +#endif }; } // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h @@ -85,7 +85,10 @@ void clearMetadata(std::string entry_name) const override; std::string getMetadata(std::string entry_name) const override; -#ifndef EMSCRIPTEN +#ifdef EMSCRIPTEN + std::vector getAllThreadsWeb() const override; + void replaceThreadWeb(const WebThread &thread) const override; +#else static void clearSensitiveData(); static void initialize(std::string &databasePath); #endif diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -1356,7 +1356,21 @@ return (entry == nullptr) ? "" : entry->data; } -#ifndef EMSCRIPTEN +#ifdef EMSCRIPTEN +std::vector SQLiteQueryExecutor::getAllThreadsWeb() const { + auto threads = SQLiteQueryExecutor::getStorage().get_all(); + std::vector webThreads; + webThreads.reserve(threads.size()); + for (const auto &thread : threads) { + webThreads.emplace_back(thread); + } + return webThreads; +}; + +void SQLiteQueryExecutor::replaceThreadWeb(const WebThread &thread) const { + SQLiteQueryExecutor::getStorage().replace(thread.toThread()); +}; +#else void SQLiteQueryExecutor::clearSensitiveData() { if (file_exists(SQLiteQueryExecutor::sqliteFilePath) && std::remove(SQLiteQueryExecutor::sqliteFilePath.c_str())) { diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/Thread.h b/native/cpp/CommonCpp/DatabaseManagers/entities/Thread.h --- a/native/cpp/CommonCpp/DatabaseManagers/entities/Thread.h +++ b/native/cpp/CommonCpp/DatabaseManagers/entities/Thread.h @@ -3,6 +3,8 @@ #include #include +#include "Nullable.h" + namespace comm { struct Thread { @@ -24,4 +26,65 @@ int pinned_count; }; +struct WebThread { + std::string id; + int type; + NullableString name; + NullableString description; + std::string color; + std::string creation_time; + NullableString parent_thread_id; + NullableString containing_thread_id; + NullableString community; + std::string members; + std::string roles; + std::string current_user; + NullableString source_message_id; + int replies_count; + NullableString avatar; + int pinned_count; + + WebThread() = default; + + WebThread(const Thread &thread) { + id = thread.id; + type = thread.type; + name = NullableString(thread.name); + description = NullableString(thread.description); + color = thread.color; + creation_time = std::to_string(thread.creation_time); + parent_thread_id = NullableString(thread.parent_thread_id); + containing_thread_id = NullableString(thread.containing_thread_id); + community = NullableString(thread.community); + members = thread.members; + roles = thread.roles; + current_user = thread.current_user; + source_message_id = NullableString(thread.source_message_id); + replies_count = thread.replies_count; + avatar = NullableString(thread.avatar); + pinned_count = thread.pinned_count; + } + + Thread toThread() const { + Thread thread; + thread.id = id; + thread.type = type; + thread.name = name.resetValue(); + thread.description = description.resetValue(); + thread.color = color; + thread.creation_time = std::stoll(creation_time); + thread.parent_thread_id = parent_thread_id.resetValue(); + thread.containing_thread_id = containing_thread_id.resetValue(); + thread.community = community.resetValue(); + thread.members = members; + thread.roles = roles; + thread.current_user = current_user; + thread.source_message_id = source_message_id.resetValue(); + thread.replies_count = replies_count; + thread.avatar = avatar.resetValue(); + thread.pinned_count = pinned_count; + return thread; + } +}; + } // namespace comm diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp --- a/web/cpp/SQLiteQueryExecutorBindings.cpp +++ b/web/cpp/SQLiteQueryExecutorBindings.cpp @@ -26,6 +26,24 @@ .field("id", &UserInfo::id) .field("userInfo", &UserInfo::user_info); + value_object("WebThread") + .field("id", &WebThread::id) + .field("type", &WebThread::type) + .field("name", &WebThread::name) + .field("description", &WebThread::description) + .field("color", &WebThread::color) + .field("creationTime", &WebThread::creation_time) + .field("parentThreadID", &WebThread::parent_thread_id) + .field("containingThreadID", &WebThread::containing_thread_id) + .field("community", &WebThread::community) + .field("members", &WebThread::members) + .field("roles", &WebThread::roles) + .field("currentUser", &WebThread::current_user) + .field("sourceMessageID", &WebThread::source_message_id) + .field("repliesCount", &WebThread::replies_count) + .field("avatar", &WebThread::avatar) + .field("pinnedCount", &WebThread::pinned_count); + class_("SQLiteQueryExecutor") .constructor() .function("updateDraft", &SQLiteQueryExecutor::updateDraft) @@ -49,7 +67,11 @@ .function("replaceUser", &SQLiteQueryExecutor::replaceUser) .function("removeUsers", &SQLiteQueryExecutor::removeUsers) .function("removeAllUsers", &SQLiteQueryExecutor::removeAllUsers) - .function("getAllUsers", &SQLiteQueryExecutor::getAllUsers); + .function("getAllUsers", &SQLiteQueryExecutor::getAllUsers) + .function("replaceThreadWeb", &SQLiteQueryExecutor::replaceThreadWeb) + .function("getAllThreadsWeb", &SQLiteQueryExecutor::getAllThreadsWeb) + .function("removeAllThreads", &SQLiteQueryExecutor::removeAllThreads) + .function("removeThreads", &SQLiteQueryExecutor::removeThreads); } } // namespace comm diff --git a/web/database/_generated/comm-query-executor.js b/web/database/_generated/comm-query-executor.js --- a/web/database/_generated/comm-query-executor.js +++ b/web/database/_generated/comm-query-executor.js @@ -129,17 +129,17 @@ bd:Ga};Ub(l,t);return[w,B,Ga]})},fa:function(a,b,c,d,f,g,k){var h=bc(c,d);b=S(b);g=W(f,g);Q([],[a],function(n){function q(){Zb("Cannot call "+p+" due to unbound types",h)}n=n[0];var p=n.name+"."+b;b.startsWith("@@")&&(b=Symbol[b.substring(2)]);var r=n.Na.constructor;void 0===r[b]?(q.ub=c-1,r[b]=q):(Lb(r,b,p),r[b].Ua[c-1]=q);Q([],h,function(v){v=[v[0],null].concat(v.slice(1));v=ac(p,v,null,g,k);void 0===r[b].Ua?(v.ub=c-1,r[b]=v):r[b].Ua[c-1]=v;return[]});return[]})},o:function(a,b,c,d,f,g){0{Zb("Cannot construct "+h.name+" due to unbound types",k)};Q([],k,function(q){q.splice(1,0,null);h.Na.nb[b-1]=ac(n,q,null,f,g); return[]});return[]})},d:function(a,b,c,d,f,g,k,h){var n=bc(c,d);b=S(b);g=W(f,g);Q([],[a],function(q){function p(){Zb("Cannot call "+r+" due to unbound types",n)}q=q[0];var r=q.name+"."+b;b.startsWith("@@")&&(b=Symbol[b.substring(2)]);h&&q.Na.Hd.push(b);var v=q.Na.xb,l=v[b];void 0===l||void 0===l.Ua&&l.className!==q.name&&l.ub===c-2?(p.ub=c-2,p.className=q.name,v[b]=p):(Lb(v,b,r),v[b].Ua[c-2]=p);Q([],n,function(t){t=ac(r,t,q,g,k);void 0===v[b].Ua?(t.ub=c-2,v[b]=t):v[b].Ua[c-2]=t;return[]});return[]})}, -ca:function(a,b){b=S(b);R(a,{name:b,fromWireType:function(c){var d=ec(c);dc(c);return d},toWireType:function(c,d){return Sb(d)},argPackAdvance:8,readValueFromPointer:mb,ab:null})},x:function(a,b,c){c=vb(c);b=S(b);R(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,f){return f},argPackAdvance:8,readValueFromPointer:fc(b,c),ab:null})},f:function(a,b,c,d,f){b=S(b);-1===f&&(f=4294967295);f=vb(c);var g=h=>h;if(0===d){var k=32-8*c;g=h=>h<>>k}c=b.includes("unsigned")?function(h,n){return n>>> +ca:function(a,b){b=S(b);R(a,{name:b,fromWireType:function(c){var d=ec(c);dc(c);return d},toWireType:function(c,d){return Sb(d)},argPackAdvance:8,readValueFromPointer:mb,ab:null})},x:function(a,b,c){c=vb(c);b=S(b);R(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,f){return f},argPackAdvance:8,readValueFromPointer:fc(b,c),ab:null})},g:function(a,b,c,d,f){b=S(b);-1===f&&(f=4294967295);f=vb(c);var g=h=>h;if(0===d){var k=32-8*c;g=h=>h<>>k}c=b.includes("unsigned")?function(h,n){return n>>> 0}:function(h,n){return n};R(a,{name:b,fromWireType:g,toWireType:c,argPackAdvance:8,readValueFromPointer:gc(b,f,0!==d),ab:null})},c:function(a,b,c){function d(g){g>>=2;var k=E;return new f(va,k[g+1],k[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=S(c);R(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{ud:!0})},y:function(a,b){b=S(b);var c="std::string"===b;R(a,{name:b,fromWireType:function(d){var f=E[d>>2],g=d+4;if(c)for(var k= g,h=0;h<=f;++h){var n=g+h;if(h==f||0==z[n]){k=y(k,n-k);if(void 0===q)var q=k;else q+=String.fromCharCode(0),q+=k;k=n+1}}else{q=Array(f);for(h=0;h>2]=k;if(c&& -g)ta(f,z,n,k+1);else if(g)for(g=0;gwa;var h=1}else 4===b&&(d=lc,f=mc,g=nc,k=()=>E,h=2);R(a,{name:c,fromWireType:function(n){for(var q=E[n>>2],p=k(),r,v=n+4,l=0;l<=q;++l){var t=n+4+l*b;if(l== -q||0==p[t>>h])v=d(v,t-v),void 0===r?r=v:(r+=String.fromCharCode(0),r+=v),v=t+b}X(n);return r},toWireType:function(n,q){"string"!=typeof q&&T("Cannot pass non-string to C++ string type "+c);var p=g(q),r=wc(4+p+b);E[r>>2]=p>>h;f(q,r+4,p+b);null!==n&&n.push(X,r);return r},argPackAdvance:8,readValueFromPointer:mb,ab:function(n){X(n)}})},i:function(a,b,c,d,f,g){kb[a]={name:S(b),lc:W(c,d),jb:W(f,g),Fc:[]}},g:function(a,b,c,d,f,g,k,h,n,q){kb[a].Fc.push({ld:S(b),td:c,Kb:W(d,f),sd:g,Md:k,Ld:W(h,n),Nd:q})}, +g)ta(f,z,n,k+1);else if(g)for(g=0;gwa;var h=1}else 4===b&&(d=lc,f=mc,g=nc,k=()=>E,h=2);R(a,{name:c,fromWireType:function(n){for(var q=E[n>>2],p=k(),r,v=n+4,l=0;l<=q;++l){var t=n+4+l*b;if(l== +q||0==p[t>>h])v=d(v,t-v),void 0===r?r=v:(r+=String.fromCharCode(0),r+=v),v=t+b}X(n);return r},toWireType:function(n,q){"string"!=typeof q&&T("Cannot pass non-string to C++ string type "+c);var p=g(q),r=wc(4+p+b);E[r>>2]=p>>h;f(q,r+4,p+b);null!==n&&n.push(X,r);return r},argPackAdvance:8,readValueFromPointer:mb,ab:function(n){X(n)}})},i:function(a,b,c,d,f,g){kb[a]={name:S(b),lc:W(c,d),jb:W(f,g),Fc:[]}},f:function(a,b,c,d,f,g,k,h,n,q){kb[a].Fc.push({ld:S(b),td:c,Kb:W(d,f),sd:g,Md:k,Ld:W(h,n),Nd:q})}, ea:function(a,b){b=S(b);R(a,{xd:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},w:function(){return Date.now()},z:function(a,b,c){a=ec(a);b=oc(b,"emval::as");var d=[],f=Sb(d);E[c>>2]=f;return b.toWireType(d,a)},ka:function(a,b,c,d){a=rc[a];b=ec(b);c=qc(c);a(b,c,null,d)},ia:dc,ja:function(a,b){var c=tc(a,b),d=c[0];b=d.name+"_$"+c.slice(1).map(function(p){return p.name}).join("_")+"$";var f=uc[b];if(void 0!==f)return f;f=["retType"];for(var g=[d],k="",h=0;h>2]=a.getSeconds();D[b+4>>2]=a.getMinutes();D[b+8>>2]=a.getHours();D[b+12>>2]=a.getDate();D[b+16>>2]=a.getMonth();D[b+20>>2]=a.getFullYear()-1900;D[b+24>>2]=a.getDay(); +g);f=sc(a);return uc[b]=f},A:function(a,b){a=ec(a);b=ec(b);return Sb(a[b])},B:function(a){4>2]=a.getSeconds();D[b+4>>2]=a.getMinutes();D[b+8>>2]=a.getHours();D[b+12>>2]=a.getDate();D[b+16>>2]=a.getMonth();D[b+20>>2]=a.getFullYear()-1900;D[b+24>>2]=a.getDay(); var c=new Date(a.getFullYear(),0,1);D[b+28>>2]=(a.getTime()-c.getTime())/864E5|0;D[b+36>>2]=-(60*a.getTimezoneOffset());var d=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();D[b+32>>2]=(d!=c&&a.getTimezoneOffset()==Math.min(c,d))|0},N:function(a,b,c,d,f,g){try{var k=M.lb(d);if(!k)return-8;var h=M.qb(k,a,f,b,c),n=h.La;D[g>>2]=h.tc;return n}catch(q){if("undefined"==typeof M||!(q instanceof M.Ga))throw q;return-q.Ma}},O:function(a,b,c,d,f,g){try{var k=M.lb(f);if(k&&c&2){var h= -z.slice(a,a+b);M.zb(k,h,g,b,d)}}catch(n){if("undefined"==typeof M||!(n instanceof M.Ga))throw n;return-n.Ma}},aa:yc,k:function(){x("")},K:function(){return 2147483648},v:zc,l:function(a){var b=z.length;a>>>=0;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);var f=Math;d=Math.max(a,d);f=f.min.call(f,2147483648,d+(65536-d%65536)%65536);a:{try{pa.grow(f-va.byteLength+65535>>>16);za();var g=1;break a}catch(k){}g=void 0}if(g)return!0}return!1},Q:function(a,b){var c= -0;Bc().forEach(function(d,f){var g=b+c;f=E[a+4*f>>2]=g;for(g=0;g>0]=d.charCodeAt(g);A[f>>0]=0;c+=d.length+1});return 0},R:function(a,b){var c=Bc();E[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+1});E[b>>2]=d;return 0},j:function(a){try{var b=P(a);M.close(b);return 0}catch(c){if("undefined"==typeof M||!(c instanceof M.Ga))throw c;return c.Ma}},I:function(a,b){try{var c=P(a);A[b>>0]=c.tty?2:M.Sa(c.mode)?3:M.yb(c.mode)?7:4;return 0}catch(d){if("undefined"==typeof M||!(d instanceof +z.slice(a,a+b);M.zb(k,h,g,b,d)}}catch(n){if("undefined"==typeof M||!(n instanceof M.Ga))throw n;return-n.Ma}},aa:yc,j:function(){x("")},K:function(){return 2147483648},v:zc,m:function(a){var b=z.length;a>>>=0;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);var f=Math;d=Math.max(a,d);f=f.min.call(f,2147483648,d+(65536-d%65536)%65536);a:{try{pa.grow(f-va.byteLength+65535>>>16);za();var g=1;break a}catch(k){}g=void 0}if(g)return!0}return!1},Q:function(a,b){var c= +0;Bc().forEach(function(d,f){var g=b+c;f=E[a+4*f>>2]=g;for(g=0;g>0]=d.charCodeAt(g);A[f>>0]=0;c+=d.length+1});return 0},R:function(a,b){var c=Bc();E[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+1});E[b>>2]=d;return 0},k:function(a){try{var b=P(a);M.close(b);return 0}catch(c){if("undefined"==typeof M||!(c instanceof M.Ga))throw c;return c.Ma}},I:function(a,b){try{var c=P(a);A[b>>0]=c.tty?2:M.Sa(c.mode)?3:M.yb(c.mode)?7:4;return 0}catch(d){if("undefined"==typeof M||!(d instanceof M.Ga))throw d;return d.Ma}},t:function(a,b,c,d){try{a:{var f=P(a);a=b;for(var g=b=0;g>2],h=E[a+4>>2];a+=8;var n=M.read(f,A,k,h,void 0);if(0>n){var q=-1;break a}b+=n;if(n>2]=q;return 0}catch(p){if("undefined"==typeof M||!(p instanceof M.Ga))throw p;return p.Ma}},C:function(a,b,c,d,f){try{b=c+2097152>>>0<4194305-!!b?(b>>>0)+4294967296*c:NaN;if(isNaN(b))return 61;var g=P(a);M.cb(g,b,d);G=[g.position>>>0,(F=g.position,1<=+Math.abs(F)?0>>0:~~+Math.ceil((F-+(~~F>>>0))/4294967296)>>>0:0)];D[f>>2]=G[0];D[f+4>>2]=G[1];g.ac&&0===b&&0===d&&(g.ac=null);return 0}catch(k){if("undefined"==typeof M||!(k instanceof M.Ga))throw k;return k.Ma}},T:function(a){try{var b=P(a);return b.Ka&&b.Ka.fsync?-b.Ka.fsync(b):0}catch(c){if("undefined"==typeof M||!(c instanceof M.Ga))throw c;return c.Ma}},p:function(a,b,c,d){try{a:{var f=P(a);a=b;for(var g=b=0;g>2],h=E[a+4>>2];a+=8;var n=M.write(f,A,k,h,void 0);if(0>n){var q= -1;break a}b+=n}q=b}E[d>>2]=q;return 0}catch(p){if("undefined"==typeof M||!(p instanceof M.Ga))throw p;return p.Ma}},F:function(){},G:function(a,b,c,d){return Gc(a,b,c,d)}},Z=function(){function a(c){e.asm=c.exports;pa=e.asm.ma;za();Aa=e.asm.ra;Ca.unshift(e.asm.na);Ka("wasm-instantiate")}var b={a:Lc};Ja("wasm-instantiate");if(e.instantiateWasm)try{return e.instantiateWasm(b,a)}catch(c){return u("Module.instantiateWasm callback failed with error: "+c),!1}b=Na(b);a(b[0]);return e.asm}(); diff --git a/web/database/_generated/comm_query_executor.wasm b/web/database/_generated/comm_query_executor.wasm index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ = { +value: T, +isNull: boolean, @@ -8,3 +10,93 @@ export type NullableString = Nullable; export type NullableInt = Nullable; + +export type WebClientDBThreadInfo = { + +id: string, + +type: number, + +name: NullableString, + +avatar: NullableString, + +description: NullableString, + +color: string, + +creationTime: string, + +parentThreadID: NullableString, + +containingThreadID: NullableString, + +community: NullableString, + +members: string, + +roles: string, + +currentUser: string, + +sourceMessageID: NullableString, + +repliesCount: number, + +pinnedCount: number, +}; + +function createNullableString(value: ?string): NullableString { + if (value === null || value === undefined) { + return { + value: '', + isNull: true, + }; + } + return { + value, + isNull: false, + }; +} + +function clientDBThreadInfoToWebThread( + info: ClientDBThreadInfo, +): WebClientDBThreadInfo { + return { + id: info.id, + type: info.type, + name: createNullableString(info.name), + avatar: createNullableString(info.avatar), + description: createNullableString(info.description), + color: info.color, + creationTime: info.creationTime, + parentThreadID: createNullableString(info.parentThreadID), + containingThreadID: createNullableString(info.containingThreadID), + community: createNullableString(info.community), + members: info.members, + roles: info.roles, + currentUser: info.currentUser, + sourceMessageID: createNullableString(info.sourceMessageID), + repliesCount: info.repliesCount, + pinnedCount: info.pinnedCount || 0, + }; +} + +function webThreadToClientDBThreadInfo( + thread: WebClientDBThreadInfo, +): ClientDBThreadInfo { + let result: ClientDBThreadInfo = { + id: thread.id, + type: thread.type, + name: thread.name.isNull ? null : thread.name.value, + avatar: thread.avatar.isNull ? null : thread.avatar.value, + description: thread.description.isNull ? null : thread.description.value, + color: thread.color, + creationTime: thread.creationTime, + parentThreadID: thread.parentThreadID.isNull + ? null + : thread.parentThreadID.value, + containingThreadID: thread.containingThreadID.isNull + ? null + : thread.containingThreadID.value, + community: thread.community.isNull ? null : thread.community.value, + members: thread.members, + roles: thread.roles, + currentUser: thread.currentUser, + repliesCount: thread.repliesCount, + pinnedCount: thread.pinnedCount, + }; + if (!thread.sourceMessageID.isNull) { + result = { + ...result, + sourceMessageID: thread.sourceMessageID.value, + }; + } + return result; +} + +export { clientDBThreadInfoToWebThread, webThreadToClientDBThreadInfo }; diff --git a/web/database/types/entities.test.js b/web/database/types/entities.test.js new file mode 100644 --- /dev/null +++ b/web/database/types/entities.test.js @@ -0,0 +1,64 @@ +// @flow + +import type { ClientDBThreadInfo } from 'lib/types/thread-types.js'; + +import { + clientDBThreadInfoToWebThread, + webThreadToClientDBThreadInfo, +} from './entities.js'; + +const clientDBThreadInfo: ClientDBThreadInfo = { + id: '84015', + type: 6, + name: 'atul_web', + description: 'Hello world!', + color: '4b87aa', + creationTime: '1679595843051', + parentThreadID: '1', + members: + '[{"id":"256","role":null,"permissions":{"know_of":{"value":true,"source":"1"},"visible":{"value":true,"source":"1"},"voiced":{"value":true,"source":"1"},"edit_entries":{"value":true,"source":"1"},"edit_thread":{"value":true,"source":"1"},"edit_thread_description":{"value":true,"source":"1"},"edit_thread_color":{"value":true,"source":"1"},"delete_thread":{"value":true,"source":"1"},"create_subthreads":{"value":true,"source":"1"},"create_sidebars":{"value":true,"source":"1"},"join_thread":{"value":true,"source":"1"},"edit_permissions":{"value":true,"source":"1"},"add_members":{"value":true,"source":"1"},"remove_members":{"value":true,"source":"1"},"change_role":{"value":true,"source":"1"},"leave_thread":{"value":false,"source":null},"react_to_message":{"value":false,"source":null},"edit_message":{"value":false,"source":null}},"isSender":false},{"id":"83809","role":"84016","permissions":{"know_of":{"value":true,"source":"84015"},"visible":{"value":true,"source":"84015"},"voiced":{"value":true,"source":"84015"},"edit_entries":{"value":true,"source":"84015"},"edit_thread":{"value":true,"source":"84015"},"edit_thread_description":{"value":true,"source":"84015"},"edit_thread_color":{"value":true,"source":"84015"},"delete_thread":{"value":false,"source":null},"create_subthreads":{"value":false,"source":null},"create_sidebars":{"value":true,"source":"84015"},"join_thread":{"value":false,"source":null},"edit_permissions":{"value":false,"source":null},"add_members":{"value":false,"source":null},"remove_members":{"value":false,"source":null},"change_role":{"value":false,"source":null},"leave_thread":{"value":false,"source":null},"react_to_message":{"value":true,"source":"84015"},"edit_message":{"value":true,"source":"84015"}},"isSender":true},{"id":"83969","role":"84016","permissions":{"know_of":{"value":true,"source":"84015"},"visible":{"value":true,"source":"84015"},"voiced":{"value":true,"source":"84015"},"edit_entries":{"value":true,"source":"84015"},"edit_thread":{"value":true,"source":"84015"},"edit_thread_description":{"value":true,"source":"84015"},"edit_thread_color":{"value":true,"source":"84015"},"delete_thread":{"value":false,"source":null},"create_subthreads":{"value":false,"source":null},"create_sidebars":{"value":true,"source":"84015"},"join_thread":{"value":false,"source":null},"edit_permissions":{"value":false,"source":null},"add_members":{"value":false,"source":null},"remove_members":{"value":false,"source":null},"change_role":{"value":false,"source":null},"leave_thread":{"value":false,"source":null},"react_to_message":{"value":true,"source":"84015"},"edit_message":{"value":true,"source":"84015"}},"isSender":true}]', + roles: + '{"84016":{"id":"84016","name":"Members","permissions":{"know_of":true,"visible":true,"voiced":true,"react_to_message":true,"edit_message":true,"edit_entries":true,"edit_thread":true,"edit_thread_color":true,"edit_thread_description":true,"create_sidebars":true,"descendant_open_know_of":true,"descendant_open_visible":true,"child_open_join_thread":true},"isDefault":true}}', + currentUser: + '{"role":"84016","permissions":{"know_of":{"value":true,"source":"84015"},"visible":{"value":true,"source":"84015"},"voiced":{"value":true,"source":"84015"},"edit_entries":{"value":true,"source":"84015"},"edit_thread":{"value":true,"source":"84015"},"edit_thread_description":{"value":true,"source":"84015"},"edit_thread_color":{"value":true,"source":"84015"},"delete_thread":{"value":false,"source":null},"create_subthreads":{"value":false,"source":null},"create_sidebars":{"value":true,"source":"84015"},"join_thread":{"value":false,"source":null},"edit_permissions":{"value":false,"source":null},"add_members":{"value":false,"source":null},"remove_members":{"value":false,"source":null},"change_role":{"value":false,"source":null},"leave_thread":{"value":false,"source":null},"react_to_message":{"value":true,"source":"84015"},"edit_message":{"value":true,"source":"84015"}},"subscription":{"home":true,"pushNotifs":true},"unread":false}', + repliesCount: 0, + containingThreadID: '1', + community: '1', + avatar: null, + pinnedCount: 0, +}; + +const clientDBThreadInfoWithAvatar: ClientDBThreadInfo = { + ...clientDBThreadInfo, + avatar: '{"type":"emoji","color":"4b87aa","emoji":"😀"}', +}; + +const clientDBThreadInfoWithSourceMessageID: ClientDBThreadInfo = { + ...clientDBThreadInfo, + sourceMessageID: '123', +}; + +describe('ClientDBThreadInfo <> WebClientDBThreadInfo', () => { + it('should successfully convert clientDBThreadInfo', () => { + const webThread = clientDBThreadInfoToWebThread(clientDBThreadInfo); + expect(clientDBThreadInfo).toStrictEqual( + webThreadToClientDBThreadInfo(webThread), + ); + }); + it('should successfully convert clientDBThreadInfo with nullable field (field: ?type)', () => { + const webThread = clientDBThreadInfoToWebThread( + clientDBThreadInfoWithAvatar, + ); + expect(clientDBThreadInfoWithAvatar).toStrictEqual( + webThreadToClientDBThreadInfo(webThread), + ); + }); + it('should successfully convert clientDBThreadInfo with not existing field (field?: type)', () => { + const webThread = clientDBThreadInfoToWebThread( + clientDBThreadInfoWithSourceMessageID, + ); + expect(clientDBThreadInfoWithSourceMessageID).toStrictEqual( + webThreadToClientDBThreadInfo(webThread), + ); + }); +}); diff --git a/web/database/types/sqlite-query-executor.js b/web/database/types/sqlite-query-executor.js --- a/web/database/types/sqlite-query-executor.js +++ b/web/database/types/sqlite-query-executor.js @@ -4,6 +4,8 @@ import type { ClientDBUserInfo } from 'lib/ops/user-store-ops.js'; import type { ClientDBDraftInfo } from 'lib/types/draft-types.js'; +import { type WebClientDBThreadInfo } from './entities.js'; + declare export class SQLiteQueryExecutor { constructor(sqliteFilePath: string): void; @@ -30,6 +32,11 @@ removeAllUsers(): void; getAllUsers(): ClientDBUserInfo[]; + replaceThreadWeb(thread: WebClientDBThreadInfo): void; + removeThreads(ids: $ReadOnlyArray): void; + removeAllThreads(): void; + getAllThreadsWeb(): WebClientDBThreadInfo[]; + // method is provided to manually signal that a C++ object // is no longer needed and can be deleted delete(): void;