Skip to content

Conversation

@abnegate
Copy link
Member

@abnegate abnegate commented Nov 3, 2025

This PR contains updates to the Web SDK for version 21.4.0.

Summary by CodeRabbit

Release Notes v21.4.0

  • New Features

    • Operator class enables atomic row modifications (update, upsert, bulk update, bulk upsert)
    • total parameter added to list queries to skip row counting for improved performance
  • Updates

    • Permissions API streamlined across database, storage, and table operations
    • Execution status expanded with "Scheduled" state

@coderabbitai
Copy link

coderabbitai bot commented Nov 3, 2025

Walkthrough

Version 21.4.0 introduces a new Operator utility class for atomic row modifications with methods for numeric operations, array manipulations, string transformations, and date operations. The ExecutionStatus enum gains a Scheduled status value. Multiple service list operations (accounts, databases, functions, storage, tables, teams) add an optional total parameter to control row count calculation. Query helper methods are refactored to delegate to existing internal methods. Documentation examples are updated to use typed Permission/Role objects instead of string-based permissions and to demonstrate the new total parameter. Package version and SDK headers are bumped to 21.4.0.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50–70 minutes

  • src/operator.ts: New Operator class introduces substantial logic across 20+ static factory methods with conditional validation for numeric operations, array handling, and type normalization. Requires careful verification of JSON serialization, parameter handling consistency, and edge case validation.
  • Service files (src/services/account.ts, databases.ts, functions.ts, storage.ts, tables-db.ts, teams.ts): Multiple files share a repetitive pattern of adding total parameter to list methods across overloads, but variations in rest parameter tuples and parameter destructuring logic across different services require file-specific validation to ensure consistency.
  • Query refactoring (src/query.ts): Six methods updated to delegate to internal helpers; verify that the behavioral equivalence is maintained and that generated query strings match previous implementations.
  • Documentation examples: While repetitive (adding total and Permission updates), span 10+ files; a sample verification suffices for pattern validation, but widespread changes warrant spot-checking.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The PR title "feat: Web SDK update for version 21.4.0" is generic and uses non-descriptive terminology. While it correctly indicates this is a version bump and mentions the SDK, the term "update" provides minimal insight into what changes were actually introduced. The changeset includes significant new features: the Operator class for atomic row modifications, a total parameter across multiple list queries for performance optimization, a new Scheduled execution status, and updates to permission handling in documentation examples. A teammate reviewing the git history would only know a version bump occurred but would not understand the primary technical changes without examining the PR details. Consider using a more specific title that highlights the primary feature. For example: "feat: Add Operator class for atomic row modifications and total parameter to list queries" or "feat: Introduce Operator class with bulk update/upsert capabilities" would better communicate the main changes to reviewers scanning the history.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef1e00b and e2a67c2.

📒 Files selected for processing (31)
  • CHANGELOG.md (1 hunks)
  • README.md (1 hunks)
  • docs/examples/account/list-identities.md (1 hunks)
  • docs/examples/account/list-logs.md (1 hunks)
  • docs/examples/databases/create-document.md (2 hunks)
  • docs/examples/databases/list-documents.md (1 hunks)
  • docs/examples/databases/update-document.md (2 hunks)
  • docs/examples/databases/upsert-document.md (2 hunks)
  • docs/examples/functions/list-executions.md (1 hunks)
  • docs/examples/storage/create-file.md (2 hunks)
  • docs/examples/storage/list-files.md (1 hunks)
  • docs/examples/storage/update-file.md (2 hunks)
  • docs/examples/tablesdb/create-row.md (2 hunks)
  • docs/examples/tablesdb/list-rows.md (1 hunks)
  • docs/examples/tablesdb/update-row.md (2 hunks)
  • docs/examples/tablesdb/upsert-row.md (2 hunks)
  • docs/examples/teams/list-memberships.md (1 hunks)
  • docs/examples/teams/list.md (1 hunks)
  • package.json (1 hunks)
  • src/client.ts (1 hunks)
  • src/enums/execution-status.ts (1 hunks)
  • src/index.ts (2 hunks)
  • src/models.ts (1 hunks)
  • src/operator.ts (1 hunks)
  • src/query.ts (6 hunks)
  • src/services/account.ts (2 hunks)
  • src/services/databases.ts (2 hunks)
  • src/services/functions.ts (2 hunks)
  • src/services/storage.ts (2 hunks)
  • src/services/tables-db.ts (2 hunks)
  • src/services/teams.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
src/services/tables-db.ts (1)
src/models.ts (3)
  • Row (238-267)
  • DefaultRow (269-272)
  • RowList (14-23)
src/services/databases.ts (1)
src/models.ts (3)
  • Document (277-306)
  • DefaultDocument (308-311)
  • DocumentList (28-37)
src/services/functions.ts (1)
src/models.ts (1)
  • ExecutionList (126-135)
src/query.ts (2)
src/client.ts (1)
  • Query (814-814)
src/index.ts (1)
  • Query (8-8)
src/services/storage.ts (1)
src/models.ts (1)
  • FileList (84-93)
src/operator.ts (1)
src/index.ts (2)
  • Condition (25-25)
  • Operator (25-25)
src/services/teams.ts (1)
src/models.ts (4)
  • Preferences (598-599)
  • DefaultPreferences (601-604)
  • TeamList (98-107)
  • MembershipList (112-121)
src/services/account.ts (1)
src/models.ts (2)
  • IdentityList (56-65)
  • LogList (70-79)
🔇 Additional comments (27)
src/query.ts (1)

310-358: LGTM! Good refactoring to eliminate code duplication.

The six date helper methods (createdBefore, createdAfter, createdBetween, updatedBefore, updatedAfter, updatedBetween) have been refactored to delegate to the existing lessThan, greaterThan, and between methods. This follows the DRY principle and maintains identical behavior while reducing code duplication.

docs/examples/databases/create-document.md (1)

1-20: LGTM! Good migration to typed permission objects.

The documentation has been updated to use typed Permission and Role objects instead of string-based permissions. This improves type safety, provides better IDE support, and reduces the likelihood of runtime errors from string typos.

docs/examples/account/list-logs.md (1)

9-12: LGTM! Documentation accurately reflects the new total parameter.

The example correctly demonstrates the optional total parameter for list queries, which allows skipping row counting for improved performance.

docs/examples/tablesdb/list-rows.md (1)

9-15: LGTM! Example properly demonstrates the new total parameter for TablesDB.

The documentation correctly shows the optional total parameter for listRows, consistent with the broader PR pattern of adding this parameter across list endpoints.

CHANGELOG.md (1)

3-7: LGTM! Changelog entry accurately documents version 21.4.0 features.

The changelog clearly describes the two main additions:

  1. Performance improvement via optional total parameter
  2. New Operator class for atomic row modifications
src/models.ts (1)

1033-1035: LGTM! Documentation comment correctly updated for new "scheduled" status.

The comment now includes "scheduled" as a possible execution status value, aligning with the ExecutionStatus enum enhancement mentioned in the AI summary.

docs/examples/account/list-identities.md (1)

9-12: LGTM! Example correctly demonstrates the total parameter for identity listing.

The documentation properly shows the optional total parameter for listIdentities, consistent with the performance optimization pattern applied across all list endpoints.

docs/examples/storage/create-file.md (2)

1-1: LGTM! Import additions support typed permissions.

The addition of Permission and Role imports enables the use of type-safe permission definitions in the example.


13-13: LGTM! Example demonstrates best practice with typed permissions.

The change from string-based "read(\"any\")" to typed Permission.read(Role.any()) improves type safety and developer experience by providing better IDE autocomplete and reducing the risk of typos.

docs/examples/databases/list-documents.md (1)

9-15: LGTM! Example properly documents the total parameter for document listing.

The documentation correctly demonstrates the optional total parameter for listDocuments, enabling developers to skip row counting for improved performance when needed.

docs/examples/storage/list-files.md (1)

9-14: LGTM! Example correctly shows the total parameter for file listing.

The documentation properly demonstrates the optional total parameter for listFiles, completing the consistent pattern of adding this performance optimization across all list endpoints in the SDK.

docs/examples/storage/update-file.md (2)

1-1: LGTM: Improved type safety with Permission and Role imports.

The addition of Permission and Role to the imports aligns with the SDK's typed permission API.


13-13: LGTM: Typed permission usage improves API clarity.

The change from string-based permissions to Permission.read(Role.any()) provides better type safety and IDE support.

docs/examples/tablesdb/create-row.md (1)

1-1: LGTM: Consistent typed permission usage.

The import and usage changes align perfectly with the SDK-wide pattern of using typed Permission and Role objects instead of string literals.

Also applies to: 20-20

docs/examples/tablesdb/upsert-row.md (1)

1-1: LGTM: Documentation updated with typed permissions.

The changes correctly demonstrate the use of typed permission objects, improving the example's clarity and type safety.

Also applies to: 14-14

docs/examples/databases/upsert-document.md (1)

1-1: LGTM: Typed permissions for databases.

The update to use Permission.read(Role.any()) is consistent with the SDK-wide improvement to typed permission handling.

Also applies to: 14-14

docs/examples/tablesdb/update-row.md (1)

1-1: LGTM: Consistent documentation update.

The typed permission approach is correctly applied, matching the pattern used throughout the SDK documentation.

Also applies to: 14-14

docs/examples/databases/update-document.md (1)

1-1: LGTM: Final documentation update completes the pattern.

This change completes the consistent update of all documentation examples to use typed permissions, improving the overall SDK documentation quality.

Also applies to: 14-14

src/index.ts (2)

35-36: LGTM: ExecutionTrigger and ExecutionStatus exports verified.

Both enum modules exist and are properly defined. The files src/enums/execution-trigger.ts and src/enums/execution-status.ts correctly export their respective enums at the module level, and the re-exports in src/index.ts are correctly structured.


25-25: LGTM: New Operator and Condition exports verified and properly implemented.

The exports for Operator and Condition have been verified to exist in the ./operator module (enum at line 5, class at line 20). They are well-positioned, follow the existing export pattern, and the module is properly implemented. The changes are approved.

src/enums/execution-status.ts (1)

6-6: LGTM: New ExecutionStatus member is backward compatible.

Verification confirms the addition of Scheduled = 'scheduled' is safe. The codebase uses ExecutionStatus only as a type annotation with no switch statements, exhaustive checks, or type guards operating on ExecutionStatus values. The new member will not break existing functionality.

src/services/functions.ts (1)

19-67: listExecutions: total flag wiring looks correct

Overloads, parsing, and payload propagation for total?: boolean are consistent and backward‑compatible. LGTM.

src/services/databases.ts (1)

353-414: listDocuments: consistent addition of total flag

JSDoc, overloads, tuple mapping, and payload handling for total are correct and non‑breaking. Looks good.

src/services/storage.ts (1)

21-75: listFiles: total propagation is correct and safe

Overloads and payload wiring for total are accurate; maintains backward compatibility. LGTM.

src/services/tables-db.ts (1)

353-413: listRows: total flag addition matches SDK conventions

Cleanly threaded through types and payload; no changes needed.

src/services/account.ts (2)

196-237: listIdentities: total support added correctly

Parsing and payload handling for total are sound; overloads remain backward‑compatible. LGTM.


331-372: listLogs: mirrors listIdentities implementation

Accurate addition of total in types and payload. No further changes required.

Comment on lines +35 to 47
paramsOrFirst?: { queries?: string[], search?: string, total?: boolean } | string[],
...rest: [(string)?, (boolean)?]
): Promise<Models.TeamList<Preferences>> {
let params: { queries?: string[], search?: string };
let params: { queries?: string[], search?: string, total?: boolean };

if (!paramsOrFirst || (paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) {
params = (paramsOrFirst || {}) as { queries?: string[], search?: string };
params = (paramsOrFirst || {}) as { queries?: string[], search?: string, total?: boolean };
} else {
params = {
queries: paramsOrFirst as string[],
search: rest[0] as string
search: rest[0] as string,
total: rest[1] as boolean
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't swallow tuple parameters when queries are omitted.

Calling the tuple overload as teams.list(undefined, undefined, false) should forward total=false, but the if (!paramsOrFirst …) branch treats it as the object overload and ignores the rest args, so the new flag is dropped. Please remove the !paramsOrFirst guard (and default queries explicitly) so tuple calls without a queries array still propagate search/total.

-        if (!paramsOrFirst || (paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) {
-            params = (paramsOrFirst || {}) as { queries?: string[], search?: string, total?: boolean };
+        if (paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst)) {
+            params = paramsOrFirst as { queries?: string[], search?: string, total?: boolean };
         } else {
             params = {
-                queries: paramsOrFirst as string[],
+                queries: Array.isArray(paramsOrFirst) ? paramsOrFirst : undefined,
                 search: rest[0] as string,
                 total: rest[1] as boolean
             };
         }
📝 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.

Suggested change
paramsOrFirst?: { queries?: string[], search?: string, total?: boolean } | string[],
...rest: [(string)?, (boolean)?]
): Promise<Models.TeamList<Preferences>> {
let params: { queries?: string[], search?: string };
let params: { queries?: string[], search?: string, total?: boolean };
if (!paramsOrFirst || (paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst))) {
params = (paramsOrFirst || {}) as { queries?: string[], search?: string };
params = (paramsOrFirst || {}) as { queries?: string[], search?: string, total?: boolean };
} else {
params = {
queries: paramsOrFirst as string[],
search: rest[0] as string
search: rest[0] as string,
total: rest[1] as boolean
};
paramsOrFirst?: { queries?: string[], search?: string, total?: boolean } | string[],
...rest: [(string)?, (boolean)?]
): Promise<Models.TeamList<Preferences>> {
let params: { queries?: string[], search?: string, total?: boolean };
if (paramsOrFirst && typeof paramsOrFirst === 'object' && !Array.isArray(paramsOrFirst)) {
params = paramsOrFirst as { queries?: string[], search?: string, total?: boolean };
} else {
params = {
queries: Array.isArray(paramsOrFirst) ? paramsOrFirst : undefined,
search: rest[0] as string,
total: rest[1] as boolean
};
🤖 Prompt for AI Agents
In src/services/teams.ts around lines 35 to 47, the current guard "if
(!paramsOrFirst || (paramsOrFirst && typeof paramsOrFirst === 'object' &&
!Array.isArray(paramsOrFirst)))" causes tuple overload calls like
teams.list(undefined, undefined, false) to be treated as the object overload and
drop the rest args; remove the "!paramsOrFirst" part so the branch only matches
when paramsOrFirst is an object (i.e., "if (typeof paramsOrFirst === 'object' &&
!Array.isArray(paramsOrFirst))"), and when creating params in that branch
explicitly default queries to an empty array (e.g., queries:
(paramsOrFirst?.queries ?? [])) so tuple calls with an undefined first argument
still propagate search and total correctly.

*/
static createdBefore = (value: string): string =>
new Query("createdBefore", undefined, value).toString();
Query.lessThan("$createdAt", value);
Copy link
Member Author

Choose a reason for hiding this comment

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

Intentional to fix error that "createdBefore" query type doesn't exist

@abnegate abnegate merged commit de72141 into main Nov 3, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants