Skip to content

Conversation

@tothandras
Copy link
Contributor

@tothandras tothandras commented Sep 11, 2025

Summary by CodeRabbit

  • New Features
    • Introduced Entitlements V2 as the default surface, offering expanded customer entitlement operations: list, create, get, delete, override, manage grants, fetch value/history, and reset usage.
    • Added top-level Entitlements V2 with V2 list/get and global grants listing, plus ability to void grants (legacy path maintained with deprecation note).
  • Chores
    • Preserved backward compatibility by exposing previous functionality as entitlementsV1 alongside the new entitlements surface in both Customers and the main client.

@tothandras tothandras requested a review from GAlexIHU September 11, 2025 16:37
@tothandras tothandras requested a review from a team as a code owner September 11, 2025 16:37
@tothandras tothandras added the release-note/feature Release note: Exciting New Features label Sep 11, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 11, 2025

📝 Walkthrough

Walkthrough

Adds V2 entitlements surfaces alongside existing V1 in JavaScript client: new CustomerEntitlementsV2, EntitlementsV2, and GrantsV2 classes with /api/v2 endpoints; wires dual properties (entitlementsV1 and entitlements) in Customers and OpenMeter clients; retains V1 classes/methods for backward compatibility.

Changes

Cohort / File(s) Summary of changes
Customers entitlements V2 surface
api/client/javascript/src/client/customers.ts
Introduces CustomerEntitlementsV2 with list/create/get/delete/override/listGrants/createGrant/value/history/resetUsage targeting /api/v2; exposes dual properties in Customers: entitlementsV1 (V1) and entitlements (V2); initializes both in constructor; V1 class unchanged.
Entitlements module V2
api/client/javascript/src/client/entitlements.ts
Adds EntitlementsV2 (list, get) and GrantsV2 (list, void); uses /api/v2 for new endpoints and legacy /api/v1/grants/{grantId} for void; preserves existing V1 Entitlements/Grants; response handling via transformResponse.
Client wiring for V2
api/client/javascript/src/client/index.ts
OpenMeter now exposes entitlementsV1 (V1) and entitlements (V2); constructor instantiates both; type of entitlements updated to EntitlementsV2.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change: adding Entitlements V2 methods to the JavaScript SDK, uses a conventional-commit prefix ("feat(api)"), and avoids unnecessary detail. It aligns with the changeset which introduces V2 entitlements surfaces while preserving V1 compatibility.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/entitlements-v2-js-sdk

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
Contributor

@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

🧹 Nitpick comments (5)
api/client/javascript/src/client/entitlements.ts (3)

404-417: Minor ergonomics: destructure options to avoid leaking unknown props

To keep the request options clean and avoid passing stray fields, destructure options to extract query.

-  public async list(
-    options?: RequestOptions & {
-      query?: operations['listEntitlementsV2']['parameters']['query']
-    }
-  ) {
-    const resp = await this.client.GET('/api/v2/entitlements', {
-      params: {
-        query: options?.query,
-      },
-      ...options,
-    })
+  public async list(
+    options?: RequestOptions & {
+      query?: operations['listEntitlementsV2']['parameters']['query']
+    }
+  ) {
+    const { query, ...opts } = options ?? {}
+    const resp = await this.client.GET('/api/v2/entitlements', {
+      params: { query },
+      ...opts,
+    })

453-466: Repeat the options destructuring pattern here

Same rationale as above for GrantsV2.list.

-  public async list(
-    options?: RequestOptions & {
-      query?: operations['listGrantsV2']['parameters']['query']
-    }
-  ) {
-    const resp = await this.client.GET('/api/v2/grants', {
-      params: {
-        query: options?.query,
-      },
-      ...options,
-    })
+  public async list(
+    options?: RequestOptions & {
+      query?: operations['listGrantsV2']['parameters']['query']
+    }
+  ) {
+    const { query, ...opts } = options ?? {}
+    const resp = await this.client.GET('/api/v2/grants', {
+      params: { query },
+      ...opts,
+    })

478-492: Consider renaming method to voidGrant (keep alias for consistency)

void is a keyword; while valid as a property, voidGrant reads clearer and aligns with the operation name. You can keep void as a thin alias to avoid surprises.

-  public async void(
+  public async voidGrant(
     grantId: operations['voidGrant']['parameters']['path']['grantId'],
     options?: RequestOptions
   ) {
     const resp = await this.client.DELETE('/api/v1/grants/{grantId}', {
       params: {
         path: {
           grantId,
         },
       },
       ...options,
     })
 
     return transformResponse(resp)
   }
+
+  /** @deprecated Use `voidGrant` */
+  public async void(
+    grantId: operations['voidGrant']['parameters']['path']['grantId'],
+    options?: RequestOptions
+  ) {
+    return this.voidGrant(grantId, options)
+  }
api/client/javascript/src/client/customers.ts (2)

20-22: Expose V2 by default but mark V1 as deprecated

Good dual-surface. Add deprecation JSDoc on V1 to steer users.

-  public entitlementsV1: CustomerEntitlements
+  /** @deprecated Use `entitlements` (V2). */
+  public entitlementsV1: CustomerEntitlements

Also applies to: 26-28


392-419: Nit: destructure options to avoid passing extraneous fields

Same ergonomics pattern as elsewhere.

-  public async list(
+  public async list(
     customerIdOrKey: operations['listCustomerEntitlementsV2']['parameters']['path']['customerIdOrKey'],
     options?: RequestOptions & {
       query?: operations['listCustomerEntitlementsV2']['parameters']['query']
     }
   ) {
-    const resp = await this.client.GET(
+    const { query, ...opts } = options ?? {}
+    const resp = await this.client.GET(
       '/api/v2/customers/{customerIdOrKey}/entitlements',
       {
         params: {
           path: { customerIdOrKey },
-          query: options?.query,
+          query,
         },
-        ...options,
+        ...opts,
       }
     )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39796d7 and f21b23d.

📒 Files selected for processing (3)
  • api/client/javascript/src/client/customers.ts (2 hunks)
  • api/client/javascript/src/client/entitlements.ts (1 hunks)
  • api/client/javascript/src/client/index.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
api/client/javascript/src/client/customers.ts (3)
api/client/javascript/src/client/schemas.ts (1)
  • operations (11775-26482)
api/client/javascript/src/client/common.ts (1)
  • RequestOptions (6-6)
api/client/javascript/src/client/utils.ts (1)
  • transformResponse (15-35)
api/client/javascript/src/client/entitlements.ts (3)
api/client/javascript/src/client/schemas.ts (2)
  • paths (1-2417)
  • operations (11775-26482)
api/client/javascript/src/client/common.ts (1)
  • RequestOptions (6-6)
api/client/javascript/src/client/utils.ts (1)
  • transformResponse (15-35)
api/client/javascript/src/client/index.ts (1)
api/client/javascript/src/client/entitlements.ts (2)
  • Entitlements (17-269)
  • EntitlementsV2 (390-438)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Artifacts / Container image
  • GitHub Check: Test
  • GitHub Check: Code Generators
  • GitHub Check: Build
  • GitHub Check: Lint
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
api/client/javascript/src/client/index.ts (2)

11-11: Import looks good

Brings both V1 and V2 into scope cleanly.


56-58: Avoid breaking change: keep entitlements as V1, add entitlementsV2 for V2

Changing the canonical entitlements to V2 will break existing consumers using V1 methods (create/delete/override/reset). Keep entitlements as V1, add entitlementsV2, and mark V1 deprecated in JSDoc.

-  public entitlementsV1: Entitlements
-  public entitlements: EntitlementsV2
+  /** @deprecated Use `entitlementsV2` moving forward. */
+  public entitlementsV1: Entitlements
+  // Back-compat: keep V1 on the canonical name
+  public entitlements: Entitlements
+  // New V2 surface
+  public entitlementsV2: EntitlementsV2
api/client/javascript/src/client/entitlements.ts (1)

425-437: LGTM: get endpoint wiring and typing are correct

Correct path, params, and return handling via transformResponse.

api/client/javascript/src/client/customers.ts (1)

617-641: LGTM: history endpoint models required windowSize cleanly

Clear separation of required windowSize and optional query. Path and params look correct.

Comment on lines +94 to 96
this.entitlementsV1 = new Entitlements(this.client)
this.entitlements = new EntitlementsV2(this.client)
this.events = new Events(this.client)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Wire-up to preserve back-compat and expose V2

Initialize V1 once and alias it to both entitlements and entitlementsV1; expose V2 as entitlementsV2.

-    this.entitlementsV1 = new Entitlements(this.client)
-    this.entitlements = new EntitlementsV2(this.client)
+    const entitlementsV1 = new Entitlements(this.client)
+    this.entitlements = entitlementsV1
+    this.entitlementsV1 = entitlementsV1
+    this.entitlementsV2 = new EntitlementsV2(this.client)
📝 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
this.entitlementsV1 = new Entitlements(this.client)
this.entitlements = new EntitlementsV2(this.client)
this.events = new Events(this.client)
const entitlementsV1 = new Entitlements(this.client)
this.entitlements = entitlementsV1
this.entitlementsV1 = entitlementsV1
this.entitlementsV2 = new EntitlementsV2(this.client)
this.events = new Events(this.client)
🤖 Prompt for AI Agents
In api/client/javascript/src/client/index.ts around lines 94 to 96, you should
initialize the V1 Entitlements only once and alias it for backward
compatibility: create a single instance and assign it to both
this.entitlementsV1 and this.entitlements, then instantiate V2 and assign it to
this.entitlementsV2 (leave this.events as-is); ensure you do not instantiate
Entitlements twice and that property names are exactly entitlements,
entitlementsV1, and entitlementsV2.

@tothandras tothandras merged commit 727f31e into main Sep 11, 2025
25 of 26 checks passed
@tothandras tothandras deleted the feat/entitlements-v2-js-sdk branch September 11, 2025 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants