Skip to content

Commit f962d35

Browse files
committed
chore: update RC version
1 parent df4648f commit f962d35

12 files changed

+1498
-1482
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { Client, Account } from "appwrite";
3333
To install with a CDN (content delivery network) add the following scripts to the bottom of your <body> tag, but before you use any Appwrite services:
3434

3535
```html
36-
<script src="https://cdn.jsdelivr.net/npm/appwrite@16.0.0-rc.2"></script>
36+
<script src="https://cdn.jsdelivr.net/npm/appwrite@16.0.0-rc.3"></script>
3737
```
3838

3939

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "appwrite",
33
"homepage": "https://appwrite.io/support",
44
"description": "Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API",
5-
"version": "16.0.0-rc.2",
5+
"version": "16.0.0-rc.3",
66
"license": "BSD-3-Clause",
77
"main": "dist/cjs/sdk.js",
88
"exports": {

src/client.ts

+118-66
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Models } from './models';
2-
import { Service } from './service';
32

43
/**
54
* Payload type representing a key-value pair with string keys and any values.
@@ -48,7 +47,7 @@ type RealtimeRequest = {
4847
/**
4948
* Realtime event response structure with generic payload type.
5049
*/
51-
export type RealtimeResponseEvent<T extends unknown> = {
50+
type RealtimeResponseEvent<T extends unknown> = {
5251
/**
5352
* List of event names associated with the response.
5453
*/
@@ -215,7 +214,7 @@ type Realtime = {
215214
/**
216215
* Type representing upload progress information.
217216
*/
218-
export type UploadProgress = {
217+
type UploadProgress = {
219218
/**
220219
* Identifier for the upload progress.
221220
*/
@@ -284,6 +283,8 @@ class AppwriteException extends Error {
284283
* Client that handles requests to Appwrite
285284
*/
286285
class Client {
286+
static CHUNK_SIZE = 1024 * 1024 * 5;
287+
287288
/**
288289
* Holds configuration such as project.
289290
*/
@@ -295,15 +296,14 @@ class Client {
295296
locale: '',
296297
session: '',
297298
};
298-
299299
/**
300300
* Custom headers for API requests.
301301
*/
302302
headers: Headers = {
303303
'x-sdk-name': 'Web',
304304
'x-sdk-platform': 'client',
305305
'x-sdk-language': 'web',
306-
'x-sdk-version': '16.0.0-rc.2',
306+
'x-sdk-version': '16.0.0-rc.3',
307307
'X-Appwrite-Response-Format': '1.6.0',
308308
};
309309

@@ -350,7 +350,6 @@ class Client {
350350
this.config.project = value;
351351
return this;
352352
}
353-
354353
/**
355354
* Set JWT
356355
*
@@ -365,7 +364,6 @@ class Client {
365364
this.config.jwt = value;
366365
return this;
367366
}
368-
369367
/**
370368
* Set Locale
371369
*
@@ -378,7 +376,6 @@ class Client {
378376
this.config.locale = value;
379377
return this;
380378
}
381-
382379
/**
383380
* Set Session
384381
*
@@ -394,7 +391,6 @@ class Client {
394391
return this;
395392
}
396393

397-
398394
private realtime: Realtime = {
399395
socket: undefined,
400396
timeout: undefined,
@@ -578,40 +574,18 @@ class Client {
578574
}
579575
}
580576

581-
/**
582-
* Call API endpoint with the specified method, URL, headers, and parameters.
583-
*
584-
* @param {string} method - HTTP method (e.g., 'GET', 'POST', 'PUT', 'DELETE').
585-
* @param {URL} url - The URL of the API endpoint.
586-
* @param {Headers} headers - Custom headers for the API request.
587-
* @param {Payload} params - Request parameters.
588-
* @returns {Promise<any>} - A promise that resolves with the response data.
589-
*
590-
* @typedef {Object} Payload - Request payload data.
591-
* @property {string} key - The key.
592-
* @property {string} value - The value.
593-
*/
594-
async call(method: string, url: URL, headers: Headers = {}, params: Payload = {}): Promise<any> {
577+
prepareRequest(method: string, url: URL, headers: Headers = {}, params: Payload = {}): { uri: string, options: RequestInit } {
595578
method = method.toUpperCase();
596579

597-
598580
headers = Object.assign({}, this.headers, headers);
599581

600582
let options: RequestInit = {
601583
method,
602584
headers,
603-
credentials: 'include'
604585
};
605586

606-
if (typeof window !== 'undefined' && window.localStorage) {
607-
const cookieFallback = window.localStorage.getItem('cookieFallback');
608-
if (cookieFallback) {
609-
headers['X-Fallback-Cookies'] = cookieFallback;
610-
}
611-
}
612-
613587
if (method === 'GET') {
614-
for (const [key, value] of Object.entries(Service.flatten(params))) {
588+
for (const [key, value] of Object.entries(Client.flatten(params))) {
615589
url.searchParams.append(key, value);
616590
}
617591
} else {
@@ -621,15 +595,17 @@ class Client {
621595
break;
622596

623597
case 'multipart/form-data':
624-
let formData = new FormData();
625-
626-
for (const key in params) {
627-
if (Array.isArray(params[key])) {
628-
params[key].forEach((value: any) => {
629-
formData.append(key + '[]', value);
630-
})
598+
const formData = new FormData();
599+
600+
for (const [key, value] of Object.entries(params)) {
601+
if (value instanceof File) {
602+
formData.append(key, value, value.name);
603+
} else if (Array.isArray(value)) {
604+
for (const nestedValue of value) {
605+
formData.append(`${key}[]`, nestedValue);
606+
}
631607
} else {
632-
formData.append(key, params[key]);
608+
formData.append(key, value);
633609
}
634610
}
635611

@@ -639,45 +615,121 @@ class Client {
639615
}
640616
}
641617

642-
try {
643-
let data = null;
644-
const response = await fetch(url.toString(), options);
618+
return { uri: url.toString(), options };
619+
}
620+
621+
async chunkedUpload(method: string, url: URL, headers: Headers = {}, originalPayload: Payload = {}, onProgress: (progress: UploadProgress) => void) {
622+
const file = Object.values(originalPayload).find((value) => value instanceof File);
623+
624+
if (file.size <= Client.CHUNK_SIZE) {
625+
return await this.call(method, url, headers, originalPayload);
626+
}
627+
628+
let start = 0;
629+
let response = null;
645630

646-
const warnings = response.headers.get('x-appwrite-warning');
647-
if (warnings) {
648-
warnings.split(';').forEach((warning: string) => console.warn('Warning: ' + warning));
631+
while (start < file.size) {
632+
let end = start + Client.CHUNK_SIZE; // Prepare end for the next chunk
633+
if (end >= file.size) {
634+
end = file.size; // Adjust for the last chunk to include the last byte
649635
}
650636

651-
if (response.headers.get('content-type')?.includes('application/json')) {
652-
data = await response.json();
653-
} else {
654-
data = {
655-
message: await response.text()
656-
};
637+
headers['content-range'] = `bytes ${start}-${end-1}/${file.size}`;
638+
const chunk = file.slice(start, end);
639+
640+
let payload = { ...originalPayload, file: new File([chunk], file.name)};
641+
642+
response = await this.call(method, url, headers, payload);
643+
644+
if (onProgress && typeof onProgress === 'function') {
645+
onProgress({
646+
$id: response.$id,
647+
progress: Math.round((end / file.size) * 100),
648+
sizeUploaded: end,
649+
chunksTotal: Math.ceil(file.size / Client.CHUNK_SIZE),
650+
chunksUploaded: Math.ceil(end / Client.CHUNK_SIZE)
651+
});
657652
}
658653

659-
if (400 <= response.status) {
660-
throw new AppwriteException(data?.message, response.status, data?.type, data);
654+
if (response && response.$id) {
655+
headers['x-appwrite-id'] = response.$id;
661656
}
662657

663-
const cookieFallback = response.headers.get('X-Fallback-Cookies');
658+
start = end;
659+
}
664660

665-
if (typeof window !== 'undefined' && window.localStorage && cookieFallback) {
666-
window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.');
667-
window.localStorage.setItem('cookieFallback', cookieFallback);
668-
}
661+
return response;
662+
}
663+
664+
async redirect(method: string, url: URL, headers: Headers = {}, params: Payload = {}): Promise<string> {
665+
const { uri, options } = this.prepareRequest(method, url, headers, params);
666+
667+
const response = await fetch(uri, {
668+
...options,
669+
redirect: 'manual'
670+
});
671+
672+
if (response.status !== 301 && response.status !== 302) {
673+
throw new AppwriteException('Invalid redirect', response.status);
674+
}
675+
676+
return response.headers.get('location') || '';
677+
}
678+
679+
async call(method: string, url: URL, headers: Headers = {}, params: Payload = {}, responseType = 'json'): Promise<any> {
680+
const { uri, options } = this.prepareRequest(method, url, headers, params);
681+
682+
let data: any = null;
683+
684+
const response = await fetch(uri, options);
685+
686+
const warnings = response.headers.get('x-appwrite-warning');
687+
if (warnings) {
688+
warnings.split(';').forEach((warning: string) => console.warn('Warning: ' + warning));
689+
}
669690

670-
return data;
671-
} catch (e) {
672-
if (e instanceof AppwriteException) {
673-
throw e;
691+
if (response.headers.get('content-type')?.includes('application/json')) {
692+
data = await response.json();
693+
} else if (responseType === 'arrayBuffer') {
694+
data = await response.arrayBuffer();
695+
} else {
696+
data = {
697+
message: await response.text()
698+
};
699+
}
700+
701+
if (400 <= response.status) {
702+
throw new AppwriteException(data?.message, response.status, data?.type, data);
703+
}
704+
705+
const cookieFallback = response.headers.get('X-Fallback-Cookies');
706+
707+
if (typeof window !== 'undefined' && window.localStorage && cookieFallback) {
708+
window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.');
709+
window.localStorage.setItem('cookieFallback', cookieFallback);
710+
}
711+
712+
return data;
713+
}
714+
715+
static flatten(data: Payload, prefix = ''): Payload {
716+
let output: Payload = {};
717+
718+
for (const [key, value] of Object.entries(data)) {
719+
let finalKey = prefix ? prefix + '[' + key +']' : key;
720+
if (Array.isArray(value)) {
721+
output = { ...output, ...Client.flatten(value, finalKey) };
722+
} else {
723+
output[finalKey] = value;
674724
}
675-
throw new AppwriteException((<Error>e).message);
676725
}
726+
727+
return output;
677728
}
678729
}
679730

680731
export { Client, AppwriteException };
681732
export { Query } from './query';
682-
export type { Models, Payload };
733+
export type { Models, Payload, UploadProgress };
734+
export type { RealtimeResponseEvent };
683735
export type { QueryTypes, QueryTypesList } from './query';

0 commit comments

Comments
 (0)