-
Notifications
You must be signed in to change notification settings - Fork 63
feat: Web SDK update for version 21.2.0 #137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds transaction support for Databases and TablesDB: new methods listTransactions, createTransaction, getTransaction, updateTransaction, deleteTransaction, and createOperations. Extends many CRUD and attribute methods to accept an optional transactionId and propagate it in requests. Introduces Models.Transaction and Models.TransactionList types. Narrows Query.equal/notEqual parameter types and adds Query.orderRandom. Adds ExecutionTrigger and ExecutionStatus enums and updates Execution types. Bumps SDK version to 21.2.0 and updates CDN/readme and x-sdk-version headers. Multiple documentation examples added/updated to show transactionId usage. Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/models.ts (1)
1310-1316
: Fix misdocumented field in Subscriber.
userId
is documented as “Topic ID.” It should be “User ID.”- /** - * Topic ID. - */ - userId: string; + /** + * User ID. + */ + userId: string;
🧹 Nitpick comments (12)
docs/examples/databases/list-transactions.md (2)
1-1
: Show a concrete queries usage for clarity.
Using Query helpers improves discoverability.-import { Client, Databases } from "appwrite"; +import { Client, Databases, Query } from "appwrite"; @@ -const result = await databases.listTransactions({ - queries: [] // optional -}); +const result = await databases.listTransactions({ + queries: [Query.limit(10)] // optional +});Also applies to: 9-11
9-13
: Top‑level await caveat (nit).
Some setups lack top‑level await; consider wrapping in an async IIFE in docs.docs/examples/tablesdb/update-row.md (1)
9-16
: Top-level await requires ESM/modules.If users paste this in non-module contexts, it will throw. Consider noting that the snippet must run in a JS module or wrap it in an async IIFE.
Example:
(async () => { const result = await tablesDB.updateRow({ /* ... */ }); console.log(result); })();docs/examples/tablesdb/create-transaction.md (1)
9-14
: Top-level await note (applies across new examples).Add a brief note that examples require module context (or wrap in an async IIFE) to prevent runtime confusion.
docs/examples/tablesdb/list-transactions.md (1)
9-11
: Show minimal call without empty queries.Since queries is optional, consider omitting it to reduce noise.
Apply this diff:
-const result = await tablesDB.listTransactions({ - queries: [] // optional -}); +const result = await tablesDB.listTransactions();docs/examples/databases/create-transaction.md (2)
9-11
: Clarify top‑level await requirement.These examples use top‑level
await
. Please add a brief comment indicating that the snippet must run in an ES module/bundler environment that supports top‑level await (or wrap in an async IIFE).-const result = await databases.createTransaction({ +// Note: Requires ESM / top-level await support (or wrap in an async IIFE). +const result = await databases.createTransaction({ ttl: 60 // optional });
10-10
: Specify TTL units.Add units to prevent misuse (seconds vs. milliseconds).
- ttl: 60 // optional + ttl: 60 // optional, secondsdocs/examples/databases/delete-transaction.md (1)
9-13
: Avoid logging an undefined/empty result for delete.Delete endpoints often return void/Success. Prefer awaiting the call and logging a success message; verify the actual return type in this SDK version.
-const result = await databases.deleteTransaction({ - transactionId: '<TRANSACTION_ID>' -}); - -console.log(result); +await databases.deleteTransaction({ + transactionId: '<TRANSACTION_ID>' +}); +console.log('Transaction deleted');Would you confirm what
databases.deleteTransaction
returns in 20.1.0-rc.1?docs/examples/tablesdb/delete-transaction.md (1)
9-13
: Align delete example with expected return type.Same concern as Databases: avoid capturing/printing a possibly undefined result; log a success message after awaiting.
-const result = await tablesDB.deleteTransaction({ - transactionId: '<TRANSACTION_ID>' -}); - -console.log(result); +await tablesDB.deleteTransaction({ + transactionId: '<TRANSACTION_ID>' +}); +console.log('Transaction deleted');Also, please confirm the method’s return type for TablesDB in 20.1.0-rc.1.
docs/examples/tablesdb/create-operations.md (1)
9-21
: Trim optional fields from the example and clarifyoperations
/rowId
createOperations is declared with operations?: object[] (src/services/tables-db.ts) and the client only adds 'operations' to the payload if provided; it also does not validate per-operation rowId — remove the example's rowId (or comment it as optional) in docs/examples/tablesdb/create-operations.md and keep the
operations
note marked optional.docs/examples/tablesdb/get-transaction.md (1)
9-11
: Clarify top‑level await requirement (ESM).Same as other examples: add a short note about ESM/top‑level await.
-const result = await tablesDB.getTransaction({ +// Note: Requires ESM / top-level await support (or wrap in an async IIFE). +const result = await tablesDB.getTransaction({ transactionId: '<TRANSACTION_ID>' });src/models.ts (1)
1255-1284
: Narrow Transaction.status to a string-literal union.Gives stronger type-safety and IDE help.
export type Transaction = { @@ - status: string; + status: 'pending' | 'committing' | 'committed' | 'rolled_back' | 'failed';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
README.md
(1 hunks)docs/examples/databases/create-document.md
(1 hunks)docs/examples/databases/create-operations.md
(1 hunks)docs/examples/databases/create-transaction.md
(1 hunks)docs/examples/databases/decrement-document-attribute.md
(1 hunks)docs/examples/databases/delete-document.md
(1 hunks)docs/examples/databases/delete-transaction.md
(1 hunks)docs/examples/databases/get-document.md
(1 hunks)docs/examples/databases/get-transaction.md
(1 hunks)docs/examples/databases/increment-document-attribute.md
(1 hunks)docs/examples/databases/list-documents.md
(1 hunks)docs/examples/databases/list-transactions.md
(1 hunks)docs/examples/databases/update-document.md
(1 hunks)docs/examples/databases/update-transaction.md
(1 hunks)docs/examples/databases/upsert-document.md
(1 hunks)docs/examples/tablesdb/create-operations.md
(1 hunks)docs/examples/tablesdb/create-row.md
(1 hunks)docs/examples/tablesdb/create-transaction.md
(1 hunks)docs/examples/tablesdb/decrement-row-column.md
(1 hunks)docs/examples/tablesdb/delete-row.md
(1 hunks)docs/examples/tablesdb/delete-transaction.md
(1 hunks)docs/examples/tablesdb/get-row.md
(1 hunks)docs/examples/tablesdb/get-transaction.md
(1 hunks)docs/examples/tablesdb/increment-row-column.md
(1 hunks)docs/examples/tablesdb/list-rows.md
(1 hunks)docs/examples/tablesdb/list-transactions.md
(1 hunks)docs/examples/tablesdb/update-row.md
(1 hunks)docs/examples/tablesdb/update-transaction.md
(1 hunks)docs/examples/tablesdb/upsert-row.md
(1 hunks)package.json
(1 hunks)src/client.ts
(1 hunks)src/models.ts
(2 hunks)src/query.ts
(1 hunks)src/services/databases.ts
(26 hunks)src/services/tables-db.ts
(26 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/services/databases.ts (3)
src/client.ts (3)
Models
(803-803)Payload
(803-803)AppwriteException
(801-801)src/index.ts (3)
Models
(19-19)Payload
(19-19)AppwriteException
(8-8)src/models.ts (5)
TransactionList
(221-230)Transaction
(1258-1283)Document
(274-303)DefaultDocument
(305-308)DocumentList
(25-34)
src/services/tables-db.ts (1)
src/models.ts (5)
TransactionList
(221-230)Transaction
(1258-1283)Row
(235-264)DefaultRow
(266-269)RowList
(11-20)
🔇 Additional comments (22)
README.md (1)
36-36
: CDN snippet version bump is consistent—LGTM.
Matches package.json and x-sdk header updates in src/client.ts.src/client.ts (1)
319-321
: x-sdk-version updated to 20.1.0-rc.1 — verified.
package.json:5, README.md:36, src/client.ts:319 all use 20.1.0-rc.1; no plain 20.1.0 or 20.0.0 occurrences found.package.json (1)
5-5
: Version bump looks good.
Aligned with README and client header.src/query.ts (1)
55-59
: Type narrowing for equal/notEqual is correct.
QueryTypes already unions array types via QueryTypesList, so removing “| any[]” is a no-op and simplifies the API surface.Also applies to: 65-69
docs/examples/tablesdb/get-row.md (1)
13-15
: LGTM.
Optional transactionId addition reads well.docs/examples/tablesdb/create-transaction.md (1)
10-11
: Clarify TTL units and bounds.Specify whether ttl is in seconds and acceptable range (e.g., 1–600) to avoid ambiguity.
Do you want me to update the comment once you confirm units/range?
docs/examples/tablesdb/update-transaction.md (1)
11-12
: Document commit vs. rollback behavior.Clarify whether these flags are mutually exclusive and precedence if both are true.
Once confirmed, I can add an inline comment note to the example.
docs/examples/tablesdb/decrement-row-column.md (1)
15-16
: LGTM — transactionId addition reads well.No issues spotted with the new fields.
docs/examples/databases/increment-document-attribute.md (1)
15-16
: LGTM — transactionId addition aligns with API surface.No issues with the new parameters.
docs/examples/databases/update-transaction.md (1)
9-13
: Show a decisive action: commit or rollback (avoid both false).commit: false + rollback: false is a no‑op and will confuse readers — demonstrate either commit: true or rollback: true (do not set both). Please confirm whether commit and rollback are mutually exclusive in version 20.1.0-rc.1.
docs/examples/databases/list-documents.md (1)
12-13
: LGTM: transactionId extension looks correct.The added transactionId parameter and queries formatting align with the described API changes.
docs/examples/databases/get-transaction.md (1)
1-14
: LGTM: clear, minimal getTransaction example.Reads well and matches the new API surface.
docs/examples/tablesdb/list-rows.md (1)
12-13
: LGTM: listRows now documents optional transactionId.Matches the broader transaction-enabled surface.
docs/examples/tablesdb/delete-row.md (1)
12-13
: LGTM: optional transactionId on deleteRow is documented properly.docs/examples/databases/delete-document.md (1)
12-13
: LGTM: deleteDocument shows optional transactionId correctly.src/models.ts (2)
218-231
: TransactionList type: LGTM.Structure and naming align with existing list models.
1255-1284
: No duplicate Transaction type remains.Search found a single exported declaration at src/models.ts:1258 (
export type Transaction = { ... }
).src/services/databases.ts (3)
13-62
: Transactions API surface: LGTM.Overloads, paths, headers, and payload wiring look consistent.
Also applies to: 64-115, 116-166, 234-285, 286-345
357-418
: transactionId propagation across document APIs: LGTM.Optional transactionId is correctly threaded and conditionally added to payloads.
Also applies to: 433-513, 527-594, 609-686, 701-775, 788-850, 866-946, 962-1042
64-115
: Confirm TTL constraints for createTransaction.Docs/examples (docs/examples/databases/create-transaction.md) show ttl is optional (example uses 60) but no explicit min/max in repo — if the API requires a positive integer or has a maximum, add client-side validation (Number.isInteger(ttl) && ttl > 0 and enforce server max) in src/services/databases.ts (lines 64–115).
src/services/tables-db.ts (2)
13-62
: Transactions API surface (TablesDB): LGTM.Parsers, paths, and payloads align with Databases service.
Also applies to: 64-115, 116-166, 234-285, 286-345
356-417
: transactionId propagation across row APIs: LGTM.Payload handling and overloads look consistent.
Also applies to: 431-511, 524-591, 605-679, 693-767, 779-841, 856-936, 951-1031
permissions: ["read("any")"], // optional | ||
transactionId: '<TRANSACTION_ID>' // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix invalid string quoting in permissions example.
Nested double quotes break the string. Use single quotes outside.
Apply this diff:
- permissions: ["read("any")"], // optional
+ permissions: ['read("any")'], // optional
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
permissions: ["read("any")"], // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
permissions: ['read("any")'], // optional | |
transactionId: '<TRANSACTION_ID>' // optional |
🤖 Prompt for AI Agents
In docs/examples/databases/create-document.md around lines 20 to 21, the
permissions example uses nested double quotes ("read("any")") which breaks the
string; change the outer quotes to single quotes so the line reads permissions:
['read("any")'] (leave transactionId as-is) to fix the invalid string quoting.
"name": "Walter O'Brien" | ||
} | ||
} | ||
] // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
operations is required; drop the “optional” comment.
Marking the operations array as optional is inaccurate for this endpoint.
Apply this diff:
- ] // optional
+ ]
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
] // optional | |
] |
🤖 Prompt for AI Agents
In docs/examples/databases/create-operations.md around line 21, the operations
array is incorrectly annotated as optional; remove the "optional" comment and
any wording suggesting it's optional so the documentation clearly states that
the operations array is required for this endpoint. Ensure the line now reflects
that operations must be provided (e.g., delete the " // optional" suffix and
update surrounding text if necessary to avoid implying optionality).
value: null, // optional | ||
min: null // optional | ||
min: null, // optional | ||
transactionId: '<TRANSACTION_ID>' // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use concrete numbers or omit fields instead of null
for numeric options.
As above, null
can be invalid for numeric parameters. Provide a typical value or remove the field.
- value: null, // optional
- min: null, // optional
+ value: 1, // optional; omit to use default decrement
+ // min: 0, // optional; omit if not bounding
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
value: null, // optional | |
min: null // optional | |
min: null, // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
value: 1, // optional; omit to use default decrement | |
// min: 0, // optional; omit if not bounding | |
transactionId: '<TRANSACTION_ID>' // optional |
🤖 Prompt for AI Agents
In docs/examples/databases/decrement-document-attribute.md around lines 14 to
16, the example sets numeric options to null which can be invalid; replace null
with concrete numeric examples (e.g., a decrement value and a minimum like 0) or
remove the optional numeric fields entirely, and for transactionId either omit
it or show a realistic placeholder string if needed for the example.
queries: [], // optional | ||
transactionId: '<TRANSACTION_ID>' // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unsupported queries from getDocument example.
getDocument
doesn’t accept a queries array; including it is misleading documentation.
Apply this diff:
- queries: [], // optional
transactionId: '<TRANSACTION_ID>' // optional
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
queries: [], // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
transactionId: '<TRANSACTION_ID>' // optional |
🤖 Prompt for AI Agents
In docs/examples/databases/get-document.md around lines 13 to 14, the example
includes an unsupported queries: [] parameter for getDocument; remove the
queries line entirely and leave only supported options (e.g., transactionId if
needed) so the example reflects the actual API signature.
permissions: ["read("any")"], // optional | ||
transactionId: '<TRANSACTION_ID>' // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix invalid string quoting in permissions example.
Nested double quotes break the string. Use single quotes outside.
Apply this diff:
- permissions: ["read("any")"], // optional
+ permissions: ['read("any")'], // optional
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
permissions: ["read("any")"], // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
permissions: ['read("any")'], // optional | |
transactionId: '<TRANSACTION_ID>' // optional |
🤖 Prompt for AI Agents
In docs/examples/databases/update-document.md around lines 14-15, the
permissions example uses double quotes outside and also around the inner
argument (read("any")), which breaks the string; change the permissions array
entry to use single quotes outside so it reads permissions: ['read("any")'] and
keep the transactionId line as-is.
permissions: ["read("any")"], // optional | ||
transactionId: '<TRANSACTION_ID>' // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix invalid string quoting in permissions example.
Nested double quotes break the string. Use single quotes outside.
Apply this diff:
- permissions: ["read("any")"], // optional
+ permissions: ['read("any")'], // optional
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
permissions: ["read("any")"], // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
permissions: ['read("any")'], // optional | |
transactionId: '<TRANSACTION_ID>' // optional |
🤖 Prompt for AI Agents
In docs/examples/tablesdb/update-row.md around lines 14 to 15, the permissions
example uses nested double quotes which break the string; change the outer
quotes to single quotes so the inner double quotes remain valid (e.g.,
permissions: ['read("any")']), ensuring the string is properly quoted and
remains a valid literal.
permissions: ["read("any")"], // optional | ||
transactionId: '<TRANSACTION_ID>' // optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix invalid permissions syntax; use Permission/Role helpers.
["read("any")"]
is syntactically invalid (nested quotes) and likely not accepted by the SDK. Use the helpers instead.
Apply within the changed lines:
- permissions: ["read("any")"], // optional
+ permissions: [Permission.read(Role.any())], // optional
Also add the necessary imports at the top of this file (outside the changed range):
-import { Client, TablesDB } from "appwrite";
+import { Client, TablesDB, Permission, Role } from "appwrite";
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
permissions: ["read("any")"], // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
import { Client, TablesDB, Permission, Role } from "appwrite"; |
permissions: ["read("any")"], // optional | |
transactionId: '<TRANSACTION_ID>' // optional | |
permissions: [Permission.read(Role.any())], // optional | |
transactionId: '<TRANSACTION_ID>' // optional |
🤖 Prompt for AI Agents
In docs/examples/tablesdb/upsert-row.md around lines 14 to 15, the permissions
value uses invalid string syntax ["read("any")"]; replace it with the SDK
permission/role helper (e.g., Permission.read("any") or Role.read("any") per
your SDK) and pass that helper result (or an array of helpers) as the
permissions field, and also add the corresponding import statement(s) at the top
of the file (outside the changed range) for Permission/Role so the example
compiles.
/** | ||
* Update a transaction, to either commit or roll back its operations. | ||
* | ||
* @param {string} params.transactionId - Transaction ID. | ||
* @param {boolean} params.commit - Commit transaction? | ||
* @param {boolean} params.rollback - Rollback transaction? | ||
* @throws {AppwriteException} | ||
* @returns {Promise<Models.Transaction>} | ||
*/ | ||
updateTransaction(params: { transactionId: string, commit?: boolean, rollback?: boolean }): Promise<Models.Transaction>; | ||
/** | ||
* Update a transaction, to either commit or roll back its operations. | ||
* | ||
* @param {string} transactionId - Transaction ID. | ||
* @param {boolean} commit - Commit transaction? | ||
* @param {boolean} rollback - Rollback transaction? | ||
* @throws {AppwriteException} | ||
* @returns {Promise<Models.Transaction>} | ||
* @deprecated Use the object parameter style method for a better developer experience. | ||
*/ | ||
updateTransaction(transactionId: string, commit?: boolean, rollback?: boolean): Promise<Models.Transaction>; | ||
updateTransaction( | ||
paramsOrFirst: { transactionId: string, commit?: boolean, rollback?: boolean } | string, | ||
...rest: [(boolean)?, (boolean)?] | ||
): Promise<Models.Transaction> { | ||
let params: { transactionId: string, commit?: boolean, rollback?: boolean }; | ||
|
||
if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { | ||
params = (paramsOrFirst || {}) as { transactionId: string, commit?: boolean, rollback?: boolean }; | ||
} else { | ||
params = { | ||
transactionId: paramsOrFirst as string, | ||
commit: rest[0] as boolean, | ||
rollback: rest[1] as boolean | ||
}; | ||
} | ||
|
||
const transactionId = params.transactionId; | ||
const commit = params.commit; | ||
const rollback = params.rollback; | ||
|
||
if (typeof transactionId === 'undefined') { | ||
throw new AppwriteException('Missing required parameter: "transactionId"'); | ||
} | ||
|
||
const apiPath = '/databases/transactions/{transactionId}'.replace('{transactionId}', transactionId); | ||
const payload: Payload = {}; | ||
if (typeof commit !== 'undefined') { | ||
payload['commit'] = commit; | ||
} | ||
if (typeof rollback !== 'undefined') { | ||
payload['rollback'] = rollback; | ||
} | ||
const uri = new URL(this.client.config.endpoint + apiPath); | ||
|
||
const apiHeaders: { [header: string]: string } = { | ||
'content-type': 'application/json', | ||
} | ||
|
||
return this.client.call( | ||
'patch', | ||
uri, | ||
apiHeaders, | ||
payload | ||
); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enforce commit XOR rollback in updateTransaction.
Prevent ambiguous client calls by requiring exactly one of commit/rollback.
const transactionId = params.transactionId;
const commit = params.commit;
const rollback = params.rollback;
+ // Exactly one of commit or rollback must be true
+ if ((commit ? 1 : 0) + (rollback ? 1 : 0) !== 1) {
+ throw new AppwriteException('Provide exactly one of "commit" or "rollback".');
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
/** | |
* Update a transaction, to either commit or roll back its operations. | |
* | |
* @param {string} params.transactionId - Transaction ID. | |
* @param {boolean} params.commit - Commit transaction? | |
* @param {boolean} params.rollback - Rollback transaction? | |
* @throws {AppwriteException} | |
* @returns {Promise<Models.Transaction>} | |
*/ | |
updateTransaction(params: { transactionId: string, commit?: boolean, rollback?: boolean }): Promise<Models.Transaction>; | |
/** | |
* Update a transaction, to either commit or roll back its operations. | |
* | |
* @param {string} transactionId - Transaction ID. | |
* @param {boolean} commit - Commit transaction? | |
* @param {boolean} rollback - Rollback transaction? | |
* @throws {AppwriteException} | |
* @returns {Promise<Models.Transaction>} | |
* @deprecated Use the object parameter style method for a better developer experience. | |
*/ | |
updateTransaction(transactionId: string, commit?: boolean, rollback?: boolean): Promise<Models.Transaction>; | |
updateTransaction( | |
paramsOrFirst: { transactionId: string, commit?: boolean, rollback?: boolean } | string, | |
...rest: [(boolean)?, (boolean)?] | |
): Promise<Models.Transaction> { | |
let params: { transactionId: string, commit?: boolean, rollback?: boolean }; | |
if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { | |
params = (paramsOrFirst || {}) as { transactionId: string, commit?: boolean, rollback?: boolean }; | |
} else { | |
params = { | |
transactionId: paramsOrFirst as string, | |
commit: rest[0] as boolean, | |
rollback: rest[1] as boolean | |
}; | |
} | |
const transactionId = params.transactionId; | |
const commit = params.commit; | |
const rollback = params.rollback; | |
if (typeof transactionId === 'undefined') { | |
throw new AppwriteException('Missing required parameter: "transactionId"'); | |
} | |
const apiPath = '/databases/transactions/{transactionId}'.replace('{transactionId}', transactionId); | |
const payload: Payload = {}; | |
if (typeof commit !== 'undefined') { | |
payload['commit'] = commit; | |
} | |
if (typeof rollback !== 'undefined') { | |
payload['rollback'] = rollback; | |
} | |
const uri = new URL(this.client.config.endpoint + apiPath); | |
const apiHeaders: { [header: string]: string } = { | |
'content-type': 'application/json', | |
} | |
return this.client.call( | |
'patch', | |
uri, | |
apiHeaders, | |
payload | |
); | |
} | |
/** | |
* Update a transaction, to either commit or roll back its operations. | |
* | |
* @param {string} params.transactionId - Transaction ID. | |
* @param {boolean} params.commit - Commit transaction? | |
* @param {boolean} params.rollback - Rollback transaction? | |
* @throws {AppwriteException} | |
* @returns {Promise<Models.Transaction>} | |
*/ | |
updateTransaction(params: { transactionId: string, commit?: boolean, rollback?: boolean }): Promise<Models.Transaction>; | |
/** | |
* Update a transaction, to either commit or roll back its operations. | |
* | |
* @param {string} transactionId - Transaction ID. | |
* @param {boolean} commit - Commit transaction? | |
* @param {boolean} rollback - Rollback transaction? | |
* @throws {AppwriteException} | |
* @returns {Promise<Models.Transaction>} | |
* @deprecated Use the object parameter style method for a better developer experience. | |
*/ | |
updateTransaction(transactionId: string, commit?: boolean, rollback?: boolean): Promise<Models.Transaction>; | |
updateTransaction( | |
paramsOrFirst: { transactionId: string, commit?: boolean, rollback?: boolean } | string, | |
...rest: [(boolean)?, (boolean)?] | |
): Promise<Models.Transaction> { | |
let params: { transactionId: string, commit?: boolean, rollback?: boolean }; | |
if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { | |
params = (paramsOrFirst || {}) as { transactionId: string, commit?: boolean, rollback?: boolean }; | |
} else { | |
params = { | |
transactionId: paramsOrFirst as string, | |
commit: rest[0] as boolean, | |
rollback: rest[1] as boolean | |
}; | |
} | |
const transactionId = params.transactionId; | |
const commit = params.commit; | |
const rollback = params.rollback; | |
// Exactly one of commit or rollback must be true | |
if ((commit ? 1 : 0) + (rollback ? 1 : 0) !== 1) { | |
throw new AppwriteException('Provide exactly one of "commit" or "rollback".'); | |
} | |
if (typeof transactionId === 'undefined') { | |
throw new AppwriteException('Missing required parameter: "transactionId"'); | |
} | |
const apiPath = '/databases/transactions/{transactionId}'.replace('{transactionId}', transactionId); | |
const payload: Payload = {}; | |
if (typeof commit !== 'undefined') { | |
payload['commit'] = commit; | |
} | |
if (typeof rollback !== 'undefined') { | |
payload['rollback'] = rollback; | |
} | |
const uri = new URL(this.client.config.endpoint + apiPath); | |
const apiHeaders: { [header: string]: string } = { | |
'content-type': 'application/json', | |
} | |
return this.client.call( | |
'patch', | |
uri, | |
apiHeaders, | |
payload | |
); | |
} |
🤖 Prompt for AI Agents
In src/services/databases.ts around lines 167 to 233, the updateTransaction
implementation must enforce that exactly one of commit or rollback is provided
(XOR) to avoid ambiguous calls; add a validation after extracting commit and
rollback that checks (Boolean(commit) === Boolean(rollback)) and if true throw
new AppwriteException('Exactly one of "commit" or "rollback" must be
specified'); keep the existing payload building but only proceed when validation
passes so callers must supply exactly one of the two flags.
/** | ||
* Update a transaction, to either commit or roll back its operations. | ||
* | ||
* @param {string} params.transactionId - Transaction ID. | ||
* @param {boolean} params.commit - Commit transaction? | ||
* @param {boolean} params.rollback - Rollback transaction? | ||
* @throws {AppwriteException} | ||
* @returns {Promise<Models.Transaction>} | ||
*/ | ||
updateTransaction(params: { transactionId: string, commit?: boolean, rollback?: boolean }): Promise<Models.Transaction>; | ||
/** | ||
* Update a transaction, to either commit or roll back its operations. | ||
* | ||
* @param {string} transactionId - Transaction ID. | ||
* @param {boolean} commit - Commit transaction? | ||
* @param {boolean} rollback - Rollback transaction? | ||
* @throws {AppwriteException} | ||
* @returns {Promise<Models.Transaction>} | ||
* @deprecated Use the object parameter style method for a better developer experience. | ||
*/ | ||
updateTransaction(transactionId: string, commit?: boolean, rollback?: boolean): Promise<Models.Transaction>; | ||
updateTransaction( | ||
paramsOrFirst: { transactionId: string, commit?: boolean, rollback?: boolean } | string, | ||
...rest: [(boolean)?, (boolean)?] | ||
): Promise<Models.Transaction> { | ||
let params: { transactionId: string, commit?: boolean, rollback?: boolean }; | ||
|
||
if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { | ||
params = (paramsOrFirst || {}) as { transactionId: string, commit?: boolean, rollback?: boolean }; | ||
} else { | ||
params = { | ||
transactionId: paramsOrFirst as string, | ||
commit: rest[0] as boolean, | ||
rollback: rest[1] as boolean | ||
}; | ||
} | ||
|
||
const transactionId = params.transactionId; | ||
const commit = params.commit; | ||
const rollback = params.rollback; | ||
|
||
if (typeof transactionId === 'undefined') { | ||
throw new AppwriteException('Missing required parameter: "transactionId"'); | ||
} | ||
|
||
const apiPath = '/tablesdb/transactions/{transactionId}'.replace('{transactionId}', transactionId); | ||
const payload: Payload = {}; | ||
if (typeof commit !== 'undefined') { | ||
payload['commit'] = commit; | ||
} | ||
if (typeof rollback !== 'undefined') { | ||
payload['rollback'] = rollback; | ||
} | ||
const uri = new URL(this.client.config.endpoint + apiPath); | ||
|
||
const apiHeaders: { [header: string]: string } = { | ||
'content-type': 'application/json', | ||
} | ||
|
||
return this.client.call( | ||
'patch', | ||
uri, | ||
apiHeaders, | ||
payload | ||
); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enforce commit XOR rollback in updateTransaction.
Mirror the Databases guard here.
const transactionId = params.transactionId;
const commit = params.commit;
const rollback = params.rollback;
+ // Exactly one of commit or rollback must be true
+ if ((commit ? 1 : 0) + (rollback ? 1 : 0) !== 1) {
+ throw new AppwriteException('Provide exactly one of "commit" or "rollback".');
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
/** | |
* Update a transaction, to either commit or roll back its operations. | |
* | |
* @param {string} params.transactionId - Transaction ID. | |
* @param {boolean} params.commit - Commit transaction? | |
* @param {boolean} params.rollback - Rollback transaction? | |
* @throws {AppwriteException} | |
* @returns {Promise<Models.Transaction>} | |
*/ | |
updateTransaction(params: { transactionId: string, commit?: boolean, rollback?: boolean }): Promise<Models.Transaction>; | |
/** | |
* Update a transaction, to either commit or roll back its operations. | |
* | |
* @param {string} transactionId - Transaction ID. | |
* @param {boolean} commit - Commit transaction? | |
* @param {boolean} rollback - Rollback transaction? | |
* @throws {AppwriteException} | |
* @returns {Promise<Models.Transaction>} | |
* @deprecated Use the object parameter style method for a better developer experience. | |
*/ | |
updateTransaction(transactionId: string, commit?: boolean, rollback?: boolean): Promise<Models.Transaction>; | |
updateTransaction( | |
paramsOrFirst: { transactionId: string, commit?: boolean, rollback?: boolean } | string, | |
...rest: [(boolean)?, (boolean)?] | |
): Promise<Models.Transaction> { | |
let params: { transactionId: string, commit?: boolean, rollback?: boolean }; | |
if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { | |
params = (paramsOrFirst || {}) as { transactionId: string, commit?: boolean, rollback?: boolean }; | |
} else { | |
params = { | |
transactionId: paramsOrFirst as string, | |
commit: rest[0] as boolean, | |
rollback: rest[1] as boolean | |
}; | |
} | |
const transactionId = params.transactionId; | |
const commit = params.commit; | |
const rollback = params.rollback; | |
if (typeof transactionId === 'undefined') { | |
throw new AppwriteException('Missing required parameter: "transactionId"'); | |
} | |
const apiPath = '/tablesdb/transactions/{transactionId}'.replace('{transactionId}', transactionId); | |
const payload: Payload = {}; | |
if (typeof commit !== 'undefined') { | |
payload['commit'] = commit; | |
} | |
if (typeof rollback !== 'undefined') { | |
payload['rollback'] = rollback; | |
} | |
const uri = new URL(this.client.config.endpoint + apiPath); | |
const apiHeaders: { [header: string]: string } = { | |
'content-type': 'application/json', | |
} | |
return this.client.call( | |
'patch', | |
uri, | |
apiHeaders, | |
payload | |
); | |
} | |
updateTransaction( | |
paramsOrFirst: { transactionId: string, commit?: boolean, rollback?: boolean } | string, | |
...rest: [(boolean)?, (boolean)?] | |
): Promise<Models.Transaction> { | |
let params: { transactionId: string, commit?: boolean, rollback?: boolean }; | |
if ((paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) { | |
params = (paramsOrFirst || {}) as { transactionId: string, commit?: boolean, rollback?: boolean }; | |
} else { | |
params = { | |
transactionId: paramsOrFirst as string, | |
commit: rest[0] as boolean, | |
rollback: rest[1] as boolean | |
}; | |
} | |
const transactionId = params.transactionId; | |
const commit = params.commit; | |
const rollback = params.rollback; | |
// Exactly one of commit or rollback must be true | |
if ((commit ? 1 : 0) + (rollback ? 1 : 0) !== 1) { | |
throw new AppwriteException('Provide exactly one of "commit" or "rollback".'); | |
} | |
if (typeof transactionId === 'undefined') { | |
throw new AppwriteException('Missing required parameter: "transactionId"'); | |
} | |
const apiPath = '/tablesdb/transactions/{transactionId}'.replace('{transactionId}', transactionId); | |
const payload: Payload = {}; | |
if (typeof commit !== 'undefined') { | |
payload['commit'] = commit; | |
} | |
if (typeof rollback !== 'undefined') { | |
payload['rollback'] = rollback; | |
} | |
const uri = new URL(this.client.config.endpoint + apiPath); | |
const apiHeaders: { [header: string]: string } = { | |
'content-type': 'application/json', | |
} | |
return this.client.call( | |
'patch', | |
uri, | |
apiHeaders, | |
payload | |
); | |
} |
🤖 Prompt for AI Agents
In src/services/tables-db.ts around lines 167 to 233, the updateTransaction
method must enforce that exactly one of commit or rollback is provided (XOR)
like the Databases guard; add validation after extracting commit and rollback
that throws an AppwriteException when both are undefined or both are defined
(i.e., if (! (typeof commit !== 'undefined' ^ typeof rollback !== 'undefined'))
throw new AppwriteException('Either "commit" or "rollback" must be provided, but
not both'); ensuring the rest of the payload building remains unchanged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/services/tables-db.ts (1)
167-233
: Enforce commit XOR rollback validation.This is a duplicate of a previous review comment. The method currently accepts both
commit
androllback
as optional parameters without validating that exactly one must be provided. This allows invalid scenarios where both are specified or neither is specified, which could lead to ambiguous transaction states or API errors.Apply this diff to enforce the XOR constraint:
const transactionId = params.transactionId; const commit = params.commit; const rollback = params.rollback; if (typeof transactionId === 'undefined') { throw new AppwriteException('Missing required parameter: "transactionId"'); } + + // Exactly one of commit or rollback must be true + if ((commit ? 1 : 0) + (rollback ? 1 : 0) !== 1) { + throw new AppwriteException('Provide exactly one of "commit" or "rollback".'); + }
🧹 Nitpick comments (4)
docs/examples/account/update-email-verification.md (1)
3-14
: Wrap top‑level await for broader compatibilitySome environments don’t support top‑level await. Wrap in an async IIFE and add basic error handling.
-const client = new Client() - .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const account = new Account(client); - -const result = await account.updateEmailVerification({ - userId: '<USER_ID>', - secret: '<SECRET>' -}); - -console.log(result); +;(async () => { + const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>') // Your project ID + + const account = new Account(client) + + const result = await account.updateEmailVerification({ + userId: '<USER_ID>', + secret: '<SECRET>', + }) + + console.log(result) +})().catch(console.error)docs/examples/account/create-email-verification.md (1)
3-13
: Wrap top‑level await and add basic error handlingUse an async IIFE for wider runtime compatibility.
-const client = new Client() - .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const account = new Account(client); - -const result = await account.createEmailVerification({ - url: 'https://example.com' -}); - -console.log(result); +;(async () => { + const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>') // Your project ID + + const account = new Account(client) + + const result = await account.createEmailVerification({ + url: 'https://example.com', + }) + + console.log(result) +})().catch(console.error)src/models.ts (1)
1258-1286
: Narrow Transaction.status typeExpose exact states to catch typos at compile time.
- /** - * Current status of the transaction. One of: pending, committing, committed, rolled_back, failed. - */ - status: string; + /** + * Current status of the transaction. + */ + status: 'pending' | 'committing' | 'committed' | 'rolled_back' | 'failed';src/services/account.ts (1)
2735-2784
: Email/phone verification updates LGTM; consider endpoint constantsOverloads, validation, and new paths look correct. Optional: extract shared constants to reduce duplication/typo risk:
- EMAIL_VERIFICATION_PATH = '/account/verifications/email'
- PHONE_VERIFICATION_PATH = '/account/verifications/phone'
Then reuse across create/update methods.
Also applies to: 2786-2797, 2829-2829, 2856-2912, 2914-2923, 2959-2959, 2989-2989, 3049-3049
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
CHANGELOG.md
(1 hunks)README.md
(1 hunks)docs/examples/account/create-email-verification.md
(1 hunks)docs/examples/account/update-email-verification.md
(1 hunks)package.json
(1 hunks)src/client.ts
(1 hunks)src/enums/execution-status.ts
(1 hunks)src/enums/execution-trigger.ts
(1 hunks)src/models.ts
(5 hunks)src/services/account.ts
(6 hunks)src/services/tables-db.ts
(24 hunks)
✅ Files skipped from review due to trivial changes (2)
- package.json
- CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
- src/client.ts
- README.md
🧰 Additional context used
🧬 Code graph analysis (2)
src/services/account.ts (1)
src/models.ts (1)
Token
(777-802)
src/services/tables-db.ts (1)
src/models.ts (5)
TransactionList
(224-233)Transaction
(1261-1286)Row
(238-267)DefaultRow
(269-272)RowList
(14-23)
🔇 Additional comments (12)
src/enums/execution-trigger.ts (1)
1-5
: Enum addition LGTMValues and casing are consistent with usage in Models.Execution.
src/enums/execution-status.ts (1)
1-6
: Enum addition LGTMNames/values align with execution lifecycle and updated model typing.
src/models.ts (4)
1-2
: Imports LGTMEnums are correctly imported for typed Execution fields.
221-233
: TransactionList shape LGTMConsistent with other *List types (total + items array).
1031-1031
: Typed trigger LGTMSwitch to ExecutionTrigger improves safety and DX.
1035-1035
: Typed status LGTMUsing ExecutionStatus narrows the domain and prevents invalid strings.
src/services/tables-db.ts (6)
13-62
: LGTM!The
listTransactions
method is well-implemented with proper overloading for both object-style and deprecated parameter-style calling conventions. The payload construction and routing are correct.
64-114
: LGTM!The
createTransaction
method correctly implements transaction creation with an optional TTL parameter. The method signature and payload handling are appropriate.
116-165
: LGTM!The
getTransaction
method properly validates the requiredtransactionId
parameter and routes to the correct endpoint.
234-284
: LGTM!The
deleteTransaction
method correctly implements transaction deletion with proper parameter validation.
286-344
: LGTM!The
createOperations
method is correctly implemented for creating multiple operations within a transaction. The required parameter validation and payload construction are appropriate.
346-417
: LGTM! Consistent transactionId integration across row operations.All row operation methods (
listRows
,createRow
,getRow
,upsertRow
,updateRow
,deleteRow
,decrementRowColumn
,incrementRowColumn
) have been correctly extended to accept an optionaltransactionId
parameter. The implementation is consistent across all methods:
- Proper overloading for both object-style and deprecated parameter-style signatures
- Correct parameter extraction and type definitions
- Consistent payload construction with conditional
transactionId
inclusion- Existing validation and error handling preserved
Also applies to: 419-511, 513-591, 593-679, 681-767, 769-841, 843-936, 938-1031
requestPath: string; | ||
/** | ||
* HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous. | ||
* HTTP request headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc wording mismatches type (array vs object)
Comment says “key‑value object” but the type is Headers[]
. Align the wording.
- * HTTP request headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.
+ * HTTP request headers as an array of name/value pairs. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
* HTTP request headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous. | |
* HTTP request headers as an array of name/value pairs. This will return only whitelisted headers. All headers are returned if execution is created as synchronous. |
🤖 Prompt for AI Agents
In src/models.ts around line 1045, the doc comment incorrectly calls the value a
"key-value object" while the type is Headers[]; update the comment wording to
say it returns an array of header objects (Headers[]) — for example: "HTTP
request headers as an array of header objects (Headers[]). This will return only
whitelisted headers; all headers are returned if execution is created as
synchronous." Ensure the updated text matches the exact shape and semantics of
Headers[].
This PR contains updates to the Web SDK for version 21.2.0.
Summary by CodeRabbit
New Features
Documentation
Refactor
Chores