Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 29 additions & 36 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,36 @@
# Change Log

## 29.0.0

* Breaking: requests send `X-Appwrite-Response-Format: 2.5.0`; responses follow the 2.5 shapes
* Breaking: missing response fields are filled with their documented defaults
* Breaking: `oauth2` `resource` params now take `string[]` on `authorize`, `authorizePost`, `createDeviceAuthorization`, `createPAR` and `createToken`
* Breaking: nullable model fields are typed `T | null`, such as `Locale.city`, `Presence.status` and `Execution.scheduledAt`
* Added: `Push` service with `subscribe`, `unsubscribe`, `onNotificationOpened` and `close` for web push
* Added: `Topic` helper
* Added: `Query` aggregates (`count`, `countDistinct`, `sum`, `avg`, `min`, `max` and more), `groupBy`, `having`, `distinct`, joins, `relationship`, `covers`, `spatialEquals` and `page`
* Added: `Query.builder()` to chain queries; realtime subscriptions accept a builder for `queries`
* Added: `ExecutionTrigger.Email`
* Updated: nullable request params accept `null`, such as `account.createEmailPasswordSession` `duration`
* Fixed: list and object defaults filled into a response are copied per model, and object defaults are `{}` instead of `[]`

## 28.3.0

* Added: `analytics.createEvent` in a new `Analytics` service to send tracking events
* Added: `Tracking` helper that auto-tracks pageviews, outbound links, downloads, scroll depth and engagement time
* Added: `avatars.updatePhoto` and `avatars.deletePhoto` to manage the user's custom profile photo, and the `Account` model
* Added: `Webflow` to the `OAuthProvider` enum
* Added: optional `state` on `account.createOAuth2Session` and `account.createOAuth2Token`, returned unchanged on the success and failure URLs
* Added: optional `duration` on `account.createEmailPasswordSession` to set the session length
* Added: optional `current` on `account.deleteSessions` to keep the current session signed in
* Added: optional `membershipId` on `teams.createMembership`
* Added: optional `total` on `account.listSessions`, the `locale` list methods and `listTransactions`

## 28.2.0-rc.7

* Added: `Analytics` service and the `Tracking` auto-tracking helper, which were missing from `28.2.0-rc.5` and `rc.6`
* Changed: `Tracking` takes `new Analytics(client)` and a property id instead of an emitter callback; the adapter to `createEvent` now lives inside the SDK
* Changed: `enableAllAutoTracking()` is now `start()`
* Removed: `AnalyticsEventEmitter`; the option types are now `TrackingEventOptions` and `TrackingOptions`

## 28.2.0-rc.6

* Added: `Push.onNotificationOpened()` fires when a user taps a shown notification
* Added: `Push.getInitialNotification()` (returns `null` on web) and the `PushNotificationOpened` type
* Added: tapping a push notification focuses then closes the page
* Fixed: `subscribe()` resolves the signed-in user from `cookieFallback`, not just an explicit session
* Fixed: background notifications de-duplicate by title, so each distinct title posts once
* Updated: clearer error messages for missing credentials in push

## 28.2.0-rc.5

* Updated: regenerated with sdk-generator 5.5.0; no SDK code changes

## 28.2.0-rc.3

* Added: background push notifications render the server `notification` title, body, and image
* Added: notification `data` now carries `topic` and `payload`
* Fixed: a server-sent title dedupes to one notification per topic instead of one per subscription
* Fixed: malformed push payloads no longer break notification rendering
## 28.2.0

## 28.2.0-rc.2

* Added: `Push` service for MQTT realtime push messages
* Added: `Topic` and `ResolvedTopic` builders for push topic filters
* Added: `Client.setPushEndpoint()` and `Client.setPushClientId()`
* Added: `Avatars.deletePhoto()` method
* Added: `Models.Account` type
* Added: `Webflow` to the `OAuthProvider` enum
* Updated: `Client.chunkedUpload()` accepts a `responseType`, supports `text`, and falls back without a file
* Added: `account` passkey methods `listPasskeys`, `createPasskey`, `getPasskey`, `updatePasskey`, `deletePasskey` and `updatePasskeyVerification`
* Added: `account.createPasskeyToken` and `account.updatePasskeyToken` for passkey sign-in
* Added: `Passkey`, `PasskeyList`, `PasskeyChallenge` and `TokenSecret` models

## 28.1.0

Expand Down Expand Up @@ -250,4 +244,3 @@
* Fix pong response & chunked upload
* Add `ping` support to `Realtime` service


57 changes: 36 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# 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-2.3.0-blue.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-2.5.0-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 targets Appwrite server version 2.3.x as shipped on Appwrite Cloud.** Self-hosted releases can lag behind Cloud — if you run an older self-hosted build, use a matching older SDK from [previous releases](https://github.com/appwrite/sdk-for-web/releases) when APIs differ.
**This SDK targets Appwrite server version 2.5.x as shipped on Appwrite Cloud.** Self-hosted releases can lag behind Cloud — if you run an older self-hosted build, use a matching older SDK from [previous releases](https://github.com/appwrite/sdk-for-web/releases) when APIs differ.

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 Web 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)

Expand All @@ -33,7 +33,7 @@ import { Client, Account } from 'appwrite';
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:

```html
<script src="https://cdn.jsdelivr.net/npm/appwrite@28.2.0-rc.7"></script>
<script src="https://cdn.jsdelivr.net/npm/appwrite@29.0.0"></script>
```

## Getting Started
Expand Down Expand Up @@ -66,7 +66,12 @@ Once your SDK object is set, access any of the Appwrite services and choose any
const account = new Account(client);

// Register User
account.create(ID.unique(), "email@example.com", "password", "Walter O'Brien")
account.create({
userId: ID.unique(),
email: "email@example.com",
password: "password",
name: "Walter O'Brien"
})
.then(function (response) {
console.log(response);
}, function (error) {
Expand All @@ -89,7 +94,12 @@ client
const account = new Account(client);

// Register User
account.create(ID.unique(), "email@example.com", "password", "Walter O'Brien")
account.create({
userId: ID.unique(),
email: "email@example.com",
password: "password",
name: "Walter O'Brien"
})
.then(function (response) {
console.log(response);
}, function (error) {
Expand All @@ -99,11 +109,11 @@ account.create(ID.unique(), "email@example.com", "password", "Walter O'Brien")

### Type Safety with Models

The Appwrite Web SDK provides type safety when working with database documents through generic methods. Methods like `listDocuments`, `getDocument`, and others accept a generic type parameter that allows you to specify your custom model type for full type safety.
The Appwrite Web SDK provides type safety when working with table rows through generic methods. Methods like `listRows`, `getRow`, and others accept a generic type parameter that allows you to specify your custom model type for full type safety.

**TypeScript:**
```typescript
interface Book {
interface Book extends Models.Row {
name: string;
author: string;
releaseYear?: string;
Expand All @@ -112,15 +122,15 @@ interface Book {
isCheckedOut: boolean;
}

const databases = new Databases(client);
const tablesDB = new TablesDB(client);

try {
const documents = await databases.listDocuments<Book>(
'your-database-id',
'your-collection-id'
);
const result = await tablesDB.listRows<Book>({
databaseId: 'your-database-id',
tableId: 'your-table-id'
});

documents.documents.forEach(book => {
result.rows.forEach(book => {
console.log(`Book: ${book.name} by ${book.author}`); // Now you have full type safety
});
} catch (error) {
Expand All @@ -140,16 +150,16 @@ try {
* @property {boolean} isCheckedOut
*/

const databases = new Databases(client);
const tablesDB = new TablesDB(client);

try {
/** @type {Models.DocumentList<Book>} */
const documents = await databases.listDocuments(
'your-database-id',
'your-collection-id'
);
/** @type {Models.RowList<Book>} */
const result = await tablesDB.listRows({
databaseId: 'your-database-id',
tableId: 'your-table-id'
});

documents.documents.forEach(book => {
result.rows.forEach(book => {
console.log(`Book: ${book.name} by ${book.author}`); // Type hints available in IDE
});
} catch (error) {
Expand All @@ -165,7 +175,12 @@ The Appwrite Web SDK raises an `AppwriteException` object with `message`, `code`

```javascript
try {
const user = await account.create(ID.unique(), "email@example.com", "password", "Walter O'Brien");
const user = await account.create({
userId: ID.unique(),
email: "email@example.com",
password: "password",
name: "Walter O'Brien"
});
console.log('User created:', user);
} catch (error) {
console.error('Appwrite error:', error.message);
Expand Down
13 changes: 13 additions & 0 deletions docs/examples/account/create-passkey-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.createPasskeyToken();

console.log(result);
```
16 changes: 16 additions & 0 deletions docs/examples/account/create-passkey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.createPasskey({
passkeyId: '<PASSKEY_ID>', // optional
name: '<NAME>', // optional
});

console.log(result);
```
15 changes: 15 additions & 0 deletions docs/examples/account/delete-passkey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.deletePasskey({
passkeyId: '<PASSKEY_ID>',
});

console.log(result);
```
15 changes: 15 additions & 0 deletions docs/examples/account/get-passkey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.getPasskey({
passkeyId: '<PASSKEY_ID>',
});

console.log(result);
```
16 changes: 16 additions & 0 deletions docs/examples/account/list-passkeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.listPasskeys({
queries: [], // optional
total: false, // optional
});

console.log(result);
```
16 changes: 16 additions & 0 deletions docs/examples/account/update-passkey-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.updatePasskeyToken({
challengeId: '<CHALLENGE_ID>',
credential: {},
});

console.log(result);
```
16 changes: 16 additions & 0 deletions docs/examples/account/update-passkey-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.updatePasskeyVerification({
passkeyId: '<PASSKEY_ID>',
credential: {},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passkey verification example uses an invalid credential

This sends {} as the WebAuthn credential, but updatePasskeyVerification requires the JSON result of PublicKeyCredential.toJSON(); running this example fails API validation instead of completing registration. The update-passkey-token.md example uses the same empty credential placeholder.

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/examples/account/update-passkey-verification.md
Line: 12

Comment:
**Passkey verification example uses an invalid credential**

This sends `{}` as the WebAuthn credential, but `updatePasskeyVerification` requires the JSON result of `PublicKeyCredential.toJSON()`; running this example fails API validation instead of completing registration. The `update-passkey-token.md` example uses the same empty credential placeholder.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

🟡 Minor · documentation · Reply if this doesn't apply.

});

console.log(result);
```
16 changes: 16 additions & 0 deletions docs/examples/account/update-passkey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```javascript
import { Client, Account } from 'appwrite';

const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID

const account = new Account(client);

const result = await account.updatePasskey({
passkeyId: '<PASSKEY_ID>',
name: '<NAME>',
});

console.log(result);
```
2 changes: 1 addition & 1 deletion docs/examples/analytics/create-event.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const result = await analytics.createEvent({
url: 'https://example.com',
domain: '<DOMAIN>', // optional
referrer: '<REFERRER>', // optional
screenWidth: null, // optional
screenWidth: 0, // optional
sessionHash: '<SESSION_HASH>', // optional
scrollDepth: 0, // optional
engagementTime: 0, // optional
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/oauth2/authorize-post.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const result = await oauth2.authorizePost({
prompt: '<PROMPT>', // optional
maxAge: 0, // optional
authorizationDetails: '<AUTHORIZATION_DETAILS>', // optional
resource: '', // optional
resource: [], // optional
audience: '<AUDIENCE>', // optional
requestUri: '<REQUEST_URI>', // optional
});
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/oauth2/authorize.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const result = await oauth2.authorize({
prompt: '<PROMPT>', // optional
maxAge: 0, // optional
authorizationDetails: '<AUTHORIZATION_DETAILS>', // optional
resource: '', // optional
resource: [], // optional
audience: '<AUDIENCE>', // optional
requestUri: '<REQUEST_URI>', // optional
});
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/oauth2/create-device-authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const result = await oauth2.createDeviceAuthorization({
clientId: '<CLIENT_ID>', // optional
scope: '<SCOPE>', // optional
authorizationDetails: '<AUTHORIZATION_DETAILS>', // optional
resource: '', // optional
resource: [], // optional
audience: '<AUDIENCE>', // optional
});

Expand Down
2 changes: 1 addition & 1 deletion docs/examples/oauth2/create-par.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const result = await oauth2.createPAR({
prompt: '<PROMPT>', // optional
maxAge: 0, // optional
authorizationDetails: '<AUTHORIZATION_DETAILS>', // optional
resource: '', // optional
resource: [], // optional
audience: '<AUDIENCE>', // optional
});

Expand Down
2 changes: 1 addition & 1 deletion docs/examples/oauth2/create-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const result = await oauth2.createToken({
clientSecret: '<CLIENT_SECRET>', // optional
codeVerifier: '<CODE_VERIFIER>', // optional
redirectUri: 'https://example.com', // optional
resource: '', // optional
resource: [], // optional
audience: '<AUDIENCE>', // optional
});

Expand Down
1 change: 1 addition & 0 deletions docs/examples/teams/create-membership.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const result = await teams.createMembership({
phone: '+12065550100', // optional
url: 'https://example.com', // optional
name: '<NAME>', // optional
membershipId: '<MEMBERSHIP_ID>', // optional
});

console.log(result);
Expand Down
Loading