From f9cb8f02902920c9e570a1d818e11f54a1b73da3 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 2 Feb 2026 12:04:25 +0000 Subject: [PATCH 1/2] Add array-based enum parameters --- .github/workflows/publish.yml | 17 +-- CHANGELOG.md | 4 + LICENSE | 2 +- README.md | 4 +- docs/examples/account/create-jwt.md | 4 +- docs/examples/avatars/get-screenshot.md | 10 +- docs/examples/databases/update-document.md | 8 +- docs/examples/databases/upsert-document.md | 8 +- docs/examples/tablesdb/update-row.md | 8 +- docs/examples/tablesdb/upsert-row.md | 8 +- docs/examples/teams/create-membership.md | 4 +- docs/examples/teams/update-membership.md | 4 +- package.json | 9 +- rollup.config.js | 14 ++- src/channel.ts | 134 +++++++++++++++++++++ src/client.ts | 47 +++++++- src/enums/browser-permission.ts | 22 ++++ src/enums/o-auth-provider.ts | 1 - src/enums/output.ts | 9 -- src/enums/roles.ts | 5 + src/index.ts | 6 +- src/models.ts | 8 ++ src/query.ts | 63 ++++++++-- src/services/account.ts | 31 ++++- src/services/avatars.ts | 33 ++--- src/services/databases.ts | 14 +-- src/services/storage.ts | 16 +-- src/services/teams.ts | 37 +++--- 28 files changed, 422 insertions(+), 108 deletions(-) create mode 100644 src/channel.ts create mode 100644 src/enums/browser-permission.ts delete mode 100644 src/enums/output.ts create mode 100644 src/enums/roles.ts diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9e8e7165..41c7a69c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -5,6 +5,10 @@ on: types: [published] workflow_dispatch: +permissions: + id-token: write + contents: read + jobs: publish: runs-on: ubuntu-latest @@ -12,14 +16,15 @@ jobs: steps: - uses: actions/checkout@v4 - # Setup Node.js environment - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '22' registry-url: 'https://registry.npmjs.org' - # Determine release tag based on the tag name + - name: Update npm to latest version for OIDC support + run: npm install -g npm@latest + - name: Determine release tag id: release_tag run: | @@ -29,14 +34,10 @@ jobs: echo "tag=latest" >> "$GITHUB_OUTPUT" fi - # Install dependencies (if any) and build your project (if necessary) - name: Install dependencies and build run: | npm install npm run build - # Publish to NPM with the appropriate tag - name: Publish - run: npm publish --tag ${{ steps.release_tag.outputs.tag }} - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_NO_ORG }} + run: npm publish --provenance --access public --tag ${{ steps.release_tag.outputs.tag }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab9bcca..02d4efe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log +## 0.20.0 + +* Add array-based enum parameters (e.g., `permissions: BrowserPermission[]`). + ## 0.19.0 * Add `getScreenshot` method to `Avatars` service diff --git a/LICENSE b/LICENSE index c1602fcd..6f8702b5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2025 Appwrite (https://appwrite.io) and individual contributors. +Copyright (c) 2026 Appwrite (https://appwrite.io) and individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index 6b771d55..ee5c4eb5 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # Appwrite React Native SDK ![License](https://img.shields.io/github/license/appwrite/sdk-for-react-native.svg?style=flat-square) -![Version](https://img.shields.io/badge/api%20version-1.8.0-blue.svg?style=flat-square) +![Version](https://img.shields.io/badge/api%20version-1.8.1-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) **This SDK is compatible with Appwrite server version 1.8.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-react-native/releases).** -Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the React Native SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs) +Appwrite is an open-source backend as a service server that abstracts and simplifies complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the React Native SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs) ![Appwrite](https://github.com/appwrite/appwrite/raw/main/public/images/github.png) diff --git a/docs/examples/account/create-jwt.md b/docs/examples/account/create-jwt.md index 217dc787..fbb3f362 100644 --- a/docs/examples/account/create-jwt.md +++ b/docs/examples/account/create-jwt.md @@ -6,6 +6,8 @@ const client = new Client() const account = new Account(client); -const result = await account.createJWT(); +const result = await account.createJWT({ + duration: 0 // optional +}); console.log(result); diff --git a/docs/examples/avatars/get-screenshot.md b/docs/examples/avatars/get-screenshot.md index 2e4b84de..8e216803 100644 --- a/docs/examples/avatars/get-screenshot.md +++ b/docs/examples/avatars/get-screenshot.md @@ -1,4 +1,4 @@ -import { Client, Avatars, Theme, Timezone, Output } from "react-native-appwrite"; +import { Client, Avatars, Theme, Timezone, BrowserPermission, ImageFormat } from "react-native-appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -15,21 +15,21 @@ const result = avatars.getScreenshot({ viewportWidth: 1920, // optional viewportHeight: 1080, // optional scale: 2, // optional - theme: Theme.Light, // optional + theme: Theme.Dark, // optional userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15', // optional fullpage: true, // optional locale: 'en-US', // optional - timezone: Timezone.AfricaAbidjan, // optional + timezone: Timezone.AmericaNewYork, // optional latitude: 37.7749, // optional longitude: -122.4194, // optional accuracy: 100, // optional touch: true, // optional - permissions: ["geolocation","notifications"], // optional + permissions: [BrowserPermission.Geolocation, BrowserPermission.Notifications], // optional sleep: 3, // optional width: 800, // optional height: 600, // optional quality: 85, // optional - output: Output.Jpg // optional + output: ImageFormat.Jpeg // optional }); console.log(result); diff --git a/docs/examples/databases/update-document.md b/docs/examples/databases/update-document.md index a82fa523..2be12b1a 100644 --- a/docs/examples/databases/update-document.md +++ b/docs/examples/databases/update-document.md @@ -10,7 +10,13 @@ const result = await databases.updateDocument({ databaseId: '', collectionId: '', documentId: '', - data: {}, // optional + data: { + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 33, + "isAdmin": false + }, // optional permissions: ["read("any")"], // optional transactionId: '' // optional }); diff --git a/docs/examples/databases/upsert-document.md b/docs/examples/databases/upsert-document.md index b6d2bed4..fcf1fb48 100644 --- a/docs/examples/databases/upsert-document.md +++ b/docs/examples/databases/upsert-document.md @@ -10,7 +10,13 @@ const result = await databases.upsertDocument({ databaseId: '', collectionId: '', documentId: '', - data: {}, + data: { + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + }, // optional permissions: ["read("any")"], // optional transactionId: '' // optional }); diff --git a/docs/examples/tablesdb/update-row.md b/docs/examples/tablesdb/update-row.md index b53b927b..9ba5054f 100644 --- a/docs/examples/tablesdb/update-row.md +++ b/docs/examples/tablesdb/update-row.md @@ -10,7 +10,13 @@ const result = await tablesDB.updateRow({ databaseId: '', tableId: '', rowId: '', - data: {}, // optional + data: { + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 33, + "isAdmin": false + }, // optional permissions: ["read("any")"], // optional transactionId: '' // optional }); diff --git a/docs/examples/tablesdb/upsert-row.md b/docs/examples/tablesdb/upsert-row.md index 28909273..bea81ba4 100644 --- a/docs/examples/tablesdb/upsert-row.md +++ b/docs/examples/tablesdb/upsert-row.md @@ -10,7 +10,13 @@ const result = await tablesDB.upsertRow({ databaseId: '', tableId: '', rowId: '', - data: {}, // optional + data: { + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 33, + "isAdmin": false + }, // optional permissions: ["read("any")"], // optional transactionId: '' // optional }); diff --git a/docs/examples/teams/create-membership.md b/docs/examples/teams/create-membership.md index e89d2ded..665fffab 100644 --- a/docs/examples/teams/create-membership.md +++ b/docs/examples/teams/create-membership.md @@ -1,4 +1,4 @@ -import { Client, Teams } from "react-native-appwrite"; +import { Client, Teams, Roles } from "react-native-appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -8,7 +8,7 @@ const teams = new Teams(client); const result = await teams.createMembership({ teamId: '', - roles: [], + roles: [Roles.Admin], email: 'email@example.com', // optional userId: '', // optional phone: '+12065550100', // optional diff --git a/docs/examples/teams/update-membership.md b/docs/examples/teams/update-membership.md index ada28634..4e352616 100644 --- a/docs/examples/teams/update-membership.md +++ b/docs/examples/teams/update-membership.md @@ -1,4 +1,4 @@ -import { Client, Teams } from "react-native-appwrite"; +import { Client, Teams, Roles } from "react-native-appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -9,7 +9,7 @@ const teams = new Teams(client); const result = await teams.updateMembership({ teamId: '', membershipId: '', - roles: [] + roles: [Roles.Admin] }); console.log(result); diff --git a/package.json b/package.json index 3db97fd6..f82bf3b5 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "react-native-appwrite", "homepage": "https://appwrite.io/support", - "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", - "version": "0.19.0", + "description": "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API", + "version": "0.20.0", "license": "BSD-3-Clause", "main": "dist/cjs/sdk.js", "exports": { @@ -26,6 +26,7 @@ }, "devDependencies": { "@rollup/plugin-typescript": "8.3.2", + "@types/json-bigint": "1.0.4", "playwright": "1.56.1", "rollup": "2.75.4", "serve-handler": "6.1.0", @@ -34,7 +35,9 @@ }, "dependencies": { "expo-file-system": "18.*.*", - "react-native": ">=0.76.7 <1.0.0" + "json-bigint": "1.0.0", + "react-native": ">=0.76.7 <1.0.0", + "bignumber.js": "^9.0.0" }, "peerDependencies": { "expo": "*" diff --git a/rollup.config.js b/rollup.config.js index fb0b38c5..8b8b474b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,9 +1,11 @@ import pkg from "./package.json"; import typescript from "@rollup/plugin-typescript"; +const external = Object.keys(pkg.dependencies ?? {}); + export default { - external: Object.keys(pkg.dependencies), input: "src/index.ts", + external, plugins: [typescript()], output: [ { @@ -17,5 +19,15 @@ export default { file: pkg.module, sourcemap: true, }, + { + format: "iife", + file: pkg.jsdelivr, + name: "Appwrite", + extend: true, + globals: { + "json-bigint": "JSONbig", + "bignumber.js": "BigNumber", + }, + }, ], }; diff --git a/src/channel.ts b/src/channel.ts new file mode 100644 index 00000000..1d68ded7 --- /dev/null +++ b/src/channel.ts @@ -0,0 +1,134 @@ +interface Root {} +interface Database { _db: any } +interface Collection { _coll: any } +interface Document { _doc: any } +interface TablesDB { _tdb: any } +interface Table { _tbl: any } +interface Row { _row: any } +interface Bucket { _bkt: any } +interface File { _file: any } +interface Func { _fn: any } +interface Execution { _exec: any } +interface Team { _team: any } +interface Membership { _mem: any } +interface Resolved { _res: any } + +type Actionable = Document | Row | File | Execution | Team | Membership; + +function normalize(id: string): string { + const trimmed = id.trim(); + return trimmed === "" ? "*" : trimmed; +} + +export class Channel { + declare _type: T; + + private constructor(private readonly segments: string[]) {} + + private next(segment: string, id: string = "*"): Channel { + return new Channel([...this.segments, segment, normalize(id)]) as any; + } + + private resolve(action: string): Channel { + return new Channel([...this.segments, action]) as any; + } + + toString(): string { + return this.segments.join("."); + } + + // --- DATABASE ROUTE --- + // Only available on Channel + collection(this: Channel, id: string = "*"): Channel { + return this.next("collections", id); + } + + // Only available on Channel + document(this: Channel, id: string = "*"): Channel { + return this.next("documents", id); + } + + // --- TABLESDB ROUTE --- + table(this: Channel, id: string = "*"): Channel { + return this.next
("tables", id); + } + + row(this: Channel
, id: string = "*"): Channel { + return this.next("rows", id); + } + + // --- BUCKET ROUTE --- + file(this: Channel, id: string = "*"): Channel { + return this.next("files", id); + } + + // --- FUNCTION ROUTE --- + execution(this: Channel, id: string = "*"): Channel { + return this.next("executions", id); + } + + // --- TERMINAL ACTIONS --- + // Restricted to the Actionable union + create(this: Channel): Channel { + return this.resolve("create"); + } + + update(this: Channel): Channel { + return this.resolve("update"); + } + + delete(this: Channel): Channel { + return this.resolve("delete"); + } + + // --- ROOT FACTORIES --- + static database(id: string = "*") { + return new Channel(["databases", normalize(id)]); + } + + static tablesdb(id: string = "*") { + return new Channel(["tablesdb", normalize(id)]); + } + + static bucket(id: string = "*") { + return new Channel(["buckets", normalize(id)]); + } + + static function(id: string = "*") { + return new Channel(["functions", normalize(id)]); + } + + static team(id: string = "*") { + return new Channel(["teams", normalize(id)]); + } + + static membership(id: string = "*") { + return new Channel(["memberships", normalize(id)]); + } + + static account(userId: string = ""): string { + const id = normalize(userId); + return id === "*" ? "account" : `account.${id}`; + } + + // Global events + static get documents(): string { + return "documents"; + } + + static get rows(): string { + return "rows"; + } + + static get files(): string { + return "files"; + } + + static get executions(): string { + return "executions"; + } +} + +// Export types for backward compatibility with realtime +export type ActionableChannel = Channel | Channel | Channel | Channel | Channel | Channel; +export type ResolvedChannel = Channel; diff --git a/src/client.ts b/src/client.ts index 7bcdd095..a1c6632f 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,6 +1,33 @@ import { Models } from './models'; import { Service } from './service'; import { Platform } from 'react-native'; +import JSONbigModule from 'json-bigint'; +import BigNumber from 'bignumber.js'; +const JSONbigParser = JSONbigModule({ storeAsString: false }); +const JSONbigSerializer = JSONbigModule({ useNativeBigInt: true }); + +const MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER); +const MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER); + +function reviver(_key: string, value: any): any { + if (BigNumber.isBigNumber(value)) { + if (value.isInteger()) { + const str = value.toFixed(); + const bi = BigInt(str); + if (bi >= MIN_SAFE && bi <= MAX_SAFE) { + return Number(str); + } + return bi; + } + return value.toNumber(); + } + return value; +} + +const JSONbig = { + parse: (text: string) => JSONbigParser.parse(text, reviver), + stringify: JSONbigSerializer.stringify +}; type Payload = { [key: string]: any; @@ -115,7 +142,7 @@ class Client { 'x-sdk-name': 'React Native', 'x-sdk-platform': 'client', 'x-sdk-language': 'reactnative', - 'x-sdk-version': '0.19.0', + 'x-sdk-version': '0.20.0', 'X-Appwrite-Response-Format': '1.8.0', }; @@ -129,6 +156,10 @@ class Client { * @returns {this} */ setEndpoint(endpoint: string): this { + if (!endpoint || typeof endpoint !== 'string') { + throw new AppwriteException('Endpoint must be a valid string'); + } + if (!endpoint.startsWith('http://') && !endpoint.startsWith('https://')) { throw new AppwriteException('Invalid endpoint URL: ' + endpoint); } @@ -147,6 +178,10 @@ class Client { * @returns {this} */ setEndpointRealtime(endpointRealtime: string): this { + if (!endpointRealtime || typeof endpointRealtime !== 'string') { + throw new AppwriteException('Endpoint must be a valid string'); + } + if (!endpointRealtime.startsWith('ws://') && !endpointRealtime.startsWith('wss://')) { throw new AppwriteException('Invalid realtime endpoint URL: ' + endpointRealtime); } @@ -278,7 +313,7 @@ class Client { } this.realtime.heartbeat = window?.setInterval(() => { - this.realtime.socket?.send(JSON.stringify({ + this.realtime.socket?.send(JSONbig.stringify({ type: 'ping' })); }, 20_000); @@ -347,7 +382,7 @@ class Client { }, onMessage: (event) => { try { - const message: RealtimeResponse = JSON.parse(event.data); + const message: RealtimeResponse = JSONbig.parse(event.data); this.realtime.lastMessage = message; switch (message.type) { case 'event': @@ -454,7 +489,7 @@ class Client { } else { switch (headers['content-type']) { case 'application/json': - options.body = JSON.stringify(params); + options.body = JSONbig.stringify(params); break; case 'multipart/form-data': @@ -487,7 +522,7 @@ class Client { } if (response.headers.get('content-type')?.includes('application/json')) { - data = await response.json(); + data = JSONbig.parse(await response.text()); } else if (responseType === 'arrayBuffer') { data = await response.arrayBuffer(); } else { @@ -499,7 +534,7 @@ class Client { if (400 <= response.status) { let responseText = ''; if (response.headers.get('content-type')?.includes('application/json')) { - responseText = JSON.stringify(data); + responseText = JSONbig.stringify(data); } else { responseText = data?.message; } diff --git a/src/enums/browser-permission.ts b/src/enums/browser-permission.ts new file mode 100644 index 00000000..77b62f46 --- /dev/null +++ b/src/enums/browser-permission.ts @@ -0,0 +1,22 @@ +export enum BrowserPermission { + Geolocation = 'geolocation', + Camera = 'camera', + Microphone = 'microphone', + Notifications = 'notifications', + Midi = 'midi', + Push = 'push', + ClipboardRead = 'clipboard-read', + ClipboardWrite = 'clipboard-write', + PaymentHandler = 'payment-handler', + Usb = 'usb', + Bluetooth = 'bluetooth', + Accelerometer = 'accelerometer', + Gyroscope = 'gyroscope', + Magnetometer = 'magnetometer', + AmbientLightSensor = 'ambient-light-sensor', + BackgroundSync = 'background-sync', + PersistentStorage = 'persistent-storage', + ScreenWakeLock = 'screen-wake-lock', + WebShare = 'web-share', + XrSpatialTracking = 'xr-spatial-tracking', +} \ No newline at end of file diff --git a/src/enums/o-auth-provider.ts b/src/enums/o-auth-provider.ts index 7a3fcb3f..3382e3bf 100644 --- a/src/enums/o-auth-provider.ts +++ b/src/enums/o-auth-provider.ts @@ -38,5 +38,4 @@ export enum OAuthProvider { Yandex = 'yandex', Zoho = 'zoho', Zoom = 'zoom', - Mock = 'mock', } \ No newline at end of file diff --git a/src/enums/output.ts b/src/enums/output.ts deleted file mode 100644 index c339a512..00000000 --- a/src/enums/output.ts +++ /dev/null @@ -1,9 +0,0 @@ -export enum Output { - Jpg = 'jpg', - Jpeg = 'jpeg', - Png = 'png', - Webp = 'webp', - Heic = 'heic', - Avif = 'avif', - Gif = 'gif', -} \ No newline at end of file diff --git a/src/enums/roles.ts b/src/enums/roles.ts new file mode 100644 index 00000000..f548f935 --- /dev/null +++ b/src/enums/roles.ts @@ -0,0 +1,5 @@ +export enum Roles { + Admin = 'admin', + Developer = 'developer', + Owner = 'owner', +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index a949462c..50baa582 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ export { Query } from './query'; export { Permission } from './permission'; export { Role } from './role'; export { ID } from './id'; +export { Channel } from './channel'; export { Operator, Condition } from './operator'; export { AuthenticatorType } from './enums/authenticator-type'; export { AuthenticationFactor } from './enums/authentication-factor'; @@ -24,9 +25,10 @@ export { CreditCard } from './enums/credit-card'; export { Flag } from './enums/flag'; export { Theme } from './enums/theme'; export { Timezone } from './enums/timezone'; -export { Output } from './enums/output'; +export { BrowserPermission } from './enums/browser-permission'; +export { ImageFormat } from './enums/image-format'; export { ExecutionMethod } from './enums/execution-method'; export { ImageGravity } from './enums/image-gravity'; -export { ImageFormat } from './enums/image-format'; +export { Roles } from './enums/roles'; export { ExecutionTrigger } from './enums/execution-trigger'; export { ExecutionStatus } from './enums/execution-status'; diff --git a/src/models.ts b/src/models.ts index 8731110c..cbe1e894 100644 --- a/src/models.ts +++ b/src/models.ts @@ -904,6 +904,14 @@ export namespace Models { * Total number of chunks uploaded */ chunksUploaded: number; + /** + * Whether file contents are encrypted at rest. + */ + encryption: boolean; + /** + * Compression algorithm used for the file. Will be one of none, [gzip](https://en.wikipedia.org/wiki/Gzip), or [zstd](https://en.wikipedia.org/wiki/Zstd). + */ + compression: string; } /** diff --git a/src/query.ts b/src/query.ts index 89a88ef3..5b33fb2a 100644 --- a/src/query.ts +++ b/src/query.ts @@ -1,5 +1,8 @@ -type QueryTypesSingle = string | number | boolean; -export type QueryTypesList = string[] | number[] | boolean[] | Query[] | any[]; +import JSONbigModule from 'json-bigint'; +const JSONbig = JSONbigModule({ useNativeBigInt: true }); + +type QueryTypesSingle = string | number | bigint | boolean; +export type QueryTypesList = string[] | number[] | bigint[] | boolean[] | Query[] | any[]; export type QueryTypes = QueryTypesSingle | QueryTypesList; type AttributesTypes = string | string[]; @@ -26,7 +29,7 @@ export class Query { } toString(): string { - return JSON.stringify({ + return JSONbig.stringify({ method: this.method, attribute: this.attribute, values: this.values, @@ -39,6 +42,16 @@ export class Query { static notEqual = (attribute: string, value: QueryTypes): string => new Query("notEqual", attribute, value).toString(); + /** + * Filter resources where attribute matches a regular expression pattern. + * + * @param {string} attribute The attribute to filter on. + * @param {string} pattern The regular expression pattern to match. + * @returns {string} + */ + static regex = (attribute: string, pattern: string): string => + new Query("regex", attribute, pattern).toString(); + static lessThan = (attribute: string, value: QueryTypes): string => new Query("lessThan", attribute, value).toString(); @@ -57,7 +70,25 @@ export class Query { static isNotNull = (attribute: string): string => new Query("isNotNull", attribute).toString(); - static between = (attribute: string, start: string | number, end: string | number) => + /** + * Filter resources where the specified attributes exist. + * + * @param {string[]} attributes The list of attributes that must exist. + * @returns {string} + */ + static exists = (attributes: string[]): string => + new Query("exists", undefined, attributes).toString(); + + /** + * Filter resources where the specified attributes do not exist. + * + * @param {string[]} attributes The list of attributes that must not exist. + * @returns {string} + */ + static notExists = (attributes: string[]): string => + new Query("notExists", undefined, attributes).toString(); + + static between = (attribute: string, start: string | number | bigint, end: string | number | bigint) => new Query("between", attribute, [start, end] as QueryTypesList).toString(); static startsWith = (attribute: string, value: string): string => @@ -128,11 +159,11 @@ export class Query { * Filter resources where attribute is not between start and end (exclusive). * * @param {string} attribute - * @param {string | number} start - * @param {string | number} end + * @param {string | number | bigint} start + * @param {string | number | bigint} end * @returns {string} */ - static notBetween = (attribute: string, start: string | number, end: string | number): string => + static notBetween = (attribute: string, start: string | number | bigint, end: string | number | bigint): string => new Query("notBetween", attribute, [start, end] as QueryTypesList).toString(); /** @@ -212,10 +243,24 @@ export class Query { Query.between("$updatedAt", start, end); static or = (queries: string[]) => - new Query("or", undefined, queries.map((query) => JSON.parse(query))).toString(); + new Query("or", undefined, queries.map((query) => JSONbig.parse(query))).toString(); static and = (queries: string[]) => - new Query("and", undefined, queries.map((query) => JSON.parse(query))).toString(); + new Query("and", undefined, queries.map((query) => JSONbig.parse(query))).toString(); + + /** + * Filter array elements where at least one element matches all the specified queries. + * + * @param {string} attribute The attribute containing the array to filter on. + * @param {string[]} queries The list of query strings to match against array elements. + * @returns {string} + */ + static elemMatch = (attribute: string, queries: string[]): string => + new Query( + "elemMatch", + attribute, + queries.map((query) => JSONbig.parse(query)) + ).toString(); /** * Filter resources where attribute is at a specific distance from the given coordinates. diff --git a/src/services/account.ts b/src/services/account.ts index 7ef9574d..cee6e8b5 100644 --- a/src/services/account.ts +++ b/src/services/account.ts @@ -280,13 +280,42 @@ export class Account extends Service { /** * Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame. * + * @param {number} params.duration - Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds. * @throws {AppwriteException} * @returns {Promise} */ - createJWT(): Promise { + createJWT(params?: { duration?: number }): Promise; + /** + * Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame. + * + * @param {number} duration - Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + createJWT(duration?: number): Promise; + createJWT( + paramsOrFirst?: { duration?: number } | number + ): Promise { + let params: { duration?: number }; + + if (!paramsOrFirst || (paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { + params = (paramsOrFirst || {}) as { duration?: number }; + } else { + params = { + duration: paramsOrFirst as number + }; + } + + const duration = params.duration; + const apiPath = '/account/jwts'; const payload: Payload = {}; + if (typeof duration !== 'undefined') { + payload['duration'] = duration; + } + const uri = new URL(this.client.config.endpoint + apiPath); return this.client.call('post', uri, { 'content-type': 'application/json', diff --git a/src/services/avatars.ts b/src/services/avatars.ts index 4a07449f..e7f475ce 100644 --- a/src/services/avatars.ts +++ b/src/services/avatars.ts @@ -10,7 +10,8 @@ import { CreditCard } from '../enums/credit-card'; import { Flag } from '../enums/flag'; import { Theme } from '../enums/theme'; import { Timezone } from '../enums/timezone'; -import { Output } from '../enums/output'; +import { BrowserPermission } from '../enums/browser-permission'; +import { ImageFormat } from '../enums/image-format'; export class Avatars extends Service { @@ -584,16 +585,16 @@ export class Avatars extends Service { * @param {number} params.longitude - Geolocation longitude. Pass a number between -180 to 180. Defaults to 0. * @param {number} params.accuracy - Geolocation accuracy in meters. Pass a number between 0 to 100000. Defaults to 0. * @param {boolean} params.touch - Enable touch support. Pass 0 for no touch, or 1 for touch enabled. Defaults to 0. - * @param {string[]} params.permissions - Browser permissions to grant. Pass an array of permission names like ["geolocation", "camera", "microphone"]. Defaults to empty. + * @param {BrowserPermission[]} params.permissions - Browser permissions to grant. Pass an array of permission names like ["geolocation", "camera", "microphone"]. Defaults to empty. * @param {number} params.sleep - Wait time in seconds before taking the screenshot. Pass an integer between 0 to 10. Defaults to 0. * @param {number} params.width - Output image width. Pass 0 to use original width, or an integer between 1 to 2000. Defaults to 0 (original width). * @param {number} params.height - Output image height. Pass 0 to use original height, or an integer between 1 to 2000. Defaults to 0 (original height). * @param {number} params.quality - Screenshot quality. Pass an integer between 0 to 100. Defaults to keep existing image quality. - * @param {Output} params.output - Output format type (jpeg, jpg, png, gif and webp). + * @param {ImageFormat} params.output - Output format type (jpeg, jpg, png, gif and webp). * @throws {AppwriteException} * @returns {ArrayBuffer} */ - getScreenshot(params: { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: string[], sleep?: number, width?: number, height?: number, quality?: number, output?: Output }): Promise; + getScreenshot(params: { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: BrowserPermission[], sleep?: number, width?: number, height?: number, quality?: number, output?: ImageFormat }): Promise; /** * Use this endpoint to capture a screenshot of any website URL. This endpoint uses a headless browser to render the webpage and capture it as an image. * @@ -615,25 +616,25 @@ export class Avatars extends Service { * @param {number} longitude - Geolocation longitude. Pass a number between -180 to 180. Defaults to 0. * @param {number} accuracy - Geolocation accuracy in meters. Pass a number between 0 to 100000. Defaults to 0. * @param {boolean} touch - Enable touch support. Pass 0 for no touch, or 1 for touch enabled. Defaults to 0. - * @param {string[]} permissions - Browser permissions to grant. Pass an array of permission names like ["geolocation", "camera", "microphone"]. Defaults to empty. + * @param {BrowserPermission[]} permissions - Browser permissions to grant. Pass an array of permission names like ["geolocation", "camera", "microphone"]. Defaults to empty. * @param {number} sleep - Wait time in seconds before taking the screenshot. Pass an integer between 0 to 10. Defaults to 0. * @param {number} width - Output image width. Pass 0 to use original width, or an integer between 1 to 2000. Defaults to 0 (original width). * @param {number} height - Output image height. Pass 0 to use original height, or an integer between 1 to 2000. Defaults to 0 (original height). * @param {number} quality - Screenshot quality. Pass an integer between 0 to 100. Defaults to keep existing image quality. - * @param {Output} output - Output format type (jpeg, jpg, png, gif and webp). + * @param {ImageFormat} output - Output format type (jpeg, jpg, png, gif and webp). * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. */ - getScreenshot(url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: string[], sleep?: number, width?: number, height?: number, quality?: number, output?: Output): Promise; + getScreenshot(url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: BrowserPermission[], sleep?: number, width?: number, height?: number, quality?: number, output?: ImageFormat): Promise; getScreenshot( - paramsOrFirst: { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: string[], sleep?: number, width?: number, height?: number, quality?: number, output?: Output } | string, - ...rest: [(object)?, (number)?, (number)?, (number)?, (Theme)?, (string)?, (boolean)?, (string)?, (Timezone)?, (number)?, (number)?, (number)?, (boolean)?, (string[])?, (number)?, (number)?, (number)?, (number)?, (Output)?] + paramsOrFirst: { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: BrowserPermission[], sleep?: number, width?: number, height?: number, quality?: number, output?: ImageFormat } | string, + ...rest: [(object)?, (number)?, (number)?, (number)?, (Theme)?, (string)?, (boolean)?, (string)?, (Timezone)?, (number)?, (number)?, (number)?, (boolean)?, (BrowserPermission[])?, (number)?, (number)?, (number)?, (number)?, (ImageFormat)?] ): Promise { - let params: { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: string[], sleep?: number, width?: number, height?: number, quality?: number, output?: Output }; + let params: { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: BrowserPermission[], sleep?: number, width?: number, height?: number, quality?: number, output?: ImageFormat }; if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { - params = (paramsOrFirst || {}) as { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: string[], sleep?: number, width?: number, height?: number, quality?: number, output?: Output }; + params = (paramsOrFirst || {}) as { url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: BrowserPermission[], sleep?: number, width?: number, height?: number, quality?: number, output?: ImageFormat }; } else { params = { url: paramsOrFirst as string, @@ -650,12 +651,12 @@ export class Avatars extends Service { longitude: rest[10] as number, accuracy: rest[11] as number, touch: rest[12] as boolean, - permissions: rest[13] as string[], + permissions: rest[13] as BrowserPermission[], sleep: rest[14] as number, width: rest[15] as number, height: rest[16] as number, quality: rest[17] as number, - output: rest[18] as Output + output: rest[18] as ImageFormat }; } @@ -1108,16 +1109,16 @@ export class Avatars extends Service { * @param {number} longitude * @param {number} accuracy * @param {boolean} touch - * @param {string[]} permissions + * @param {BrowserPermission[]} permissions * @param {number} sleep * @param {number} width * @param {number} height * @param {number} quality - * @param {Output} output + * @param {ImageFormat} output * @throws {AppwriteException} * @returns {URL} */ - getScreenshotURL(url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: string[], sleep?: number, width?: number, height?: number, quality?: number, output?: Output): URL { + getScreenshotURL(url: string, headers?: object, viewportWidth?: number, viewportHeight?: number, scale?: number, theme?: Theme, userAgent?: string, fullpage?: boolean, locale?: string, timezone?: Timezone, latitude?: number, longitude?: number, accuracy?: number, touch?: boolean, permissions?: BrowserPermission[], sleep?: number, width?: number, height?: number, quality?: number, output?: ImageFormat): URL { const apiPath = '/avatars/screenshots'; const payload: Payload = {}; diff --git a/src/services/databases.ts b/src/services/databases.ts index e25662e9..19955920 100644 --- a/src/services/databases.ts +++ b/src/services/databases.ts @@ -571,7 +571,7 @@ export class Databases extends Service { * @returns {Promise} * @deprecated This API has been deprecated since 1.8.0. Please use `TablesDB.upsertRow` instead. */ - upsertDocument(params: { databaseId: string, collectionId: string, documentId: string, data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string }): Promise; + upsertDocument(params: { databaseId: string, collectionId: string, documentId: string, data?: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string }): Promise; /** * 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. * @@ -585,15 +585,15 @@ export class Databases extends Service { * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. */ - upsertDocument(databaseId: string, collectionId: string, documentId: string, data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string): Promise; + upsertDocument(databaseId: string, collectionId: string, documentId: string, data?: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string): Promise; upsertDocument( - paramsOrFirst: { databaseId: string, collectionId: string, documentId: string, data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string } | string, + paramsOrFirst: { databaseId: string, collectionId: string, documentId: string, data?: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string } | string, ...rest: [(string)?, (string)?, (Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>)?, (string[])?, (string)?] ): Promise { - let params: { databaseId: string, collectionId: string, documentId: string, data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string }; + let params: { databaseId: string, collectionId: string, documentId: string, data?: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string }; if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { - params = (paramsOrFirst || {}) as { databaseId: string, collectionId: string, documentId: string, data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string }; + params = (paramsOrFirst || {}) as { databaseId: string, collectionId: string, documentId: string, data?: Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>, permissions?: string[], transactionId?: string }; } else { params = { databaseId: paramsOrFirst as string, @@ -624,10 +624,6 @@ export class Databases extends Service { throw new AppwriteException('Missing required parameter: "documentId"'); } - if (typeof data === 'undefined') { - throw new AppwriteException('Missing required parameter: "data"'); - } - const apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}'.replace('{databaseId}', databaseId).replace('{collectionId}', collectionId).replace('{documentId}', documentId); const payload: Payload = {}; diff --git a/src/services/storage.ts b/src/services/storage.ts index e1d4a310..f9f6748b 100644 --- a/src/services/storage.ts +++ b/src/services/storage.ts @@ -289,10 +289,10 @@ export class Storage extends Service { /** * Update a file by its unique ID. Only users with write permissions have access to update this resource. * - * @param {string} params.bucketId - Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket). - * @param {string} params.fileId - File unique ID. - * @param {string} params.name - Name of the file - * @param {string[]} params.permissions - An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string} params.bucketId - Bucket unique ID. + * @param {string} params.fileId - File ID. + * @param {string} params.name - File name. + * @param {string[]} params.permissions - An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). * @throws {AppwriteException} * @returns {Promise} */ @@ -300,10 +300,10 @@ export class Storage extends Service { /** * Update a file by its unique ID. Only users with write permissions have access to update this resource. * - * @param {string} bucketId - Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket). - * @param {string} fileId - File unique ID. - * @param {string} name - Name of the file - * @param {string[]} permissions - An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string} bucketId - Bucket unique ID. + * @param {string} fileId - File ID. + * @param {string} name - File name. + * @param {string[]} permissions - An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. diff --git a/src/services/teams.ts b/src/services/teams.ts index ae8c4ea4..19a462b6 100644 --- a/src/services/teams.ts +++ b/src/services/teams.ts @@ -5,6 +5,7 @@ import type { UploadProgress, Payload } from '../client'; import * as FileSystem from 'expo-file-system'; import { Platform } from 'react-native'; +import { Roles } from '../enums/roles'; export class Teams extends Service { @@ -371,7 +372,7 @@ export class Teams extends Service { * * * @param {string} params.teamId - Team ID. - * @param {string[]} params.roles - Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. + * @param {Roles[]} params.roles - Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. * @param {string} params.email - Email of the new team member. * @param {string} params.userId - ID of the user to be added to a team. * @param {string} params.phone - Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212. @@ -380,7 +381,7 @@ export class Teams extends Service { * @throws {AppwriteException} * @returns {Promise} */ - createMembership(params: { teamId: string, roles: string[], email?: string, userId?: string, phone?: string, url?: string, name?: string }): Promise; + createMembership(params: { teamId: string, roles: Roles[], email?: string, userId?: string, phone?: string, url?: string, name?: string }): Promise; /** * Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team. * @@ -392,7 +393,7 @@ export class Teams extends Service { * * * @param {string} teamId - Team ID. - * @param {string[]} roles - Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. + * @param {Roles[]} roles - Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. * @param {string} email - Email of the new team member. * @param {string} userId - ID of the user to be added to a team. * @param {string} phone - Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212. @@ -402,19 +403,19 @@ export class Teams extends Service { * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. */ - createMembership(teamId: string, roles: string[], email?: string, userId?: string, phone?: string, url?: string, name?: string): Promise; + createMembership(teamId: string, roles: Roles[], email?: string, userId?: string, phone?: string, url?: string, name?: string): Promise; createMembership( - paramsOrFirst: { teamId: string, roles: string[], email?: string, userId?: string, phone?: string, url?: string, name?: string } | string, - ...rest: [(string[])?, (string)?, (string)?, (string)?, (string)?, (string)?] + paramsOrFirst: { teamId: string, roles: Roles[], email?: string, userId?: string, phone?: string, url?: string, name?: string } | string, + ...rest: [(Roles[])?, (string)?, (string)?, (string)?, (string)?, (string)?] ): Promise { - let params: { teamId: string, roles: string[], email?: string, userId?: string, phone?: string, url?: string, name?: string }; + let params: { teamId: string, roles: Roles[], email?: string, userId?: string, phone?: string, url?: string, name?: string }; if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { - params = (paramsOrFirst || {}) as { teamId: string, roles: string[], email?: string, userId?: string, phone?: string, url?: string, name?: string }; + params = (paramsOrFirst || {}) as { teamId: string, roles: Roles[], email?: string, userId?: string, phone?: string, url?: string, name?: string }; } else { params = { teamId: paramsOrFirst as string, - roles: rest[0] as string[], + roles: rest[0] as Roles[], email: rest[1] as string, userId: rest[2] as string, phone: rest[3] as string, @@ -531,36 +532,36 @@ export class Teams extends Service { * * @param {string} params.teamId - Team ID. * @param {string} params.membershipId - Membership ID. - * @param {string[]} params.roles - An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. + * @param {Roles[]} params.roles - An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. * @throws {AppwriteException} * @returns {Promise} */ - updateMembership(params: { teamId: string, membershipId: string, roles: string[] }): Promise; + updateMembership(params: { teamId: string, membershipId: string, roles: Roles[] }): Promise; /** * Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). * * * @param {string} teamId - Team ID. * @param {string} membershipId - Membership ID. - * @param {string[]} roles - An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. + * @param {Roles[]} roles - An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. */ - updateMembership(teamId: string, membershipId: string, roles: string[]): Promise; + updateMembership(teamId: string, membershipId: string, roles: Roles[]): Promise; updateMembership( - paramsOrFirst: { teamId: string, membershipId: string, roles: string[] } | string, - ...rest: [(string)?, (string[])?] + paramsOrFirst: { teamId: string, membershipId: string, roles: Roles[] } | string, + ...rest: [(string)?, (Roles[])?] ): Promise { - let params: { teamId: string, membershipId: string, roles: string[] }; + let params: { teamId: string, membershipId: string, roles: Roles[] }; if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { - params = (paramsOrFirst || {}) as { teamId: string, membershipId: string, roles: string[] }; + params = (paramsOrFirst || {}) as { teamId: string, membershipId: string, roles: Roles[] }; } else { params = { teamId: paramsOrFirst as string, membershipId: rest[0] as string, - roles: rest[1] as string[] + roles: rest[1] as Roles[] }; } From ec20ef214b71b5b83d976da324ec054ec2b21097 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 2 Feb 2026 12:29:14 +0000 Subject: [PATCH 2/2] update changelog etc --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02d4efe0..737ef947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## 0.20.0 * Add array-based enum parameters (e.g., `permissions: BrowserPermission[]`). +* Breaking change: `Output` enum has been removed; use `ImageFormat` instead. +* Add `Channel` helpers for Realtime. ## 0.19.0