Conversation
There was a problem hiding this comment.
Pull request overview
Adds SDK support for a more secure “download invoice for a user’s payment” API endpoint and includes a manual integration example showcasing pricing/portal flows (including invoice download).
Changes:
- Added a new OpenAPI path + operation for
/users/{user_id}/payments/{payment_id}/invoice.pdf(PDF invoice download). - Added
User.retrieveInvoice(userId, paymentId)to fetch the invoice PDF. - Added a new manual example script for “vibe code platform” integrations and invoice retrieval.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
packages/sdk/src/api/schema.d.ts |
Updates generated OpenAPI typings to include the new secure invoice download endpoint. |
packages/sdk/src/api/User.ts |
Adds retrieveInvoice() method on the User API. |
packages/sdk/src/__tests__/manual/vibe-code-platform-integration.ts |
Adds a manual integration/example script including invoice retrieval usage. |
Comments suppressed due to low confidence (2)
packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:34
- With
exactOptionalPropertyTypes: true, passingplanId: planIdwhereplanIdisstring | undefinedis a real type error (hence the@ts-expect-error). Instead of suppressing types, build the options object soplanIdis omitted when undefined (or narrowplanIdbefore passing it). This keeps the example type-safe and avoids relying on compiler suppression.
async function createFreemiusCheckout(
user: { email: string; firstName?: string; lastName?: string },
planId?: string
): Promise<Checkout> {
// @ts-expect-error - The planId can be undefined and depending on some TS config it can cause error, but in practice this is fine.
const checkout = await freemius.checkout.create({
user,
planId: planId,
isSandbox: SANDBOX,
});
packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:49
const hasActiveSubscription = subscription?.canceled_at == nullevaluates totruewhensubscriptionisnull/undefined(becauseundefined == null), which can incorrectly treat a missing/failed subscription fetch as an active subscription. Use a strict check that only returns true when a subscription exists and is not cancelled (e.g.subscription?.canceled_at === null).
const subscription = entitlement ? await freemius.api.license.retrieveSubscription(entitlement.fsLicenseId) : null;
const hasActiveSubscription = subscription?.canceled_at == null;
packages/sdk/src/api/User.ts
Outdated
| payment_id: this.getIdForPath(paymentId), | ||
| }, | ||
| }, | ||
| responseType: 'blob', |
There was a problem hiding this comment.
openapi-fetch client options use parseAs: 'blob' for binary/PDF responses (see Payment.retrieveInvoice). responseType: 'blob' is not part of the openapi-fetch API, so this likely won’t typecheck and may not parse the PDF correctly at runtime. Switch this call to use parseAs: 'blob' (and remove responseType).
| responseType: 'blob', | |
| parseAs: 'blob', |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:208
- These commented-out test invocations with hardcoded production credentials should be removed before committing. Leaving commented-out code with real credentials in the repository poses a security risk and reduces code maintainability. If these are needed for testing, they should be in a separate local file that's gitignored, or use environment variables for credentials.
// getSubscriptionAndPayments({ fsLicenseId: '1868256', fsUserId: '5723112' }).then((data) => {
// console.log(data);
// });
async function cancelSubscription(entitlement: Pick<PurchaseEntitlementData, 'fsLicenseId'>): Promise<boolean> {
const subscription = await freemius.api.license.retrieveSubscription(entitlement.fsLicenseId);
if (!subscription || subscription.canceled_at != null) {
return false;
}
await freemius.api.subscription.cancel(subscription.id!);
return true;
}
// cancelSubscription({ fsLicenseId: '1867816' }).then((result) => {
// console.log('Cancellation result:', result);
// });
async function getInvoice(userId: string, paymentId: string): Promise<Blob | null> {
const invoice = await freemius.api.user.retrieveInvoice(userId, paymentId);
return invoice;
}
// getInvoice('5723112', '1917010').then((invoice) => {
// if (invoice) {
// console.log('Invoice retrieved successfully:', invoice);
// } else {
// console.log('Failed to retrieve invoice.');
// }
// });
packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:34
- The
@ts-expect-errordirective is suppressing a type error for potentially undefined planId. According to the TypeScript best practice and the minimalist philosophy mentioned in the coding guidelines, this should be handled explicitly. Either make planId optional in the checkout.create() signature or handle the undefined case properly without suppressing the error.
// @ts-expect-error - The planId can be undefined and depending on some TS config it can cause error, but in practice this is fine.
const checkout = await freemius.checkout.create({
user,
planId: planId,
isSandbox: SANDBOX,
});
packages/sdk/src/api/User.ts:257
- The return type is inconsistent with the similar method in Payment.ts. The Payment.retrieveInvoice method explicitly casts the response to Blob (line 58 in Payment.ts), but this method returns response.data directly. For consistency and type safety, consider explicitly typing or casting the return value to Blob, similar to the existing Payment.retrieveInvoice implementation.
return response.data;
packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:119
- This sample code contains hardcoded production credentials (email and license/plan IDs). For a manual test/example file that may be committed to the repository, these should be replaced with placeholder values or environment variables to avoid exposing real user data.
getPricingData({ email: 'swas@freemius.com' }, { fsLicenseId: '1868448', fsPlanId: '40918' }).then((data) => {
console.log(data);
});
… + Add sample codes for vibe code platform integrations [api] Use a different endpoint [fix] Per feedback [test] Improve the data structure of the vibe code UI [changeset]
ac3a5e4 to
afd82c3
Compare
… + Add sample codes for vibe code platform integrations