Skip to content
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

feat: type declaration #334

Merged
merged 29 commits into from
Feb 22, 2023
Merged

feat: type declaration #334

merged 29 commits into from
Feb 22, 2023

Conversation

ankitdas13
Copy link
Contributor

@ankitdas13 ankitdas13 commented Jan 2, 2023

Feature Proposal

Added Declaration files for type support

Changes

There is no breaking changes, only package.json has been updated and added Razorpay, Api instance d.ts files including modules

Api reference

Addon api
Plans api
Items api

Added (13 Feb)

(Reviewer Anurag)

Invoices api
Settlements api & api
fundAccount api

(Reviewer Siddhant)

Transfers api
Orders api

Added (14 Feb)

Payment api
QrCode api
Refund api
Virtual Account api

Customer api
PaymentLink api
Subscriptions api
Card api

Code snippets doc of all entities

Usage

import Razorpay = require("./dist/razorpay")

const instance =  new Razorpay({
    key_id: "",
    key_secret: ""
})

Copy link

@sidag95 sidag95 left a comment

Choose a reason for hiding this comment

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

Leaving some initial comments


declare class Razorpay {
static VERSION: string
static validateWebhookSignature: boolean
Copy link

Choose a reason for hiding this comment

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

question: ‏Should this be a function that returns a boolean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added validateWebhookSignature from utility.d.ts with return type

/**
* Fetches a addon given Addon ID
*
* @param {String} addonId
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets add description for each param and return typedef

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added description from documentation

* Fetches a addon given Addon ID
*
* @param {String} addonId
*
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets add the optional callback param here

*
* @param {String} addonId
*
* @return {Promise}
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets update the return type based on whether the callback prop was provided

/**
* Fetches a addon given Addon ID
*
* @param {String} addonId
Copy link

Choose a reason for hiding this comment

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

question: ‏Is it {String} or {string} or it doesn't matter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to {string} according to JSDoc reference

/**
* Get all addons
*
* @param {Object} params
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Can we define the object structure here?

@@ -0,0 +1,41 @@
interface IOption<T> {
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets make the configuration options explicit instead of Generic

put(params: IPayload): Promise<any>
patch(params: IPayload): Promise<any>
delete(params: IPayload): Promise<any>
private allowedHeaders;
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets remove these since these are internal and not exposed to the user

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed all internal functions


interface IPayload {
url: string,
params: IOption<any>
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Make IPayload a Generic and pass that to a params, lets not use IOption here

Copy link

Choose a reason for hiding this comment

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

Can we pass options to each API call?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


interface IPayload {
url: string,
params: IOption<any>
Copy link

Choose a reason for hiding this comment

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

This is data and not params

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to data: T

* your webhook secret
*
*/
export function validatePaymentVerification(payload: IRazorpayWebhook, signature: string, secret: string): boolean
Copy link

@sidag95 sidag95 Jan 23, 2023

Choose a reason for hiding this comment

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

suggestion: ‏Can we use union types here for the 3 different cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Used overloading here

*/
id: string,
/**
* The unique identifier of the created add-on.
Copy link

Choose a reason for hiding this comment

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

question: ‏This is same as id?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to Indicates the type of entity.

description?: string;
}

export interface IRazorpayAddonId {
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets rename this to IRazorpayAddon

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

import { IRazorpayItemId } from './items';


export interface IRazorpayAddon {
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets remove this in favour of IRazorpayItemCreateRequestBody

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

active?: boolean;
}

export interface IRazorpayItemId extends IRazorpayItem{
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets rename this to IRazorpayItem

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -0,0 +1,64 @@
import { IRazorpayQuery } from "./api";

export interface IRazorpayItem {
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets make this internal and rename to IRazorpayItemBaseRequestBody.

Then, lets create two implementations, IRazorpayItemCreateRequestBody extends IRazorpayItemBaseRequestBody
and IRazorpayItemUpdateRequestBody extends IRazorpayItemBaseRequestBody

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed these interfaces inside namespace


declare class Razorpay {
static VERSION: string
static validateWebhookSignature(body: string, signature: string, secret: string): ReturnType<typeof validateWebhookSignature>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
static validateWebhookSignature(body: string, signature: string, secret: string): ReturnType<typeof validateWebhookSignature>
static validateWebhookSignature: typeof validateWebhookSignature

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added typeof validateWebhookSignature

@@ -1 +1,48 @@
declare module "razorpay";
import API, { IRazorpayHeaders } from './types/api'
import customers from "./types/customers"
Copy link
Member

Choose a reason for hiding this comment

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

Remove the imports if we are not adding the type.d.ts files for each module.

And instead add any:

  customers: any;

constructor(config: IRazorpayConfig)
api: API
customers: ReturnType<typeof customers>
addons: ReturnType<typeof addons>
Copy link
Member

Choose a reason for hiding this comment

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

Nice to have:

Add jsdoc comment and link to API docs.

/**
* Delete a addon given Addon ID
*
* @param {string} addonId - addon id to be fetched
Copy link
Member

Choose a reason for hiding this comment

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

We should not mix and match jsdoc types + typescript explicit types.

Just this will suffice:

@param addonId - addon id to be fetched

@@ -0,0 +1,56 @@
export interface IRazorpayWebhook {
Copy link
Member

Choose a reason for hiding this comment

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

In the utils file, it will be a good thing if we also define the smaller util typedefs.

eg:

function getDateInSecs(date: Date): number {
  return (+new Date(date))/1000
}

function normalizeDate(date: Date): number {
  return isNumber(date)? date : getDateInSecs(date)
}

Typing smaller utils are good way to increase overall TS coverage since those utils might be used in lot of places, and TS will be able to infer more stricter types.

Comment on lines 45 to 47
export function validatePaymentVerification(payload: IRazorpayVerifyPayment, signature: string, secret: string): boolean
export function validatePaymentVerification(payload: IRazorpayVerifySubscription, signature: string, secret: string): boolean
export function validatePaymentVerification(payload: IRazorpayVerifyPaymentLink, signature: string, secret: string): boolean
Copy link
Member

Choose a reason for hiding this comment

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

These 3 overloads can be instead changed to use union since validatePaymentVerification function doesn't return anything different based on the payload param

export function validatePaymentVerification(payload: IRazorpayVerifyPayment | IRazorpayVerifySubscription | IRazorpayVerifyPaymentLink, signature: string, secret: string): boolean

@anuraghazra
Copy link
Member

TODO:

  1. Ensure no breaking change is happening cause of types.
  2. Use yalc/verdaccio to test if the public types are correctly defined and getting resolved. (you can also try out this tool https://arethetypeswrong.github.io)


export type RequiredOptional<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>

export interface RazorpayQuery {
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets name this RazorpayPaginationOptions

count: number;
items: Settlements.RazorpayInstantSettlement[];
}>
fetchAllOndemandSettlement(params: RazorpayQuery | { 'expand[]': 'ondemand_payouts' }, callback: (err: INormalizeError | null, data: {
Copy link

Choose a reason for hiding this comment

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

question: ‏Why are these mutually exclusive? Isn't expand an optional parameter?

* @param params - Check [doc](https://razorpay.com/docs/api/settlements/instant#fetch-instant-settlement-by-id) for required params
*
*/
fetchOndemandSettlementById(settlementId: string, params: { 'expand[]': 'ondemand_payouts' }): Promise<Settlements.RazorpayInstantSettlement>;
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏Lets mark params and 'expand[]' optional

Copy link

@sidag95 sidag95 left a comment

Choose a reason for hiding this comment

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

Added a few comments

* These pairs can be useful for storing additional information about the entity.
* A maximum of 15 key-value pairs, each of 256 characters (maximum), are supported.
*/
notes?: IMap<string | number>;
Copy link

Choose a reason for hiding this comment

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

question: ‏Can we confirm if this is an object or an array of objects?

* @param params - Check [doc](https://razorpay.com/docs/api/payments/route/transfers/#reverse-a-transfer) for required params
*
*/
reverse(transferId: string, params?: { amount: number }): Promise<Transfers.RazorpayReversal>
Copy link

Choose a reason for hiding this comment

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

question: ‏Is params optional here?

* Fetch settlement details
*
*/
fetchSettlements(): Promise<{
Copy link

Choose a reason for hiding this comment

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

question: ‏We can't pass anything to this function?

};
}

interface RazorpayVirtualAccountReceiver {
Copy link

Choose a reason for hiding this comment

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

question: ‏Everything is optional?

}
}

declare function plans(api: any): {
Copy link

Choose a reason for hiding this comment

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

question:@ankitdas13 Payments has Plans types

@ankitdas13
Copy link
Contributor Author

ankitdas13 commented Feb 17, 2023

@sidag95 Updated changelog.md for new release. Could you please let me know if it is looking good according to what we made changes?

## 2.8.5 - 

feat(Typescript): Migrated the SDK to TypeScript for better type safety and improved development experience.
- Added TypeScript definitions for all modules and functions in the SDK.
- Added comments throughout the codebase to improve readability and maintainability.
- Added a type declarations file (*.d.ts) to provide better type checking and editor support for consumers of the SDK.
- Improved the build process to incorporate the TypeScript compiler and generate both CommonJS and ES module versions of the SDK.

Overall, this update should provide a better developer experience for anyone using the SDK, by leveraging the power of TypeScript's static type checking and providing clearer documentation and comments throughout the codebase.

CHANGELOG.md Outdated
- Added TypeScript definitions for all modules and functions in the SDK.
- Added comments throughout the codebase to improve readability and maintainability.
- Added a type declarations file (*.d.ts) to provide better type checking and editor support for consumers of the SDK.
- Improved the build process to incorporate the TypeScript compiler and generate both CommonJS and ES module versions of the SDK.

Choose a reason for hiding this comment

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

@sidag95 Are we also releasing ES modules? This is cool.

Copy link

Choose a reason for hiding this comment

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

No this is not supported. @ankitdas13 Lets remove ES module version. We are not realsing it in ES modules. Let's remove this line.

@@ -7,7 +7,8 @@
"scripts": {
"prepublish": "npm test",
"clean": "rm -rf dist && mkdir dist",
"cp-ts": "cp lib/razorpay.d.ts dist/",
"cp-types":"mkdir dist/types && cp lib/types/* dist/types && cp lib/utils/*d.ts dist/utils",
Copy link

Choose a reason for hiding this comment

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

question: ‏Can we generate a single ts file and ship that? Do we have to copy all the type files here? Is that the standard practice?

If you see https://github.com/razorpay/blade/blob/master/packages/blade/package.json#L37, there seems to be a single ts file for all the components.

Copy link

Choose a reason for hiding this comment

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

@anuraghazra Any comments on the above? Should we have a single type file or is shipping multiple files fine?

CHANGELOG.md Outdated
@@ -1,5 +1,15 @@
# Changelog

## 2.8.5 -

feat(Typescript): Migrated the SDK to TypeScript for better type safety and improved development experience.
Copy link

Choose a reason for hiding this comment

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

suggestion: ‏We haven't migrated to Typescript yet. I think this is a little misleading. Lets just say that we are releasing typescript definitions for our consumers to use.

CHANGELOG.md Outdated
@@ -1,5 +1,15 @@
# Changelog

## 2.8.5 - 2023-02-21

feat(Typescript):
Copy link

Choose a reason for hiding this comment

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

Suggested change
feat(Typescript):
feat(Typescript): add typescript definitions

CHANGELOG.md Outdated

feat(Typescript):

- Added TypeScript definitions for all modules and functions in the SDK.
Copy link

Choose a reason for hiding this comment

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

Suggested change
- Added TypeScript definitions for all modules and functions in the SDK.
- TypeScript definitions for all modules and functions in the SDK.

Copy link

@sidag95 sidag95 left a comment

Choose a reason for hiding this comment

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

LGTM

"promise": "^8.1.0",
"request": "^2.88.0",
"request-promise": "^4.2.6"
"request-promise": "^4.2.6",

Choose a reason for hiding this comment

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

Please note that this package is deprecated.

@ankitdas13 ankitdas13 merged commit db52ce1 into master Feb 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants