Glench / ExtPay

The JavaScript library for ExtensionPay.com — payments for your browser extensions, no server needed.
https://extensionpay.com
Other
507 stars 64 forks source link

Add Typescript declarations #24

Closed geoffreylitt closed 2 years ago

geoffreylitt commented 2 years ago

I'm using ExtPay from Typescript and found it quite helpful to add type declarations for the library. I've pasted my type declarations below if you want to publish them directly with the library.

declare module "extpay" {
  interface User {
    /** user.paid is meant to be a simple way to tell if the user should have paid features activated.
     * For subscription payments, paid is only true if subscriptionStatus is active. */
    paid: boolean

    /** date that the user first paid or null. */
    paidAt: Date | null

    /** date the user installed the extension. */
    installedAt: Date

    /** date the user confirmed their free trial. */
    trialStartedAt: Date | null

    /** active means the user's subscription is paid-for.
     * past_due means the user's most recent subscription payment has failed (expired card, insufficient funds, etc).
     * canceled means that the user has canceled their subscription and the end of their last paid period has passed. */
    subscriptionStatus?: "active" | "past_due" | "canceled"

    /** date that the user's subscription is set to cancel or did cancel at. */
    subscriptionCancelAt?: Date | null
  }

  interface ExtPay {
    getUser: () => Promise<User>
    onPaid: {
      addListener: (cb: (user: User) => void) => void
    }
    openPaymentPage: () => Promise<void>
    openTrialPage: () => Promise<void>
    onTrialStarted: {
      addListener: (cb: (user: User) => void) => void
    }
    startBackground: () => void
  }

  export default function ExtPay(extensionId: string): ExtPay
}
burkybang commented 2 years ago

Thanks for sharing. Here are the types I wrote for myself.

interface ExtPay {
  onPaid: ExtPay.OnPaid;
  onTrialStarted: ExtPay.OnTrialStarted;

  getUser(): Promise<ExtPay.User>;

  openPaymentPage(): Promise<void>;

  openTrialPage(displayText?: string): Promise<void>;

  startBackground(): void;
}

declare namespace ExtPay {

  type SubscriptionStatus = 'active' | 'past_due' | 'canceled';

  interface User {
    paid: boolean;
    paidAt: null | Date;
    installedAt: string;
    trialStartedAt: null | Date;
    subscriptionStatus?: SubscriptionStatus;
    subscriptionCancelAt?: null | Date;
  }

  interface OnPaid {
    addListener(callback: (user: User) => void): void;
  }

  interface OnTrialStarted {
    addListener(callback: () => void): void;
  }

}

declare function ExtPay(extension_id: string): ExtPay
Glench commented 2 years ago

Guys, this is awesome, thank you for your contributions!

Can either of you tell me how I would test these or point me toward a resource? I'm pretty new to TypeScript

geoffreylitt commented 2 years ago

I've never published an npm library with types, but I think these instructions cover how to do it:

https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#including-declarations-in-your-npm-package

At a quick glance I don't see any major differences between my definitions and @burkybang but maybe I am missing some reasons why the other approach is better. I think it's nice to have the comments above the fields because that helps provide useful autocomplete documentation in the editor.

For testing, I would start a typescript project; install the library with these type declarations added; and then see if you get autocompletions / type errors. You can also test out the type declarations without modifying the library itself.

burkybang commented 2 years ago

I'm not sure myself. I've got some repos with type declarations listed on my GitHub. I normally just share them that way.

@geoffreylitt I agree, I think we are just writing the same thing in different ways. Your comments are absolutely helpful, and I would definitely include them if @Glench is wanting to add type declarations to his repo. I don't have comments because I made it for my own use.

Actually, I'm not even using those anymore since I decided to completely rewrite ExtPay.js in TypeScirpt.

Glench commented 2 years ago

Actually, I'm not even using those anymore since I decided to completely rewrite ExtPay.js in TypeScirpt.

Cool! Want to share it in a new discussion?

So getting the types file into package.json is easy, but I'm having some trouble figuring out how to actually test out that TypeScript is picking it up.

Right now I just have a test file that consists of

import ExtPay from './'

When I run this with tsc on that file it complains: File 'types.d.ts' is not a module.. I have no idea what that means since clearly it's a module that I copied and pasted from @geoffreylitt's example. Any ideas? I'll keep researching in the meantime.

Glench commented 2 years ago

Ok whatever, I just yolo'd and tested it out after publishing to npm and it works fine. 3993ed429b34085b3c812da9572e650f5a303ce9 Thank you both for your input and @burkybang I'd love to see your copy of ExtPay.ts!

burkybang commented 2 years ago

@Glench It's too difficult to show without showing a ton of unrelated code.