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

This commit is contained in:
Alan Bridgeman 2026-01-29 10:56:44 -06:00
parent 91f1630cc6
commit 01306bf3a3
6 changed files with 154 additions and 44 deletions

View file

@ -11,41 +11,91 @@ import { getValueFromEnvironmentVariable } from '../utils/env-vars.js';
import type { BridgemanAccessibleAppClaims } from './types/BridgemanAccessibleAppClaims.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 = {
// ------------------
// Basic app metadata
// ------------------
/** The base URL of the app */
baseAppUrl?: URL,
/** The abbreviation of the app */
appAbbrv?: string,
/** If a subscription is required */
subscriptionRequired?: boolean,
/** The subscription tiers available for the app */
subscriptionTiers?: AppSubscriptionTier[],
/** The name of the app */
/** The (potentially localized) name of the app */
appName?: string | {
/** Localized versions of the app name */
[language: string]: string
},
// -----------------------------------------------------------
// Necessary interconnected details (contacts, scopes, etc...)
// -----------------------------------------------------------
/** The email addresses of the contacts for the app */
contacts?: string[],
/** The scopes an app token COULD ask for (token scopes would have to ask for this or a subset of this list) */
scopes?: Scopes[],
/** 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,
contacts?: string[],
/** 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[],
// -----------------------------------------------------
// Optional Mechanical Details (how the OAuth app works)
// -----------------------------------------------------
/** The type of vault to use for the keystore */
vault_type?: "azure" | "hashicorp" | "file",
/** The default method for authentication */
auth_default_method?: "query" | "form_post" | "PAR",
/** Whether to use JWT as the default authentication method */
auth_default_use_JWT?: boolean,
/** The default response mode for authentication */
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) */
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 {
@ -54,19 +104,21 @@ export class OAuthApp extends App {
private baseAppUrl?: URL;
private appAbbrv?: string;
private subscriptionRequired?: boolean;
private subscriptionTiers?: AppSubscriptionTier[];
private appName?: string | { [language: string]: string };
private contacts?: string[];
private scopes?: Scopes[];
private logo_url?: URL;
private tos_url?: URL;
private policy_url?: URL;
private vault_type?: "azure" | "hashicorp" | "file";
private auth_default_method?: "query" | "form_post" | "PAR";
private auth_default_use_JWT?: boolean;
private auth_default_response_mode?: 'query' | 'fragment' | 'form_post';
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;
@ -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_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 |
* | 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 |
* | 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) |
* | 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 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.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.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.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_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.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();
this.onAuth = onAuth;
this.saveSecret = saveSecret;
@ -118,19 +178,21 @@ export class OAuthApp extends App {
if(typeof options !== 'undefined') {
this.baseAppUrl = options.baseAppUrl;
this.appAbbrv = options.appAbbrv;
this.subscriptionRequired = options.subscriptionRequired;
this.subscriptionTiers = options.subscriptionTiers;
this.appName = options.appName;
this.contacts = options.contacts;
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.auth_default_method = options.auth_default_method;
this.auth_default_use_JWT = options.auth_default_use_JWT;
this.auth_default_response_mode = options.auth_default_response_mode;
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,
subscription_required: this.subscriptionRequired ?? false,
subscription_tiers: this.subscriptionTiers
subscription_tiers: this.subscriptionTiers,
addons: this.addons,
webhooks: this.webhooks
},
this.appName,
this.scopes,