diff --git a/CHANGELOG.md b/CHANGELOG.md index 9095ec8..5923160 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 18.0.0 -* Add `<REGION>` to doc examples due to the new multi region endpoints +* Add `` to doc examples due to the new multi region endpoints * Remove `Gif` from ImageFormat enum * Remove `search` param from `listExecutions` method * Add `token` param to `getFilePreview` and `getFileView` for File tokens usage diff --git a/README.md b/README.md index 48e37b6..0488f5f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Appwrite Web SDK ![License](https://img.shields.io/github/license/appwrite/sdk-for-web.svg?style=flat-square) -![Version](https://img.shields.io/badge/api%20version-1.7.0-blue.svg?style=flat-square) +![Version](https://img.shields.io/badge/api%20version-1.7.4-blue.svg?style=flat-square) [![Build Status](https://img.shields.io/travis/com/appwrite/sdk-generator?style=flat-square)](https://travis-ci.com/appwrite/sdk-generator) [![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) [![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord) diff --git a/docs/examples/databases/create-document.md b/docs/examples/databases/create-document.md index 401a674..64dfcec 100644 --- a/docs/examples/databases/create-document.md +++ b/docs/examples/databases/create-document.md @@ -2,6 +2,7 @@ import { Client, Databases } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setAdmin('') // .setSession('') // The user session to authenticate with .setKey('') // .setJWT(''); // Your secret JSON Web Token diff --git a/docs/examples/databases/decrement-document-attribute.md b/docs/examples/databases/decrement-document-attribute.md new file mode 100644 index 0000000..10d785a --- /dev/null +++ b/docs/examples/databases/decrement-document-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.decrementDocumentAttribute( + '', // databaseId + '', // collectionId + '', // documentId + '', // attribute + null, // value (optional) + null // min (optional) +); + +console.log(result); diff --git a/docs/examples/databases/increment-document-attribute.md b/docs/examples/databases/increment-document-attribute.md new file mode 100644 index 0000000..4b32be9 --- /dev/null +++ b/docs/examples/databases/increment-document-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.incrementDocumentAttribute( + '', // databaseId + '', // collectionId + '', // documentId + '', // attribute + null, // value (optional) + null // max (optional) +); + +console.log(result); diff --git a/src/client.ts b/src/client.ts index f36d800..2416943 100644 --- a/src/client.ts +++ b/src/client.ts @@ -679,9 +679,9 @@ class Client { } async chunkedUpload(method: string, url: URL, headers: Headers = {}, originalPayload: Payload = {}, onProgress: (progress: UploadProgress) => void) { - const file = Object.values(originalPayload).find((value) => value instanceof File); + const [fileParam, file] = Object.entries(originalPayload).find(([_, value]) => value instanceof File) ?? []; - if (!file) { + if (!file || !fileParam) { throw new Error('File not found in payload'); } @@ -701,7 +701,8 @@ class Client { headers['content-range'] = `bytes ${start}-${end-1}/${file.size}`; const chunk = file.slice(start, end); - let payload = { ...originalPayload, file: new File([chunk], file.name)}; + let payload = { ...originalPayload }; + payload[fileParam] = new File([chunk], file.name); response = await this.call(method, url, headers, payload); diff --git a/src/enums/image-format.ts b/src/enums/image-format.ts index 5aad5f0..758fad7 100644 --- a/src/enums/image-format.ts +++ b/src/enums/image-format.ts @@ -5,4 +5,5 @@ export enum ImageFormat { Webp = 'webp', Heic = 'heic', Avif = 'avif', + Gif = 'gif', } \ No newline at end of file diff --git a/src/models.ts b/src/models.ts index 87a04b0..62002ff 100644 --- a/src/models.ts +++ b/src/models.ts @@ -2,10 +2,13 @@ * Appwrite Models */ export namespace Models { + + declare const __default: unique symbol; + /** * Documents List */ - export type DocumentList = { + export type DocumentList = { /** * Total number of documents documents that matched your query. */ @@ -15,6 +18,7 @@ export namespace Models { */ documents: Document[]; } + /** * Sessions List */ @@ -28,6 +32,7 @@ export namespace Models { */ sessions: Session[]; } + /** * Identities List */ @@ -41,6 +46,7 @@ export namespace Models { */ identities: Identity[]; } + /** * Logs List */ @@ -54,6 +60,7 @@ export namespace Models { */ logs: Log[]; } + /** * Files List */ @@ -67,10 +74,11 @@ export namespace Models { */ files: File[]; } + /** * Teams List */ - export type TeamList = { + export type TeamList = { /** * Total number of teams documents that matched your query. */ @@ -80,6 +88,7 @@ export namespace Models { */ teams: Team[]; } + /** * Memberships List */ @@ -93,6 +102,7 @@ export namespace Models { */ memberships: Membership[]; } + /** * Executions List */ @@ -106,6 +116,7 @@ export namespace Models { */ executions: Execution[]; } + /** * Countries List */ @@ -119,6 +130,7 @@ export namespace Models { */ countries: Country[]; } + /** * Continents List */ @@ -132,6 +144,7 @@ export namespace Models { */ continents: Continent[]; } + /** * Languages List */ @@ -145,6 +158,7 @@ export namespace Models { */ languages: Language[]; } + /** * Currencies List */ @@ -158,6 +172,7 @@ export namespace Models { */ currencies: Currency[]; } + /** * Phones List */ @@ -171,6 +186,7 @@ export namespace Models { */ phones: Phone[]; } + /** * Locale codes list */ @@ -184,6 +200,7 @@ export namespace Models { */ localeCodes: LocaleCode[]; } + /** * Document */ @@ -192,6 +209,10 @@ export namespace Models { * Document ID. */ $id: string; + /** + * Document automatically incrementing ID. + */ + $sequence: number; /** * Collection ID. */ @@ -212,8 +233,19 @@ export namespace Models { * Document permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). */ $permissions: string[]; - [key: string]: any; } + + export type DefaultDocument = Document & { + [key: string]: any; + [__default]: true; + }; + + export type DataWithoutDocumentKeys = { + [K in string]: any; + } & { + [K in keyof Document]?: never; + }; + /** * Log */ @@ -303,10 +335,11 @@ export namespace Models { */ countryName: string; } + /** * User */ - export type User = { + export type User = { /** * User ID. */ @@ -384,6 +417,7 @@ export namespace Models { */ accessedAt: string; } + /** * AlgoMD5 */ @@ -393,6 +427,7 @@ export namespace Models { */ type: string; } + /** * AlgoSHA */ @@ -402,6 +437,7 @@ export namespace Models { */ type: string; } + /** * AlgoPHPass */ @@ -411,6 +447,7 @@ export namespace Models { */ type: string; } + /** * AlgoBcrypt */ @@ -420,6 +457,7 @@ export namespace Models { */ type: string; } + /** * AlgoScrypt */ @@ -445,6 +483,7 @@ export namespace Models { */ length: number; } + /** * AlgoScryptModified */ @@ -466,6 +505,7 @@ export namespace Models { */ signerKey: string; } + /** * AlgoArgon2 */ @@ -487,12 +527,24 @@ export namespace Models { */ threads: number; } + /** * Preferences */ export type Preferences = { - [key: string]: any; } + + export type DefaultPreferences = Preferences & { + [key: string]: any; + [__default]: true; + }; + + export type DataWithoutPreferencesKeys = { + [K in string]: any; + } & { + [K in keyof Preferences]?: never; + }; + /** * Session */ @@ -614,6 +666,7 @@ export namespace Models { */ mfaUpdatedAt: string; } + /** * Identity */ @@ -659,6 +712,7 @@ export namespace Models { */ providerRefreshToken: string; } + /** * Token */ @@ -688,6 +742,7 @@ export namespace Models { */ phrase: string; } + /** * JWT */ @@ -697,6 +752,7 @@ export namespace Models { */ jwt: string; } + /** * Locale */ @@ -730,6 +786,7 @@ export namespace Models { */ currency: string; } + /** * LocaleCode */ @@ -743,6 +800,7 @@ export namespace Models { */ name: string; } + /** * File */ @@ -792,10 +850,11 @@ export namespace Models { */ chunksUploaded: number; } + /** * Team */ - export type Team = { + export type Team = { /** * Team ID. */ @@ -821,6 +880,7 @@ export namespace Models { */ prefs: Preferences; } + /** * Membership */ @@ -878,6 +938,7 @@ export namespace Models { */ roles: string[]; } + /** * Execution */ @@ -951,6 +1012,7 @@ export namespace Models { */ scheduledAt?: string; } + /** * Country */ @@ -964,6 +1026,7 @@ export namespace Models { */ code: string; } + /** * Continent */ @@ -977,6 +1040,7 @@ export namespace Models { */ code: string; } + /** * Language */ @@ -994,6 +1058,7 @@ export namespace Models { */ nativeName: string; } + /** * Currency */ @@ -1027,6 +1092,7 @@ export namespace Models { */ namePlural: string; } + /** * Phone */ @@ -1044,6 +1110,7 @@ export namespace Models { */ countryName: string; } + /** * Headers */ @@ -1057,6 +1124,7 @@ export namespace Models { */ value: string; } + /** * MFA Challenge */ @@ -1078,6 +1146,7 @@ export namespace Models { */ expire: string; } + /** * MFA Recovery Codes */ @@ -1087,6 +1156,7 @@ export namespace Models { */ recoveryCodes: string[]; } + /** * MFAType */ @@ -1100,6 +1170,7 @@ export namespace Models { */ uri: string; } + /** * MFAFactors */ @@ -1121,6 +1192,7 @@ export namespace Models { */ recoveryCode: boolean; } + /** * Subscriber */ @@ -1162,6 +1234,7 @@ export namespace Models { */ providerType: string; } + /** * Target */ diff --git a/src/services/account.ts b/src/services/account.ts index b3f42d8..04a6710 100644 --- a/src/services/account.ts +++ b/src/services/account.ts @@ -18,7 +18,7 @@ export class Account { * @throws {AppwriteException} * @returns {Promise>} */ - get(): Promise> { + get(): Promise> { const apiPath = '/account'; const payload: Payload = {}; const uri = new URL(this.client.config.endpoint + apiPath); @@ -43,7 +43,7 @@ export class Account { * @throws {AppwriteException} * @returns {Promise>} */ - create(userId: string, email: string, password: string, name?: string): Promise> { + create(userId: string, email: string, password: string, name?: string): Promise> { if (typeof userId === 'undefined') { throw new AppwriteException('Missing required parameter: "userId"'); } @@ -90,7 +90,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updateEmail(email: string, password: string): Promise> { + updateEmail(email: string, password: string): Promise> { if (typeof email === 'undefined') { throw new AppwriteException('Missing required parameter: "email"'); } @@ -223,7 +223,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updateMFA(mfa: boolean): Promise> { + updateMFA(mfa: boolean): Promise> { if (typeof mfa === 'undefined') { throw new AppwriteException('Missing required parameter: "mfa"'); } @@ -279,7 +279,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updateMfaAuthenticator(type: AuthenticatorType, otp: string): Promise> { + updateMfaAuthenticator(type: AuthenticatorType, otp: string): Promise> { if (typeof type === 'undefined') { throw new AppwriteException('Missing required parameter: "type"'); } @@ -488,7 +488,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updateName(name: string): Promise> { + updateName(name: string): Promise> { if (typeof name === 'undefined') { throw new AppwriteException('Missing required parameter: "name"'); } @@ -518,7 +518,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updatePassword(password: string, oldPassword?: string): Promise> { + updatePassword(password: string, oldPassword?: string): Promise> { if (typeof password === 'undefined') { throw new AppwriteException('Missing required parameter: "password"'); } @@ -551,7 +551,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updatePhone(phone: string, password: string): Promise> { + updatePhone(phone: string, password: string): Promise> { if (typeof phone === 'undefined') { throw new AppwriteException('Missing required parameter: "phone"'); } @@ -585,7 +585,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise} */ - getPrefs(): Promise { + getPrefs(): Promise { const apiPath = '/account/prefs'; const payload: Payload = {}; const uri = new URL(this.client.config.endpoint + apiPath); @@ -607,7 +607,7 @@ This endpoint can also be used to convert an anonymous account to a normal one, * @throws {AppwriteException} * @returns {Promise>} */ - updatePrefs(prefs: Partial): Promise> { + updatePrefs(prefs: Partial): Promise> { if (typeof prefs === 'undefined') { throw new AppwriteException('Missing required parameter: "prefs"'); } @@ -1052,7 +1052,7 @@ A user is limited to 10 active sessions at a time by default. [Learn more about * @throws {AppwriteException} * @returns {Promise>} */ - updateStatus(): Promise> { + updateStatus(): Promise> { const apiPath = '/account/status'; const payload: Payload = {}; const uri = new URL(this.client.config.endpoint + apiPath); diff --git a/src/services/databases.ts b/src/services/databases.ts index 4f2d50a..6f8be38 100644 --- a/src/services/databases.ts +++ b/src/services/databases.ts @@ -18,7 +18,7 @@ export class Databases { * @throws {AppwriteException} * @returns {Promise>} */ - listDocuments(databaseId: string, collectionId: string, queries?: string[]): Promise> { + listDocuments(databaseId: string, collectionId: string, queries?: string[]): Promise> { if (typeof databaseId === 'undefined') { throw new AppwriteException('Missing required parameter: "databaseId"'); } @@ -48,12 +48,12 @@ export class Databases { * @param {string} databaseId * @param {string} collectionId * @param {string} documentId - * @param {Omit} data + * @param {Document extends Models.DefaultDocument ? Models.DataWithoutDocumentKeys : Omit} data * @param {string[]} permissions * @throws {AppwriteException} * @returns {Promise} */ - createDocument(databaseId: string, collectionId: string, documentId: string, data: Omit, permissions?: string[]): Promise { + createDocument(databaseId: string, collectionId: string, documentId: string, data: Document extends Models.DefaultDocument ? Models.DataWithoutDocumentKeys : Omit, permissions?: string[]): Promise { if (typeof databaseId === 'undefined') { throw new AppwriteException('Missing required parameter: "databaseId"'); } @@ -100,7 +100,7 @@ export class Databases { * @throws {AppwriteException} * @returns {Promise} */ - getDocument(databaseId: string, collectionId: string, documentId: string, queries?: string[]): Promise { + getDocument(databaseId: string, collectionId: string, documentId: string, queries?: string[]): Promise { if (typeof databaseId === 'undefined') { throw new AppwriteException('Missing required parameter: "databaseId"'); } @@ -128,7 +128,9 @@ export class Databases { ); } /** - * Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. + * **WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions. + +Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. * * @param {string} databaseId * @param {string} collectionId @@ -138,7 +140,7 @@ export class Databases { * @throws {AppwriteException} * @returns {Promise} */ - upsertDocument(databaseId: string, collectionId: string, documentId: string, data: object, permissions?: string[]): Promise { + upsertDocument(databaseId: string, collectionId: string, documentId: string, data: object, permissions?: string[]): Promise { if (typeof databaseId === 'undefined') { throw new AppwriteException('Missing required parameter: "databaseId"'); } @@ -178,12 +180,12 @@ export class Databases { * @param {string} databaseId * @param {string} collectionId * @param {string} documentId - * @param {Partial>} data + * @param {Partial>} data * @param {string[]} permissions * @throws {AppwriteException} * @returns {Promise} */ - updateDocument(databaseId: string, collectionId: string, documentId: string, data?: Partial>, permissions?: string[]): Promise { + updateDocument(databaseId: string, collectionId: string, documentId: string, data?: Partial>, permissions?: string[]): Promise { if (typeof databaseId === 'undefined') { throw new AppwriteException('Missing required parameter: "databaseId"'); } @@ -248,4 +250,96 @@ export class Databases { payload ); } + /** + * Decrement a specific attribute of a document by a given value. + * + * @param {string} databaseId + * @param {string} collectionId + * @param {string} documentId + * @param {string} attribute + * @param {number} value + * @param {number} min + * @throws {AppwriteException} + * @returns {Promise} + */ + decrementDocumentAttribute(databaseId: string, collectionId: string, documentId: string, attribute: string, value?: number, min?: number): Promise { + if (typeof databaseId === 'undefined') { + throw new AppwriteException('Missing required parameter: "databaseId"'); + } + if (typeof collectionId === 'undefined') { + throw new AppwriteException('Missing required parameter: "collectionId"'); + } + if (typeof documentId === 'undefined') { + throw new AppwriteException('Missing required parameter: "documentId"'); + } + if (typeof attribute === 'undefined') { + throw new AppwriteException('Missing required parameter: "attribute"'); + } + const apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/decrement'.replace('{databaseId}', databaseId).replace('{collectionId}', collectionId).replace('{documentId}', documentId).replace('{attribute}', attribute); + const payload: Payload = {}; + if (typeof value !== 'undefined') { + payload['value'] = value; + } + if (typeof min !== 'undefined') { + payload['min'] = min; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'content-type': 'application/json', + } + + return this.client.call( + 'patch', + uri, + apiHeaders, + payload + ); + } + /** + * Increment a specific attribute of a document by a given value. + * + * @param {string} databaseId + * @param {string} collectionId + * @param {string} documentId + * @param {string} attribute + * @param {number} value + * @param {number} max + * @throws {AppwriteException} + * @returns {Promise} + */ + incrementDocumentAttribute(databaseId: string, collectionId: string, documentId: string, attribute: string, value?: number, max?: number): Promise { + if (typeof databaseId === 'undefined') { + throw new AppwriteException('Missing required parameter: "databaseId"'); + } + if (typeof collectionId === 'undefined') { + throw new AppwriteException('Missing required parameter: "collectionId"'); + } + if (typeof documentId === 'undefined') { + throw new AppwriteException('Missing required parameter: "documentId"'); + } + if (typeof attribute === 'undefined') { + throw new AppwriteException('Missing required parameter: "attribute"'); + } + const apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/increment'.replace('{databaseId}', databaseId).replace('{collectionId}', collectionId).replace('{documentId}', documentId).replace('{attribute}', attribute); + const payload: Payload = {}; + if (typeof value !== 'undefined') { + payload['value'] = value; + } + if (typeof max !== 'undefined') { + payload['max'] = max; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'content-type': 'application/json', + } + + return this.client.call( + 'patch', + uri, + apiHeaders, + payload + ); + } } diff --git a/src/services/teams.ts b/src/services/teams.ts index bb5d9da..87b2ffe 100644 --- a/src/services/teams.ts +++ b/src/services/teams.ts @@ -17,7 +17,7 @@ export class Teams { * @throws {AppwriteException} * @returns {Promise>} */ - list(queries?: string[], search?: string): Promise> { + list(queries?: string[], search?: string): Promise> { const apiPath = '/teams'; const payload: Payload = {}; if (typeof queries !== 'undefined') { @@ -47,7 +47,7 @@ export class Teams { * @throws {AppwriteException} * @returns {Promise>} */ - create(teamId: string, name: string, roles?: string[]): Promise> { + create(teamId: string, name: string, roles?: string[]): Promise> { if (typeof teamId === 'undefined') { throw new AppwriteException('Missing required parameter: "teamId"'); } @@ -85,7 +85,7 @@ export class Teams { * @throws {AppwriteException} * @returns {Promise>} */ - get(teamId: string): Promise> { + get(teamId: string): Promise> { if (typeof teamId === 'undefined') { throw new AppwriteException('Missing required parameter: "teamId"'); } @@ -111,7 +111,7 @@ export class Teams { * @throws {AppwriteException} * @returns {Promise>} */ - updateName(teamId: string, name: string): Promise> { + updateName(teamId: string, name: string): Promise> { if (typeof teamId === 'undefined') { throw new AppwriteException('Missing required parameter: "teamId"'); } @@ -406,7 +406,7 @@ If the request is successful, a session for the user is automatically created. * @throws {AppwriteException} * @returns {Promise} */ - getPrefs(teamId: string): Promise { + getPrefs(teamId: string): Promise { if (typeof teamId === 'undefined') { throw new AppwriteException('Missing required parameter: "teamId"'); } @@ -432,7 +432,7 @@ If the request is successful, a session for the user is automatically created. * @throws {AppwriteException} * @returns {Promise} */ - updatePrefs(teamId: string, prefs: object): Promise { + updatePrefs(teamId: string, prefs: object): Promise { if (typeof teamId === 'undefined') { throw new AppwriteException('Missing required parameter: "teamId"'); }