Refined some of the types and added needed support for webhooks and addons in the OAuthApp class
All checks were successful
Publish to Private NPM Registry / publish (push) Successful in 45s
All checks were successful
Publish to Private NPM Registry / publish (push) Successful in 45s
This commit is contained in:
parent
91f1630cc6
commit
01306bf3a3
6 changed files with 154 additions and 44 deletions
|
|
@ -11,41 +11,91 @@ import { getValueFromEnvironmentVariable } from '../utils/env-vars.js';
|
||||||
|
|
||||||
import type { BridgemanAccessibleAppClaims } from './types/BridgemanAccessibleAppClaims.js';
|
import type { BridgemanAccessibleAppClaims } from './types/BridgemanAccessibleAppClaims.js';
|
||||||
import type { AppSubscriptionTier } from './types/AppSubscriptionTier.js';
|
import type { AppSubscriptionTier } from './types/AppSubscriptionTier.js';
|
||||||
|
import type { Addon } from './types/addons/Addon.js';
|
||||||
|
import type { Webhook } from './types/Webhook.js';
|
||||||
|
|
||||||
type OAuthAppOptions = {
|
type OAuthAppOptions = {
|
||||||
|
// ------------------
|
||||||
|
// Basic app metadata
|
||||||
|
// ------------------
|
||||||
|
|
||||||
/** The base URL of the app */
|
/** The base URL of the app */
|
||||||
baseAppUrl?: URL,
|
baseAppUrl?: URL,
|
||||||
|
|
||||||
/** The abbreviation of the app */
|
/** The abbreviation of the app */
|
||||||
appAbbrv?: string,
|
appAbbrv?: string,
|
||||||
/** If a subscription is required */
|
|
||||||
subscriptionRequired?: boolean,
|
/** The (potentially localized) name of the app */
|
||||||
/** The subscription tiers available for the app */
|
|
||||||
subscriptionTiers?: AppSubscriptionTier[],
|
|
||||||
/** The name of the app */
|
|
||||||
appName?: string | {
|
appName?: string | {
|
||||||
/** Localized versions of the app name */
|
/** Localized versions of the app name */
|
||||||
[language: string]: string
|
[language: string]: string
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Necessary interconnected details (contacts, scopes, etc...)
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
|
||||||
/** The email addresses of the contacts for the app */
|
/** The email addresses of the contacts for the app */
|
||||||
contacts?: string[],
|
contacts?: string[],
|
||||||
/** The scopes an app token COULD ask for (token scopes would have to ask for this or a subset of this list) */
|
|
||||||
|
/** The "available" scopes (scopes an app token COULD ask for - token scopes would have to ask for this or a subset of this list) */
|
||||||
scopes?: Scopes[],
|
scopes?: Scopes[],
|
||||||
/** The URL of the app's logo */
|
|
||||||
logo_url?: URL,
|
// -----------------------------------------------------
|
||||||
/** The URL of the app's terms of service */
|
// Optional Mechanical Details (how the OAuth app works)
|
||||||
tos_url?: URL,
|
// -----------------------------------------------------
|
||||||
/** The URL of the app's privacy policy */
|
|
||||||
policy_url?: URL,
|
|
||||||
/** The type of vault to use for the keystore */
|
/** The type of vault to use for the keystore */
|
||||||
vault_type?: "azure" | "hashicorp" | "file",
|
vault_type?: "azure" | "hashicorp" | "file",
|
||||||
|
|
||||||
/** The default method for authentication */
|
/** The default method for authentication */
|
||||||
auth_default_method?: "query" | "form_post" | "PAR",
|
auth_default_method?: "query" | "form_post" | "PAR",
|
||||||
|
|
||||||
/** Whether to use JWT as the default authentication method */
|
/** Whether to use JWT as the default authentication method */
|
||||||
auth_default_use_JWT?: boolean,
|
auth_default_use_JWT?: boolean,
|
||||||
|
|
||||||
/** The default response mode for authentication */
|
/** The default response mode for authentication */
|
||||||
auth_default_response_mode?: 'query' | 'fragment' | 'form_post'
|
auth_default_response_mode?: 'query' | 'fragment' | 'form_post'
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// For already registered apps (to stop re-registration)
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
/** The client secret for the app (if this IS set registration WON'T be done. Because re-registering isn't supported) */
|
/** The client secret for the app (if this IS set registration WON'T be done. Because re-registering isn't supported) */
|
||||||
client_secret?: string
|
client_secret?: string
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// URL stuff (policies, logo, etc...)
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
/** The URL of the app's logo */
|
||||||
|
logo_url?: URL,
|
||||||
|
|
||||||
|
/** The URL of the app's Terms of Service */
|
||||||
|
tos_url?: URL,
|
||||||
|
|
||||||
|
/** The URL of the app's Privacy Policy */
|
||||||
|
policy_url?: URL,
|
||||||
|
|
||||||
|
// ------------------------------
|
||||||
|
// Webhooks (async notifications)
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
/** The webhooks supported by the app */
|
||||||
|
webhooks?: Webhook[],
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// Purchasable Stuff (Subscriptions + Addons)
|
||||||
|
// ------------------------------------------
|
||||||
|
|
||||||
|
/** If a subscription is required */
|
||||||
|
subscriptionRequired?: boolean,
|
||||||
|
|
||||||
|
/** The subscription tiers available for the app */
|
||||||
|
subscriptionTiers?: AppSubscriptionTier[],
|
||||||
|
|
||||||
|
/** Addons offered by the app */
|
||||||
|
addons?: Addon[],
|
||||||
};
|
};
|
||||||
|
|
||||||
export class OAuthApp extends App {
|
export class OAuthApp extends App {
|
||||||
|
|
@ -54,19 +104,21 @@ export class OAuthApp extends App {
|
||||||
|
|
||||||
private baseAppUrl?: URL;
|
private baseAppUrl?: URL;
|
||||||
private appAbbrv?: string;
|
private appAbbrv?: string;
|
||||||
private subscriptionRequired?: boolean;
|
|
||||||
private subscriptionTiers?: AppSubscriptionTier[];
|
|
||||||
private appName?: string | { [language: string]: string };
|
private appName?: string | { [language: string]: string };
|
||||||
private contacts?: string[];
|
private contacts?: string[];
|
||||||
private scopes?: Scopes[];
|
private scopes?: Scopes[];
|
||||||
private logo_url?: URL;
|
|
||||||
private tos_url?: URL;
|
|
||||||
private policy_url?: URL;
|
|
||||||
private vault_type?: "azure" | "hashicorp" | "file";
|
private vault_type?: "azure" | "hashicorp" | "file";
|
||||||
private auth_default_method?: "query" | "form_post" | "PAR";
|
private auth_default_method?: "query" | "form_post" | "PAR";
|
||||||
private auth_default_use_JWT?: boolean;
|
private auth_default_use_JWT?: boolean;
|
||||||
private auth_default_response_mode?: 'query' | 'fragment' | 'form_post';
|
private auth_default_response_mode?: 'query' | 'fragment' | 'form_post';
|
||||||
private client_secret?: string;
|
private client_secret?: string;
|
||||||
|
private logo_url?: URL;
|
||||||
|
private tos_url?: URL;
|
||||||
|
private policy_url?: URL;
|
||||||
|
private webhooks?: Webhook[];
|
||||||
|
private subscriptionRequired?: boolean;
|
||||||
|
private subscriptionTiers?: AppSubscriptionTier[];
|
||||||
|
private addons?: Addon[];
|
||||||
|
|
||||||
private client: Client;
|
private client: Client;
|
||||||
|
|
||||||
|
|
@ -86,12 +138,12 @@ export class OAuthApp extends App {
|
||||||
* | APP_ABBRV | Required if `options.appAbbrv` isn't provided | The abbreviation of the client (app) |
|
* | APP_ABBRV | Required if `options.appAbbrv` isn't provided | The abbreviation of the client (app) |
|
||||||
* | APP_NAME | Required if `options.appName` isn't provided | The name of the client (only a single non-localized name is supported) |
|
* | APP_NAME | Required if `options.appName` isn't provided | The name of the client (only a single non-localized name is supported) |
|
||||||
* | CONTACT_EMAIL | Required if `options.contacts` isn't provided | A comma-separated list of email addresses to list as contacts for the client |
|
* | CONTACT_EMAIL | Required if `options.contacts` isn't provided | A comma-separated list of email addresses to list as contacts for the client |
|
||||||
* | LOGO_URL | Optional (used if `options.logo_url` isn't specified) | The URL of the client's (app's) logo |
|
|
||||||
* | TOS_URL | Optional (used if `options.tos_url` isn't specified) | The URL of the client's terms of service |
|
|
||||||
* | POLICY_URL | Optional (used if `options.policy_url` isn't specified) | The URL of the client's privacy policy |
|
|
||||||
* | SCOPES | Required if `options.scopes` isn't provided | A comma-separated list of scopes available to the client |
|
* | SCOPES | Required if `options.scopes` isn't provided | A comma-separated list of scopes available to the client |
|
||||||
* | VAULT_TYPE | Required if in production (`NODE_ENV` is `production`) | The type of vault to use for the keystore (one of azure, hashicorp, or file) |
|
* | VAULT_TYPE | Required if in production (`NODE_ENV` is `production`) | The type of vault to use for the keystore (one of azure, hashicorp, or file) |
|
||||||
* | APP_SECRET | Optional (Determines if app should register or not) | The client secret for the app (if this IS set registration WON'T be done) |
|
* | APP_SECRET | Optional (Determines if app should register or not) | The client secret for the app (if this IS set registration WON'T be done) |
|
||||||
|
* | LOGO_URL | Optional (used if `options.logo_url` isn't specified) | The URL of the client's (app's) logo |
|
||||||
|
* | TOS_URL | Optional (used if `options.tos_url` isn't specified) | The URL of the client's terms of service |
|
||||||
|
* | POLICY_URL | Optional (used if `options.policy_url` isn't specified) | The URL of the client's privacy policy |
|
||||||
*
|
*
|
||||||
* @param onAuth The callback to call when a user logs in
|
* @param onAuth The callback to call when a user logs in
|
||||||
* @param saveSecret The callback to call to save the secret
|
* @param saveSecret The callback to call to save the secret
|
||||||
|
|
@ -101,16 +153,24 @@ export class OAuthApp extends App {
|
||||||
* @param options.appName The name of the app
|
* @param options.appName The name of the app
|
||||||
* @param options.contacts The email addresses of the contacts for the app
|
* @param options.contacts The email addresses of the contacts for the app
|
||||||
* @param options.scopes The scopes an app token COULD ask for (token scopes would have to ask for this or a subset of this list)
|
* @param options.scopes The scopes an app token COULD ask for (token scopes would have to ask for this or a subset of this list)
|
||||||
* @param options.logo_url The URL of the app's logo
|
|
||||||
* @param options.tos_url The URL of the app's terms of service
|
|
||||||
* @param options.policy_url The URL of the app's privacy policy
|
|
||||||
* @param options.vault_type The type of vault to use for the keystore
|
* @param options.vault_type The type of vault to use for the keystore
|
||||||
* @param options.auth_default_method The default method for authentication
|
* @param options.auth_default_method The default method for authentication
|
||||||
* @param options.auth_default_use_JWT Whether to use JWT as the default authentication method
|
* @param options.auth_default_use_JWT Whether to use JWT as the default authentication method
|
||||||
* @param options.auth_default_response_mode The default response mode for authentication
|
* @param options.auth_default_response_mode The default response mode for authentication
|
||||||
* @param options.client_secret The client secret for the app (if this IS set registration WON'T be done. Because re-registering isn't supported)
|
* @param options.client_secret The client secret for the app (if this IS set registration WON'T be done. Because re-registering isn't supported)
|
||||||
|
* @param options.logo_url The URL of the app's logo
|
||||||
|
* @param options.tos_url The URL of the app's terms of service
|
||||||
|
* @param options.policy_url The URL of the app's privacy policy
|
||||||
|
* @param options.webhooks The webhooks supported by the app
|
||||||
|
* @param options.subscriptionRequired If a subscription is required
|
||||||
|
* @param options.subscriptionTiers The subscription tiers available for the app
|
||||||
|
* @param options.addons Addons offered by the app
|
||||||
*/
|
*/
|
||||||
constructor(onAuth: OnAuthCallback, saveSecret: (secret: string) => void | Promise<void>, options?: OAuthAppOptions) {
|
constructor(
|
||||||
|
onAuth: OnAuthCallback,
|
||||||
|
saveSecret: (secret: string) => void | Promise<void>,
|
||||||
|
options?: OAuthAppOptions
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.onAuth = onAuth;
|
this.onAuth = onAuth;
|
||||||
this.saveSecret = saveSecret;
|
this.saveSecret = saveSecret;
|
||||||
|
|
@ -118,19 +178,21 @@ export class OAuthApp extends App {
|
||||||
if(typeof options !== 'undefined') {
|
if(typeof options !== 'undefined') {
|
||||||
this.baseAppUrl = options.baseAppUrl;
|
this.baseAppUrl = options.baseAppUrl;
|
||||||
this.appAbbrv = options.appAbbrv;
|
this.appAbbrv = options.appAbbrv;
|
||||||
this.subscriptionRequired = options.subscriptionRequired;
|
|
||||||
this.subscriptionTiers = options.subscriptionTiers;
|
|
||||||
this.appName = options.appName;
|
this.appName = options.appName;
|
||||||
this.contacts = options.contacts;
|
this.contacts = options.contacts;
|
||||||
this.scopes = options.scopes;
|
this.scopes = options.scopes;
|
||||||
this.logo_url = options.logo_url;
|
|
||||||
this.tos_url = options.tos_url;
|
|
||||||
this.policy_url = options.policy_url;
|
|
||||||
this.vault_type = options.vault_type;
|
this.vault_type = options.vault_type;
|
||||||
this.auth_default_method = options.auth_default_method;
|
this.auth_default_method = options.auth_default_method;
|
||||||
this.auth_default_use_JWT = options.auth_default_use_JWT;
|
this.auth_default_use_JWT = options.auth_default_use_JWT;
|
||||||
this.auth_default_response_mode = options.auth_default_response_mode;
|
this.auth_default_response_mode = options.auth_default_response_mode;
|
||||||
this.client_secret = options.client_secret;
|
this.client_secret = options.client_secret;
|
||||||
|
this.logo_url = options.logo_url;
|
||||||
|
this.tos_url = options.tos_url;
|
||||||
|
this.policy_url = options.policy_url;
|
||||||
|
this.webhooks = options.webhooks;
|
||||||
|
this.subscriptionRequired = options.subscriptionRequired;
|
||||||
|
this.subscriptionTiers = options.subscriptionTiers;
|
||||||
|
this.addons = options.addons;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,7 +237,9 @@ export class OAuthApp extends App {
|
||||||
{
|
{
|
||||||
client_abbreviation: appAbbrv,
|
client_abbreviation: appAbbrv,
|
||||||
subscription_required: this.subscriptionRequired ?? false,
|
subscription_required: this.subscriptionRequired ?? false,
|
||||||
subscription_tiers: this.subscriptionTiers
|
subscription_tiers: this.subscriptionTiers,
|
||||||
|
addons: this.addons,
|
||||||
|
webhooks: this.webhooks
|
||||||
},
|
},
|
||||||
this.appName,
|
this.appName,
|
||||||
this.scopes,
|
this.scopes,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import type { Webhook } from './types/Webhook.js';
|
||||||
import { WebhookPurpose } from './types/WebhookPurpose.js';
|
import { WebhookPurpose } from './types/WebhookPurpose.js';
|
||||||
import type { Addon } from './types/addons/Addon.js';
|
import type { Addon } from './types/addons/Addon.js';
|
||||||
import { AddonType } from './types/addons/AddonType.js';
|
import { AddonType } from './types/addons/AddonType.js';
|
||||||
import { BillingCadence as AddonBillingCadence } from './types/addons/BillingCadence.js';
|
import { BillingCadence as AddonBillingCadence } from './types/BillingCadence.js';
|
||||||
import type { Schema as AddonSchema } from './types/addons/Schema.js';
|
import type { Schema as AddonSchema } from './types/addons/Schema.js';
|
||||||
import type { PricingStrategy } from './types/addons/PricingStrategy.js';
|
import type { PricingStrategy } from './types/addons/PricingStrategy.js';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,44 @@
|
||||||
/** App subscription tier (mostly for app registration) */
|
import { BillingCadence } from './BillingCadence.js';
|
||||||
|
|
||||||
|
/** App subscription tier */
|
||||||
export interface AppSubscriptionTier {
|
export interface AppSubscriptionTier {
|
||||||
id: string;
|
/**
|
||||||
name: string; // e.g., "Free", "Pro"
|
* A unique identifier for the subscription tier.
|
||||||
cost: number; // e.g., 1000 (cents)
|
* This is only necessary if two tiers have the same name for some reason.
|
||||||
currency: string; // e.g., "USD"
|
*/
|
||||||
description?: string;
|
id?: string;
|
||||||
features?: {
|
|
||||||
|
/** The (potentially localized) name of the subscription tier */
|
||||||
|
name: string | { [locale: string]: string };
|
||||||
|
|
||||||
|
pricing: {
|
||||||
|
/**
|
||||||
|
* The cost of the subscription tier (in cents).
|
||||||
|
* Can have multiple prices for different billing frequencies (e.g., monthly, yearly).
|
||||||
|
*/
|
||||||
|
value: number | { [frequency in BillingCadence]?: number };
|
||||||
|
|
||||||
|
/** The currency of the subscription tier */
|
||||||
|
currency: 'CAD' | 'USD' | 'EUR' | 'GBP' | 'AUD';
|
||||||
|
|
||||||
|
/** If value is a singular number a billing cadence can be set this way */
|
||||||
|
billingCadence?: BillingCadence;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A (potentially localized) description of the subscription tier */
|
||||||
|
description?: string | { [locale: string]: string };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Features included in the subscription tier.
|
||||||
|
*
|
||||||
|
* This can be a list of feature names (ex. ["prioritySupport", "customBranding"])
|
||||||
|
* Or a mapping of feature names to booleans indicating inclusion (ex. { "prioritySupport": true, "customBranding": false })
|
||||||
|
*
|
||||||
|
* The difference is in their presentation to the user.
|
||||||
|
* - As a list each tier just has it's list below it.
|
||||||
|
* - As a mapping, all features are listed in a comparison table format (where all included features are shown with checkmarks and crosses to indicate exclusion).
|
||||||
|
*/
|
||||||
|
features?: string[] | {
|
||||||
[featureName: string]: boolean; // e.g., { "prioritySupport": true, "customBranding": false }
|
[featureName: string]: boolean; // e.g., { "prioritySupport": true, "customBranding": false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { AddonType } from './AddonType.js';
|
import { AddonType } from './AddonType.js';
|
||||||
import { BillingCadence } from './BillingCadence.js';
|
import { BillingCadence } from '../BillingCadence.js';
|
||||||
import { Schema } from './Schema.js';
|
import { Schema } from './Schema.js';
|
||||||
import { PricingStrategy } from './PricingStrategy.js';
|
import { PricingStrategy } from './PricingStrategy.js';
|
||||||
|
|
||||||
|
|
@ -43,7 +43,12 @@ export type Addon = {
|
||||||
// Subscription Specific Fields
|
// Subscription Specific Fields
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|
||||||
billingCadence: BillingCadence;
|
/**
|
||||||
|
* Billing cadence for subscription addons.
|
||||||
|
* Note, if the pricing strategy has a `unit_amount` with multiple billing cadences,
|
||||||
|
* this field can be omitted / is ignored to allow the purchaser to select at buy time.
|
||||||
|
*/
|
||||||
|
billingCadence?: BillingCadence;
|
||||||
} | {
|
} | {
|
||||||
/** Type of addon/purchase */
|
/** Type of addon/purchase */
|
||||||
type: AddonType.ONE_TIME;
|
type: AddonType.ONE_TIME;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { BillingCadence } from '../BillingCadence.js';
|
||||||
|
|
||||||
/** The strategy/mechanism used to calculate the cost of a purchase of an addon at buy time */
|
/** The strategy/mechanism used to calculate the cost of a purchase of an addon at buy time */
|
||||||
export type PricingStrategy = {
|
export type PricingStrategy = {
|
||||||
/** The currency in which the pricing is specified */
|
/** The currency in which the pricing is specified */
|
||||||
|
|
@ -18,8 +20,14 @@ export type PricingStrategy = {
|
||||||
*/
|
*/
|
||||||
type: 'per_unit',
|
type: 'per_unit',
|
||||||
|
|
||||||
/** Per Unit Price (in cents) */
|
/**
|
||||||
unit_amount: number,
|
* Per Unit Price (in cents)
|
||||||
|
*
|
||||||
|
* Can be:
|
||||||
|
* - A single number (applies to all billing cadences)
|
||||||
|
* - Or an object specifying different amounts per billing cadence
|
||||||
|
*/
|
||||||
|
unit_amount: number | { [frequency in BillingCadence]?: number },
|
||||||
|
|
||||||
/** Parameter to use for unit calculation */
|
/** Parameter to use for unit calculation */
|
||||||
unit_parameter: string
|
unit_parameter: string
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue