diff --git a/CHANGELOG.md b/CHANGELOG.md index 209c432..b9c4787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -250,4 +244,3 @@ * Fix pong response & chunked upload * Add `ping` support to `Realtime` service - diff --git a/README.md b/README.md index 02c0483..0478251 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 tag, but before you use any Appwrite services: ```html - + ``` ## Getting Started @@ -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) { @@ -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) { @@ -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; @@ -112,15 +122,15 @@ interface Book { isCheckedOut: boolean; } -const databases = new Databases(client); +const tablesDB = new TablesDB(client); try { - const documents = await databases.listDocuments( - 'your-database-id', - 'your-collection-id' - ); + 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}`); // Now you have full type safety }); } catch (error) { @@ -140,16 +150,16 @@ try { * @property {boolean} isCheckedOut */ -const databases = new Databases(client); +const tablesDB = new TablesDB(client); try { - /** @type {Models.DocumentList} */ - const documents = await databases.listDocuments( - 'your-database-id', - 'your-collection-id' - ); + /** @type {Models.RowList} */ + 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) { @@ -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); diff --git a/docs/examples/account/create-passkey-token.md b/docs/examples/account/create-passkey-token.md new file mode 100644 index 0000000..7c55296 --- /dev/null +++ b/docs/examples/account/create-passkey-token.md @@ -0,0 +1,13 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createPasskeyToken(); + +console.log(result); +``` diff --git a/docs/examples/account/create-passkey.md b/docs/examples/account/create-passkey.md new file mode 100644 index 0000000..675fa31 --- /dev/null +++ b/docs/examples/account/create-passkey.md @@ -0,0 +1,16 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createPasskey({ + passkeyId: '', // optional + name: '', // optional +}); + +console.log(result); +``` diff --git a/docs/examples/account/delete-passkey.md b/docs/examples/account/delete-passkey.md new file mode 100644 index 0000000..e9ef2c8 --- /dev/null +++ b/docs/examples/account/delete-passkey.md @@ -0,0 +1,15 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.deletePasskey({ + passkeyId: '', +}); + +console.log(result); +``` diff --git a/docs/examples/account/get-passkey.md b/docs/examples/account/get-passkey.md new file mode 100644 index 0000000..17873ae --- /dev/null +++ b/docs/examples/account/get-passkey.md @@ -0,0 +1,15 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.getPasskey({ + passkeyId: '', +}); + +console.log(result); +``` diff --git a/docs/examples/account/list-passkeys.md b/docs/examples/account/list-passkeys.md new file mode 100644 index 0000000..799444e --- /dev/null +++ b/docs/examples/account/list-passkeys.md @@ -0,0 +1,16 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.listPasskeys({ + queries: [], // optional + total: false, // optional +}); + +console.log(result); +``` diff --git a/docs/examples/account/update-passkey-token.md b/docs/examples/account/update-passkey-token.md new file mode 100644 index 0000000..4392a00 --- /dev/null +++ b/docs/examples/account/update-passkey-token.md @@ -0,0 +1,16 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePasskeyToken({ + challengeId: '', + credential: {}, +}); + +console.log(result); +``` diff --git a/docs/examples/account/update-passkey-verification.md b/docs/examples/account/update-passkey-verification.md new file mode 100644 index 0000000..13ea6eb --- /dev/null +++ b/docs/examples/account/update-passkey-verification.md @@ -0,0 +1,16 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePasskeyVerification({ + passkeyId: '', + credential: {}, +}); + +console.log(result); +``` diff --git a/docs/examples/account/update-passkey.md b/docs/examples/account/update-passkey.md new file mode 100644 index 0000000..86462a0 --- /dev/null +++ b/docs/examples/account/update-passkey.md @@ -0,0 +1,16 @@ +```javascript +import { Client, Account } from 'appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePasskey({ + passkeyId: '', + name: '', +}); + +console.log(result); +``` diff --git a/docs/examples/analytics/create-event.md b/docs/examples/analytics/create-event.md index fe73aab..55fa6fa 100644 --- a/docs/examples/analytics/create-event.md +++ b/docs/examples/analytics/create-event.md @@ -13,7 +13,7 @@ const result = await analytics.createEvent({ url: 'https://example.com', domain: '', // optional referrer: '', // optional - screenWidth: null, // optional + screenWidth: 0, // optional sessionHash: '', // optional scrollDepth: 0, // optional engagementTime: 0, // optional diff --git a/docs/examples/oauth2/authorize-post.md b/docs/examples/oauth2/authorize-post.md index 7664d10..f0ac30a 100644 --- a/docs/examples/oauth2/authorize-post.md +++ b/docs/examples/oauth2/authorize-post.md @@ -19,7 +19,7 @@ const result = await oauth2.authorizePost({ prompt: '', // optional maxAge: 0, // optional authorizationDetails: '', // optional - resource: '', // optional + resource: [], // optional audience: '', // optional requestUri: '', // optional }); diff --git a/docs/examples/oauth2/authorize.md b/docs/examples/oauth2/authorize.md index 495fd11..cd48dcf 100644 --- a/docs/examples/oauth2/authorize.md +++ b/docs/examples/oauth2/authorize.md @@ -19,7 +19,7 @@ const result = await oauth2.authorize({ prompt: '', // optional maxAge: 0, // optional authorizationDetails: '', // optional - resource: '', // optional + resource: [], // optional audience: '', // optional requestUri: '', // optional }); diff --git a/docs/examples/oauth2/create-device-authorization.md b/docs/examples/oauth2/create-device-authorization.md index 56c0236..56e15ae 100644 --- a/docs/examples/oauth2/create-device-authorization.md +++ b/docs/examples/oauth2/create-device-authorization.md @@ -11,7 +11,7 @@ const result = await oauth2.createDeviceAuthorization({ clientId: '', // optional scope: '', // optional authorizationDetails: '', // optional - resource: '', // optional + resource: [], // optional audience: '', // optional }); diff --git a/docs/examples/oauth2/create-par.md b/docs/examples/oauth2/create-par.md index c345b2c..a2ce80e 100644 --- a/docs/examples/oauth2/create-par.md +++ b/docs/examples/oauth2/create-par.md @@ -19,7 +19,7 @@ const result = await oauth2.createPAR({ prompt: '', // optional maxAge: 0, // optional authorizationDetails: '', // optional - resource: '', // optional + resource: [], // optional audience: '', // optional }); diff --git a/docs/examples/oauth2/create-token.md b/docs/examples/oauth2/create-token.md index 0a2a3c7..f9d5d1b 100644 --- a/docs/examples/oauth2/create-token.md +++ b/docs/examples/oauth2/create-token.md @@ -16,7 +16,7 @@ const result = await oauth2.createToken({ clientSecret: '', // optional codeVerifier: '', // optional redirectUri: 'https://example.com', // optional - resource: '', // optional + resource: [], // optional audience: '', // optional }); diff --git a/docs/examples/teams/create-membership.md b/docs/examples/teams/create-membership.md index e7e03ea..e31bbda 100644 --- a/docs/examples/teams/create-membership.md +++ b/docs/examples/teams/create-membership.md @@ -15,6 +15,7 @@ const result = await teams.createMembership({ phone: '+12065550100', // optional url: 'https://example.com', // optional name: '', // optional + membershipId: '', // optional }); console.log(result); diff --git a/package-lock.json b/package-lock.json index 794a463..af6fe77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "appwrite", - "version": "28.2.0-rc.7", + "version": "29.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "appwrite", - "version": "28.2.0-rc.7", + "version": "29.0.0", "license": "BSD-3-Clause", "dependencies": { "buffer": "6.0.3", diff --git a/package.json b/package.json index b0d5e1d..b7cbd40 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "appwrite", "homepage": "https://appwrite.io/support", "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": "28.2.0-rc.7", + "version": "29.0.0", "license": "BSD-3-Clause", "main": "dist/cjs/sdk.js", "exports": { diff --git a/src/client.ts b/src/client.ts index eb7140a..3efaa41 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,6 +1,6 @@ import { Models } from './models'; import { Channel, ActionableChannel, ResolvedChannel } from './channel'; -import { Query } from './query'; +import { flattenParam, normalizeQueries, type QueryInput } from './query'; import { ID } from './id'; import JSONbigModule from 'json-bigint'; const JSONbigParser = JSONbigModule({ storeAsString: false }); @@ -45,6 +45,79 @@ export const JSONbig = { stringify: JSONbigSerializer.stringify, }; +type DefaultsShape = string | { items: DefaultsShape }; + +type DefaultsModel = { + defaults?: Record; + properties?: Record; +}; + +type Defaults = { + root: DefaultsShape; + models: Record; +}; + +export function applyDefaults(value: T, tree: Defaults): T { + return fillDefaults(value, tree.root, tree.models) as T; +} + +function cloneDefault(value: unknown): unknown { + if (Array.isArray(value)) { + return value.map(cloneDefault); + } + if (typeof value === 'object' && value !== null) { + const copy: Record = {}; + for (const [key, member] of Object.entries(value)) { + copy[key] = cloneDefault(member); + } + return copy; + } + return value; +} + +function fillDefaults( + value: unknown, + shape: DefaultsShape, + models: Record, +): unknown { + if (typeof shape !== 'string') { + if (!Array.isArray(value)) { + return value; + } + const items = shape.items; + return value.map((item) => fillDefaults(item, items, models)); + } + const model = models[shape]; + if (!model || typeof value !== 'object' || value === null) { + return value; + } + if (Array.isArray(value)) { + return value; + } + const result: Record = { ...model.defaults, ...value }; + // Each item gets its own copy of a filled-in list or object, so mutating one doesn't change the rest + for (const key of Object.keys(model.defaults ?? {})) { + if (!Object.prototype.hasOwnProperty.call(value, key)) { + result[key] = cloneDefault(result[key]); + } + } + for (const [key, child] of Object.entries(model.properties ?? {})) { + if (key in result) { + result[key] = fillDefaults(result[key], child, models); + } + } + // The spread drops the non-enumerable JSON toString that Client.call attaches. + if (Object.prototype.hasOwnProperty.call(value, 'toString')) { + Object.defineProperty(result, 'toString', { + value: () => JSONbig.stringify(result), + writable: true, + enumerable: false, + configurable: true, + }); + } + return result; +} + /** * Payload type representing a key-value pair with string keys and any values. */ @@ -401,8 +474,8 @@ class Client { 'x-sdk-name': 'Web', 'x-sdk-platform': 'client', 'x-sdk-language': 'web', - 'x-sdk-version': '28.2.0-rc.7', - 'X-Appwrite-Response-Format': '2.3.0', + 'x-sdk-version': '29.0.0', + 'X-Appwrite-Response-Format': '2.5.0', }; /** @@ -929,7 +1002,7 @@ class Client { | ResolvedChannel | (Channel | ActionableChannel | ResolvedChannel)[], callback: (payload: RealtimeResponseEvent) => void, - queries: (string | Query)[] = [], + queries: QueryInput = [], ): () => void { const channelArray = Array.isArray(channels) ? channels : [channels]; // Convert Channel instances to strings @@ -948,9 +1021,7 @@ class Client { this.realtime.channels.add(channel), ); - const queryStrings = (queries ?? []).map((q) => - typeof q === 'string' ? q : q.toString(), - ); + const queryStrings = normalizeQueries(queries); let subscriptionId = ''; const attempts = this.realtime.subscriptions.size + 1; @@ -1003,6 +1074,10 @@ class Client { ): { uri: string; options: RequestInit } { method = method.toUpperCase(); + for (const key of Object.keys(params)) { + params[key] = flattenParam(params[key]); + } + headers = Object.assign({}, this.headers, headers); if (typeof window !== 'undefined' && window.localStorage) { @@ -1295,7 +1370,7 @@ class Client { } if (400 <= response.status) { - let responseText: string; + let responseText; if ( response.headers .get('content-type') @@ -1356,7 +1431,7 @@ class Client { } export { Client, AppwriteException }; -export { Query } from './query'; +export { Query, QueryBuilder, flattenParam } from './query'; export type { Models, Payload, UploadProgress }; export type { RealtimeResponseEvent }; -export type { QueryTypes, QueryTypesList } from './query'; +export type { QueryTypes, QueryTypesList, QueryInput } from './query'; diff --git a/src/enums/execution-trigger.ts b/src/enums/execution-trigger.ts index 84fa8f6..b16a878 100644 --- a/src/enums/execution-trigger.ts +++ b/src/enums/execution-trigger.ts @@ -2,4 +2,5 @@ export enum ExecutionTrigger { Http = 'http', Schedule = 'schedule', Event = 'event', + Email = 'email', } diff --git a/src/index.ts b/src/index.ts index 377b0ca..e48b743 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,19 @@ /** * Appwrite Web SDK * - * This SDK targets Appwrite server version 2.3.x as shipped on Appwrite Cloud. + * 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. */ -export { Client, Query, AppwriteException } from './client'; +export { + Client, + Query, + QueryBuilder, + flattenParam, + AppwriteException, +} from './client'; export { Account } from './services/account'; export { Analytics } from './services/analytics'; export { Apps } from './services/apps'; @@ -48,11 +54,11 @@ export type { TrackingEventOptions, TrackingOptions, } from './services/analytics-tracking'; -export type { QueryTypes, QueryTypesList } from './query'; +export type { QueryTypes, QueryTypesList, QueryInput } from './query'; export { Permission } from './permission'; export { Role } from './role'; export { ID } from './id'; -export { Topic, ResolvedTopic } from './topic'; +export { Topic } from './topic'; export { Channel } from './channel'; export { Operator, Condition } from './operator'; export { AuthenticatorType } from './enums/authenticator-type'; diff --git a/src/models.ts b/src/models.ts index 11354fb..329b39a 100644 --- a/src/models.ts +++ b/src/models.ts @@ -341,7 +341,7 @@ export namespace Models { /** * Presence status. */ - status?: string; + status?: string | null; /** * Presence source. */ @@ -349,7 +349,7 @@ export namespace Models { /** * Presence expiry date in ISO 8601 format. */ - expiresAt?: string; + expiresAt?: string | null; /** * Presence metadata. */ @@ -381,15 +381,15 @@ export namespace Models { /** * Hashed user password. */ - password?: string; + password?: string | null; /** * Password hashing algorithm. */ - hash?: string; + hash?: string | null; /** * Password hashing algorithm configuration. */ - hashOptions?: object; + hashOptions?: object | null; /** * User registration date in ISO 8601 format. */ @@ -421,27 +421,27 @@ export namespace Models { /** * Canonical form of the user email address. */ - emailCanonical?: string; + emailCanonical?: string | null; /** * Whether the user email is from a free email provider. */ - emailIsFree?: boolean; + emailIsFree?: boolean | null; /** * Whether the user email is from a disposable email provider. */ - emailIsDisposable?: boolean; + emailIsDisposable?: boolean | null; /** * Whether the user email is from a corporate domain. */ - emailIsCorporate?: boolean; + emailIsCorporate?: boolean | null; /** * Whether the user email is in its canonical form. */ - emailIsCanonical?: boolean; + emailIsCanonical?: boolean | null; /** * Whether the password was found in a known data breach the last time it was checked. Null when the password has never been checked. */ - passwordPwned?: boolean; + passwordPwned?: boolean | null; /** * Phone verification status. */ @@ -465,11 +465,11 @@ export namespace Models { /** * Whether the user can impersonate other users. */ - impersonator?: boolean; + impersonator?: boolean | null; /** * ID of the original actor performing the impersonation. Present only when the current request is impersonating another user. Internal audit logs attribute the action to this user, while the impersonated target is recorded only in internal audit payload data. */ - impersonatorUserId?: string; + impersonatorUserId?: string | null; }; /** @@ -635,27 +635,27 @@ export namespace Models { /** * Canonical form of the user email address. */ - emailCanonical?: string; + emailCanonical?: string | null; /** * Whether the user email is from a free email provider. */ - emailIsFree?: boolean; + emailIsFree?: boolean | null; /** * Whether the user email is from a disposable email provider. */ - emailIsDisposable?: boolean; + emailIsDisposable?: boolean | null; /** * Whether the user email is from a corporate domain. */ - emailIsCorporate?: boolean; + emailIsCorporate?: boolean | null; /** * Whether the user email is in its canonical form. */ - emailIsCanonical?: boolean; + emailIsCanonical?: boolean | null; /** * Whether the password was found in a known data breach the last time it was checked. Null when the password has never been checked. */ - passwordPwned?: boolean; + passwordPwned?: boolean | null; /** * Phone verification status. */ @@ -679,11 +679,11 @@ export namespace Models { /** * Whether the user can impersonate other users. */ - impersonator?: boolean; + impersonator?: boolean | null; /** * ID of the original actor performing the impersonation. Present only when the current request is impersonating another user. Internal audit logs attribute the action to this user, while the impersonated target is recorded only in internal audit payload data. */ - impersonatorUserId?: string; + impersonatorUserId?: string | null; }; /** @@ -943,47 +943,47 @@ export namespace Models { /** * City */ - city?: string; + city?: string | null; /** * Name of timezone */ - timeZone?: string; + timeZone?: string | null; /** * Postal code */ - postalCode?: string; + postalCode?: string | null; /** * Latitude */ - latitude?: number; + latitude?: number | null; /** * Longitude */ - longitude?: number; + longitude?: number | null; /** * Autonomous System Number (ASN) of the IP */ - autonomousSystemNumber?: string; + autonomousSystemNumber?: string | null; /** * Organization that owns the ASN */ - autonomousSystemOrganization?: string; + autonomousSystemOrganization?: string | null; /** * Internet service provider of the IP */ - isp?: string; + isp?: string | null; /** * Connection type of the IP (e.g. cable, cellular, corporate) */ - connectionType?: string; + connectionType?: string | null; /** * User type classification of the IP (e.g. residential, business, hosting) */ - connectionUsageType?: string; + connectionUsageType?: string | null; /** * Registered organization of the IP */ - connectionOrganization?: string; + connectionOrganization?: string | null; }; /** @@ -1201,7 +1201,7 @@ export namespace Models { */ deploymentId: string; /** - * The trigger that caused the resource to execute. Possible values can be: `http`, `schedule`, or `event`. + * The trigger that caused the resource to execute. Possible values can be: `http`, `schedule`, `event`, or `email`. */ trigger: ExecutionTrigger; /** @@ -1247,7 +1247,7 @@ export namespace Models { /** * The scheduled time for execution. If left empty, execution will be queued immediately. */ - scheduledAt?: string; + scheduledAt?: string | null; }; /** @@ -1384,6 +1384,102 @@ export namespace Models { expire: string; }; + /** + * Token Secret + */ + export type TokenSecret = { + /** + * Token ID. + */ + $id: string; + /** + * Token creation date in ISO 8601 format. + */ + $createdAt: string; + /** + * User ID. + */ + userId: string; + /** + * Token secret key. Exchange it for a session with the create session endpoint. + */ + secret: string; + /** + * Token expiration date in ISO 8601 format. + */ + expire: string; + /** + * Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email. + */ + phrase: string; + }; + + /** + * Passkey + */ + export type Passkey = { + /** + * Passkey ID. + */ + $id: string; + /** + * Passkey creation date in ISO 8601 format. + */ + $createdAt: string; + /** + * Passkey update date in ISO 8601 format. + */ + $updatedAt: string; + /** + * Passkey name. + */ + name: string; + /** + * Most recent sign-in with this passkey in ISO 8601 format. Empty until the passkey is used to sign in. + */ + accessedAt: string; + }; + + /** + * Passkey Challenge + */ + export type PasskeyChallenge = { + /** + * Challenge ID. When signing in, pass it back with the credential to receive a token. + */ + $id: string; + /** + * Challenge creation date in ISO 8601 format. + */ + $createdAt: string; + /** + * ID of the passkey being registered. Empty for sign-in challenges. + */ + passkeyId: string; + /** + * Challenge expiration date in ISO 8601 format. + */ + expire: string; + /** + * WebAuthn options in JSON form. Pass them to `PublicKeyCredential.parseCreationOptionsFromJSON()` when registering, or `PublicKeyCredential.parseRequestOptionsFromJSON()` when signing in. + */ + publicKey: object; + }; + + /** + * Passkeys List + */ + export type PasskeyList = { + /** + * Total number of passkeys that matched your query. + */ + total: number; + /** + * List of passkeys. + */ + passkeys: Passkey[]; + }; + /** * MFA Recovery Codes */ @@ -1533,7 +1629,7 @@ export namespace Models { /** * Provider ID. */ - providerId?: string; + providerId?: string | null; /** * The target provider type. Can be one of the following: `email`, `sms` or `push`. */ @@ -1697,7 +1793,7 @@ export namespace Models { /** * Time the secret was last used for authentication in ISO 8601 format. Null if never used. */ - lastAccessedAt?: string; + lastAccessedAt?: string | null; }; /** @@ -1739,7 +1835,7 @@ export namespace Models { /** * Time the secret was last used for authentication in ISO 8601 format. Null if never used. */ - lastAccessedAt?: string; + lastAccessedAt?: string | null; }; /** @@ -1811,7 +1907,7 @@ export namespace Models { /** * Time an access token was last issued for the installation in ISO 8601 format. Null if never used. */ - lastAccessedAt?: string; + lastAccessedAt?: string | null; }; /** @@ -1853,7 +1949,7 @@ export namespace Models { /** * Time the app key was last used for authentication in ISO 8601 format. Null if never used. */ - lastAccessedAt?: string; + lastAccessedAt?: string | null; }; /** @@ -2015,11 +2111,11 @@ export namespace Models { /** * Granted RFC 9396 authorization details as a JSON string. */ - authorization_details?: string; + authorization_details?: string | null; /** * OpenID Connect ID token. Returned when the `openid` scope is granted. */ - id_token?: string; + id_token?: string | null; }; /** diff --git a/src/query.ts b/src/query.ts index 7a7da88..ca0b350 100644 --- a/src/query.ts +++ b/src/query.ts @@ -468,6 +468,20 @@ export class Query { queries.map((query) => JSONbig.parse(query)), ).toString(); + /** + * Constrain populated related documents on a relationship attribute. + * + * @param {string} attribute The relationship attribute to query. + * @param {string[]} queries Filter, order, select, and pagination queries applied to related documents. + * @returns {string} + */ + static relationship = (attribute: string, queries: string[]): string => + new Query( + 'relationship', + attribute, + queries.map((query) => JSONbig.parse(query)), + ).toString(); + /** * Filter resources where attribute is at a specific distance from the given coordinates. * @@ -659,4 +673,799 @@ export class Query { */ static notTouches = (attribute: string, values: any[]): string => new Query('notTouches', attribute, [values]).toString(); + + /** + * Count documents, optionally aliased. + */ + static count = (attribute: string = '*', alias: string = ''): string => + new Query( + 'count', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** + * Count distinct values of attribute, optionally aliased. + */ + static countDistinct = (attribute: string, alias: string = ''): string => + new Query( + 'countDistinct', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Sum values of `attribute`, optionally aliased. */ + static sum = (attribute: string, alias: string = ''): string => + new Query( + 'sum', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Average values of `attribute`, optionally aliased. */ + static avg = (attribute: string, alias: string = ''): string => + new Query( + 'avg', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Minimum value of `attribute`, optionally aliased. */ + static min = (attribute: string, alias: string = ''): string => + new Query( + 'min', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Maximum value of `attribute`, optionally aliased. */ + static max = (attribute: string, alias: string = ''): string => + new Query( + 'max', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Standard deviation of `attribute`, optionally aliased. */ + static stddev = (attribute: string, alias: string = ''): string => + new Query( + 'stddev', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Population standard deviation of `attribute`, optionally aliased. */ + static stddevPop = (attribute: string, alias: string = ''): string => + new Query( + 'stddevPop', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Sample standard deviation of `attribute`, optionally aliased. */ + static stddevSamp = (attribute: string, alias: string = ''): string => + new Query( + 'stddevSamp', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Variance of `attribute`, optionally aliased. */ + static variance = (attribute: string, alias: string = ''): string => + new Query( + 'variance', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Population variance of `attribute`, optionally aliased. */ + static varPop = (attribute: string, alias: string = ''): string => + new Query( + 'varPop', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Sample variance of `attribute`, optionally aliased. */ + static varSamp = (attribute: string, alias: string = ''): string => + new Query( + 'varSamp', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Bitwise AND of `attribute`, optionally aliased. */ + static bitAnd = (attribute: string, alias: string = ''): string => + new Query( + 'bitAnd', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Bitwise OR of `attribute`, optionally aliased. */ + static bitOr = (attribute: string, alias: string = ''): string => + new Query( + 'bitOr', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** Bitwise XOR of `attribute`, optionally aliased. */ + static bitXor = (attribute: string, alias: string = ''): string => + new Query( + 'bitXor', + attribute, + alias !== '' ? alias : undefined, + ).toString(); + + /** + * Group results by attributes. + */ + static groupBy = (attributes: string[]): string => + new Query('groupBy', undefined, attributes).toString(); + + /** + * Filter grouped results. `queries` are nested like `and`/`or`. + */ + static having = (queries: string[]): string => + new Query( + 'having', + undefined, + queries.map((query) => JSONbig.parse(query)), + ).toString(); + + /** Select distinct rows. */ + static distinct = (): string => new Query('distinct').toString(); + + /** + * Column-to-column join ON condition. + */ + static on = (left: string, right: string, operator: string = '='): string => + new Query('on', undefined, [left, operator, right]).toString(); + + /** + * Inner join. `table` is the joined collection/table ID. + */ + static join = ( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): string => + Query.createJoin( + 'join', + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ); + + /** Left join. `table` is the joined collection/table ID. */ + static leftJoin = ( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): string => + Query.createJoin( + 'leftJoin', + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ); + + /** Right join. `table` is the joined collection/table ID. */ + static rightJoin = ( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): string => + Query.createJoin( + 'rightJoin', + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ); + + /** Full outer join. `table` is the joined collection/table ID. */ + static fullOuterJoin = ( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): string => + Query.createJoin( + 'fullOuterJoin', + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ); + + /** Cross join. `table` is the joined collection/table ID. */ + static crossJoin = (table: string, alias: string = ''): string => + new Query( + 'crossJoin', + table, + alias !== '' ? alias : undefined, + ).toString(); + + /** Filter resources where `attribute` covers the given geometry. */ + static covers = (attribute: string, values: any[]): string => + new Query('covers', attribute, [values]).toString(); + + /** Filter resources where `attribute` does not cover the given geometry. */ + static notCovers = (attribute: string, values: any[]): string => + new Query('notCovers', attribute, [values]).toString(); + + /** Filter resources where `attribute` is spatially equal to the given geometry. */ + static spatialEquals = (attribute: string, values: any[]): string => + new Query('spatialEquals', attribute, [values]).toString(); + + /** Filter resources where `attribute` is not spatially equal to the given geometry. */ + static notSpatialEquals = (attribute: string, values: any[]): string => + new Query('notSpatialEquals', attribute, [values]).toString(); + + /** + * Return limit and offset queries for 1-based page pagination. + */ + static page = (page: number, perPage: number = 25): string[] => { + if (page < 1) { + throw new Error('Page must be >= 1, got ' + page); + } + if (perPage < 1) { + throw new Error('Per page must be >= 1, got ' + perPage); + } + return [Query.limit(perPage), Query.offset((page - 1) * perPage)]; + }; + + /** Start a fluent query builder. */ + static builder = (): Query.Builder => new Query.Builder(); + + private static createJoin( + method: string, + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): string { + if (Array.isArray(leftOrAliasOrOn)) { + return Query.nestedJoin(method, table, '', leftOrAliasOrOn); + } + if (Array.isArray(rightOrOn)) { + return Query.nestedJoin(method, table, leftOrAliasOrOn, rightOrOn); + } + return new Query( + method, + table, + alias !== '' + ? [leftOrAliasOrOn, operator, rightOrOn, alias] + : [leftOrAliasOrOn, operator, rightOrOn], + ).toString(); + } + + private static nestedJoin( + method: string, + table: string, + alias: string, + on: string[], + ): string { + const values: any[] = []; + if (alias !== '') { + values.push(alias); + } + for (const query of on) { + values.push(JSONbig.parse(query)); + } + return new Query(method, table, values).toString(); + } +} + +export type QueryInput = string | Query | Query.Builder | QueryInput[]; + +/** + * Fluent collector of Query fragments. Call {@link Query.Builder.build} to + * produce the `string[]` expected by list/createQuery methods. + */ +export namespace Query { + export class Builder { + private readonly queries: string[] = []; + + build(): string[] { + return [...this.queries]; + } + + equal(attribute: string, value: QueryTypes): this { + return this.push(Query.equal(attribute, value)); + } + + notEqual(attribute: string, value: QueryTypes): this { + return this.push(Query.notEqual(attribute, value)); + } + + lessThan(attribute: string, value: QueryTypes): this { + return this.push(Query.lessThan(attribute, value)); + } + + lessThanEqual(attribute: string, value: QueryTypes): this { + return this.push(Query.lessThanEqual(attribute, value)); + } + + greaterThan(attribute: string, value: QueryTypes): this { + return this.push(Query.greaterThan(attribute, value)); + } + + greaterThanEqual(attribute: string, value: QueryTypes): this { + return this.push(Query.greaterThanEqual(attribute, value)); + } + + search(attribute: string, value: string): this { + return this.push(Query.search(attribute, value)); + } + + isNull(attribute: string): this { + return this.push(Query.isNull(attribute)); + } + + isNotNull(attribute: string): this { + return this.push(Query.isNotNull(attribute)); + } + + between( + attribute: string, + start: string | number | bigint, + end: string | number | bigint, + ): this { + return this.push(Query.between(attribute, start, end)); + } + + startsWith(attribute: string, value: string): this { + return this.push(Query.startsWith(attribute, value)); + } + + endsWith(attribute: string, value: string): this { + return this.push(Query.endsWith(attribute, value)); + } + + select(attributes: string[]): this { + return this.push(Query.select(attributes)); + } + + cursorAfter(documentId: string): this { + return this.push(Query.cursorAfter(documentId)); + } + + cursorBefore(documentId: string): this { + return this.push(Query.cursorBefore(documentId)); + } + + orderAsc(attribute: string): this { + return this.push(Query.orderAsc(attribute)); + } + + orderDesc(attribute: string): this { + return this.push(Query.orderDesc(attribute)); + } + + orderRandom(): this { + return this.push(Query.orderRandom()); + } + + limit(limit: number): this { + return this.push(Query.limit(limit)); + } + + offset(offset: number): this { + return this.push(Query.offset(offset)); + } + + contains(attribute: string, value: string | any[]): this { + return this.push(Query.contains(attribute, value)); + } + + containsAny(attribute: string, value: any[]): this { + return this.push(Query.containsAny(attribute, value)); + } + + containsAll(attribute: string, value: any[]): this { + return this.push(Query.containsAll(attribute, value)); + } + + notContains(attribute: string, value: string | any[]): this { + return this.push(Query.notContains(attribute, value)); + } + + notSearch(attribute: string, value: string): this { + return this.push(Query.notSearch(attribute, value)); + } + + notBetween( + attribute: string, + start: string | number | bigint, + end: string | number | bigint, + ): this { + return this.push(Query.notBetween(attribute, start, end)); + } + + notStartsWith(attribute: string, value: string): this { + return this.push(Query.notStartsWith(attribute, value)); + } + + notEndsWith(attribute: string, value: string): this { + return this.push(Query.notEndsWith(attribute, value)); + } + + regex(attribute: string, pattern: string): this { + return this.push(Query.regex(attribute, pattern)); + } + + exists(attributes: string[]): this { + return this.push(Query.exists(attributes)); + } + + notExists(attributes: string[]): this { + return this.push(Query.notExists(attributes)); + } + + createdBefore(value: string): this { + return this.push(Query.createdBefore(value)); + } + + createdAfter(value: string): this { + return this.push(Query.createdAfter(value)); + } + + createdBetween(start: string, end: string): this { + return this.push(Query.createdBetween(start, end)); + } + + updatedBefore(value: string): this { + return this.push(Query.updatedBefore(value)); + } + + updatedAfter(value: string): this { + return this.push(Query.updatedAfter(value)); + } + + updatedBetween(start: string, end: string): this { + return this.push(Query.updatedBetween(start, end)); + } + + or(queries: string[]): this { + return this.push(Query.or(queries)); + } + + and(queries: string[]): this { + return this.push(Query.and(queries)); + } + + elemMatch(attribute: string, queries: string[]): this { + return this.push(Query.elemMatch(attribute, queries)); + } + + relationship(attribute: string, queries: string[]): this { + return this.push(Query.relationship(attribute, queries)); + } + + distanceEqual( + attribute: string, + values: any[], + distance: number, + meters: boolean = true, + ): this { + return this.push( + Query.distanceEqual(attribute, values, distance, meters), + ); + } + + distanceNotEqual( + attribute: string, + values: any[], + distance: number, + meters: boolean = true, + ): this { + return this.push( + Query.distanceNotEqual(attribute, values, distance, meters), + ); + } + + distanceGreaterThan( + attribute: string, + values: any[], + distance: number, + meters: boolean = true, + ): this { + return this.push( + Query.distanceGreaterThan(attribute, values, distance, meters), + ); + } + + distanceLessThan( + attribute: string, + values: any[], + distance: number, + meters: boolean = true, + ): this { + return this.push( + Query.distanceLessThan(attribute, values, distance, meters), + ); + } + + intersects(attribute: string, values: any[]): this { + return this.push(Query.intersects(attribute, values)); + } + + notIntersects(attribute: string, values: any[]): this { + return this.push(Query.notIntersects(attribute, values)); + } + + crosses(attribute: string, values: any[]): this { + return this.push(Query.crosses(attribute, values)); + } + + notCrosses(attribute: string, values: any[]): this { + return this.push(Query.notCrosses(attribute, values)); + } + + overlaps(attribute: string, values: any[]): this { + return this.push(Query.overlaps(attribute, values)); + } + + notOverlaps(attribute: string, values: any[]): this { + return this.push(Query.notOverlaps(attribute, values)); + } + + touches(attribute: string, values: any[]): this { + return this.push(Query.touches(attribute, values)); + } + + notTouches(attribute: string, values: any[]): this { + return this.push(Query.notTouches(attribute, values)); + } + + count(attribute: string = '*', alias: string = ''): this { + return this.push(Query.count(attribute, alias)); + } + + countDistinct(attribute: string, alias: string = ''): this { + return this.push(Query.countDistinct(attribute, alias)); + } + + sum(attribute: string, alias: string = ''): this { + return this.push(Query.sum(attribute, alias)); + } + + avg(attribute: string, alias: string = ''): this { + return this.push(Query.avg(attribute, alias)); + } + + min(attribute: string, alias: string = ''): this { + return this.push(Query.min(attribute, alias)); + } + + max(attribute: string, alias: string = ''): this { + return this.push(Query.max(attribute, alias)); + } + + stddev(attribute: string, alias: string = ''): this { + return this.push(Query.stddev(attribute, alias)); + } + + stddevPop(attribute: string, alias: string = ''): this { + return this.push(Query.stddevPop(attribute, alias)); + } + + stddevSamp(attribute: string, alias: string = ''): this { + return this.push(Query.stddevSamp(attribute, alias)); + } + + variance(attribute: string, alias: string = ''): this { + return this.push(Query.variance(attribute, alias)); + } + + varPop(attribute: string, alias: string = ''): this { + return this.push(Query.varPop(attribute, alias)); + } + + varSamp(attribute: string, alias: string = ''): this { + return this.push(Query.varSamp(attribute, alias)); + } + + bitAnd(attribute: string, alias: string = ''): this { + return this.push(Query.bitAnd(attribute, alias)); + } + + bitOr(attribute: string, alias: string = ''): this { + return this.push(Query.bitOr(attribute, alias)); + } + + bitXor(attribute: string, alias: string = ''): this { + return this.push(Query.bitXor(attribute, alias)); + } + + groupBy(attributes: string[]): this { + return this.push(Query.groupBy(attributes)); + } + + having(queries: string[]): this { + return this.push(Query.having(queries)); + } + + distinct(): this { + return this.push(Query.distinct()); + } + + join( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): this { + return this.push( + Query.join(table, leftOrAliasOrOn, rightOrOn, operator, alias), + ); + } + + leftJoin( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): this { + return this.push( + Query.leftJoin( + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ), + ); + } + + rightJoin( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): this { + return this.push( + Query.rightJoin( + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ), + ); + } + + fullOuterJoin( + table: string, + leftOrAliasOrOn: string | string[], + rightOrOn: string | string[] = '', + operator: string = '=', + alias: string = '', + ): this { + return this.push( + Query.fullOuterJoin( + table, + leftOrAliasOrOn, + rightOrOn, + operator, + alias, + ), + ); + } + + crossJoin(table: string, alias: string = ''): this { + return this.push(Query.crossJoin(table, alias)); + } + + vectorDot(attribute: string, vector: number[]): this { + return this.push(Query.vectorDot(attribute, vector)); + } + + vectorCosine(attribute: string, vector: number[]): this { + return this.push(Query.vectorCosine(attribute, vector)); + } + + vectorEuclidean(attribute: string, vector: number[]): this { + return this.push(Query.vectorEuclidean(attribute, vector)); + } + + covers(attribute: string, values: any[]): this { + return this.push(Query.covers(attribute, values)); + } + + notCovers(attribute: string, values: any[]): this { + return this.push(Query.notCovers(attribute, values)); + } + + spatialEquals(attribute: string, values: any[]): this { + return this.push(Query.spatialEquals(attribute, values)); + } + + notSpatialEquals(attribute: string, values: any[]): this { + return this.push(Query.notSpatialEquals(attribute, values)); + } + + page(page: number, perPage: number = 25): this { + return this.push(Query.page(page, perPage)); + } + + private push(query: string | string[]): this { + if (Array.isArray(query)) { + this.queries.push(...query); + } else { + this.queries.push(query); + } + return this; + } + } +} + +export function normalizeQueries(queries?: QueryInput | null): string[] { + if (queries == null) { + return []; + } + if (queries instanceof Query.Builder) { + return queries.build(); + } + if (!Array.isArray(queries)) { + if (queries instanceof Query) { + return [queries.toString()]; + } + if (typeof queries === 'string') { + return [queries]; + } + return []; + } + + const out: string[] = []; + for (const item of queries) { + out.push(...normalizeQueries(item)); + } + return out; } + +function isQueryValue(value: unknown): value is Query | Query.Builder { + return value instanceof Query.Builder || value instanceof Query; +} + +export function flattenParam(value: unknown): unknown { + if (isQueryValue(value)) { + return normalizeQueries(value); + } + if (!Array.isArray(value)) { + return value; + } + + const out: unknown[] = []; + for (const item of value) { + if (isQueryValue(item)) { + out.push(...normalizeQueries(item)); + } else { + out.push(flattenParam(item)); + } + } + return out; +} + +export const QueryBuilder = Query.Builder; +export type QueryBuilder = Query.Builder; diff --git a/src/services/account.ts b/src/services/account.ts index 8d95139..0bba6b4 100644 --- a/src/services/account.ts +++ b/src/services/account.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; import { AuthenticatorType } from '../enums/authenticator-type'; @@ -30,7 +35,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -139,7 +187,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -208,7 +299,39 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2ConsentList', + models: { + oauth2ConsentList: { + defaults: { + total: 0, + consents: [], + }, + properties: { + consents: { + items: 'oauth2Consent', + }, + }, + }, + oauth2Consent: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + appId: '', + cimdUrl: '', + scopes: [], + resources: [], + authorizationDetails: '[]', + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -264,7 +387,28 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Consent', + models: { + oauth2Consent: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + appId: '', + cimdUrl: '', + scopes: [], + resources: [], + authorizationDetails: '[]', + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -403,7 +547,40 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2ConsentTokenList', + models: { + oauth2ConsentTokenList: { + defaults: { + total: 0, + tokens: [], + }, + properties: { + tokens: { + items: 'oauth2ConsentToken', + }, + }, + }, + oauth2ConsentToken: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + consentId: '', + userId: '', + appId: '', + cimdUrl: '', + scopes: [], + resources: [], + authorizationDetails: '[]', + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -477,7 +654,29 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2ConsentToken', + models: { + oauth2ConsentToken: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + consentId: '', + userId: '', + appId: '', + cimdUrl: '', + scopes: [], + resources: [], + authorizationDetails: '[]', + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -633,7 +832,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -702,7 +944,40 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'identityList', + models: { + identityList: { + defaults: { + total: 0, + identities: [], + }, + properties: { + identities: { + items: 'identity', + }, + }, + }, + identity: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + provider: '', + providerUid: '', + providerEmail: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + providerIdToken: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -812,7 +1087,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'jwt', + models: { + jwt: { + defaults: { + jwt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -873,7 +1160,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -932,7 +1262,20 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaType', + models: { + mfaType: { + defaults: { + secret: '', + uri: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -990,7 +1333,20 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaType', + models: { + mfaType: { + defaults: { + secret: '', + uri: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1071,7 +1427,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1151,7 +1550,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1325,7 +1767,22 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaChallenge', + models: { + mfaChallenge: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1385,7 +1842,22 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaChallenge', + models: { + mfaChallenge: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1463,7 +1935,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1540,7 +2052,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1560,7 +2112,23 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaFactors', + models: { + mfaFactors: { + defaults: { + totp: false, + phone: false, + email: false, + recoveryCode: false, + custom: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1579,7 +2147,23 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaFactors', + models: { + mfaFactors: { + defaults: { + totp: false, + phone: false, + email: false, + recoveryCode: false, + custom: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1599,7 +2183,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaRecoveryCodes', + models: { + mfaRecoveryCodes: { + defaults: { + recoveryCodes: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1618,7 +2214,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaRecoveryCodes', + models: { + mfaRecoveryCodes: { + defaults: { + recoveryCodes: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1639,7 +2247,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaRecoveryCodes', + models: { + mfaRecoveryCodes: { + defaults: { + recoveryCodes: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1659,7 +2279,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaRecoveryCodes', + models: { + mfaRecoveryCodes: { + defaults: { + recoveryCodes: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1680,7 +2312,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaRecoveryCodes', + models: { + mfaRecoveryCodes: { + defaults: { + recoveryCodes: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1700,7 +2344,19 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'mfaRecoveryCodes', + models: { + mfaRecoveryCodes: { + defaults: { + recoveryCodes: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1761,7 +2417,544 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + + /** + * Get the list of verified passkeys registered by the currently logged in user. + * + * @param {string[]} params.queries - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter and order on the following attributes: $id, $createdAt, $updatedAt, name, accessedAt + * @param {boolean} params.total - When set to false, the total count returned will be 0 and will not be calculated. + * @throws {AppwriteException} + * @returns {Promise} + */ + listPasskeys(params?: { + queries?: string[]; + total?: boolean; + }): Promise; + /** + * Get the list of verified passkeys registered by the currently logged in user. + * + * @param {string[]} queries - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter and order on the following attributes: $id, $createdAt, $updatedAt, name, accessedAt + * @param {boolean} total - When set to false, the total count returned will be 0 and will not be calculated. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + listPasskeys( + queries?: string[], + total?: boolean, + ): Promise; + listPasskeys( + paramsOrFirst?: { queries?: string[]; total?: boolean } | string[], + ...rest: [boolean?] + ): Promise { + let params: { queries?: string[]; total?: boolean }; + + if ( + (typeof paramsOrFirst === 'undefined' && rest.length === 0) || + (paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst)) + ) { + params = (paramsOrFirst || {}) as { + queries?: string[]; + total?: boolean; + }; + } else { + params = { + queries: paramsOrFirst as string[], + total: rest[0] as boolean, + }; + } + + const queries = params.queries; + const total = params.total; + + const apiPath = '/account/passkeys'; + const apiPayload: Payload = {}; + if (typeof queries !== 'undefined') { + apiPayload['queries'] = queries; + } + if (typeof total !== 'undefined') { + apiPayload['total'] = total; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + accept: 'application/json', + }; + + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'passkeyList', + models: { + passkeyList: { + defaults: { + total: 0, + passkeys: [], + }, + properties: { + passkeys: { + items: 'passkey', + }, + }, + }, + passkey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + accessedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + + /** + * Start registering a passkey for the currently logged in user. The session must have signed in or completed an MFA challenge within the last 10 minutes. Pass the returned `publicKey` options to `navigator.credentials.create()`, then complete the registration with [Update passkey verification](/docs/references/cloud/client-web/account#updatePasskeyVerification). The passkey stays pending until verified, and the challenge expires after 5 minutes. + * + * @param {string} params.passkeyId - Passkey ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. + * @param {string} params.name - Passkey name, shown when listing passkeys. Max length: 128 chars. + * @throws {AppwriteException} + * @returns {Promise} + */ + createPasskey(params?: { + passkeyId?: string; + name?: string; + }): Promise; + /** + * Start registering a passkey for the currently logged in user. The session must have signed in or completed an MFA challenge within the last 10 minutes. Pass the returned `publicKey` options to `navigator.credentials.create()`, then complete the registration with [Update passkey verification](/docs/references/cloud/client-web/account#updatePasskeyVerification). The passkey stays pending until verified, and the challenge expires after 5 minutes. + * + * @param {string} passkeyId - Passkey ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. + * @param {string} name - Passkey name, shown when listing passkeys. Max length: 128 chars. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + createPasskey( + passkeyId?: string, + name?: string, + ): Promise; + createPasskey( + paramsOrFirst?: { passkeyId?: string; name?: string } | string, + ...rest: [string?] + ): Promise { + let params: { passkeyId?: string; name?: string }; + + if ( + (typeof paramsOrFirst === 'undefined' && rest.length === 0) || + (paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst)) + ) { + params = (paramsOrFirst || {}) as { + passkeyId?: string; + name?: string; + }; + } else { + params = { + passkeyId: paramsOrFirst as string, + name: rest[0] as string, + }; + } + + const passkeyId = params.passkeyId; + const name = params.name; + + const apiPath = '/account/passkeys'; + const apiPayload: Payload = {}; + if (typeof passkeyId !== 'undefined') { + apiPayload['passkeyId'] = passkeyId; + } + if (typeof name !== 'undefined') { + apiPayload['name'] = name; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + 'content-type': 'application/json', + accept: 'application/json', + }; + + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'passkeyChallenge', + models: { + passkeyChallenge: { + defaults: { + $id: '', + $createdAt: '', + passkeyId: '', + expire: '', + publicKey: {}, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + + /** + * Get a verified passkey of the currently logged in user by its unique ID. + * + * @param {string} params.passkeyId - Passkey ID. + * @throws {AppwriteException} + * @returns {Promise} + */ + getPasskey(params: { passkeyId: string }): Promise; + /** + * Get a verified passkey of the currently logged in user by its unique ID. + * + * @param {string} passkeyId - Passkey ID. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + getPasskey(passkeyId: string): Promise; + getPasskey( + paramsOrFirst: { passkeyId: string } | string, + ): Promise { + let params: { passkeyId: string }; + + if ( + paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst) + ) { + params = (paramsOrFirst || {}) as { passkeyId: string }; + } else { + params = { + passkeyId: paramsOrFirst as string, + }; + } + + const passkeyId = params.passkeyId; + + if (typeof passkeyId === 'undefined' || passkeyId === '') { + throw new AppwriteException( + 'Missing required parameter: "passkeyId"', + ); + } + const apiPath = '/account/passkeys/{passkeyId}'.replace( + '{passkeyId}', + encodeURIComponent(String(passkeyId)), + ); + const apiPayload: Payload = {}; + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + accept: 'application/json', + }; + + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'passkey', + models: { + passkey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + accessedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + + /** + * Rename a passkey of the currently logged in user. + * + * @param {string} params.passkeyId - Passkey ID. + * @param {string} params.name - Passkey name. Max length: 128 chars. + * @throws {AppwriteException} + * @returns {Promise} + */ + updatePasskey(params: { + passkeyId: string; + name: string; + }): Promise; + /** + * Rename a passkey of the currently logged in user. + * + * @param {string} passkeyId - Passkey ID. + * @param {string} name - Passkey name. Max length: 128 chars. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + updatePasskey(passkeyId: string, name: string): Promise; + updatePasskey( + paramsOrFirst: { passkeyId: string; name: string } | string, + ...rest: [string?] + ): Promise { + let params: { passkeyId: string; name: string }; + + if ( + paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst) + ) { + params = (paramsOrFirst || {}) as { + passkeyId: string; + name: string; + }; + } else { + params = { + passkeyId: paramsOrFirst as string, + name: rest[0] as string, + }; + } + + const passkeyId = params.passkeyId; + const name = params.name; + + if (typeof passkeyId === 'undefined' || passkeyId === '') { + throw new AppwriteException( + 'Missing required parameter: "passkeyId"', + ); + } + if (typeof name === 'undefined') { + throw new AppwriteException('Missing required parameter: "name"'); + } + const apiPath = '/account/passkeys/{passkeyId}'.replace( + '{passkeyId}', + encodeURIComponent(String(passkeyId)), + ); + const apiPayload: Payload = {}; + if (typeof name !== 'undefined') { + apiPayload['name'] = name; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + 'content-type': 'application/json', + accept: 'application/json', + }; + + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'passkey', + models: { + passkey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + accessedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + + /** + * Delete a passkey from the currently logged in user. The passkey can no longer be used to sign in, although it may remain stored on the user's device. The session must have signed in or completed an MFA challenge within the last 10 minutes. + * + * @param {string} params.passkeyId - Passkey ID. + * @throws {AppwriteException} + * @returns {Promise<{}>} + */ + deletePasskey(params: { passkeyId: string }): Promise<{}>; + /** + * Delete a passkey from the currently logged in user. The passkey can no longer be used to sign in, although it may remain stored on the user's device. The session must have signed in or completed an MFA challenge within the last 10 minutes. + * + * @param {string} passkeyId - Passkey ID. + * @throws {AppwriteException} + * @returns {Promise<{}>} + * @deprecated Use the object parameter style method for a better developer experience. + */ + deletePasskey(passkeyId: string): Promise<{}>; + deletePasskey(paramsOrFirst: { passkeyId: string } | string): Promise<{}> { + let params: { passkeyId: string }; + + if ( + paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst) + ) { + params = (paramsOrFirst || {}) as { passkeyId: string }; + } else { + params = { + passkeyId: paramsOrFirst as string, + }; + } + + const passkeyId = params.passkeyId; + + if (typeof passkeyId === 'undefined' || passkeyId === '') { + throw new AppwriteException( + 'Missing required parameter: "passkeyId"', + ); + } + const apiPath = '/account/passkeys/{passkeyId}'.replace( + '{passkeyId}', + encodeURIComponent(String(passkeyId)), + ); + const apiPayload: Payload = {}; + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + 'content-type': 'application/json', + accept: 'application/json', + }; + + return this.client.call('delete', uri, apiHeaders, apiPayload); + } + + /** + * Complete a passkey registration started with [Create passkey](/docs/references/cloud/client-web/account#createPasskey). Pass the JSON form of the credential returned by `navigator.credentials.create()`, for example `credential.toJSON()`. Each registration can be verified once; a failed attempt requires starting it again. + * + * @param {string} params.passkeyId - Passkey ID. + * @param {object} params.credential - Registration credential returned by the authenticator, in the JSON form produced by `PublicKeyCredential.toJSON()`. + * @throws {AppwriteException} + * @returns {Promise} + */ + updatePasskeyVerification(params: { + passkeyId: string; + credential: object; + }): Promise; + /** + * Complete a passkey registration started with [Create passkey](/docs/references/cloud/client-web/account#createPasskey). Pass the JSON form of the credential returned by `navigator.credentials.create()`, for example `credential.toJSON()`. Each registration can be verified once; a failed attempt requires starting it again. + * + * @param {string} passkeyId - Passkey ID. + * @param {object} credential - Registration credential returned by the authenticator, in the JSON form produced by `PublicKeyCredential.toJSON()`. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + updatePasskeyVerification( + passkeyId: string, + credential: object, + ): Promise; + updatePasskeyVerification( + paramsOrFirst: { passkeyId: string; credential: object } | string, + ...rest: [object?] + ): Promise { + let params: { passkeyId: string; credential: object }; + + if ( + paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst) + ) { + params = (paramsOrFirst || {}) as { + passkeyId: string; + credential: object; + }; + } else { + params = { + passkeyId: paramsOrFirst as string, + credential: rest[0] as object, + }; + } + + const passkeyId = params.passkeyId; + const credential = params.credential; + + if (typeof passkeyId === 'undefined' || passkeyId === '') { + throw new AppwriteException( + 'Missing required parameter: "passkeyId"', + ); + } + if (typeof credential === 'undefined') { + throw new AppwriteException( + 'Missing required parameter: "credential"', + ); + } + const apiPath = '/account/passkeys/{passkeyId}/verification'.replace( + '{passkeyId}', + encodeURIComponent(String(passkeyId)), + ); + const apiPayload: Payload = {}; + if (typeof credential !== 'undefined') { + apiPayload['credential'] = credential; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + 'content-type': 'application/json', + accept: 'application/json', + }; + + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'passkey', + models: { + passkey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + accessedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1841,7 +3034,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1921,7 +3157,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2006,7 +3285,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2075,7 +3397,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2170,7 +3509,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2245,7 +3601,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2338,7 +3711,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2390,7 +3780,58 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'sessionList', + models: { + sessionList: { + defaults: { + total: 0, + sessions: [], + }, + properties: { + sessions: { + items: 'session', + }, + }, + }, + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2463,7 +3904,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2473,14 +3954,14 @@ export class Account { * * @param {string} params.email - User email. * @param {string} params.password - User password. Must be at least 8 chars. - * @param {number} params.duration - Session length in seconds. Minimum is 60 seconds, and it cannot exceed the project maximum session length. Defaults to the project maximum session length. + * @param {number | null} params.duration - Session length in seconds. Minimum is 60 seconds, and it cannot exceed the project maximum session length. Defaults to the project maximum session length. * @throws {AppwriteException} * @returns {Promise} */ createEmailPasswordSession(params: { email: string; password: string; - duration?: number; + duration?: number | null; }): Promise; /** * Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user. Use the optional `duration` parameter to create a shorter session, for example when the user doesn't choose "remember me". It must be at least 60 seconds and cannot exceed the project maximum session length. @@ -2489,7 +3970,7 @@ export class Account { * * @param {string} email - User email. * @param {string} password - User password. Must be at least 8 chars. - * @param {number} duration - Session length in seconds. Minimum is 60 seconds, and it cannot exceed the project maximum session length. Defaults to the project maximum session length. + * @param {number | null} duration - Session length in seconds. Minimum is 60 seconds, and it cannot exceed the project maximum session length. Defaults to the project maximum session length. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -2497,14 +3978,19 @@ export class Account { createEmailPasswordSession( email: string, password: string, - duration?: number, + duration?: number | null, ): Promise; createEmailPasswordSession( paramsOrFirst: - { email: string; password: string; duration?: number } | string, - ...rest: [string?, number?] + | { email: string; password: string; duration?: number | null } + | string, + ...rest: [string?, (number | null)?] ): Promise { - let params: { email: string; password: string; duration?: number }; + let params: { + email: string; + password: string; + duration?: number | null; + }; if ( paramsOrFirst && @@ -2514,13 +4000,13 @@ export class Account { params = (paramsOrFirst || {}) as { email: string; password: string; - duration?: number; + duration?: number | null; }; } else { params = { email: paramsOrFirst as string, password: rest[0] as string, - duration: rest[1] as number, + duration: rest[1] as number | null, }; } @@ -2555,7 +4041,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2718,7 +4244,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -2794,7 +4360,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3005,7 +4611,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3077,7 +4723,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3133,7 +4819,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3190,7 +4916,47 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'session', + models: { + session: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + expire: '', + provider: '', + providerUid: '', + providerAccessToken: '', + providerAccessTokenExpiry: '', + providerRefreshToken: '', + ip: '', + osCode: '', + osName: '', + osVersion: '', + clientType: '', + clientCode: '', + clientName: '', + clientVersion: '', + clientEngine: '', + clientEngineVersion: '', + deviceName: '', + deviceBrand: '', + deviceModel: '', + countryCode: '', + countryName: '', + current: false, + factors: [], + secret: '', + mfaUpdatedAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3267,7 +5033,50 @@ export class Account { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'user', + models: { + user: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + registration: '', + status: true, + labels: [], + passwordUpdate: '', + email: '', + phone: '', + emailVerification: false, + phoneVerification: false, + mfa: false, + targets: [], + accessedAt: '', + }, + properties: { + targets: { + items: 'target', + }, + }, + }, + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3362,7 +5171,26 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'target', + models: { + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3441,7 +5269,26 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'target', + models: { + target: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + userId: '', + providerType: '', + identifier: '', + expired: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3590,7 +5437,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3698,7 +5562,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3841,6 +5722,138 @@ export class Account { } } + /** + * Start signing in with a passkey. No email or user ID is needed: pass the returned `publicKey` options to `navigator.credentials.get()` and the user picks one of their passkeys. Then call [Update passkey token](/docs/references/cloud/client-web/account#updatePasskeyToken) with the credential to receive a token, and exchange it with [Create session](/docs/references/cloud/client-web/account#createSession). The challenge expires after 5 minutes. + * + * @throws {AppwriteException} + * @returns {Promise} + */ + createPasskeyToken(): Promise { + const apiPath = '/account/tokens/passkey'; + const apiPayload: Payload = {}; + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + 'content-type': 'application/json', + accept: 'application/json', + }; + + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'passkeyChallenge', + models: { + passkeyChallenge: { + defaults: { + $id: '', + $createdAt: '', + passkeyId: '', + expire: '', + publicKey: {}, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + + /** + * Complete a passkey sign-in started with [Create passkey token](/docs/references/cloud/client-web/account#createPasskeyToken). Pass the challenge ID and the JSON form of the credential returned by `navigator.credentials.get()`, for example `credential.toJSON()`. The returned token includes its secret and expires after 1 minute: exchange it for a session with [Create session](/docs/references/cloud/client-web/account#createSession). Passkeys require user verification, so the session also satisfies MFA. Each challenge can only be used once. + * + * @param {string} params.challengeId - Challenge ID returned by createPasskeyToken. + * @param {object} params.credential - Authentication credential returned by the authenticator, in the JSON form produced by `PublicKeyCredential.toJSON()`. + * @throws {AppwriteException} + * @returns {Promise} + */ + updatePasskeyToken(params: { + challengeId: string; + credential: object; + }): Promise; + /** + * Complete a passkey sign-in started with [Create passkey token](/docs/references/cloud/client-web/account#createPasskeyToken). Pass the challenge ID and the JSON form of the credential returned by `navigator.credentials.get()`, for example `credential.toJSON()`. The returned token includes its secret and expires after 1 minute: exchange it for a session with [Create session](/docs/references/cloud/client-web/account#createSession). Passkeys require user verification, so the session also satisfies MFA. Each challenge can only be used once. + * + * @param {string} challengeId - Challenge ID returned by createPasskeyToken. + * @param {object} credential - Authentication credential returned by the authenticator, in the JSON form produced by `PublicKeyCredential.toJSON()`. + * @throws {AppwriteException} + * @returns {Promise} + * @deprecated Use the object parameter style method for a better developer experience. + */ + updatePasskeyToken( + challengeId: string, + credential: object, + ): Promise; + updatePasskeyToken( + paramsOrFirst: { challengeId: string; credential: object } | string, + ...rest: [object?] + ): Promise { + let params: { challengeId: string; credential: object }; + + if ( + paramsOrFirst && + typeof paramsOrFirst === 'object' && + !Array.isArray(paramsOrFirst) + ) { + params = (paramsOrFirst || {}) as { + challengeId: string; + credential: object; + }; + } else { + params = { + challengeId: paramsOrFirst as string, + credential: rest[0] as object, + }; + } + + const challengeId = params.challengeId; + const credential = params.credential; + + if (typeof challengeId === 'undefined') { + throw new AppwriteException( + 'Missing required parameter: "challengeId"', + ); + } + if (typeof credential === 'undefined') { + throw new AppwriteException( + 'Missing required parameter: "credential"', + ); + } + const apiPath = '/account/tokens/passkey'; + const apiPayload: Payload = {}; + if (typeof challengeId !== 'undefined') { + apiPayload['challengeId'] = challengeId; + } + if (typeof credential !== 'undefined') { + apiPayload['credential'] = credential; + } + const uri = new URL(this.client.config.endpoint + apiPath); + + const apiHeaders: { [header: string]: string } = { + 'X-Appwrite-Project': this.client.config.project, + 'content-type': 'application/json', + accept: 'application/json', + }; + + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'tokenSecret', + models: { + tokenSecret: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); + } + /** * Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST /v1/account/sessions/token](https://appwrite.io/docs/references/cloud/client-web/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes. * @@ -3911,7 +5924,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -3972,7 +6002,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4034,7 +6081,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4109,7 +6173,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4182,7 +6263,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4243,7 +6341,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4320,7 +6435,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4340,7 +6472,24 @@ export class Account { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -4415,6 +6564,23 @@ export class Account { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'token', + models: { + token: { + defaults: { + $id: '', + $createdAt: '', + userId: '', + secret: '', + expire: '', + phrase: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/analytics-tracking.ts b/src/services/analytics-tracking.ts index 04f6b31..e1bed9a 100644 --- a/src/services/analytics-tracking.ts +++ b/src/services/analytics-tracking.ts @@ -213,6 +213,7 @@ export class Tracking { name, url: options.url ?? this.currentPageUrl(), referrer: options.referrer, + screenWidth: this.viewportWidth(), scrollDepth: options.scrollDepth, engagementTime: options.engagementTime, // The endpoint takes props as a flat alternating key/value list. @@ -636,6 +637,15 @@ export class Tracking { return window.location.href; } + // The endpoint buckets this as viewport width in CSS pixels, so it is + // `innerWidth` rather than `screen.width` scaled by devicePixelRatio. + private viewportWidth(): number | undefined { + if (typeof window === 'undefined' || !window.innerWidth) { + return undefined; + } + return window.innerWidth; + } + private findAnchor(target: EventTarget | null): HTMLAnchorElement | null { let node = target as Node | null; while (node) { diff --git a/src/services/analytics.ts b/src/services/analytics.ts index 176a25f..bcafef2 100644 --- a/src/services/analytics.ts +++ b/src/services/analytics.ts @@ -10,7 +10,7 @@ export class Analytics { /** * Send a tracking event from a browser, native app, or server-side SDK. * - * @param {string} params.propertyId - Analytics property ID or snippet ID identifying the property. + * @param {string} params.propertyId - Analytics property ID. * @param {string} params.name - Event name. "pageview" is just a conventional event name; events are not modeled specially. * @param {string} params.url - Full page URL or screen identifier. * @param {string} params.domain - Hostname (e.g. example.com). @@ -44,7 +44,7 @@ export class Analytics { /** * Send a tracking event from a browser, native app, or server-side SDK. * - * @param {string} propertyId - Analytics property ID or snippet ID identifying the property. + * @param {string} propertyId - Analytics property ID. * @param {string} name - Event name. "pageview" is just a conventional event name; events are not modeled specially. * @param {string} url - Full page URL or screen identifier. * @param {string} domain - Hostname (e.g. example.com). diff --git a/src/services/apps.ts b/src/services/apps.ts index bd67c75..42640c8 100644 --- a/src/services/apps.ts +++ b/src/services/apps.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Apps { @@ -71,7 +76,72 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appsList', + models: { + appsList: { + defaults: { + total: 0, + apps: [], + }, + properties: { + apps: { + items: 'app', + }, + }, + }, + app: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + description: '', + clientUri: '', + logoUri: '', + privacyPolicyUrl: '', + termsUrl: '', + contacts: [], + tagline: '', + tags: [], + labels: [], + images: [], + supportUrl: '', + dataDeletionUrl: '', + redirectUris: [], + postLogoutRedirectUris: [], + enabled: true, + type: 'confidential', + deviceFlow: false, + teamId: '', + userId: '', + installationScopes: [], + installationRedirectUrl: '', + secrets: [], + }, + properties: { + secrets: { + items: 'appSecret', + }, + }, + }, + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -382,7 +452,61 @@ export class Apps { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'app', + models: { + app: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + description: '', + clientUri: '', + logoUri: '', + privacyPolicyUrl: '', + termsUrl: '', + contacts: [], + tagline: '', + tags: [], + labels: [], + images: [], + supportUrl: '', + dataDeletionUrl: '', + redirectUris: [], + postLogoutRedirectUris: [], + enabled: true, + type: 'confidential', + deviceFlow: false, + teamId: '', + userId: '', + installationScopes: [], + installationRedirectUrl: '', + secrets: [], + }, + properties: { + secrets: { + items: 'appSecret', + }, + }, + }, + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -401,7 +525,34 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appScopeList', + models: { + appScopeList: { + defaults: { + total: 0, + scopes: [], + }, + properties: { + scopes: { + items: 'appScope', + }, + }, + }, + appScope: { + defaults: { + value: '', + description: '', + type: '', + category: '', + deprecated: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -420,7 +571,34 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appScopeList', + models: { + appScopeList: { + defaults: { + total: 0, + scopes: [], + }, + properties: { + scopes: { + items: 'appScope', + }, + }, + }, + appScope: { + defaults: { + value: '', + description: '', + type: '', + category: '', + deprecated: false, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -472,7 +650,61 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'app', + models: { + app: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + description: '', + clientUri: '', + logoUri: '', + privacyPolicyUrl: '', + termsUrl: '', + contacts: [], + tagline: '', + tags: [], + labels: [], + images: [], + supportUrl: '', + dataDeletionUrl: '', + redirectUris: [], + postLogoutRedirectUris: [], + enabled: true, + type: 'confidential', + deviceFlow: false, + teamId: '', + userId: '', + installationScopes: [], + installationRedirectUrl: '', + secrets: [], + }, + properties: { + secrets: { + items: 'appSecret', + }, + }, + }, + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -791,7 +1023,61 @@ export class Apps { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'app', + models: { + app: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + description: '', + clientUri: '', + logoUri: '', + privacyPolicyUrl: '', + termsUrl: '', + contacts: [], + tagline: '', + tags: [], + labels: [], + images: [], + supportUrl: '', + dataDeletionUrl: '', + redirectUris: [], + postLogoutRedirectUris: [], + enabled: true, + type: 'confidential', + deviceFlow: false, + teamId: '', + userId: '', + installationScopes: [], + installationRedirectUrl: '', + secrets: [], + }, + properties: { + secrets: { + items: 'appSecret', + }, + }, + }, + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -926,7 +1212,38 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallationList', + models: { + appInstallationList: { + defaults: { + total: 0, + installations: [], + }, + properties: { + installations: { + items: 'appInstallation', + }, + }, + }, + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1001,7 +1318,27 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1150,7 +1487,23 @@ export class Apps { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Token', + models: { + oauth2Token: { + defaults: { + access_token: '', + token_type: 'Bearer', + expires_in: 0, + refresh_token: '', + scope: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1232,7 +1585,37 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appKeyList', + models: { + appKeyList: { + defaults: { + total: 0, + keys: [], + }, + properties: { + keys: { + items: 'appKey', + }, + }, + }, + appKey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1287,7 +1670,26 @@ export class Apps { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appKey', + models: { + appKey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1348,7 +1750,26 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appKey', + models: { + appKey: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1492,7 +1913,37 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appSecretList', + models: { + appSecretList: { + defaults: { + total: 0, + secrets: [], + }, + properties: { + secrets: { + items: 'appSecret', + }, + }, + }, + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1547,7 +1998,26 @@ export class Apps { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appSecretPlaintext', + models: { + appSecretPlaintext: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1616,7 +2086,26 @@ export class Apps { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appSecret', + models: { + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1749,7 +2238,61 @@ export class Apps { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'app', + models: { + app: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + description: '', + clientUri: '', + logoUri: '', + privacyPolicyUrl: '', + termsUrl: '', + contacts: [], + tagline: '', + tags: [], + labels: [], + images: [], + supportUrl: '', + dataDeletionUrl: '', + redirectUris: [], + postLogoutRedirectUris: [], + enabled: true, + type: 'confidential', + deviceFlow: false, + teamId: '', + userId: '', + installationScopes: [], + installationRedirectUrl: '', + secrets: [], + }, + properties: { + secrets: { + items: 'appSecret', + }, + }, + }, + appSecret: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + secret: '', + hint: '', + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/services/databases.ts b/src/services/databases.ts index 98102c1..c09d0fd 100644 --- a/src/services/databases.ts +++ b/src/services/databases.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Databases { @@ -75,7 +80,35 @@ export class Databases { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transactionList', + models: { + transactionList: { + defaults: { + total: 0, + transactions: [], + }, + properties: { + transactions: { + items: 'transaction', + }, + }, + }, + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -129,7 +162,24 @@ export class Databases { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -188,7 +238,24 @@ export class Databases { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -279,7 +346,24 @@ export class Databases { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -414,7 +498,24 @@ export class Databases { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -551,7 +652,36 @@ export class Databases { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'documentList', + models: { + documentList: { + defaults: { + total: 0, + documents: [], + }, + properties: { + documents: { + items: 'document', + }, + }, + }, + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -561,8 +691,8 @@ export class Databases { * @param {string} params.collectionId - Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents. * @param {string} params.documentId - Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. * @param {Document extends Models.DefaultDocument ? Partial & Record : Partial & Omit} params.data - Document data as JSON object. - * @param {string[]} params.permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {string[] | null} params.permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated This API has been deprecated since 1.8.0. Please use `TablesDB.createRow` instead. @@ -576,8 +706,8 @@ export class Databases { data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }): Promise; /** * Create a new 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. @@ -586,8 +716,8 @@ export class Databases { * @param {string} collectionId - Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents. * @param {string} documentId - Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. * @param {Document extends Models.DefaultDocument ? Partial & Record : Partial & Omit} data - Document data as JSON object. - * @param {string[]} permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {string[] | null} permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -599,8 +729,8 @@ export class Databases { data: Document extends Models.DefaultDocument ? Partial & Record : Partial & Omit, - permissions?: string[], - transactionId?: string, + permissions?: string[] | null, + transactionId?: string | null, ): Promise; createDocument( paramsOrFirst: @@ -612,8 +742,8 @@ export class Databases { ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; } | string, ...rest: [ @@ -623,8 +753,8 @@ export class Databases { ? Partial & Record : Partial & Omit)?, - string[]?, - string?, + (string[] | null)?, + (string | null)?, ] ): Promise { let params: { @@ -635,8 +765,8 @@ export class Databases { ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; if ( @@ -652,8 +782,8 @@ export class Databases { ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; } else { params = { @@ -664,8 +794,8 @@ export class Databases { ? Partial & Record : Partial & Omit, - permissions: rest[3] as string[], - transactionId: rest[4] as string, + permissions: rest[3] as string[] | null, + transactionId: rest[4] as string | null, }; } @@ -722,7 +852,25 @@ export class Databases { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -853,7 +1001,25 @@ export class Databases { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -863,8 +1029,8 @@ export class Databases { * @param {string} params.collectionId - Collection ID. * @param {string} params.documentId - Document ID. * @param {Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>} params.data - Document data as JSON object. Include all required attributes of the document to be created or updated. - * @param {string[]} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {string[] | null} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated This API has been deprecated since 1.8.0. Please use `TablesDB.upsertRow` instead. @@ -879,8 +1045,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }): 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. @@ -889,8 +1055,8 @@ export class Databases { * @param {string} collectionId - Collection ID. * @param {string} documentId - Document ID. * @param {Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>} data - Document data as JSON object. Include all required attributes of the document to be created or updated. - * @param {string[]} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {string[] | null} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -903,8 +1069,8 @@ export class Databases { ? Partial & Record : Partial & Partial>, - permissions?: string[], - transactionId?: string, + permissions?: string[] | null, + transactionId?: string | null, ): Promise; upsertDocument( paramsOrFirst: @@ -916,8 +1082,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; } | string, ...rest: [ @@ -927,8 +1093,8 @@ export class Databases { ? Partial & Record : Partial & Partial>)?, - string[]?, - string?, + (string[] | null)?, + (string | null)?, ] ): Promise { let params: { @@ -939,8 +1105,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; if ( @@ -956,8 +1122,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; } else { params = { @@ -968,8 +1134,8 @@ export class Databases { ? Partial & Record : Partial & Partial>, - permissions: rest[3] as string[], - transactionId: rest[4] as string, + permissions: rest[3] as string[] | null, + transactionId: rest[4] as string | null, }; } @@ -1024,7 +1190,25 @@ export class Databases { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1034,8 +1218,8 @@ export class Databases { * @param {string} params.collectionId - Collection ID. * @param {string} params.documentId - Document ID. * @param {Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>} params.data - Document data as JSON object. Include only attribute and value pairs to be updated. - * @param {string[]} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {string[] | null} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated This API has been deprecated since 1.8.0. Please use `TablesDB.updateRow` instead. @@ -1050,8 +1234,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }): Promise; /** * Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated. @@ -1060,8 +1244,8 @@ export class Databases { * @param {string} collectionId - Collection ID. * @param {string} documentId - Document ID. * @param {Document extends Models.DefaultDocument ? Partial & Record : Partial & Partial>} data - Document data as JSON object. Include only attribute and value pairs to be updated. - * @param {string[]} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {string[] | null} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -1074,8 +1258,8 @@ export class Databases { ? Partial & Record : Partial & Partial>, - permissions?: string[], - transactionId?: string, + permissions?: string[] | null, + transactionId?: string | null, ): Promise; updateDocument( paramsOrFirst: @@ -1087,8 +1271,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; } | string, ...rest: [ @@ -1098,8 +1282,8 @@ export class Databases { ? Partial & Record : Partial & Partial>)?, - string[]?, - string?, + (string[] | null)?, + (string | null)?, ] ): Promise { let params: { @@ -1110,8 +1294,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; if ( @@ -1127,8 +1311,8 @@ export class Databases { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; } else { params = { @@ -1139,8 +1323,8 @@ export class Databases { ? Partial & Record : Partial & Partial>, - permissions: rest[3] as string[], - transactionId: rest[4] as string, + permissions: rest[3] as string[] | null, + transactionId: rest[4] as string | null, }; } @@ -1195,7 +1379,25 @@ export class Databases { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1324,8 +1526,8 @@ export class Databases { * @param {string} params.documentId - Document ID. * @param {string} params.attribute - Attribute key. * @param {number} params.value - Value to increment the attribute by. The value must be a number. - * @param {number} params.min - Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown. - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {number | null} params.min - Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown. + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated This API has been deprecated since 1.8.0. Please use `TablesDB.decrementRowColumn` instead. @@ -1338,8 +1540,8 @@ export class Databases { documentId: string; attribute: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; }): Promise; /** * Decrement a specific attribute of a document by a given value. @@ -1349,8 +1551,8 @@ export class Databases { * @param {string} documentId - Document ID. * @param {string} attribute - Attribute key. * @param {number} value - Value to increment the attribute by. The value must be a number. - * @param {number} min - Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown. - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {number | null} min - Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown. + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -1363,8 +1565,8 @@ export class Databases { documentId: string, attribute: string, value?: number, - min?: number, - transactionId?: string, + min?: number | null, + transactionId?: string | null, ): Promise; decrementDocumentAttribute< Document extends Models.Document = Models.DefaultDocument, @@ -1376,11 +1578,18 @@ export class Databases { documentId: string; attribute: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; } | string, - ...rest: [string?, string?, string?, number?, number?, string?] + ...rest: [ + string?, + string?, + string?, + number?, + (number | null)?, + (string | null)?, + ] ): Promise { let params: { databaseId: string; @@ -1388,8 +1597,8 @@ export class Databases { documentId: string; attribute: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; }; if ( @@ -1403,8 +1612,8 @@ export class Databases { documentId: string; attribute: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; }; } else { params = { @@ -1413,8 +1622,8 @@ export class Databases { documentId: rest[1] as string, attribute: rest[2] as string, value: rest[3] as number, - min: rest[4] as number, - transactionId: rest[5] as string, + min: rest[4] as number | null, + transactionId: rest[5] as string | null, }; } @@ -1473,7 +1682,25 @@ export class Databases { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1484,8 +1711,8 @@ export class Databases { * @param {string} params.documentId - Document ID. * @param {string} params.attribute - Attribute key. * @param {number} params.value - Value to increment the attribute by. The value must be a number. - * @param {number} params.max - Maximum value for the attribute. If the current value is greater than this value, an error will be thrown. - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {number | null} params.max - Maximum value for the attribute. If the current value is greater than this value, an error will be thrown. + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated This API has been deprecated since 1.8.0. Please use `TablesDB.incrementRowColumn` instead. @@ -1498,8 +1725,8 @@ export class Databases { documentId: string; attribute: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; }): Promise; /** * Increment a specific attribute of a document by a given value. @@ -1509,8 +1736,8 @@ export class Databases { * @param {string} documentId - Document ID. * @param {string} attribute - Attribute key. * @param {number} value - Value to increment the attribute by. The value must be a number. - * @param {number} max - Maximum value for the attribute. If the current value is greater than this value, an error will be thrown. - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {number | null} max - Maximum value for the attribute. If the current value is greater than this value, an error will be thrown. + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -1523,8 +1750,8 @@ export class Databases { documentId: string, attribute: string, value?: number, - max?: number, - transactionId?: string, + max?: number | null, + transactionId?: string | null, ): Promise; incrementDocumentAttribute< Document extends Models.Document = Models.DefaultDocument, @@ -1536,11 +1763,18 @@ export class Databases { documentId: string; attribute: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; } | string, - ...rest: [string?, string?, string?, number?, number?, string?] + ...rest: [ + string?, + string?, + string?, + number?, + (number | null)?, + (string | null)?, + ] ): Promise { let params: { databaseId: string; @@ -1548,8 +1782,8 @@ export class Databases { documentId: string; attribute: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; }; if ( @@ -1563,8 +1797,8 @@ export class Databases { documentId: string; attribute: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; }; } else { params = { @@ -1573,8 +1807,8 @@ export class Databases { documentId: rest[1] as string, attribute: rest[2] as string, value: rest[3] as number, - max: rest[4] as number, - transactionId: rest[5] as string, + max: rest[4] as number | null, + transactionId: rest[5] as string | null, }; } @@ -1633,6 +1867,24 @@ export class Databases { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/documents-db.ts b/src/services/documents-db.ts index 82a86a9..b43eb23 100644 --- a/src/services/documents-db.ts +++ b/src/services/documents-db.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class DocumentsDB { @@ -74,7 +79,35 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transactionList', + models: { + transactionList: { + defaults: { + total: 0, + transactions: [], + }, + properties: { + transactions: { + items: 'transaction', + }, + }, + }, + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -127,7 +160,24 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -185,7 +235,24 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -275,7 +342,24 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -408,7 +492,24 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -544,7 +645,36 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'documentList', + models: { + documentList: { + defaults: { + total: 0, + documents: [], + }, + properties: { + documents: { + items: 'document', + }, + }, + }, + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -714,7 +844,25 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -832,7 +980,36 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'documentList', + models: { + documentList: { + defaults: { + total: 0, + documents: [], + }, + properties: { + documents: { + items: 'document', + }, + }, + }, + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -962,7 +1139,25 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1132,7 +1327,25 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1302,7 +1515,25 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1578,7 +1809,25 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1737,6 +1986,24 @@ export class DocumentsDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/functions.ts b/src/services/functions.ts index 7ab3248..4dd9a3e 100644 --- a/src/services/functions.ts +++ b/src/services/functions.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; import { ExecutionMethod } from '../enums/execution-method'; @@ -91,7 +96,59 @@ export class Functions { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'executionList', + models: { + executionList: { + defaults: { + total: 0, + executions: [], + }, + properties: { + executions: { + items: 'execution', + }, + }, + }, + execution: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + resourceId: '', + resourceType: 'functions', + deploymentId: '', + requestMethod: '', + requestPath: '', + requestHeaders: [], + responseStatusCode: 0, + responseBody: '', + responseHeaders: [], + logs: '', + errors: '', + duration: 0, + }, + properties: { + requestHeaders: { + items: 'headers', + }, + responseHeaders: { + items: 'headers', + }, + }, + }, + headers: { + defaults: { + name: '', + value: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -103,7 +160,7 @@ export class Functions { * @param {string} params.xpath - HTTP path of execution. Path can include query params. Default value is / * @param {ExecutionMethod} params.method - HTTP method of execution. Default value is POST. * @param {object} params.headers - HTTP headers of execution. Defaults to empty. - * @param {string} params.scheduledAt - Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes. + * @param {string | null} params.scheduledAt - Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes. * @throws {AppwriteException} * @returns {Promise} */ @@ -114,7 +171,7 @@ export class Functions { xpath?: string; method?: ExecutionMethod; headers?: object; - scheduledAt?: string; + scheduledAt?: string | null; }): Promise; /** * Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously. @@ -125,7 +182,7 @@ export class Functions { * @param {string} xpath - HTTP path of execution. Path can include query params. Default value is / * @param {ExecutionMethod} method - HTTP method of execution. Default value is POST. * @param {object} headers - HTTP headers of execution. Defaults to empty. - * @param {string} scheduledAt - Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes. + * @param {string | null} scheduledAt - Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -137,7 +194,7 @@ export class Functions { xpath?: string, method?: ExecutionMethod, headers?: object, - scheduledAt?: string, + scheduledAt?: string | null, ): Promise; createExecution( paramsOrFirst: @@ -148,7 +205,7 @@ export class Functions { xpath?: string; method?: ExecutionMethod; headers?: object; - scheduledAt?: string; + scheduledAt?: string | null; } | string, ...rest: [ @@ -157,7 +214,7 @@ export class Functions { string?, ExecutionMethod?, object?, - string?, + (string | null)?, ] ): Promise { let params: { @@ -167,7 +224,7 @@ export class Functions { xpath?: string; method?: ExecutionMethod; headers?: object; - scheduledAt?: string; + scheduledAt?: string | null; }; if ( @@ -182,7 +239,7 @@ export class Functions { xpath?: string; method?: ExecutionMethod; headers?: object; - scheduledAt?: string; + scheduledAt?: string | null; }; } else { params = { @@ -192,7 +249,7 @@ export class Functions { xpath: rest[2] as string, method: rest[3] as ExecutionMethod, headers: rest[4] as object, - scheduledAt: rest[5] as string, + scheduledAt: rest[5] as string | null, }; } @@ -240,7 +297,48 @@ export class Functions { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'execution', + models: { + execution: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + resourceId: '', + resourceType: 'functions', + deploymentId: '', + requestMethod: '', + requestPath: '', + requestHeaders: [], + responseStatusCode: 0, + responseBody: '', + responseHeaders: [], + logs: '', + errors: '', + duration: 0, + }, + properties: { + requestHeaders: { + items: 'headers', + }, + responseHeaders: { + items: 'headers', + }, + }, + }, + headers: { + defaults: { + name: '', + value: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -314,6 +412,47 @@ export class Functions { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'execution', + models: { + execution: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + resourceId: '', + resourceType: 'functions', + deploymentId: '', + requestMethod: '', + requestPath: '', + requestHeaders: [], + responseStatusCode: 0, + responseBody: '', + responseHeaders: [], + logs: '', + errors: '', + duration: 0, + }, + properties: { + requestHeaders: { + items: 'headers', + }, + responseHeaders: { + items: 'headers', + }, + }, + }, + headers: { + defaults: { + name: '', + value: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/locale.ts b/src/services/locale.ts index d7e6a82..e99c17d 100644 --- a/src/services/locale.ts +++ b/src/services/locale.ts @@ -1,4 +1,4 @@ -import { Client, type Payload } from '../client'; +import { Client, type Payload, applyDefaults } from '../client'; import type { Models } from '../models'; export class Locale { @@ -26,7 +26,25 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'locale', + models: { + locale: { + defaults: { + ip: '', + countryCode: '', + country: '', + continentCode: '', + continent: '', + eu: false, + currency: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -78,7 +96,31 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'localeCodeList', + models: { + localeCodeList: { + defaults: { + total: 0, + localeCodes: [], + }, + properties: { + localeCodes: { + items: 'localeCode', + }, + }, + }, + localeCode: { + defaults: { + code: '', + name: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -130,7 +172,31 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'continentList', + models: { + continentList: { + defaults: { + total: 0, + continents: [], + }, + properties: { + continents: { + items: 'continent', + }, + }, + }, + continent: { + defaults: { + name: '', + code: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -182,7 +248,31 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'countryList', + models: { + countryList: { + defaults: { + total: 0, + countries: [], + }, + properties: { + countries: { + items: 'country', + }, + }, + }, + country: { + defaults: { + name: '', + code: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -234,7 +324,31 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'countryList', + models: { + countryList: { + defaults: { + total: 0, + countries: [], + }, + properties: { + countries: { + items: 'country', + }, + }, + }, + country: { + defaults: { + name: '', + code: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -288,7 +402,32 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'phoneList', + models: { + phoneList: { + defaults: { + total: 0, + phones: [], + }, + properties: { + phones: { + items: 'phone', + }, + }, + }, + phone: { + defaults: { + code: '', + countryCode: '', + countryName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -340,7 +479,36 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'currencyList', + models: { + currencyList: { + defaults: { + total: 0, + currencies: [], + }, + properties: { + currencies: { + items: 'currency', + }, + }, + }, + currency: { + defaults: { + symbol: '', + name: '', + symbolNative: '', + decimalDigits: 0, + rounding: 0, + code: '', + namePlural: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -392,6 +560,31 @@ export class Locale { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'languageList', + models: { + languageList: { + defaults: { + total: 0, + languages: [], + }, + properties: { + languages: { + items: 'language', + }, + }, + }, + language: { + defaults: { + name: '', + code: '', + nativeName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/messaging.ts b/src/services/messaging.ts index 740ecf1..dba2024 100644 --- a/src/services/messaging.ts +++ b/src/services/messaging.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Messaging { @@ -101,7 +106,26 @@ export class Messaging { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'subscriber', + models: { + subscriber: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + targetId: '', + userId: '', + userName: '', + topicId: '', + providerType: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/services/oauth-2.ts b/src/services/oauth-2.ts index 0cb439c..6b176f6 100644 --- a/src/services/oauth-2.ts +++ b/src/services/oauth-2.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Oauth2 { @@ -97,7 +102,19 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Approve', + models: { + oauth2Approve: { + defaults: { + redirectUrl: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -114,7 +131,7 @@ export class Oauth2 { * @param {string} params.prompt - OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. * @param {number} params.maxAge - OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. * @param {string} params.authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} params.audience - Compatibility alias for a single OAuth2 resource indicator URI. * @param {string} params.requestUri - OAuth2 authorization request handle returned by the pushed authorization request endpoint. * @throws {AppwriteException} @@ -132,7 +149,7 @@ export class Oauth2 { prompt?: string; maxAge?: number; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; }): Promise; @@ -150,7 +167,7 @@ export class Oauth2 { * @param {string} prompt - OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. * @param {number} maxAge - OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. * @param {string} authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} audience - Compatibility alias for a single OAuth2 resource indicator URI. * @param {string} requestUri - OAuth2 authorization request handle returned by the pushed authorization request endpoint. * @throws {AppwriteException} @@ -169,7 +186,7 @@ export class Oauth2 { prompt?: string, maxAge?: number, authorizationDetails?: string, - resource?: string, + resource?: string[], audience?: string, requestUri?: string, ): Promise; @@ -187,7 +204,7 @@ export class Oauth2 { prompt?: string; maxAge?: number; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; } @@ -203,7 +220,7 @@ export class Oauth2 { string?, number?, string?, - string?, + string[]?, string?, string?, ] @@ -220,7 +237,7 @@ export class Oauth2 { prompt?: string; maxAge?: number; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; }; @@ -243,7 +260,7 @@ export class Oauth2 { prompt?: string; maxAge?: number; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; }; @@ -260,7 +277,7 @@ export class Oauth2 { prompt: rest[7] as string, maxAge: rest[8] as number, authorizationDetails: rest[9] as string, - resource: rest[10] as string, + resource: rest[10] as string[], audience: rest[11] as string, requestUri: rest[12] as string, }; @@ -334,7 +351,20 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Authorize', + models: { + oauth2Authorize: { + defaults: { + grantId: '', + redirectUrl: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -349,9 +379,9 @@ export class Oauth2 { * @param {string} params.codeChallenge - PKCE code challenge. Required when OAuth2 app is public. * @param {string} params.codeChallengeMethod - PKCE code challenge method. Required when OAuth2 app is public. * @param {string} params.prompt - OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. - * @param {number} params.maxAge - OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. + * @param {number | null} params.maxAge - OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. * @param {string} params.authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} params.audience - Compatibility alias for a single OAuth2 resource indicator URI. * @param {string} params.requestUri - OAuth2 authorization request handle returned by the pushed authorization request endpoint. * @throws {AppwriteException} @@ -367,9 +397,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; }): Promise; @@ -385,9 +415,9 @@ export class Oauth2 { * @param {string} codeChallenge - PKCE code challenge. Required when OAuth2 app is public. * @param {string} codeChallengeMethod - PKCE code challenge method. Required when OAuth2 app is public. * @param {string} prompt - OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. - * @param {number} maxAge - OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. + * @param {number | null} maxAge - OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. * @param {string} authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} audience - Compatibility alias for a single OAuth2 resource indicator URI. * @param {string} requestUri - OAuth2 authorization request handle returned by the pushed authorization request endpoint. * @throws {AppwriteException} @@ -404,9 +434,9 @@ export class Oauth2 { codeChallenge?: string, codeChallengeMethod?: string, prompt?: string, - maxAge?: number, + maxAge?: number | null, authorizationDetails?: string, - resource?: string, + resource?: string[], audience?: string, requestUri?: string, ): Promise; @@ -422,9 +452,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; } @@ -438,9 +468,9 @@ export class Oauth2 { string?, string?, string?, - number?, - string?, + (number | null)?, string?, + string[]?, string?, string?, ] @@ -455,9 +485,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; }; @@ -478,9 +508,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; requestUri?: string; }; @@ -495,9 +525,9 @@ export class Oauth2 { codeChallenge: rest[5] as string, codeChallengeMethod: rest[6] as string, prompt: rest[7] as string, - maxAge: rest[8] as number, + maxAge: rest[8] as number | null, authorizationDetails: rest[9] as string, - resource: rest[10] as string, + resource: rest[10] as string[], audience: rest[11] as string, requestUri: rest[12] as string, }; @@ -572,7 +602,20 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Authorize', + models: { + oauth2Authorize: { + defaults: { + grantId: '', + redirectUrl: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -581,7 +624,7 @@ export class Oauth2 { * @param {string} params.clientId - OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. * @param {string} params.scope - Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`. * @param {string} params.authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} params.audience - Compatibility alias for a single OAuth2 resource indicator URI. * @throws {AppwriteException} * @returns {Promise} @@ -590,7 +633,7 @@ export class Oauth2 { clientId?: string; scope?: string; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; }): Promise; /** @@ -599,7 +642,7 @@ export class Oauth2 { * @param {string} clientId - OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. * @param {string} scope - Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`. * @param {string} authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} audience - Compatibility alias for a single OAuth2 resource indicator URI. * @throws {AppwriteException} * @returns {Promise} @@ -609,7 +652,7 @@ export class Oauth2 { clientId?: string, scope?: string, authorizationDetails?: string, - resource?: string, + resource?: string[], audience?: string, ): Promise; createDeviceAuthorization( @@ -618,17 +661,17 @@ export class Oauth2 { clientId?: string; scope?: string; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; } | string, - ...rest: [string?, string?, string?, string?] + ...rest: [string?, string?, string[]?, string?] ): Promise { let params: { clientId?: string; scope?: string; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; }; @@ -642,7 +685,7 @@ export class Oauth2 { clientId?: string; scope?: string; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; }; } else { @@ -650,7 +693,7 @@ export class Oauth2 { clientId: paramsOrFirst as string, scope: rest[0] as string, authorizationDetails: rest[1] as string, - resource: rest[2] as string, + resource: rest[2] as string[], audience: rest[3] as string, }; } @@ -688,7 +731,24 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2DeviceAuthorization', + models: { + oauth2DeviceAuthorization: { + defaults: { + device_code: '', + user_code: '', + verification_uri: '', + verification_uri_complete: '', + expires_in: 0, + interval: 0, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -747,7 +807,30 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Grant', + models: { + oauth2Grant: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + appId: '', + scopes: [], + resources: [], + authorizationDetails: '[]', + prompt: '', + redirectUri: '', + authTime: 0, + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -804,7 +887,30 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Grant', + models: { + oauth2Grant: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + appId: '', + scopes: [], + resources: [], + authorizationDetails: '[]', + prompt: '', + redirectUri: '', + authTime: 0, + expire: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1141,7 +1247,30 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2OrganizationList', + models: { + oauth2OrganizationList: { + defaults: { + total: 0, + organizations: [], + }, + properties: { + organizations: { + items: 'oauth2Organization', + }, + }, + }, + oauth2Organization: { + defaults: { + $id: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1156,9 +1285,9 @@ export class Oauth2 { * @param {string} params.codeChallenge - PKCE code challenge. Required when OAuth2 app is public. * @param {string} params.codeChallengeMethod - PKCE code challenge method. Required when OAuth2 app is public. * @param {string} params.prompt - OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. - * @param {number} params.maxAge - OIDC max_age parameter for customization of consent screen. + * @param {number | null} params.maxAge - OIDC max_age parameter for customization of consent screen. * @param {string} params.authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} params.audience - Compatibility alias for a single OAuth2 resource indicator URI. * @throws {AppwriteException} * @returns {Promise} @@ -1173,9 +1302,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; }): Promise; /** @@ -1190,9 +1319,9 @@ export class Oauth2 { * @param {string} codeChallenge - PKCE code challenge. Required when OAuth2 app is public. * @param {string} codeChallengeMethod - PKCE code challenge method. Required when OAuth2 app is public. * @param {string} prompt - OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. - * @param {number} maxAge - OIDC max_age parameter for customization of consent screen. + * @param {number | null} maxAge - OIDC max_age parameter for customization of consent screen. * @param {string} authorizationDetails - Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - * @param {string} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} audience - Compatibility alias for a single OAuth2 resource indicator URI. * @throws {AppwriteException} * @returns {Promise} @@ -1208,9 +1337,9 @@ export class Oauth2 { codeChallenge?: string, codeChallengeMethod?: string, prompt?: string, - maxAge?: number, + maxAge?: number | null, authorizationDetails?: string, - resource?: string, + resource?: string[], audience?: string, ): Promise; createPAR( @@ -1225,9 +1354,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; } | string, @@ -1240,9 +1369,9 @@ export class Oauth2 { string?, string?, string?, - number?, - string?, + (number | null)?, string?, + string[]?, string?, ] ): Promise { @@ -1256,9 +1385,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; }; @@ -1277,9 +1406,9 @@ export class Oauth2 { codeChallenge?: string; codeChallengeMethod?: string; prompt?: string; - maxAge?: number; + maxAge?: number | null; authorizationDetails?: string; - resource?: string; + resource?: string[]; audience?: string; }; } else { @@ -1293,9 +1422,9 @@ export class Oauth2 { codeChallenge: rest[5] as string, codeChallengeMethod: rest[6] as string, prompt: rest[7] as string, - maxAge: rest[8] as number, + maxAge: rest[8] as number | null, authorizationDetails: rest[9] as string, - resource: rest[10] as string, + resource: rest[10] as string[], audience: rest[11] as string, }; } @@ -1380,7 +1509,20 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2PAR', + models: { + oauth2PAR: { + defaults: { + request_uri: '', + expires_in: 0, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1462,7 +1604,32 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2ProjectList', + models: { + oauth2ProjectList: { + defaults: { + total: 0, + projects: [], + }, + properties: { + projects: { + items: 'oauth2Project', + }, + }, + }, + oauth2Project: { + defaults: { + $id: '', + region: '', + endpoint: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1521,7 +1688,19 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Reject', + models: { + oauth2Reject: { + defaults: { + redirectUrl: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1641,7 +1820,7 @@ export class Oauth2 { * @param {string} params.clientSecret - OAuth2 client secret. Required for confidential apps. * @param {string} params.codeVerifier - PKCE code verifier. Required for public apps. * @param {string} params.redirectUri - Redirect URI. Required for `authorization_code` grant type. - * @param {string} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} params.resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} params.audience - Compatibility alias for a single OAuth2 resource indicator URI. * @throws {AppwriteException} * @returns {Promise} @@ -1655,7 +1834,7 @@ export class Oauth2 { clientSecret?: string; codeVerifier?: string; redirectUri?: string; - resource?: string; + resource?: string[]; audience?: string; }): Promise; /** @@ -1669,7 +1848,7 @@ export class Oauth2 { * @param {string} clientSecret - OAuth2 client secret. Required for confidential apps. * @param {string} codeVerifier - PKCE code verifier. Required for public apps. * @param {string} redirectUri - Redirect URI. Required for `authorization_code` grant type. - * @param {string} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. + * @param {string[]} resource - RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. * @param {string} audience - Compatibility alias for a single OAuth2 resource indicator URI. * @throws {AppwriteException} * @returns {Promise} @@ -1684,7 +1863,7 @@ export class Oauth2 { clientSecret?: string, codeVerifier?: string, redirectUri?: string, - resource?: string, + resource?: string[], audience?: string, ): Promise; createToken( @@ -1698,7 +1877,7 @@ export class Oauth2 { clientSecret?: string; codeVerifier?: string; redirectUri?: string; - resource?: string; + resource?: string[]; audience?: string; } | string, @@ -1710,7 +1889,7 @@ export class Oauth2 { string?, string?, string?, - string?, + string[]?, string?, ] ): Promise { @@ -1723,7 +1902,7 @@ export class Oauth2 { clientSecret?: string; codeVerifier?: string; redirectUri?: string; - resource?: string; + resource?: string[]; audience?: string; }; @@ -1741,7 +1920,7 @@ export class Oauth2 { clientSecret?: string; codeVerifier?: string; redirectUri?: string; - resource?: string; + resource?: string[]; audience?: string; }; } else { @@ -1754,7 +1933,7 @@ export class Oauth2 { clientSecret: rest[4] as string, codeVerifier: rest[5] as string, redirectUri: rest[6] as string, - resource: rest[7] as string, + resource: rest[7] as string[], audience: rest[8] as string, }; } @@ -1817,6 +1996,22 @@ export class Oauth2 { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'oauth2Token', + models: { + oauth2Token: { + defaults: { + access_token: '', + token_type: 'Bearer', + expires_in: 0, + refresh_token: '', + scope: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/organization.ts b/src/services/organization.ts index 4ae3386..21deae2 100644 --- a/src/services/organization.ts +++ b/src/services/organization.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Organization { @@ -74,7 +79,38 @@ export class Organization { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallationList', + models: { + appInstallationList: { + defaults: { + total: 0, + installations: [], + }, + properties: { + installations: { + items: 'appInstallation', + }, + }, + }, + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -147,7 +183,27 @@ export class Organization { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -205,40 +261,64 @@ export class Organization { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** * Update an app installation on the organization. Only organization members with the owner role can update installations. The installation's granted scopes are refreshed to the scopes the app currently requests; previously issued installation access tokens are revoked. * * @param {string} params.installationId - Installation unique ID. - * @param {string} params.authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. + * @param {string | null} params.authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. * @throws {AppwriteException} * @returns {Promise} */ updateInstallation(params: { installationId: string; - authorizationDetails?: string; + authorizationDetails?: string | null; }): Promise; /** * Update an app installation on the organization. Only organization members with the owner role can update installations. The installation's granted scopes are refreshed to the scopes the app currently requests; previously issued installation access tokens are revoked. * * @param {string} installationId - Installation unique ID. - * @param {string} authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. + * @param {string | null} authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. */ updateInstallation( installationId: string, - authorizationDetails?: string, + authorizationDetails?: string | null, ): Promise; updateInstallation( paramsOrFirst: - { installationId: string; authorizationDetails?: string } | string, - ...rest: [string?] + | { installationId: string; authorizationDetails?: string | null } + | string, + ...rest: [(string | null)?] ): Promise { - let params: { installationId: string; authorizationDetails?: string }; + let params: { + installationId: string; + authorizationDetails?: string | null; + }; if ( paramsOrFirst && @@ -247,12 +327,12 @@ export class Organization { ) { params = (paramsOrFirst || {}) as { installationId: string; - authorizationDetails?: string; + authorizationDetails?: string | null; }; } else { params = { installationId: paramsOrFirst as string, - authorizationDetails: rest[0] as string, + authorizationDetails: rest[0] as string | null, }; } @@ -280,7 +360,27 @@ export class Organization { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/services/presences.ts b/src/services/presences.ts index df362c3..1dba9a2 100644 --- a/src/services/presences.ts +++ b/src/services/presences.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Presences { @@ -87,7 +92,35 @@ export class Presences { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'presenceList', + models: { + presenceList: { + defaults: { + total: 0, + presences: [], + }, + properties: { + presences: { + items: 'presence', + }, + }, + }, + presence: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + userId: '', + source: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -145,7 +178,24 @@ export class Presences { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'presence', + models: { + presence: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + userId: '', + source: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -268,7 +318,24 @@ export class Presences { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'presence', + models: { + presence: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + userId: '', + source: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -400,7 +467,24 @@ export class Presences { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'presence', + models: { + presence: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + userId: '', + source: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/services/push.ts b/src/services/push.ts index 1c3dd5b..c93628a 100644 --- a/src/services/push.ts +++ b/src/services/push.ts @@ -6,7 +6,7 @@ import type { } from 'mqtt'; import { Client } from '../client'; -import type { ResolvedTopic, Topic } from '../topic'; +import type { Topic } from '../topic'; /** A message delivered on a subscribed topic (the MQTT analog of a Realtime event). */ export interface PushMessage { @@ -253,7 +253,7 @@ export class Push { * Subscribe to one or more topics. Resolves to a {@link PushSubscription} handle. * * Each topic is a string or a `Topic` builder, e.g. - * `Topic.path(['user', userId]).all()`. + * `Topic.path(['user', userId])`. * * Called with only a callback, `subscribe((message) => {...}, options)` subscribes to the * signed-in user's own topic, `users/`, like FCM/APNs delivery to a device. The @@ -275,18 +275,12 @@ export class Push { options?: SubscribeOptions, ): Promise; subscribe( - topics: - string | Topic | ResolvedTopic | (string | Topic | ResolvedTopic)[], + topics: string | Topic | (string | Topic)[], callback: MessageCallback, options?: SubscribeOptions, ): Promise; async subscribe( - topicsOrCallback: - | string - | Topic - | ResolvedTopic - | (string | Topic | ResolvedTopic)[] - | MessageCallback, + topicsOrCallback: string | Topic | (string | Topic)[] | MessageCallback, callbackOrOptions?: MessageCallback | SubscribeOptions, topicOptions: SubscribeOptions = {}, ): Promise { @@ -303,12 +297,7 @@ export class Push { } private async subscribeWith( - topicsOrCallback: - | string - | Topic - | ResolvedTopic - | (string | Topic | ResolvedTopic)[] - | MessageCallback, + topicsOrCallback: string | Topic | (string | Topic)[] | MessageCallback, callbackOrOptions: MessageCallback | SubscribeOptions | undefined, topicOptions: SubscribeOptions, ): Promise { @@ -884,22 +873,25 @@ export class Push { } } - /** Post a browser notification for a message a background subscription matched. */ + /** + * Post a browser notification for a message a background subscription matched. A data-only + * message, an envelope without a notification title or body, posts none. + */ private notify( message: PushMessage, title: string, content: NotificationContent, ): void { if ( + !content.visible || typeof Notification === 'undefined' || Notification.permission !== 'granted' ) { return; } - const raw = !content.present; // `image` is not in the DOM typings, but Chromium-based browsers show it. const options: NotificationOptions & { image?: string } = { - body: content.body ?? (raw ? message.data : undefined), + body: content.body ?? (content.raw ? message.data : undefined), image: content.image, data: { topic: message.topic, payload: message.data }, }; @@ -941,33 +933,51 @@ class SupersededError extends Error { /** What a message's `notification` block asks a background notification to show. */ interface NotificationContent { - /** Whether the message has a `notification` block at all. */ - present: boolean; + /** Whether the payload is not a JSON object, so it is shown as it is. */ + raw: boolean; + /** Whether a notification is posted: raw, or an envelope with a title or body. */ + visible: boolean; title?: string; body?: string; image?: string; } -/** The server's `notification` block in a message; empty when the payload has none or is not JSON. */ -function notificationContent(message: PushMessage): NotificationContent { - let notification: unknown; +/** The server's `notification` block in a payload, or null when the payload is not a JSON object. */ +function notificationBlock(data: string): Record | null { + let envelope: unknown; try { - notification = (JSON.parse(message.data) as { notification?: unknown }) - ?.notification; + envelope = JSON.parse(data); } catch { - return { present: false }; + return null; } - if (typeof notification !== 'object' || notification === null) { - return { present: false }; + if ( + typeof envelope !== 'object' || + envelope === null || + Array.isArray(envelope) + ) { + return null; } + const notification = (envelope as { notification?: unknown }).notification; + return typeof notification === 'object' && notification !== null + ? (notification as Record) + : {}; +} + +/** What a message asks a background notification to show; raw when it is not a JSON object. */ +function notificationContent(message: PushMessage): NotificationContent { + const block = notificationBlock(message.data); + const raw = block === null; const field = (name: string): string | undefined => { - const value = (notification as Record)[name]; + const value = block?.[name]; return typeof value === 'string' && value !== '' ? value : undefined; }; + const title = field('title'); + const body = field('body'); return { - present: true, - title: field('title'), - body: field('body'), + raw, + visible: raw || title !== undefined || body !== undefined, + title, + body, image: field('image'), }; } diff --git a/src/services/realtime.ts b/src/services/realtime.ts index 91aff43..59dc761 100644 --- a/src/services/realtime.ts +++ b/src/services/realtime.ts @@ -1,10 +1,11 @@ import { AppwriteException, Client, JSONbig } from '../client'; import { Channel, ActionableChannel, ResolvedChannel } from '../channel'; -import { Query } from '../query'; +import { normalizeQueries, type QueryInput } from '../query'; import { ID } from '../id'; + export type RealtimeSubscriptionUpdate = { channels?: (string | Channel | ActionableChannel | ResolvedChannel)[]; - queries?: (string | Query)[]; + queries?: QueryInput; }; export type RealtimeSubscription = { @@ -214,6 +215,7 @@ export class Realtime { if (jwt) { queryParams += `&jwt=${encodeURIComponent(jwt)}`; } + const endpoint = this.client.config.endpointRealtime !== '' ? this.client.config.endpointRealtime @@ -245,6 +247,7 @@ export class Realtime { try { const connectionId = ++this.connectionId; const socket = (this.socket = new WebSocket(url)); + socket.addEventListener('open', () => { if (connectionId !== this.connectionId) { return; @@ -500,7 +503,7 @@ export class Realtime { public async subscribe( channel: string | Channel | ActionableChannel | ResolvedChannel, callback: (event: RealtimeResponseEvent) => void, - queries?: (string | Query)[], + queries?: QueryInput, ): Promise; /** @@ -515,7 +518,7 @@ export class Realtime { string | Channel | ActionableChannel | ResolvedChannel )[], callback: (event: RealtimeResponseEvent) => void, - queries?: (string | Query)[], + queries?: QueryInput, ): Promise; /** @@ -528,7 +531,7 @@ export class Realtime { public async subscribe( channel: string | Channel | ActionableChannel | ResolvedChannel, callback: (event: RealtimeResponseEvent) => void, - queries?: (string | Query)[], + queries?: QueryInput, ): Promise; /** @@ -543,7 +546,7 @@ export class Realtime { string | Channel | ActionableChannel | ResolvedChannel )[], callback: (event: RealtimeResponseEvent) => void, - queries?: (string | Query)[], + queries?: QueryInput, ): Promise; public async subscribe( @@ -554,7 +557,7 @@ export class Realtime { | ResolvedChannel | (string | Channel | ActionableChannel | ResolvedChannel)[], callback: (event: RealtimeResponseEvent) => void, - queries: (string | Query)[] = [], + queries: QueryInput = [], ): Promise { const channelArray = Array.isArray(channelsOrChannel) ? channelsOrChannel @@ -566,21 +569,7 @@ export class Realtime { ); const channels = new Set(channelStrings); - // Convert queries to array of strings - // Ensure each query is a separate string in the array - const queryStrings: string[] = []; - for (const q of queries ?? []) { - if (Array.isArray(q)) { - // Handle nested arrays: [[q1, q2]] -> [q1, q2] - for (const inner of q) { - queryStrings.push( - typeof inner === 'string' ? inner : inner.toString(), - ); - } - } else { - queryStrings.push(typeof q === 'string' ? q : q.toString()); - } - } + const queryStrings = normalizeQueries(queries); const subscriptionId = this.generateUniqueSubscriptionId(); @@ -631,23 +620,7 @@ export class Realtime { } if (changes.queries !== undefined) { - const nextQueries: string[] = []; - for (const q of changes.queries) { - if (Array.isArray(q)) { - for (const inner of q) { - nextQueries.push( - typeof inner === 'string' - ? inner - : (inner as Query).toString(), - ); - } - } else { - nextQueries.push( - typeof q === 'string' ? q : q.toString(), - ); - } - } - subscription.queries = nextQueries; + subscription.queries = normalizeQueries(changes.queries); } this.enqueuePendingSubscribe(subscriptionId); diff --git a/src/services/storage.ts b/src/services/storage.ts index bd0220f..0d33a6f 100644 --- a/src/services/storage.ts +++ b/src/services/storage.ts @@ -3,6 +3,7 @@ import { Client, type Payload, UploadProgress, + applyDefaults, } from '../client'; import type { Models } from '../models'; @@ -117,7 +118,45 @@ export class Storage { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'fileList', + models: { + fileList: { + defaults: { + total: 0, + files: [], + }, + properties: { + files: { + items: 'file', + }, + }, + }, + file: { + defaults: { + $id: '', + bucketId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + name: '', + folder: '', + key: '', + signature: '', + mimeType: '', + sizeOriginal: 0, + sizeActual: 0, + chunksTotal: 0, + chunksUploaded: 0, + encryption: false, + compression: 'none', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -341,7 +380,34 @@ export class Storage { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'file', + models: { + file: { + defaults: { + $id: '', + bucketId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + name: '', + folder: '', + key: '', + signature: '', + mimeType: '', + sizeOriginal: 0, + sizeActual: 0, + chunksTotal: 0, + chunksUploaded: 0, + encryption: false, + compression: 'none', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -350,7 +416,7 @@ export class Storage { * @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). + * @param {string[] | null} 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} */ @@ -358,7 +424,7 @@ export class Storage { bucketId: string; fileId: string; name?: string; - permissions?: string[]; + permissions?: string[] | null; }): Promise; /** * Update a file by its unique ID. Only users with write permissions have access to update this resource. @@ -366,7 +432,7 @@ export class Storage { * @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). + * @param {string[] | null} 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. @@ -375,7 +441,7 @@ export class Storage { bucketId: string, fileId: string, name?: string, - permissions?: string[], + permissions?: string[] | null, ): Promise; updateFile( paramsOrFirst: @@ -383,16 +449,16 @@ export class Storage { bucketId: string; fileId: string; name?: string; - permissions?: string[]; + permissions?: string[] | null; } | string, - ...rest: [string?, string?, string[]?] + ...rest: [string?, string?, (string[] | null)?] ): Promise { let params: { bucketId: string; fileId: string; name?: string; - permissions?: string[]; + permissions?: string[] | null; }; if ( @@ -404,14 +470,14 @@ export class Storage { bucketId: string; fileId: string; name?: string; - permissions?: string[]; + permissions?: string[] | null; }; } else { params = { bucketId: paramsOrFirst as string, fileId: rest[0] as string, name: rest[1] as string, - permissions: rest[2] as string[], + permissions: rest[2] as string[] | null, }; } @@ -446,7 +512,34 @@ export class Storage { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'file', + models: { + file: { + defaults: { + $id: '', + bucketId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + name: '', + folder: '', + key: '', + signature: '', + mimeType: '', + sizeOriginal: 0, + sizeActual: 0, + chunksTotal: 0, + chunksUploaded: 0, + encryption: false, + compression: 'none', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/services/tables-db.ts b/src/services/tables-db.ts index 00acbed..789d25c 100644 --- a/src/services/tables-db.ts +++ b/src/services/tables-db.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class TablesDB { @@ -74,7 +79,35 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transactionList', + models: { + transactionList: { + defaults: { + total: 0, + transactions: [], + }, + properties: { + transactions: { + items: 'transaction', + }, + }, + }, + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -127,7 +160,24 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -185,7 +235,24 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -275,7 +342,24 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -408,7 +492,24 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -538,7 +639,36 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'rowList', + models: { + rowList: { + defaults: { + total: 0, + rows: [], + }, + properties: { + rows: { + items: 'row', + }, + }, + }, + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -548,8 +678,8 @@ export class TablesDB { * @param {string} params.tableId - Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable). Make sure to define columns before creating rows. * @param {string} params.rowId - Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. * @param {Row extends Models.DefaultRow ? Partial & Record : Partial & Omit} params.data - Row data as JSON object. - * @param {string[]} params.permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {string[] | null} params.permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} */ @@ -560,8 +690,8 @@ export class TablesDB { data: Row extends Models.DefaultRow ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }): Promise; /** * Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable) API or directly from your database console. @@ -570,8 +700,8 @@ export class TablesDB { * @param {string} tableId - Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable). Make sure to define columns before creating rows. * @param {string} rowId - Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. * @param {Row extends Models.DefaultRow ? Partial & Record : Partial & Omit} data - Row data as JSON object. - * @param {string[]} permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {string[] | null} permissions - An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -583,8 +713,8 @@ export class TablesDB { data: Row extends Models.DefaultRow ? Partial & Record : Partial & Omit, - permissions?: string[], - transactionId?: string, + permissions?: string[] | null, + transactionId?: string | null, ): Promise; createRow( paramsOrFirst: @@ -595,8 +725,8 @@ export class TablesDB { data: Row extends Models.DefaultRow ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; } | string, ...rest: [ @@ -605,8 +735,8 @@ export class TablesDB { (Row extends Models.DefaultRow ? Partial & Record : Partial & Omit)?, - string[]?, - string?, + (string[] | null)?, + (string | null)?, ] ): Promise { let params: { @@ -616,8 +746,8 @@ export class TablesDB { data: Row extends Models.DefaultRow ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; if ( @@ -632,8 +762,8 @@ export class TablesDB { data: Row extends Models.DefaultRow ? Partial & Record : Partial & Omit; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; } else { params = { @@ -643,8 +773,8 @@ export class TablesDB { data: rest[2] as Row extends Models.DefaultRow ? Partial & Record : Partial & Omit, - permissions: rest[3] as string[], - transactionId: rest[4] as string, + permissions: rest[3] as string[] | null, + transactionId: rest[4] as string | null, }; } @@ -695,7 +825,25 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'row', + models: { + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -814,7 +962,25 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'row', + models: { + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -824,8 +990,8 @@ export class TablesDB { * @param {string} params.tableId - Table ID. * @param {string} params.rowId - Row ID. * @param {Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>} params.data - Row data as JSON object. Include all required columns of the row to be created or updated. - * @param {string[]} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {string[] | null} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} */ @@ -836,8 +1002,8 @@ export class TablesDB { data?: Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }): Promise; /** * Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable) API or directly from your database console. @@ -846,8 +1012,8 @@ export class TablesDB { * @param {string} tableId - Table ID. * @param {string} rowId - Row ID. * @param {Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>} data - Row data as JSON object. Include all required columns of the row to be created or updated. - * @param {string[]} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {string[] | null} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -859,8 +1025,8 @@ export class TablesDB { data?: Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>, - permissions?: string[], - transactionId?: string, + permissions?: string[] | null, + transactionId?: string | null, ): Promise; upsertRow( paramsOrFirst: @@ -872,8 +1038,8 @@ export class TablesDB { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; } | string, ...rest: [ @@ -882,8 +1048,8 @@ export class TablesDB { (Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>)?, - string[]?, - string?, + (string[] | null)?, + (string | null)?, ] ): Promise { let params: { @@ -893,8 +1059,8 @@ export class TablesDB { data?: Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; if ( @@ -910,8 +1076,8 @@ export class TablesDB { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; } else { params = { @@ -922,8 +1088,8 @@ export class TablesDB { ? Partial & Record : Partial & Partial>, - permissions: rest[3] as string[], - transactionId: rest[4] as string, + permissions: rest[3] as string[] | null, + transactionId: rest[4] as string | null, }; } @@ -969,7 +1135,25 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'row', + models: { + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -979,8 +1163,8 @@ export class TablesDB { * @param {string} params.tableId - Table ID. * @param {string} params.rowId - Row ID. * @param {Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>} params.data - Row data as JSON object. Include only columns and value pairs to be updated. - * @param {string[]} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {string[] | null} params.permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} */ @@ -991,8 +1175,8 @@ export class TablesDB { data?: Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }): Promise; /** * Update a row by its unique ID. Using the patch method you can pass only specific fields that will get updated. @@ -1001,8 +1185,8 @@ export class TablesDB { * @param {string} tableId - Table ID. * @param {string} rowId - Row ID. * @param {Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>} data - Row data as JSON object. Include only columns and value pairs to be updated. - * @param {string[]} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {string[] | null} permissions - An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -1014,8 +1198,8 @@ export class TablesDB { data?: Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>, - permissions?: string[], - transactionId?: string, + permissions?: string[] | null, + transactionId?: string | null, ): Promise; updateRow( paramsOrFirst: @@ -1027,8 +1211,8 @@ export class TablesDB { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; } | string, ...rest: [ @@ -1037,8 +1221,8 @@ export class TablesDB { (Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>)?, - string[]?, - string?, + (string[] | null)?, + (string | null)?, ] ): Promise { let params: { @@ -1048,8 +1232,8 @@ export class TablesDB { data?: Row extends Models.DefaultRow ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; if ( @@ -1065,8 +1249,8 @@ export class TablesDB { ? Partial & Record : Partial & Partial>; - permissions?: string[]; - transactionId?: string; + permissions?: string[] | null; + transactionId?: string | null; }; } else { params = { @@ -1077,8 +1261,8 @@ export class TablesDB { ? Partial & Record : Partial & Partial>, - permissions: rest[3] as string[], - transactionId: rest[4] as string, + permissions: rest[3] as string[] | null, + transactionId: rest[4] as string | null, }; } @@ -1124,7 +1308,25 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'row', + models: { + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1243,8 +1445,8 @@ export class TablesDB { * @param {string} params.rowId - Row ID. * @param {string} params.column - Column key. * @param {number} params.value - Value to increment the column by. The value must be a number. - * @param {number} params.min - Minimum value for the column. If the current value is lesser than this value, an exception will be thrown. - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {number | null} params.min - Minimum value for the column. If the current value is lesser than this value, an exception will be thrown. + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} */ @@ -1254,8 +1456,8 @@ export class TablesDB { rowId: string; column: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; }): Promise; /** * Decrement a specific column of a row by a given value. @@ -1265,8 +1467,8 @@ export class TablesDB { * @param {string} rowId - Row ID. * @param {string} column - Column key. * @param {number} value - Value to increment the column by. The value must be a number. - * @param {number} min - Minimum value for the column. If the current value is lesser than this value, an exception will be thrown. - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {number | null} min - Minimum value for the column. If the current value is lesser than this value, an exception will be thrown. + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -1277,8 +1479,8 @@ export class TablesDB { rowId: string, column: string, value?: number, - min?: number, - transactionId?: string, + min?: number | null, + transactionId?: string | null, ): Promise; decrementRowColumn( paramsOrFirst: @@ -1288,11 +1490,18 @@ export class TablesDB { rowId: string; column: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; } | string, - ...rest: [string?, string?, string?, number?, number?, string?] + ...rest: [ + string?, + string?, + string?, + number?, + (number | null)?, + (string | null)?, + ] ): Promise { let params: { databaseId: string; @@ -1300,8 +1509,8 @@ export class TablesDB { rowId: string; column: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; }; if ( @@ -1315,8 +1524,8 @@ export class TablesDB { rowId: string; column: string; value?: number; - min?: number; - transactionId?: string; + min?: number | null; + transactionId?: string | null; }; } else { params = { @@ -1325,8 +1534,8 @@ export class TablesDB { rowId: rest[1] as string, column: rest[2] as string, value: rest[3] as number, - min: rest[4] as number, - transactionId: rest[5] as string, + min: rest[4] as number | null, + transactionId: rest[5] as string | null, }; } @@ -1378,7 +1587,25 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'row', + models: { + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1389,8 +1616,8 @@ export class TablesDB { * @param {string} params.rowId - Row ID. * @param {string} params.column - Column key. * @param {number} params.value - Value to increment the column by. The value must be a number. - * @param {number} params.max - Maximum value for the column. If the current value is greater than this value, an error will be thrown. - * @param {string} params.transactionId - Transaction ID for staging the operation. + * @param {number | null} params.max - Maximum value for the column. If the current value is greater than this value, an error will be thrown. + * @param {string | null} params.transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} */ @@ -1400,8 +1627,8 @@ export class TablesDB { rowId: string; column: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; }): Promise; /** * Increment a specific column of a row by a given value. @@ -1411,8 +1638,8 @@ export class TablesDB { * @param {string} rowId - Row ID. * @param {string} column - Column key. * @param {number} value - Value to increment the column by. The value must be a number. - * @param {number} max - Maximum value for the column. If the current value is greater than this value, an error will be thrown. - * @param {string} transactionId - Transaction ID for staging the operation. + * @param {number | null} max - Maximum value for the column. If the current value is greater than this value, an error will be thrown. + * @param {string | null} transactionId - Transaction ID for staging the operation. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -1423,8 +1650,8 @@ export class TablesDB { rowId: string, column: string, value?: number, - max?: number, - transactionId?: string, + max?: number | null, + transactionId?: string | null, ): Promise; incrementRowColumn( paramsOrFirst: @@ -1434,11 +1661,18 @@ export class TablesDB { rowId: string; column: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; } | string, - ...rest: [string?, string?, string?, number?, number?, string?] + ...rest: [ + string?, + string?, + string?, + number?, + (number | null)?, + (string | null)?, + ] ): Promise { let params: { databaseId: string; @@ -1446,8 +1680,8 @@ export class TablesDB { rowId: string; column: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; }; if ( @@ -1461,8 +1695,8 @@ export class TablesDB { rowId: string; column: string; value?: number; - max?: number; - transactionId?: string; + max?: number | null; + transactionId?: string | null; }; } else { params = { @@ -1471,8 +1705,8 @@ export class TablesDB { rowId: rest[1] as string, column: rest[2] as string, value: rest[3] as number, - max: rest[4] as number, - transactionId: rest[5] as string, + max: rest[4] as number | null, + transactionId: rest[5] as string | null, }; } @@ -1524,6 +1758,24 @@ export class TablesDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'row', + models: { + row: { + defaults: { + $id: '', + $sequence: '', + $tableId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } } diff --git a/src/services/teams.ts b/src/services/teams.ts index 692cb2b..66cf6dc 100644 --- a/src/services/teams.ts +++ b/src/services/teams.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class Teams { @@ -87,7 +92,34 @@ export class Teams { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'teamList', + models: { + teamList: { + defaults: { + total: 0, + teams: [], + }, + properties: { + teams: { + items: 'team', + }, + }, + }, + team: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + total: 0, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -175,7 +207,23 @@ export class Teams { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'team', + models: { + team: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + total: 0, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -233,7 +281,23 @@ export class Teams { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'team', + models: { + team: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + total: 0, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -308,7 +372,23 @@ export class Teams { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'team', + models: { + team: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + name: '', + total: 0, + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -443,7 +523,38 @@ export class Teams { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallationList', + models: { + appInstallationList: { + defaults: { + total: 0, + installations: [], + }, + properties: { + installations: { + items: 'appInstallation', + }, + }, + }, + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -534,7 +645,27 @@ export class Teams { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -609,7 +740,27 @@ export class Teams { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -617,21 +768,21 @@ export class Teams { * * @param {string} params.teamId - Team ID. * @param {string} params.installationId - Installation unique ID. - * @param {string} params.authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. + * @param {string | null} params.authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. * @throws {AppwriteException} * @returns {Promise} */ updateInstallation(params: { teamId: string; installationId: string; - authorizationDetails?: string; + authorizationDetails?: string | null; }): Promise; /** * Update an app installation on a team. Only team members with the owner role can update installations. The installation's granted scopes are refreshed to the scopes the app currently requests; previously issued installation access tokens are revoked. * * @param {string} teamId - Team ID. * @param {string} installationId - Installation unique ID. - * @param {string} authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. + * @param {string | null} authorizationDetails - Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -639,22 +790,22 @@ export class Teams { updateInstallation( teamId: string, installationId: string, - authorizationDetails?: string, + authorizationDetails?: string | null, ): Promise; updateInstallation( paramsOrFirst: | { teamId: string; installationId: string; - authorizationDetails?: string; + authorizationDetails?: string | null; } | string, - ...rest: [string?, string?] + ...rest: [string?, (string | null)?] ): Promise { let params: { teamId: string; installationId: string; - authorizationDetails?: string; + authorizationDetails?: string | null; }; if ( @@ -665,13 +816,13 @@ export class Teams { params = (paramsOrFirst || {}) as { teamId: string; installationId: string; - authorizationDetails?: string; + authorizationDetails?: string | null; }; } else { params = { teamId: paramsOrFirst as string, installationId: rest[0] as string, - authorizationDetails: rest[1] as string, + authorizationDetails: rest[1] as string | null, }; } @@ -705,7 +856,27 @@ export class Teams { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'appInstallation', + models: { + appInstallation: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + appId: '', + teamId: '', + scopes: [], + authorizationDetails: [], + createdById: '', + createdByName: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -881,7 +1052,44 @@ export class Teams { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'membershipList', + models: { + membershipList: { + defaults: { + total: 0, + memberships: [], + }, + properties: { + memberships: { + items: 'membership', + }, + }, + }, + membership: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + userName: '', + userEmail: '', + userPhone: '', + teamId: '', + teamName: '', + invited: '', + joined: '', + confirm: false, + mfa: false, + userAccessedAt: '', + roles: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -901,6 +1109,7 @@ export class Teams { * @param {string} params.phone - Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212. * @param {string} params.url - URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API. * @param {string} params.name - Name of the new team member. Max length: 128 chars. + * @param {string} params.membershipId - Membership ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. * @throws {AppwriteException} * @returns {Promise} */ @@ -912,6 +1121,7 @@ export class Teams { phone?: string; url?: string; name?: string; + membershipId?: 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. @@ -930,6 +1140,7 @@ export class Teams { * @param {string} phone - Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212. * @param {string} url - URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API. * @param {string} name - Name of the new team member. Max length: 128 chars. + * @param {string} membershipId - Membership ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. * @throws {AppwriteException} * @returns {Promise} * @deprecated Use the object parameter style method for a better developer experience. @@ -942,6 +1153,7 @@ export class Teams { phone?: string, url?: string, name?: string, + membershipId?: string, ): Promise; createMembership( paramsOrFirst: @@ -953,9 +1165,18 @@ export class Teams { phone?: string; url?: string; name?: string; + membershipId?: string; } | string, - ...rest: [string[]?, string?, string?, string?, string?, string?] + ...rest: [ + string[]?, + string?, + string?, + string?, + string?, + string?, + string?, + ] ): Promise { let params: { teamId: string; @@ -965,6 +1186,7 @@ export class Teams { phone?: string; url?: string; name?: string; + membershipId?: string; }; if ( @@ -980,6 +1202,7 @@ export class Teams { phone?: string; url?: string; name?: string; + membershipId?: string; }; } else { params = { @@ -990,6 +1213,7 @@ export class Teams { phone: rest[3] as string, url: rest[4] as string, name: rest[5] as string, + membershipId: rest[6] as string, }; } @@ -1000,6 +1224,7 @@ export class Teams { const phone = params.phone; const url = params.url; const name = params.name; + const membershipId = params.membershipId; if (typeof teamId === 'undefined' || teamId === '') { throw new AppwriteException('Missing required parameter: "teamId"'); @@ -1030,6 +1255,9 @@ export class Teams { if (typeof name !== 'undefined') { apiPayload['name'] = name; } + if (typeof membershipId !== 'undefined') { + apiPayload['membershipId'] = membershipId; + } const uri = new URL(this.client.config.endpoint + apiPath); const apiHeaders: { [header: string]: string } = { @@ -1038,7 +1266,33 @@ export class Teams { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'membership', + models: { + membership: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + userName: '', + userEmail: '', + userPhone: '', + teamId: '', + teamName: '', + invited: '', + joined: '', + confirm: false, + mfa: false, + userAccessedAt: '', + roles: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1113,7 +1367,33 @@ export class Teams { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'membership', + models: { + membership: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + userName: '', + userEmail: '', + userPhone: '', + teamId: '', + teamName: '', + invited: '', + joined: '', + confirm: false, + mfa: false, + userAccessedAt: '', + roles: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1205,7 +1485,33 @@ export class Teams { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'membership', + models: { + membership: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + userName: '', + userEmail: '', + userPhone: '', + teamId: '', + teamName: '', + invited: '', + joined: '', + confirm: false, + mfa: false, + userAccessedAt: '', + roles: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1398,7 +1704,33 @@ export class Teams { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'membership', + models: { + membership: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + userId: '', + userName: '', + userEmail: '', + userPhone: '', + teamId: '', + teamName: '', + invited: '', + joined: '', + confirm: false, + mfa: false, + userAccessedAt: '', + roles: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/services/vectors-db.ts b/src/services/vectors-db.ts index af957f3..cbffda8 100644 --- a/src/services/vectors-db.ts +++ b/src/services/vectors-db.ts @@ -1,4 +1,9 @@ -import { AppwriteException, Client, type Payload } from '../client'; +import { + AppwriteException, + Client, + type Payload, + applyDefaults, +} from '../client'; import type { Models } from '../models'; export class VectorsDB { @@ -74,7 +79,35 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transactionList', + models: { + transactionList: { + defaults: { + total: 0, + transactions: [], + }, + properties: { + transactions: { + items: 'transaction', + }, + }, + }, + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -127,7 +160,24 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -185,7 +235,24 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -275,7 +342,24 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -408,7 +492,24 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'transaction', + models: { + transaction: { + defaults: { + $id: '', + $createdAt: '', + $updatedAt: '', + status: 'pending', + operations: 0, + expiresAt: '', + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -544,7 +645,36 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'documentList', + models: { + documentList: { + defaults: { + total: 0, + documents: [], + }, + properties: { + documents: { + items: 'document', + }, + }, + }, + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -714,7 +844,25 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -853,7 +1001,36 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('post', uri, apiHeaders, apiPayload); + const request = this.client.call('post', uri, apiHeaders, apiPayload); + const defaults = { + root: 'documentList', + models: { + documentList: { + defaults: { + total: 0, + documents: [], + }, + properties: { + documents: { + items: 'document', + }, + }, + }, + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -983,7 +1160,25 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('get', uri, apiHeaders, apiPayload); + const request = this.client.call('get', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1153,7 +1348,25 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('put', uri, apiHeaders, apiPayload); + const request = this.client.call('put', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** @@ -1323,7 +1536,25 @@ export class VectorsDB { accept: 'application/json', }; - return this.client.call('patch', uri, apiHeaders, apiPayload); + const request = this.client.call('patch', uri, apiHeaders, apiPayload); + const defaults = { + root: 'document', + models: { + document: { + defaults: { + $id: '', + $sequence: '', + $collectionId: '', + $databaseId: '', + $createdAt: '', + $updatedAt: '', + $permissions: [], + }, + }, + }, + }; + + return request.then((response) => applyDefaults(response, defaults)); } /** diff --git a/src/topic.ts b/src/topic.ts index cd6cea0..071d5ae 100644 --- a/src/topic.ts +++ b/src/topic.ts @@ -1,6 +1,6 @@ /** * Validate the levels passed to `path()`: a non-empty array of non-empty strings, none holding - * the level separator `/` or the wildcards `+` and `#` (use `any()` and `all()` for those). + * the level separator `/` or the MQTT wildcards `+` and `#`. */ function levelsOf(levels: unknown): string[] { if (!Array.isArray(levels)) { @@ -28,17 +28,14 @@ function levelsOf(levels: unknown): string[] { `"${level}" contains "/", split it: path([${parts}])`, ); } - if (level === '+') { - throw new Error('"+" is reserved, use any()'); - } if (level.includes('+')) { - throw new Error(`"${level}" contains "+", use any() for wildcards`); - } - if (level === '#') { - throw new Error('"#" is reserved, use all()'); + throw new Error(`"${level}" contains "+", not allowed in a topic`); } if (level.includes('#')) { - throw new Error(`"${level}" contains "#", use all() for wildcards`); + throw new Error(`"${level}" contains "#", not allowed in a topic`); + } + if (level.includes('\0')) { + throw new Error(`level at index ${index} contains a NUL character`); } return level; }); @@ -48,11 +45,7 @@ function levelsOf(levels: unknown): string[] { * Helper to build MQTT topics for `Push`, level by level. * * Topic.path(['user', userId, 'notification']); // "user/123/notification" - * Topic.path(['user']).any().path(['notification']); // "user/+/notification" - * Topic.path(['org']).any().path(['logs']).all(); // "org/+/logs/#" - * - * `any()` matches exactly one level and `all()` everything below, at any depth (including the - * parent itself). `all()` ends the topic, so it returns a {@link ResolvedTopic}. + * Topic.path(['org', orgId]).path(['logs']); // "org/42/logs" */ export class Topic { private constructor(private readonly levels: readonly string[]) {} @@ -62,41 +55,11 @@ export class Topic { return new Topic(levelsOf(levels)); } - /** Start a topic with a single-level wildcard (`+`). */ - static any(): Topic { - return new Topic(['+']); - } - - /** The multi-level wildcard alone (`#`): matches every topic. */ - static all(): ResolvedTopic { - return new ResolvedTopic(['#']); - } - /** Append the given levels. */ path(levels: string[]): Topic { return new Topic([...this.levels, ...levelsOf(levels)]); } - /** Append a single-level wildcard (`+`): matches exactly one level. */ - any(): Topic { - return new Topic([...this.levels, '+']); - } - - /** Append the multi-level wildcard (`#`) and end the topic. */ - all(): ResolvedTopic { - return new ResolvedTopic([...this.levels, '#']); - } - - toString(): string { - return this.levels.join('/'); - } -} - -/** A topic ended by `all()`: nothing can be appended after the `#` wildcard. */ -export class ResolvedTopic { - /** @internal Created by {@link Topic.all}. */ - constructor(private readonly levels: readonly string[]) {} - toString(): string { return this.levels.join('/'); }