fix(revenuecat): address PR review feedback

- create_purchase: wrap JSON.parse(attributes) with try/catch and clear error
- update_subscriber_attributes: drop subscriber output (endpoint returns
  empty body) and guard JSON.parse on attributes
- grant_entitlement: throw when both duration and endTimeMs are provided,
  matching defer_google_subscription behavior
This commit is contained in:
Waleed Latif
2026-05-06 22:17:10 -07:00
parent 6c7a18e5f5
commit 85f181abeb
4 changed files with 24 additions and 19 deletions
+9 -2
View File
@@ -135,8 +135,15 @@ export const revenuecatCreatePurchaseTool: ToolConfig<
body.introductory_price = params.introductoryPrice
}
if (params.attributes !== undefined && params.attributes !== '') {
body.attributes =
typeof params.attributes === 'string' ? JSON.parse(params.attributes) : params.attributes
if (typeof params.attributes === 'string') {
try {
body.attributes = JSON.parse(params.attributes)
} catch {
throw new Error('attributes must be a valid JSON object')
}
} else {
body.attributes = params.attributes
}
}
if (params.updatedAtMs !== undefined) body.updated_at_ms = params.updatedAtMs
return body
@@ -70,6 +70,9 @@ export const revenuecatGrantEntitlementTool: ToolConfig<
if (!params.duration && params.endTimeMs === undefined) {
throw new Error('Provide either duration or endTimeMs to grant a promotional entitlement')
}
if (params.duration && params.endTimeMs !== undefined) {
throw new Error('Provide only one of duration or endTimeMs — they cannot be used together')
}
const body: Record<string, unknown> = {}
if (params.endTimeMs !== undefined) body.end_time_ms = params.endTimeMs
else if (params.duration) body.duration = params.duration
-1
View File
@@ -399,7 +399,6 @@ export interface UpdateSubscriberAttributesResponse extends ToolResponse {
output: {
updated: boolean
app_user_id: string
subscriber: RevenueCatSubscriber
}
}
@@ -2,12 +2,7 @@ import type {
UpdateSubscriberAttributesParams,
UpdateSubscriberAttributesResponse,
} from '@/tools/revenuecat/types'
import {
extractSubscriber,
SUBSCRIBER_OUTPUT,
shapeSubscriber,
throwIfRevenueCatError,
} from '@/tools/revenuecat/types'
import { throwIfRevenueCatError } from '@/tools/revenuecat/types'
import type { ToolConfig } from '@/tools/types'
export const revenuecatUpdateSubscriberAttributesTool: ToolConfig<
@@ -51,22 +46,27 @@ export const revenuecatUpdateSubscriberAttributesTool: ToolConfig<
'Content-Type': 'application/json',
}),
body: (params) => {
const attributes =
typeof params.attributes === 'string' ? JSON.parse(params.attributes) : params.attributes
let attributes: unknown
if (typeof params.attributes === 'string') {
try {
attributes = JSON.parse(params.attributes)
} catch {
throw new Error('attributes must be a valid JSON object')
}
} else {
attributes = params.attributes
}
return { attributes }
},
},
transformResponse: async (response, params) => {
await throwIfRevenueCatError(response)
const data = await response.json().catch(() => ({}))
const subscriber = shapeSubscriber(extractSubscriber(data))
return {
success: true,
output: {
updated: true,
app_user_id: subscriber.original_app_user_id || (params?.appUserId ?? ''),
subscriber,
app_user_id: params?.appUserId ?? '',
},
}
},
@@ -80,9 +80,5 @@ export const revenuecatUpdateSubscriberAttributesTool: ToolConfig<
type: 'string',
description: 'The app user ID of the updated subscriber',
},
subscriber: {
...SUBSCRIBER_OUTPUT,
description: 'The updated subscriber object after applying the attribute changes',
},
},
}