diff --git a/public/dist/scripts/app-all.js b/public/dist/scripts/app-all.js index adb894c8e2..3a3323682f 100644 --- a/public/dist/scripts/app-all.js +++ b/public/dist/scripts/app-all.js @@ -5,13 +5,14 @@ function rejected(value){try{step(generator["throw"](value));}catch(e){reject(e) function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected);} step((generator=generator.apply(thisArg,_arguments||[])).next());});} class AppwriteException extends Error{constructor(message,code=0,response=''){super(message);this.name='AppwriteException';this.message=message;this.code=code;this.response=response;}} -class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',endpointRealtime:'',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:4.0.1','X-Appwrite-Response-Format':'0.10.0',};this.realtime={socket:undefined,timeout:undefined,channels:{},lastMessage:undefined,createSocket:()=>{var _a,_b;const channels=new URLSearchParams();channels.set('project',this.config.project);for(const property in this.realtime.channels){channels.append('channels[]',property);} -if(((_a=this.realtime.socket)===null||_a===void 0?void 0:_a.readyState)===WebSocket.OPEN){this.realtime.socket.close();} -this.realtime.socket=new WebSocket(this.config.endpointRealtime+'/realtime?'+channels.toString());(_b=this.realtime.socket)===null||_b===void 0?void 0:_b.addEventListener('message',this.realtime.authenticate);for(const channel in this.realtime.channels){this.realtime.channels[channel].forEach(callback=>{var _a;(_a=this.realtime.socket)===null||_a===void 0?void 0:_a.addEventListener('message',callback);});} -this.realtime.socket.addEventListener('close',event=>{var _a,_b,_c;if(((_b=(_a=this.realtime)===null||_a===void 0?void 0:_a.lastMessage)===null||_b===void 0?void 0:_b.type)==='error'&&((_c=this.realtime)===null||_c===void 0?void 0:_c.lastMessage.data).code===1008){return;} -console.error('Realtime got disconnected. Reconnect will be attempted in 1 second.',event.reason);setTimeout(()=>{this.realtime.createSocket();},1000);});},authenticate:(event)=>{var _a,_b,_c;const message=JSON.parse(event.data);if(message.type==='connected'&&((_a=this.realtime.socket)===null||_a===void 0?void 0:_a.readyState)===WebSocket.OPEN){const cookie=JSON.parse((_b=window.localStorage.getItem('cookieFallback'))!==null&&_b!==void 0?_b:"{}");const session=cookie===null||cookie===void 0?void 0:cookie[`a_session_${this.config.project}`];const data=message.data;if(session&&!data.user){(_c=this.realtime.socket)===null||_c===void 0?void 0:_c.send(JSON.stringify({type:"authentication",data:{session}}));}}},onMessage:(channel,callback)=>(event)=>{try{const message=JSON.parse(event.data);this.realtime.lastMessage=message;if(message.type==='event'){let data=message.data;if(data.channels&&data.channels.includes(channel)){callback(data);}} -else if(message.type==='error'){throw message.data;}} -catch(e){console.error(e);}}};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');} +class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',endpointRealtime:'',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:4.0.1','X-Appwrite-Response-Format':'0.10.0',};this.realtime={socket:undefined,timeout:undefined,url:'',channels:new Set(),subscriptions:new Map(),subscriptionsCounter:0,reconnect:true,reconnectAttempts:0,lastMessage:undefined,connect:()=>{clearTimeout(this.realtime.timeout);this.realtime.timeout=window===null||window===void 0?void 0:window.setTimeout(()=>{this.realtime.createSocket();},50);},getTimeout:()=>{switch(true){case this.realtime.reconnectAttempts<5:return 1000;case this.realtime.reconnectAttempts<15:return 5000;case this.realtime.reconnectAttempts<100:return 10000;default:return 60000;}},createSocket:()=>{var _a,_b;if(this.realtime.channels.size<1) +return;const channels=new URLSearchParams();channels.set('project',this.config.project);this.realtime.channels.forEach(channel=>{channels.append('channels[]',channel);});const url=this.config.endpointRealtime+'/realtime?'+channels.toString();if(url!==this.realtime.url||!this.realtime.socket||((_a=this.realtime.socket)===null||_a===void 0?void 0:_a.readyState)>WebSocket.OPEN){if(this.realtime.socket&&((_b=this.realtime.socket)===null||_b===void 0?void 0:_b.readyState){this.realtime.reconnectAttempts=0;});this.realtime.socket.addEventListener('close',event=>{var _a,_b,_c;if(!this.realtime.reconnect||(((_b=(_a=this.realtime)===null||_a===void 0?void 0:_a.lastMessage)===null||_b===void 0?void 0:_b.type)==='error'&&((_c=this.realtime)===null||_c===void 0?void 0:_c.lastMessage.data).code===1008)){this.realtime.reconnect=true;return;} +const timeout=this.realtime.getTimeout();console.error(`Realtime got disconnected. Reconnect will be attempted in ${timeout / 1000} seconds.`,event.reason);setTimeout(()=>{this.realtime.reconnectAttempts++;this.realtime.createSocket();},timeout);});}},onMessage:(event)=>{var _a,_b;try{const message=JSON.parse(event.data);this.realtime.lastMessage=message;switch(message.type){case'connected':const cookie=JSON.parse((_a=window.localStorage.getItem('cookieFallback'))!==null&&_a!==void 0?_a:'{}');const session=cookie===null||cookie===void 0?void 0:cookie[`a_session_${this.config.project}`];const messageData=message.data;if(session&&!messageData.user){(_b=this.realtime.socket)===null||_b===void 0?void 0:_b.send(JSON.stringify({type:'authentication',data:{session}}));} +break;case'event':let data=message.data;if(data===null||data===void 0?void 0:data.channels){const isSubscribed=data.channels.some(channel=>this.realtime.channels.has(channel));if(!isSubscribed) +return;this.realtime.subscriptions.forEach(subscription=>{if(data.channels.some(channel=>subscription.channels.includes(channel))){setTimeout(()=>subscription.callback(data));}});} +break;case'error':throw message.data;default:break;}} +catch(e){console.error(e);}},cleanUp:channels=>{this.realtime.channels.forEach(channel=>{if(channels.includes(channel)){let found=Array.from(this.realtime.subscriptions).some(([_key,subscription])=>{return subscription.channels.includes(channel);});if(!found){this.realtime.channels.delete(channel);}}});}};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');} if(typeof password==='undefined'){throw new AppwriteException('Missing required parameter: "password"');} let path='/account';let payload={};if(typeof email!=='undefined'){payload['email']=email;} if(typeof password!=='undefined'){payload['password']=password;} @@ -462,20 +463,20 @@ const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri, if(typeof emailVerification==='undefined'){throw new AppwriteException('Missing required parameter: "emailVerification"');} let path='/users/{userId}/verification'.replace('{userId}',userId);let payload={};if(typeof emailVerification!=='undefined'){payload['emailVerification']=emailVerification;} const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);})};} -setEndpoint(endpoint){this.config.endpoint=endpoint;this.config.endpointRealtime=this.config.endpointRealtime||this.config.endpoint.replace("https://","wss://").replace("http://","ws://");return this;} +setEndpoint(endpoint){this.config.endpoint=endpoint;this.config.endpointRealtime=this.config.endpointRealtime||this.config.endpoint.replace('https://','wss://').replace('http://','ws://');return this;} setEndpointRealtime(endpointRealtime){this.config.endpointRealtime=endpointRealtime;return this;} setProject(value){this.headers['X-Appwrite-Project']=value;this.config.project=value;return this;} setKey(value){this.headers['X-Appwrite-Key']=value;this.config.key=value;return this;} setJWT(value){this.headers['X-Appwrite-JWT']=value;this.config.jwt=value;return this;} setLocale(value){this.headers['X-Appwrite-Locale']=value;this.config.locale=value;return this;} setMode(value){this.headers['X-Appwrite-Mode']=value;this.config.mode=value;return this;} -subscribe(channels,callback){let channelArray=typeof channels==='string'?[channels]:channels;let savedChannels=[];channelArray.forEach((channel,index)=>{if(!(channel in this.realtime.channels)){this.realtime.channels[channel]=[];} -savedChannels[index]={name:channel,index:(this.realtime.channels[channel].push(this.realtime.onMessage(channel,callback))-1)};clearTimeout(this.realtime.timeout);this.realtime.timeout=window===null||window===void 0?void 0:window.setTimeout(()=>{this.realtime.createSocket();},1);});return()=>{savedChannels.forEach(channel=>{var _a;(_a=this.realtime.socket)===null||_a===void 0?void 0:_a.removeEventListener('message',this.realtime.channels[channel.name][channel.index]);this.realtime.channels[channel.name].splice(channel.index,1);});};} -call(method,url,headers={},params={}){var _a,_b;return __awaiter(this,void 0,void 0,function*(){method=method.toUpperCase();headers=Object.assign(Object.assign({},headers),this.headers);let options={method,headers,credentials:'include'};if(typeof window!=='undefined'&&window.localStorage){headers['X-Fallback-Cookies']=(_a=window.localStorage.getItem('cookieFallback'))!==null&&_a!==void 0?_a:"";} +subscribe(channels,callback){let channelArray=typeof channels==='string'?[channels]:channels;channelArray.forEach(channel=>this.realtime.channels.add(channel));const counter=this.realtime.subscriptionsCounter++;this.realtime.subscriptions.set(counter,{channels:channelArray,callback});this.realtime.connect();return()=>{this.realtime.subscriptions.delete(counter);this.realtime.cleanUp(channelArray);this.realtime.connect();};} +call(method,url,headers={},params={}){var _a,_b;return __awaiter(this,void 0,void 0,function*(){method=method.toUpperCase();headers=Object.assign(Object.assign({},headers),this.headers);let options={method,headers,credentials:'include'};if(typeof window!=='undefined'&&window.localStorage){headers['X-Fallback-Cookies']=(_a=window.localStorage.getItem('cookieFallback'))!==null&&_a!==void 0?_a:'';} if(method==='GET'){for(const[key,value]of Object.entries(this.flatten(params))){url.searchParams.append(key,value);}} -else{switch(headers['content-type']){case'application/json':options.body=JSON.stringify(params);break;case'multipart/form-data':let formData=new FormData();for(const key in params){if(Array.isArray(params[key])){params[key].forEach((value)=>{formData.append(key+'[]',value);})}else{formData.append(key,params[key]);}} +else{switch(headers['content-type']){case'application/json':options.body=JSON.stringify(params);break;case'multipart/form-data':let formData=new FormData();for(const key in params){if(Array.isArray(params[key])){params[key].forEach((value)=>{formData.append(key+'[]',value);});} +else{formData.append(key,params[key]);}} options.body=formData;delete headers['content-type'];break;}} -try{let data=null;const response=yield crossFetch.fetch(url.toString(),options);if((_b=response.headers.get("content-type"))===null||_b===void 0?void 0:_b.includes("application/json")){data=yield response.json();} +try{let data=null;const response=yield crossFetch.fetch(url.toString(),options);if((_b=response.headers.get('content-type'))===null||_b===void 0?void 0:_b.includes('application/json')){data=yield response.json();} else{data={message:yield response.text()};} if(400<=response.status){throw new AppwriteException(data===null||data===void 0?void 0:data.message,response.status,data);} const cookieFallback=response.headers.get('X-Fallback-Cookies');if(typeof window!=='undefined'&&window.localStorage&&cookieFallback){window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.');window.localStorage.setItem('cookieFallback',cookieFallback);} diff --git a/public/dist/scripts/app-dep.js b/public/dist/scripts/app-dep.js index 2f2bc8e0ad..d605f48b6c 100644 --- a/public/dist/scripts/app-dep.js +++ b/public/dist/scripts/app-dep.js @@ -5,13 +5,14 @@ function rejected(value){try{step(generator["throw"](value));}catch(e){reject(e) function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected);} step((generator=generator.apply(thisArg,_arguments||[])).next());});} class AppwriteException extends Error{constructor(message,code=0,response=''){super(message);this.name='AppwriteException';this.message=message;this.code=code;this.response=response;}} -class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',endpointRealtime:'',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:4.0.1','X-Appwrite-Response-Format':'0.10.0',};this.realtime={socket:undefined,timeout:undefined,channels:{},lastMessage:undefined,createSocket:()=>{var _a,_b;const channels=new URLSearchParams();channels.set('project',this.config.project);for(const property in this.realtime.channels){channels.append('channels[]',property);} -if(((_a=this.realtime.socket)===null||_a===void 0?void 0:_a.readyState)===WebSocket.OPEN){this.realtime.socket.close();} -this.realtime.socket=new WebSocket(this.config.endpointRealtime+'/realtime?'+channels.toString());(_b=this.realtime.socket)===null||_b===void 0?void 0:_b.addEventListener('message',this.realtime.authenticate);for(const channel in this.realtime.channels){this.realtime.channels[channel].forEach(callback=>{var _a;(_a=this.realtime.socket)===null||_a===void 0?void 0:_a.addEventListener('message',callback);});} -this.realtime.socket.addEventListener('close',event=>{var _a,_b,_c;if(((_b=(_a=this.realtime)===null||_a===void 0?void 0:_a.lastMessage)===null||_b===void 0?void 0:_b.type)==='error'&&((_c=this.realtime)===null||_c===void 0?void 0:_c.lastMessage.data).code===1008){return;} -console.error('Realtime got disconnected. Reconnect will be attempted in 1 second.',event.reason);setTimeout(()=>{this.realtime.createSocket();},1000);});},authenticate:(event)=>{var _a,_b,_c;const message=JSON.parse(event.data);if(message.type==='connected'&&((_a=this.realtime.socket)===null||_a===void 0?void 0:_a.readyState)===WebSocket.OPEN){const cookie=JSON.parse((_b=window.localStorage.getItem('cookieFallback'))!==null&&_b!==void 0?_b:"{}");const session=cookie===null||cookie===void 0?void 0:cookie[`a_session_${this.config.project}`];const data=message.data;if(session&&!data.user){(_c=this.realtime.socket)===null||_c===void 0?void 0:_c.send(JSON.stringify({type:"authentication",data:{session}}));}}},onMessage:(channel,callback)=>(event)=>{try{const message=JSON.parse(event.data);this.realtime.lastMessage=message;if(message.type==='event'){let data=message.data;if(data.channels&&data.channels.includes(channel)){callback(data);}} -else if(message.type==='error'){throw message.data;}} -catch(e){console.error(e);}}};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');} +class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',endpointRealtime:'',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:4.0.1','X-Appwrite-Response-Format':'0.10.0',};this.realtime={socket:undefined,timeout:undefined,url:'',channels:new Set(),subscriptions:new Map(),subscriptionsCounter:0,reconnect:true,reconnectAttempts:0,lastMessage:undefined,connect:()=>{clearTimeout(this.realtime.timeout);this.realtime.timeout=window===null||window===void 0?void 0:window.setTimeout(()=>{this.realtime.createSocket();},50);},getTimeout:()=>{switch(true){case this.realtime.reconnectAttempts<5:return 1000;case this.realtime.reconnectAttempts<15:return 5000;case this.realtime.reconnectAttempts<100:return 10000;default:return 60000;}},createSocket:()=>{var _a,_b;if(this.realtime.channels.size<1) +return;const channels=new URLSearchParams();channels.set('project',this.config.project);this.realtime.channels.forEach(channel=>{channels.append('channels[]',channel);});const url=this.config.endpointRealtime+'/realtime?'+channels.toString();if(url!==this.realtime.url||!this.realtime.socket||((_a=this.realtime.socket)===null||_a===void 0?void 0:_a.readyState)>WebSocket.OPEN){if(this.realtime.socket&&((_b=this.realtime.socket)===null||_b===void 0?void 0:_b.readyState){this.realtime.reconnectAttempts=0;});this.realtime.socket.addEventListener('close',event=>{var _a,_b,_c;if(!this.realtime.reconnect||(((_b=(_a=this.realtime)===null||_a===void 0?void 0:_a.lastMessage)===null||_b===void 0?void 0:_b.type)==='error'&&((_c=this.realtime)===null||_c===void 0?void 0:_c.lastMessage.data).code===1008)){this.realtime.reconnect=true;return;} +const timeout=this.realtime.getTimeout();console.error(`Realtime got disconnected. Reconnect will be attempted in ${timeout / 1000} seconds.`,event.reason);setTimeout(()=>{this.realtime.reconnectAttempts++;this.realtime.createSocket();},timeout);});}},onMessage:(event)=>{var _a,_b;try{const message=JSON.parse(event.data);this.realtime.lastMessage=message;switch(message.type){case'connected':const cookie=JSON.parse((_a=window.localStorage.getItem('cookieFallback'))!==null&&_a!==void 0?_a:'{}');const session=cookie===null||cookie===void 0?void 0:cookie[`a_session_${this.config.project}`];const messageData=message.data;if(session&&!messageData.user){(_b=this.realtime.socket)===null||_b===void 0?void 0:_b.send(JSON.stringify({type:'authentication',data:{session}}));} +break;case'event':let data=message.data;if(data===null||data===void 0?void 0:data.channels){const isSubscribed=data.channels.some(channel=>this.realtime.channels.has(channel));if(!isSubscribed) +return;this.realtime.subscriptions.forEach(subscription=>{if(data.channels.some(channel=>subscription.channels.includes(channel))){setTimeout(()=>subscription.callback(data));}});} +break;case'error':throw message.data;default:break;}} +catch(e){console.error(e);}},cleanUp:channels=>{this.realtime.channels.forEach(channel=>{if(channels.includes(channel)){let found=Array.from(this.realtime.subscriptions).some(([_key,subscription])=>{return subscription.channels.includes(channel);});if(!found){this.realtime.channels.delete(channel);}}});}};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');} if(typeof password==='undefined'){throw new AppwriteException('Missing required parameter: "password"');} let path='/account';let payload={};if(typeof email!=='undefined'){payload['email']=email;} if(typeof password!=='undefined'){payload['password']=password;} @@ -462,20 +463,20 @@ const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri, if(typeof emailVerification==='undefined'){throw new AppwriteException('Missing required parameter: "emailVerification"');} let path='/users/{userId}/verification'.replace('{userId}',userId);let payload={};if(typeof emailVerification!=='undefined'){payload['emailVerification']=emailVerification;} const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);})};} -setEndpoint(endpoint){this.config.endpoint=endpoint;this.config.endpointRealtime=this.config.endpointRealtime||this.config.endpoint.replace("https://","wss://").replace("http://","ws://");return this;} +setEndpoint(endpoint){this.config.endpoint=endpoint;this.config.endpointRealtime=this.config.endpointRealtime||this.config.endpoint.replace('https://','wss://').replace('http://','ws://');return this;} setEndpointRealtime(endpointRealtime){this.config.endpointRealtime=endpointRealtime;return this;} setProject(value){this.headers['X-Appwrite-Project']=value;this.config.project=value;return this;} setKey(value){this.headers['X-Appwrite-Key']=value;this.config.key=value;return this;} setJWT(value){this.headers['X-Appwrite-JWT']=value;this.config.jwt=value;return this;} setLocale(value){this.headers['X-Appwrite-Locale']=value;this.config.locale=value;return this;} setMode(value){this.headers['X-Appwrite-Mode']=value;this.config.mode=value;return this;} -subscribe(channels,callback){let channelArray=typeof channels==='string'?[channels]:channels;let savedChannels=[];channelArray.forEach((channel,index)=>{if(!(channel in this.realtime.channels)){this.realtime.channels[channel]=[];} -savedChannels[index]={name:channel,index:(this.realtime.channels[channel].push(this.realtime.onMessage(channel,callback))-1)};clearTimeout(this.realtime.timeout);this.realtime.timeout=window===null||window===void 0?void 0:window.setTimeout(()=>{this.realtime.createSocket();},1);});return()=>{savedChannels.forEach(channel=>{var _a;(_a=this.realtime.socket)===null||_a===void 0?void 0:_a.removeEventListener('message',this.realtime.channels[channel.name][channel.index]);this.realtime.channels[channel.name].splice(channel.index,1);});};} -call(method,url,headers={},params={}){var _a,_b;return __awaiter(this,void 0,void 0,function*(){method=method.toUpperCase();headers=Object.assign(Object.assign({},headers),this.headers);let options={method,headers,credentials:'include'};if(typeof window!=='undefined'&&window.localStorage){headers['X-Fallback-Cookies']=(_a=window.localStorage.getItem('cookieFallback'))!==null&&_a!==void 0?_a:"";} +subscribe(channels,callback){let channelArray=typeof channels==='string'?[channels]:channels;channelArray.forEach(channel=>this.realtime.channels.add(channel));const counter=this.realtime.subscriptionsCounter++;this.realtime.subscriptions.set(counter,{channels:channelArray,callback});this.realtime.connect();return()=>{this.realtime.subscriptions.delete(counter);this.realtime.cleanUp(channelArray);this.realtime.connect();};} +call(method,url,headers={},params={}){var _a,_b;return __awaiter(this,void 0,void 0,function*(){method=method.toUpperCase();headers=Object.assign(Object.assign({},headers),this.headers);let options={method,headers,credentials:'include'};if(typeof window!=='undefined'&&window.localStorage){headers['X-Fallback-Cookies']=(_a=window.localStorage.getItem('cookieFallback'))!==null&&_a!==void 0?_a:'';} if(method==='GET'){for(const[key,value]of Object.entries(this.flatten(params))){url.searchParams.append(key,value);}} -else{switch(headers['content-type']){case'application/json':options.body=JSON.stringify(params);break;case'multipart/form-data':let formData=new FormData();for(const key in params){if(Array.isArray(params[key])){params[key].forEach((value)=>{formData.append(key+'[]',value);})}else{formData.append(key,params[key]);}} +else{switch(headers['content-type']){case'application/json':options.body=JSON.stringify(params);break;case'multipart/form-data':let formData=new FormData();for(const key in params){if(Array.isArray(params[key])){params[key].forEach((value)=>{formData.append(key+'[]',value);});} +else{formData.append(key,params[key]);}} options.body=formData;delete headers['content-type'];break;}} -try{let data=null;const response=yield crossFetch.fetch(url.toString(),options);if((_b=response.headers.get("content-type"))===null||_b===void 0?void 0:_b.includes("application/json")){data=yield response.json();} +try{let data=null;const response=yield crossFetch.fetch(url.toString(),options);if((_b=response.headers.get('content-type'))===null||_b===void 0?void 0:_b.includes('application/json')){data=yield response.json();} else{data={message:yield response.text()};} if(400<=response.status){throw new AppwriteException(data===null||data===void 0?void 0:data.message,response.status,data);} const cookieFallback=response.headers.get('X-Fallback-Cookies');if(typeof window!=='undefined'&&window.localStorage&&cookieFallback){window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.');window.localStorage.setItem('cookieFallback',cookieFallback);} diff --git a/public/scripts/dependencies/appwrite.js b/public/scripts/dependencies/appwrite.js index 3ac3e1b67a..a98bea83ef 100644 --- a/public/scripts/dependencies/appwrite.js +++ b/public/scripts/dependencies/appwrite.js @@ -53,71 +53,128 @@ this.realtime = { socket: undefined, timeout: undefined, - channels: {}, + url: '', + channels: new Set(), + subscriptions: new Map(), + subscriptionsCounter: 0, + reconnect: true, + reconnectAttempts: 0, lastMessage: undefined, + connect: () => { + clearTimeout(this.realtime.timeout); + this.realtime.timeout = window === null || window === void 0 ? void 0 : window.setTimeout(() => { + this.realtime.createSocket(); + }, 50); + }, + getTimeout: () => { + switch (true) { + case this.realtime.reconnectAttempts < 5: + return 1000; + case this.realtime.reconnectAttempts < 15: + return 5000; + case this.realtime.reconnectAttempts < 100: + return 10000; + default: + return 60000; + } + }, createSocket: () => { var _a, _b; + if (this.realtime.channels.size < 1) + return; const channels = new URLSearchParams(); channels.set('project', this.config.project); - for (const property in this.realtime.channels) { - channels.append('channels[]', property); - } - if (((_a = this.realtime.socket) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) { - this.realtime.socket.close(); - } - this.realtime.socket = new WebSocket(this.config.endpointRealtime + '/realtime?' + channels.toString()); - (_b = this.realtime.socket) === null || _b === void 0 ? void 0 : _b.addEventListener('message', this.realtime.authenticate); - for (const channel in this.realtime.channels) { - this.realtime.channels[channel].forEach(callback => { - var _a; - (_a = this.realtime.socket) === null || _a === void 0 ? void 0 : _a.addEventListener('message', callback); + this.realtime.channels.forEach(channel => { + channels.append('channels[]', channel); + }); + const url = this.config.endpointRealtime + '/realtime?' + channels.toString(); + if (url !== this.realtime.url || // Check if URL is present + !this.realtime.socket || // Check if WebSocket has not been created + ((_a = this.realtime.socket) === null || _a === void 0 ? void 0 : _a.readyState) > WebSocket.OPEN // Check if WebSocket is CLOSING (3) or CLOSED (4) + ) { + if (this.realtime.socket && + ((_b = this.realtime.socket) === null || _b === void 0 ? void 0 : _b.readyState) < WebSocket.CLOSING // Close WebSocket if it is CONNECTING (0) or OPEN (1) + ) { + this.realtime.reconnect = false; + this.realtime.socket.close(); + } + this.realtime.url = url; + this.realtime.socket = new WebSocket(url); + this.realtime.socket.addEventListener('message', this.realtime.onMessage); + this.realtime.socket.addEventListener('open', _event => { + this.realtime.reconnectAttempts = 0; + }); + this.realtime.socket.addEventListener('close', event => { + var _a, _b, _c; + if (!this.realtime.reconnect || + (((_b = (_a = this.realtime) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.type) === 'error' && // Check if last message was of type error + ((_c = this.realtime) === null || _c === void 0 ? void 0 : _c.lastMessage.data).code === 1008 // Check for policy violation 1008 + )) { + this.realtime.reconnect = true; + return; + } + const timeout = this.realtime.getTimeout(); + console.error(`Realtime got disconnected. Reconnect will be attempted in ${timeout / 1000} seconds.`, event.reason); + setTimeout(() => { + this.realtime.reconnectAttempts++; + this.realtime.createSocket(); + }, timeout); }); } - this.realtime.socket.addEventListener('close', event => { - var _a, _b, _c; - if (((_b = (_a = this.realtime) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.type) === 'error' && ((_c = this.realtime) === null || _c === void 0 ? void 0 : _c.lastMessage.data).code === 1008) { - return; - } - console.error('Realtime got disconnected. Reconnect will be attempted in 1 second.', event.reason); - setTimeout(() => { - this.realtime.createSocket(); - }, 1000); - }); }, - authenticate: (event) => { - var _a, _b, _c; - const message = JSON.parse(event.data); - if (message.type === 'connected' && ((_a = this.realtime.socket) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) { - const cookie = JSON.parse((_b = window.localStorage.getItem('cookieFallback')) !== null && _b !== void 0 ? _b : "{}"); - const session = cookie === null || cookie === void 0 ? void 0 : cookie[`a_session_${this.config.project}`]; - const data = message.data; - if (session && !data.user) { - (_c = this.realtime.socket) === null || _c === void 0 ? void 0 : _c.send(JSON.stringify({ - type: "authentication", - data: { - session - } - })); - } - } - }, - onMessage: (channel, callback) => (event) => { + onMessage: (event) => { + var _a, _b; try { const message = JSON.parse(event.data); this.realtime.lastMessage = message; - if (message.type === 'event') { - let data = message.data; - if (data.channels && data.channels.includes(channel)) { - callback(data); - } - } - else if (message.type === 'error') { - throw message.data; + switch (message.type) { + case 'connected': + const cookie = JSON.parse((_a = window.localStorage.getItem('cookieFallback')) !== null && _a !== void 0 ? _a : '{}'); + const session = cookie === null || cookie === void 0 ? void 0 : cookie[`a_session_${this.config.project}`]; + const messageData = message.data; + if (session && !messageData.user) { + (_b = this.realtime.socket) === null || _b === void 0 ? void 0 : _b.send(JSON.stringify({ + type: 'authentication', + data: { + session + } + })); + } + break; + case 'event': + let data = message.data; + if (data === null || data === void 0 ? void 0 : data.channels) { + const isSubscribed = data.channels.some(channel => this.realtime.channels.has(channel)); + if (!isSubscribed) + return; + this.realtime.subscriptions.forEach(subscription => { + if (data.channels.some(channel => subscription.channels.includes(channel))) { + setTimeout(() => subscription.callback(data)); + } + }); + } + break; + case 'error': + throw message.data; + default: + break; } } catch (e) { console.error(e); } + }, + cleanUp: channels => { + this.realtime.channels.forEach(channel => { + if (channels.includes(channel)) { + let found = Array.from(this.realtime.subscriptions).some(([_key, subscription]) => { + return subscription.channels.includes(channel); + }); + if (!found) { + this.realtime.channels.delete(channel); + } + } + }); } }; this.account = { @@ -4264,7 +4321,7 @@ */ setEndpoint(endpoint) { this.config.endpoint = endpoint; - this.config.endpointRealtime = this.config.endpointRealtime || this.config.endpoint.replace("https://", "wss://").replace("http://", "ws://"); + this.config.endpointRealtime = this.config.endpointRealtime || this.config.endpoint.replace('https://', 'wss://').replace('http://', 'ws://'); return this; } /** @@ -4371,26 +4428,17 @@ */ subscribe(channels, callback) { let channelArray = typeof channels === 'string' ? [channels] : channels; - let savedChannels = []; - channelArray.forEach((channel, index) => { - if (!(channel in this.realtime.channels)) { - this.realtime.channels[channel] = []; - } - savedChannels[index] = { - name: channel, - index: (this.realtime.channels[channel].push(this.realtime.onMessage(channel, callback)) - 1) - }; - clearTimeout(this.realtime.timeout); - this.realtime.timeout = window === null || window === void 0 ? void 0 : window.setTimeout(() => { - this.realtime.createSocket(); - }, 1); + channelArray.forEach(channel => this.realtime.channels.add(channel)); + const counter = this.realtime.subscriptionsCounter++; + this.realtime.subscriptions.set(counter, { + channels: channelArray, + callback }); + this.realtime.connect(); return () => { - savedChannels.forEach(channel => { - var _a; - (_a = this.realtime.socket) === null || _a === void 0 ? void 0 : _a.removeEventListener('message', this.realtime.channels[channel.name][channel.index]); - this.realtime.channels[channel.name].splice(channel.index, 1); - }); + this.realtime.subscriptions.delete(counter); + this.realtime.cleanUp(channelArray); + this.realtime.connect(); }; } call(method, url, headers = {}, params = {}) { @@ -4404,7 +4452,7 @@ credentials: 'include' }; if (typeof window !== 'undefined' && window.localStorage) { - headers['X-Fallback-Cookies'] = (_a = window.localStorage.getItem('cookieFallback')) !== null && _a !== void 0 ? _a : ""; + headers['X-Fallback-Cookies'] = (_a = window.localStorage.getItem('cookieFallback')) !== null && _a !== void 0 ? _a : ''; } if (method === 'GET') { for (const [key, value] of Object.entries(this.flatten(params))) { @@ -4422,8 +4470,9 @@ if (Array.isArray(params[key])) { params[key].forEach((value) => { formData.append(key + '[]', value); - }) - } else { + }); + } + else { formData.append(key, params[key]); } } @@ -4435,7 +4484,7 @@ try { let data = null; const response = yield crossFetch.fetch(url.toString(), options); - if ((_b = response.headers.get("content-type")) === null || _b === void 0 ? void 0 : _b.includes("application/json")) { + if ((_b = response.headers.get('content-type')) === null || _b === void 0 ? void 0 : _b.includes('application/json')) { data = yield response.json(); } else {