watcha-feature/make-nextcloud-documents-integration-a-local-widget
			
			
		
		
							parent
							
								
									3ea0571c5f
								
							
						
					
					
						commit
						c5ea253181
					
				@ -1,748 +0,0 @@ | 
				
			||||
// A clone of the type definitions from posthog-js, stripped of references to transitive
 | 
				
			||||
// dependencies which we don't actually use, so that we don't need to install them.
 | 
				
			||||
//
 | 
				
			||||
// Original file lives in node_modules/posthog/dist/module.d.ts
 | 
				
			||||
 | 
				
			||||
/* eslint-disable @typescript-eslint/member-delimiter-style */ | 
				
			||||
/* eslint-disable @typescript-eslint/naming-convention */ | 
				
			||||
/* eslint-disable camelcase */ | 
				
			||||
 | 
				
			||||
// Type definitions for exported methods
 | 
				
			||||
 | 
				
			||||
declare class posthog { | 
				
			||||
    /** | 
				
			||||
     * This function initializes a new instance of the PostHog capturing object. | 
				
			||||
     * All new instances are added to the main posthog object as sub properties (such as | 
				
			||||
     * posthog.library_name) and also returned by this function. To define a | 
				
			||||
     * second instance on the page, you would call: | 
				
			||||
     * | 
				
			||||
     *     posthog.init('new token', { your: 'config' }, 'library_name'); | 
				
			||||
     * | 
				
			||||
     * and use it like so: | 
				
			||||
     * | 
				
			||||
     *     posthog.library_name.capture(...); | 
				
			||||
     * | 
				
			||||
     * @param {String} token   Your PostHog API token | 
				
			||||
     * @param {Object} [config]  A dictionary of config options to override. <a href="https://github.com/posthog/posthog-js/blob/6e0e873/src/posthog-core.js#L57-L91">See a list of default config options</a>. | 
				
			||||
     * @param {String} [name]    The name for the new posthog instance that you want created | 
				
			||||
     */ | 
				
			||||
    static init(token: string, config?: posthog.Config, name?: string): posthog | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Clears super properties and generates a new random distinct_id for this instance. | 
				
			||||
     * Useful for clearing data when a user logs out. | 
				
			||||
     */ | 
				
			||||
    static reset(reset_device_id?: boolean): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Capture an event. This is the most important and | 
				
			||||
     * frequently used PostHog function. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     // capture an event named 'Registered'
 | 
				
			||||
     *     posthog.capture('Registered', {'Gender': 'Male', 'Age': 21}); | 
				
			||||
     * | 
				
			||||
     *     // capture an event using navigator.sendBeacon
 | 
				
			||||
     *     posthog.capture('Left page', {'duration_seconds': 35}, {transport: 'sendBeacon'}); | 
				
			||||
     * | 
				
			||||
     * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc. | 
				
			||||
     * @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself. | 
				
			||||
     * @param {Object} [options] Optional configuration for this capture request. | 
				
			||||
     * @param {String} [options.transport] Transport method for network request ('XHR' or 'sendBeacon'). | 
				
			||||
     */ | 
				
			||||
    static capture( | 
				
			||||
        event_name: string, | 
				
			||||
        properties?: posthog.Properties, | 
				
			||||
        options?: { transport: 'XHR' | 'sendBeacon' } | 
				
			||||
    ): posthog.CaptureResult | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Capture a page view event, which is currently ignored by the server. | 
				
			||||
     * This function is called by default on page load unless the | 
				
			||||
     * capture_pageview configuration variable is false. | 
				
			||||
     * | 
				
			||||
     * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url. | 
				
			||||
     * @api private | 
				
			||||
     */ | 
				
			||||
    static capture_pageview(page?: string): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Register a set of super properties, which are included with all | 
				
			||||
     * events. This will overwrite previous super property values. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     // register 'Gender' as a super property
 | 
				
			||||
     *     posthog.register({'Gender': 'Female'}); | 
				
			||||
     * | 
				
			||||
     *     // register several super properties when a user signs up
 | 
				
			||||
     *     posthog.register({ | 
				
			||||
     *         'Email': 'jdoe@example.com', | 
				
			||||
     *         'Account Type': 'Free' | 
				
			||||
     *     }); | 
				
			||||
     * | 
				
			||||
     * @param {Object} properties An associative array of properties to store about the user | 
				
			||||
     * @param {Number} [days] How many days since the user's last visit to store the super properties | 
				
			||||
     */ | 
				
			||||
    static register(properties: posthog.Properties, days?: number): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Register a set of super properties only once. This will not | 
				
			||||
     * overwrite previous super property values, unlike register(). | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     // register a super property for the first time only
 | 
				
			||||
     *     posthog.register_once({ | 
				
			||||
     *         'First Login Date': new Date().toISOString() | 
				
			||||
     *     }); | 
				
			||||
     * | 
				
			||||
     * ### Notes: | 
				
			||||
     * | 
				
			||||
     * If default_value is specified, current super properties | 
				
			||||
     * with that value will be overwritten. | 
				
			||||
     * | 
				
			||||
     * @param {Object} properties An associative array of properties to store about the user | 
				
			||||
     * @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None' | 
				
			||||
     * @param {Number} [days] How many days since the users last visit to store the super properties | 
				
			||||
     */ | 
				
			||||
    static register_once(properties: posthog.Properties, default_value?: posthog.Property, days?: number): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Delete a super property stored with the current user. | 
				
			||||
     * | 
				
			||||
     * @param {String} property The name of the super property to remove | 
				
			||||
     */ | 
				
			||||
    static unregister(property: string): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Identify a user with a unique ID instead of a PostHog | 
				
			||||
     * randomly generated distinct_id. If the method is never called, | 
				
			||||
     * then unique visitors will be identified by a UUID generated | 
				
			||||
     * the first time they visit the site. | 
				
			||||
     * | 
				
			||||
     * If user properties are passed, they are also sent to posthog. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *      posthog.identify('[user unique id]') | 
				
			||||
     *      posthog.identify('[user unique id]', { email: 'john@example.com' }) | 
				
			||||
     *      posthog.identify('[user unique id]', {}, { referral_code: '12345' }) | 
				
			||||
     * | 
				
			||||
     * ### Notes: | 
				
			||||
     * | 
				
			||||
     * You can call this function to overwrite a previously set | 
				
			||||
     * unique ID for the current user. PostHog cannot translate | 
				
			||||
     * between IDs at this time, so when you change a user's ID | 
				
			||||
     * they will appear to be a new user. | 
				
			||||
     * | 
				
			||||
     * When used alone, posthog.identify will change the user's | 
				
			||||
     * distinct_id to the unique ID provided. When used in tandem | 
				
			||||
     * with posthog.alias, it will allow you to identify based on | 
				
			||||
     * unique ID and map that back to the original, anonymous | 
				
			||||
     * distinct_id given to the user upon her first arrival to your | 
				
			||||
     * site (thus connecting anonymous pre-signup activity to | 
				
			||||
     * post-signup activity). Though the two work together, do not | 
				
			||||
     * call identify() at the same time as alias(). Calling the two | 
				
			||||
     * at the same time can cause a race condition, so it is best | 
				
			||||
     * practice to call identify on the original, anonymous ID | 
				
			||||
     * right after you've aliased it. | 
				
			||||
     * | 
				
			||||
     * @param {String} [unique_id] A string that uniquely identifies a user. If not provided, the distinct_id currently in the persistent store (cookie or localStorage) will be used. | 
				
			||||
     * @param {Object} [userProperties] Optional: An associative array of properties to store about the user | 
				
			||||
     * @param {Object} [userPropertiesToSetOnce] Optional: An associative array of properties to store about the user. If property is previously set, this does not override that value. | 
				
			||||
     */ | 
				
			||||
    static identify( | 
				
			||||
        unique_id?: string, | 
				
			||||
        userPropertiesToSet?: posthog.Properties, | 
				
			||||
        userPropertiesToSetOnce?: posthog.Properties | 
				
			||||
    ): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Create an alias, which PostHog will use to link two distinct_ids going forward (not retroactively). | 
				
			||||
     * Multiple aliases can map to the same original ID, but not vice-versa. Aliases can also be chained - the | 
				
			||||
     * following is a valid scenario: | 
				
			||||
     * | 
				
			||||
     *     posthog.alias('new_id', 'existing_id'); | 
				
			||||
     *     ... | 
				
			||||
     *     posthog.alias('newer_id', 'new_id'); | 
				
			||||
     * | 
				
			||||
     * If the original ID is not passed in, we will use the current distinct_id - probably the auto-generated GUID. | 
				
			||||
     * | 
				
			||||
     * ### Notes: | 
				
			||||
     * | 
				
			||||
     * The best practice is to call alias() when a unique ID is first created for a user | 
				
			||||
     * (e.g., when a user first registers for an account and provides an email address). | 
				
			||||
     * alias() should never be called more than once for a given user, except to | 
				
			||||
     * chain a newer ID to a previously new ID, as described above. | 
				
			||||
     * | 
				
			||||
     * @param {String} alias A unique identifier that you want to use for this user in the future. | 
				
			||||
     * @param {String} [original] The current identifier being used for this user. | 
				
			||||
     */ | 
				
			||||
    static alias(alias: string, original?: string): posthog.CaptureResult | number | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Update the configuration of a posthog library instance. | 
				
			||||
     * | 
				
			||||
     * The default config is: | 
				
			||||
     * | 
				
			||||
     *     { | 
				
			||||
     *       // HTTP method for capturing requests
 | 
				
			||||
     *       api_method: 'POST' | 
				
			||||
     * | 
				
			||||
     *       // transport for sending requests ('XHR' or 'sendBeacon')
 | 
				
			||||
     *       // NB: sendBeacon should only be used for scenarios such as
 | 
				
			||||
     *       // page unload where a "best-effort" attempt to send is
 | 
				
			||||
     *       // acceptable; the sendBeacon API does not support callbacks
 | 
				
			||||
     *       // or any way to know the result of the request. PostHog
 | 
				
			||||
     *       // capturing via sendBeacon will not support any event-
 | 
				
			||||
     *       // batching or retry mechanisms.
 | 
				
			||||
     *       api_transport: 'XHR' | 
				
			||||
     * | 
				
			||||
     *       // Automatically capture clicks, form submissions and change events
 | 
				
			||||
     *       autocapture: true | 
				
			||||
     * | 
				
			||||
     *       // Capture rage clicks (beta) - useful for session recording
 | 
				
			||||
     *       rageclick: false | 
				
			||||
     * | 
				
			||||
     *       // super properties cookie expiration (in days)
 | 
				
			||||
     *       cookie_expiration: 365 | 
				
			||||
     * | 
				
			||||
     *       // super properties span subdomains
 | 
				
			||||
     *       cross_subdomain_cookie: true | 
				
			||||
     * | 
				
			||||
     *       // debug mode
 | 
				
			||||
     *       debug: false | 
				
			||||
     * | 
				
			||||
     *       // if this is true, the posthog cookie or localStorage entry
 | 
				
			||||
     *       // will be deleted, and no user persistence will take place
 | 
				
			||||
     *       disable_persistence: false | 
				
			||||
     * | 
				
			||||
     *       // if this is true, PostHog will automatically determine
 | 
				
			||||
     *       // City, Region and Country data using the IP address of
 | 
				
			||||
     *       //the client
 | 
				
			||||
     *       ip: true | 
				
			||||
     * | 
				
			||||
     *       // opt users out of capturing by this PostHog instance by default
 | 
				
			||||
     *       opt_out_capturing_by_default: false | 
				
			||||
     * | 
				
			||||
     *       // opt users out of browser data storage by this PostHog instance by default
 | 
				
			||||
     *       opt_out_persistence_by_default: false | 
				
			||||
     * | 
				
			||||
     *       // persistence mechanism used by opt-in/opt-out methods - cookie
 | 
				
			||||
     *       // or localStorage - falls back to cookie if localStorage is unavailable
 | 
				
			||||
     *       opt_out_capturing_persistence_type: 'localStorage' | 
				
			||||
     * | 
				
			||||
     *       // customize the name of cookie/localStorage set by opt-in/opt-out methods
 | 
				
			||||
     *       opt_out_capturing_cookie_prefix: null | 
				
			||||
     * | 
				
			||||
     *       // type of persistent store for super properties (cookie/
 | 
				
			||||
     *       // localStorage) if set to 'localStorage', any existing
 | 
				
			||||
     *       // posthog cookie value with the same persistence_name
 | 
				
			||||
     *       // will be transferred to localStorage and deleted
 | 
				
			||||
     *       persistence: 'cookie' | 
				
			||||
     * | 
				
			||||
     *       // name for super properties persistent store
 | 
				
			||||
     *       persistence_name: '' | 
				
			||||
     * | 
				
			||||
     *       // names of properties/superproperties which should never
 | 
				
			||||
     *       // be sent with capture() calls
 | 
				
			||||
     *       property_blacklist: [] | 
				
			||||
     * | 
				
			||||
     *       // if this is true, posthog cookies will be marked as
 | 
				
			||||
     *       // secure, meaning they will only be transmitted over https
 | 
				
			||||
     *       secure_cookie: false | 
				
			||||
     * | 
				
			||||
     *       // should we capture a page view on page load
 | 
				
			||||
     *       capture_pageview: true | 
				
			||||
     * | 
				
			||||
     *       // if you set upgrade to be true, the library will check for
 | 
				
			||||
     *       // a cookie from our old js library and import super
 | 
				
			||||
     *       // properties from it, then the old cookie is deleted
 | 
				
			||||
     *       // The upgrade config option only works in the initialization,
 | 
				
			||||
     *       // so make sure you set it when you create the library.
 | 
				
			||||
     *       upgrade: false | 
				
			||||
     * | 
				
			||||
     *       // extra HTTP request headers to set for each API request, in
 | 
				
			||||
     *       // the format {'Header-Name': value}
 | 
				
			||||
     *       xhr_headers: {} | 
				
			||||
     * | 
				
			||||
     *       // protocol for fetching in-app message resources, e.g.
 | 
				
			||||
     *       // 'https://' or 'http://'; defaults to '//' (which defers to the
 | 
				
			||||
     *       // current page's protocol)
 | 
				
			||||
     *       inapp_protocol: '//' | 
				
			||||
     * | 
				
			||||
     *       // whether to open in-app message link in new tab/window
 | 
				
			||||
     *       inapp_link_new_window: false | 
				
			||||
     * | 
				
			||||
     *      // a set of rrweb config options that PostHog users can configure
 | 
				
			||||
     *      // see https://github.com/rrweb-io/rrweb/blob/master/guide.md
 | 
				
			||||
     *      session_recording: { | 
				
			||||
     *         blockClass: 'ph-no-capture', | 
				
			||||
     *         blockSelector: null, | 
				
			||||
     *         ignoreClass: 'ph-ignore-input', | 
				
			||||
     *         maskAllInputs: false, | 
				
			||||
     *         maskInputOptions: {}, | 
				
			||||
     *         maskInputFn: null, | 
				
			||||
     *         slimDOMOptions: {}, | 
				
			||||
     *         collectFonts: false | 
				
			||||
     *      } | 
				
			||||
     * | 
				
			||||
     *      // prevent autocapture from capturing any attribute names on elements
 | 
				
			||||
     *      mask_all_element_attributes: false | 
				
			||||
     * | 
				
			||||
     *      // prevent autocapture from capturing textContent on all elements
 | 
				
			||||
     *      mask_all_text: false | 
				
			||||
     * | 
				
			||||
     *      // will disable requests to the /decide endpoint (please review documentation for details)
 | 
				
			||||
     *      // autocapture, feature flags, compression and session recording will be disabled when set to `true`
 | 
				
			||||
     *      advanced_disable_decide: false | 
				
			||||
     * | 
				
			||||
     *     } | 
				
			||||
     * | 
				
			||||
     * | 
				
			||||
     * @param {Object} config A dictionary of new configuration values to update | 
				
			||||
     */ | 
				
			||||
    static set_config(config: posthog.Config): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * returns the current config object for the library. | 
				
			||||
     */ | 
				
			||||
    static get_config<T extends keyof posthog.Config>(prop_name: T): posthog.Config[T] | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Returns the value of the super property named property_name. If no such | 
				
			||||
     * property is set, get_property() will return the undefined value. | 
				
			||||
     * | 
				
			||||
     * ### Notes: | 
				
			||||
     * | 
				
			||||
     * get_property() can only be called after the PostHog library has finished loading. | 
				
			||||
     * init() has a loaded function available to handle this automatically. For example: | 
				
			||||
     * | 
				
			||||
     *     // grab value for 'user_id' after the posthog library has loaded
 | 
				
			||||
     *     posthog.init('YOUR PROJECT TOKEN', { | 
				
			||||
     *         loaded: function(posthog) { | 
				
			||||
     *             user_id = posthog.get_property('user_id'); | 
				
			||||
     *         } | 
				
			||||
     *     }); | 
				
			||||
     * | 
				
			||||
     * @param {String} property_name The name of the super property you want to retrieve | 
				
			||||
     */ | 
				
			||||
    static get_property(property_name: string): posthog.Property | undefined | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Returns the current distinct id of the user. This is either the id automatically | 
				
			||||
     * generated by the library or the id that has been passed by a call to identify(). | 
				
			||||
     * | 
				
			||||
     * ### Notes: | 
				
			||||
     * | 
				
			||||
     * get_distinct_id() can only be called after the PostHog library has finished loading. | 
				
			||||
     * init() has a loaded function available to handle this automatically. For example: | 
				
			||||
     * | 
				
			||||
     *     // set distinct_id after the posthog library has loaded
 | 
				
			||||
     *     posthog.init('YOUR PROJECT TOKEN', { | 
				
			||||
     *         loaded: function(posthog) { | 
				
			||||
     *             distinct_id = posthog.get_distinct_id(); | 
				
			||||
     *         } | 
				
			||||
     *     }); | 
				
			||||
     */ | 
				
			||||
    static get_distinct_id(): string | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Opt the user out of data capturing and cookies/localstorage for this PostHog instance | 
				
			||||
     * | 
				
			||||
     * ### Usage | 
				
			||||
     * | 
				
			||||
     *     // opt user out
 | 
				
			||||
     *     posthog.opt_out_capturing(); | 
				
			||||
     * | 
				
			||||
     *     // opt user out with different cookie configuration from PostHog instance
 | 
				
			||||
     *     posthog.opt_out_capturing({ | 
				
			||||
     *         cookie_expiration: 30, | 
				
			||||
     *         secure_cookie: true | 
				
			||||
     *     }); | 
				
			||||
     * | 
				
			||||
     * @param {Object} [options] A dictionary of config options to override | 
				
			||||
     * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence | 
				
			||||
     * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable | 
				
			||||
     * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name | 
				
			||||
     * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this PostHog instance's config) | 
				
			||||
     * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this PostHog instance's config) | 
				
			||||
     * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this PostHog instance's config) | 
				
			||||
     */ | 
				
			||||
    static opt_out_capturing(options?: posthog.OptInOutCapturingOptions): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Opt the user in to data capturing and cookies/localstorage for this PostHog instance | 
				
			||||
     * | 
				
			||||
     * ### Usage | 
				
			||||
     * | 
				
			||||
     *     // opt user in
 | 
				
			||||
     *     posthog.opt_in_capturing(); | 
				
			||||
     * | 
				
			||||
     *     // opt user in with specific event name, properties, cookie configuration
 | 
				
			||||
     *     posthog.opt_in_capturing({ | 
				
			||||
     *         capture_event_name: 'User opted in', | 
				
			||||
     *         capture_event_properties: { | 
				
			||||
     *             'Email': 'jdoe@example.com' | 
				
			||||
     *         }, | 
				
			||||
     *         cookie_expiration: 30, | 
				
			||||
     *         secure_cookie: true | 
				
			||||
     *     }); | 
				
			||||
     * | 
				
			||||
     * @param {Object} [options] A dictionary of config options to override | 
				
			||||
     * @param {function} [options.capture] Function used for capturing a PostHog event to record the opt-in action (default is this PostHog instance's capture method) | 
				
			||||
     * @param {string} [options.capture_event_name=$opt_in] Event name to be used for capturing the opt-in action | 
				
			||||
     * @param {Object} [options.capture_properties] Set of properties to be captured along with the opt-in action | 
				
			||||
     * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence | 
				
			||||
     * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable | 
				
			||||
     * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name | 
				
			||||
     * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this PostHog instance's config) | 
				
			||||
     * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this PostHog instance's config) | 
				
			||||
     * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this PostHog instance's config) | 
				
			||||
     */ | 
				
			||||
    static opt_in_capturing(options?: posthog.OptInOutCapturingOptions): void | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Check whether the user has opted out of data capturing and cookies/localstorage for this PostHog instance | 
				
			||||
     * | 
				
			||||
     * ### Usage | 
				
			||||
     * | 
				
			||||
     *     const has_opted_out = posthog.has_opted_out_capturing(); | 
				
			||||
     *     // use has_opted_out value
 | 
				
			||||
     * | 
				
			||||
     * @param {Object} [options] A dictionary of config options to override | 
				
			||||
     * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable | 
				
			||||
     * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name | 
				
			||||
     * @returns {boolean} current opt-out status | 
				
			||||
     */ | 
				
			||||
    static has_opted_out_capturing(options?: posthog.HasOptedInOutCapturingOptions): boolean | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Check whether the user has opted in to data capturing and cookies/localstorage for this PostHog instance | 
				
			||||
     * | 
				
			||||
     * ### Usage | 
				
			||||
     * | 
				
			||||
     *     const has_opted_in = posthog.has_opted_in_capturing(); | 
				
			||||
     *     // use has_opted_in value
 | 
				
			||||
     * | 
				
			||||
     * @param {Object} [options] A dictionary of config options to override | 
				
			||||
     * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable | 
				
			||||
     * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name | 
				
			||||
     * @returns {boolean} current opt-in status | 
				
			||||
     */ | 
				
			||||
    static has_opted_in_capturing(options?: posthog.HasOptedInOutCapturingOptions): boolean | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Clear the user's opt in/out status of data capturing and cookies/localstorage for this PostHog instance | 
				
			||||
     * | 
				
			||||
     * ### Usage | 
				
			||||
     * | 
				
			||||
     *     // clear user's opt-in/out status
 | 
				
			||||
     *     posthog.clear_opt_in_out_capturing(); | 
				
			||||
     * | 
				
			||||
     *     // clear user's opt-in/out status with specific cookie configuration - should match
 | 
				
			||||
     *     // configuration used when opt_in_capturing/opt_out_capturing methods were called.
 | 
				
			||||
     *     posthog.clear_opt_in_out_capturing({ | 
				
			||||
     *         cookie_expiration: 30, | 
				
			||||
     *         secure_cookie: true | 
				
			||||
     *     }); | 
				
			||||
     * | 
				
			||||
     * @param {Object} [options] A dictionary of config options to override | 
				
			||||
     * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence | 
				
			||||
     * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable | 
				
			||||
     * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name | 
				
			||||
     * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this PostHog instance's config) | 
				
			||||
     * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this PostHog instance's config) | 
				
			||||
     * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this PostHog instance's config) | 
				
			||||
     */ | 
				
			||||
    static clear_opt_in_out_capturing(options?: posthog.ClearOptInOutCapturingOptions): void | 
				
			||||
 | 
				
			||||
    /* | 
				
			||||
     * See if feature flag is enabled for user. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     if(posthog.isFeatureEnabled('beta-feature')) { // do something }
 | 
				
			||||
     * | 
				
			||||
     * @param {Object|String} prop Key of the feature flag. | 
				
			||||
     * @param {Object|String} options (optional) If {send_event: false}, we won't send an $feature_flag_call event to PostHog. | 
				
			||||
     */ | 
				
			||||
    static isFeatureEnabled(key: string, options?: posthog.isFeatureEnabledOptions): boolean | 
				
			||||
 | 
				
			||||
    /* | 
				
			||||
     * See if feature flags are available. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     posthog.onFeatureFlags(function(featureFlags) { // do something })
 | 
				
			||||
     * | 
				
			||||
     * @param {Function} [callback] The callback function will be called once the feature flags are ready. It'll return a list of feature flags enabled for the user. | 
				
			||||
     */ | 
				
			||||
    static onFeatureFlags(callback: (flags: string[]) => void): false | undefined | 
				
			||||
 | 
				
			||||
    /* | 
				
			||||
     * Reload all feature flags for the user. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     posthog.reloadFeatureFlags() | 
				
			||||
     */ | 
				
			||||
    static reloadFeatureFlags(): void | 
				
			||||
 | 
				
			||||
    static toString(): string | 
				
			||||
 | 
				
			||||
    /* Will log all capture requests to the Javascript console, including event properties for easy debugging */ | 
				
			||||
    static debug(): void | 
				
			||||
 | 
				
			||||
    /* | 
				
			||||
     * Starts session recording and updates disable_session_recording to false. | 
				
			||||
     * Used for manual session recording management. By default, session recording is enabled and | 
				
			||||
     * starts automatically. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     posthog.startSessionRecording() | 
				
			||||
     */ | 
				
			||||
    static startSessionRecording(): void | 
				
			||||
 | 
				
			||||
    /* | 
				
			||||
     * Stops session recording and updates disable_session_recording to true. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     posthog.stopSessionRecording() | 
				
			||||
     */ | 
				
			||||
    static stopSessionRecording(): void | 
				
			||||
 | 
				
			||||
    /* | 
				
			||||
     * Check if session recording is currently running. | 
				
			||||
     * | 
				
			||||
     * ### Usage: | 
				
			||||
     * | 
				
			||||
     *     const isSessionRecordingOn = posthog.sessionRecordingStarted() | 
				
			||||
     */ | 
				
			||||
    static sessionRecordingStarted(): boolean | 
				
			||||
} | 
				
			||||
 | 
				
			||||
declare namespace posthog { | 
				
			||||
    /* eslint-disable @typescript-eslint/no-explicit-any */ | 
				
			||||
    type Property = any; | 
				
			||||
    type Properties = Record<string, Property>; | 
				
			||||
    type CaptureResult = { event: string; properties: Properties } | undefined; | 
				
			||||
    type CaptureCallback = (response: any, data: any) => void; | 
				
			||||
    /* eslint-enable @typescript-eslint/no-explicit-any */ | 
				
			||||
 | 
				
			||||
    interface Config { | 
				
			||||
        api_host?: string | 
				
			||||
        api_method?: string | 
				
			||||
        api_transport?: string | 
				
			||||
        autocapture?: boolean | 
				
			||||
        rageclick?: boolean | 
				
			||||
        cdn?: string | 
				
			||||
        cross_subdomain_cookie?: boolean | 
				
			||||
        persistence?: 'localStorage' | 'cookie' | 'memory' | 
				
			||||
        persistence_name?: string | 
				
			||||
        cookie_name?: string | 
				
			||||
        loaded?: (posthog_instance: typeof posthog) => void | 
				
			||||
        store_google?: boolean | 
				
			||||
        save_referrer?: boolean | 
				
			||||
        test?: boolean | 
				
			||||
        verbose?: boolean | 
				
			||||
        img?: boolean | 
				
			||||
        capture_pageview?: boolean | 
				
			||||
        debug?: boolean | 
				
			||||
        cookie_expiration?: number | 
				
			||||
        upgrade?: boolean | 
				
			||||
        disable_session_recording?: boolean | 
				
			||||
        disable_persistence?: boolean | 
				
			||||
        disable_cookie?: boolean | 
				
			||||
        secure_cookie?: boolean | 
				
			||||
        ip?: boolean | 
				
			||||
        opt_out_capturing_by_default?: boolean | 
				
			||||
        opt_out_persistence_by_default?: boolean | 
				
			||||
        opt_out_capturing_persistence_type?: 'localStorage' | 'cookie' | 
				
			||||
        opt_out_capturing_cookie_prefix?: string | null | 
				
			||||
        respect_dnt?: boolean | 
				
			||||
        property_blacklist?: string[] | 
				
			||||
        xhr_headers?: { [header_name: string]: string } | 
				
			||||
        inapp_protocol?: string | 
				
			||||
        inapp_link_new_window?: boolean | 
				
			||||
        request_batching?: boolean | 
				
			||||
        sanitize_properties?: (properties: posthog.Properties, event_name: string) => posthog.Properties | 
				
			||||
        properties_string_max_length?: number | 
				
			||||
        mask_all_element_attributes?: boolean | 
				
			||||
        mask_all_text?: boolean | 
				
			||||
        advanced_disable_decide?: boolean | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    interface OptInOutCapturingOptions { | 
				
			||||
        clear_persistence: boolean | 
				
			||||
        persistence_type: string | 
				
			||||
        cookie_prefix: string | 
				
			||||
        cookie_expiration: number | 
				
			||||
        cross_subdomain_cookie: boolean | 
				
			||||
        secure_cookie: boolean | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    interface HasOptedInOutCapturingOptions { | 
				
			||||
        persistence_type: string | 
				
			||||
        cookie_prefix: string | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    interface ClearOptInOutCapturingOptions { | 
				
			||||
        enable_persistence: boolean | 
				
			||||
        persistence_type: string | 
				
			||||
        cookie_prefix: string | 
				
			||||
        cookie_expiration: number | 
				
			||||
        cross_subdomain_cookie: boolean | 
				
			||||
        secure_cookie: boolean | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    interface isFeatureEnabledOptions { | 
				
			||||
        send_event: boolean | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    export class persistence { | 
				
			||||
        static properties(): posthog.Properties | 
				
			||||
 | 
				
			||||
        static load(): void | 
				
			||||
 | 
				
			||||
        static save(): void | 
				
			||||
 | 
				
			||||
        static remove(): void | 
				
			||||
 | 
				
			||||
        static clear(): void | 
				
			||||
 | 
				
			||||
        /** | 
				
			||||
         * @param {Object} props | 
				
			||||
         * @param {*=} default_value | 
				
			||||
         * @param {number=} days | 
				
			||||
         */ | 
				
			||||
        static register_once(props: Properties, default_value?: Property, days?: number): boolean | 
				
			||||
 | 
				
			||||
        /** | 
				
			||||
         * @param {Object} props | 
				
			||||
         * @param {number=} days | 
				
			||||
         */ | 
				
			||||
        static register(props: posthog.Properties, days?: number): boolean | 
				
			||||
 | 
				
			||||
        static unregister(prop: string): void | 
				
			||||
 | 
				
			||||
        static update_campaign_params(): void | 
				
			||||
 | 
				
			||||
        static update_search_keyword(referrer: string): void | 
				
			||||
 | 
				
			||||
        static update_referrer_info(referrer: string): void | 
				
			||||
 | 
				
			||||
        static get_referrer_info(): posthog.Properties | 
				
			||||
 | 
				
			||||
        static safe_merge(props: posthog.Properties): posthog.Properties | 
				
			||||
 | 
				
			||||
        static update_config(config: posthog.Config): void | 
				
			||||
 | 
				
			||||
        static set_disabled(disabled: boolean): void | 
				
			||||
 | 
				
			||||
        static set_cross_subdomain(cross_subdomain: boolean): void | 
				
			||||
 | 
				
			||||
        static get_cross_subdomain(): boolean | 
				
			||||
 | 
				
			||||
        static set_secure(secure: boolean): void | 
				
			||||
 | 
				
			||||
        static set_event_timer(event_name: string, timestamp: Date): void | 
				
			||||
 | 
				
			||||
        static remove_event_timer(event_name: string): Date | undefined | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    export class people { | 
				
			||||
        /* | 
				
			||||
         * Set properties on a user record. | 
				
			||||
         * | 
				
			||||
         * ### Usage: | 
				
			||||
         * | 
				
			||||
         *     posthog.people.set('gender', 'm'); | 
				
			||||
         * | 
				
			||||
         *     // or set multiple properties at once
 | 
				
			||||
         *     posthog.people.set({ | 
				
			||||
         *         'Company': 'Acme', | 
				
			||||
         *         'Plan': 'Premium', | 
				
			||||
         *         'Upgrade date': new Date() | 
				
			||||
         *     }); | 
				
			||||
         *     // properties can be strings, integers, dates, or lists
 | 
				
			||||
         * | 
				
			||||
         * @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values. | 
				
			||||
         * @param {*} [to] A value to set on the given property name | 
				
			||||
         * @param {Function} [callback] If provided, the callback will be called after capturing the event. | 
				
			||||
         */ | 
				
			||||
        static set( | 
				
			||||
            prop: posthog.Properties | string, | 
				
			||||
            to?: posthog.Property, | 
				
			||||
            callback?: posthog.CaptureCallback | 
				
			||||
        ): posthog.Properties | 
				
			||||
 | 
				
			||||
        /* | 
				
			||||
         * Set properties on a user record, only if they do not yet exist. | 
				
			||||
         * This will not overwrite previous people property values, unlike | 
				
			||||
         * people.set(). | 
				
			||||
         * | 
				
			||||
         * ### Usage: | 
				
			||||
         * | 
				
			||||
         *     posthog.people.set_once('First Login Date', new Date()); | 
				
			||||
         * | 
				
			||||
         *     // or set multiple properties at once
 | 
				
			||||
         *     posthog.people.set_once({ | 
				
			||||
         *         'First Login Date': new Date(), | 
				
			||||
         *         'Starting Plan': 'Premium' | 
				
			||||
         *     }); | 
				
			||||
         * | 
				
			||||
         *     // properties can be strings, integers or dates
 | 
				
			||||
         * | 
				
			||||
         * @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values. | 
				
			||||
         * @param {*} [to] A value to set on the given property name | 
				
			||||
         * @param {Function} [callback] If provided, the callback will be called after capturing the event. | 
				
			||||
         */ | 
				
			||||
        static set_once( | 
				
			||||
            prop: posthog.Properties | string, | 
				
			||||
            to?: posthog.Property, | 
				
			||||
            callback?: posthog.CaptureCallback | 
				
			||||
        ): posthog.Properties | 
				
			||||
 | 
				
			||||
        static toString(): string | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    export class featureFlags { | 
				
			||||
        static getFlags(): string[] | 
				
			||||
 | 
				
			||||
        static reloadFeatureFlags(): void | 
				
			||||
 | 
				
			||||
        /* | 
				
			||||
         * See if feature flag is enabled for user. | 
				
			||||
         * | 
				
			||||
         * ### Usage: | 
				
			||||
         * | 
				
			||||
         *     if(posthog.isFeatureEnabled('beta-feature')) { // do something }
 | 
				
			||||
         * | 
				
			||||
         * @param {Object|String} prop Key of the feature flag. | 
				
			||||
         * @param {Object|String} options (optional) If {send_event: false}, we won't send an $feature_flag_call event to PostHog. | 
				
			||||
         */ | 
				
			||||
        static isFeatureEnabled(key: string, options?: { send_event?: boolean }): boolean | 
				
			||||
 | 
				
			||||
        /* | 
				
			||||
         * See if feature flags are available. | 
				
			||||
         * | 
				
			||||
         * ### Usage: | 
				
			||||
         * | 
				
			||||
         *     posthog.onFeatureFlags(function(featureFlags) { // do something })
 | 
				
			||||
         * | 
				
			||||
         * @param {Function} [callback] The callback function will be called once the feature flags are ready. It'll return a list of feature flags enabled for the user. | 
				
			||||
         */ | 
				
			||||
        static onFeatureFlags(callback: (flags: string[]) => void): false | undefined | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    export class feature_flags extends featureFlags {} | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export type PostHog = typeof posthog; | 
				
			||||
 | 
				
			||||
export default posthog; | 
				
			||||
@ -1,355 +0,0 @@ | 
				
			||||
/* | 
				
			||||
Copyright 2021 The Matrix.org Foundation C.I.C. | 
				
			||||
 | 
				
			||||
Licensed under the Apache License, Version 2.0 (the "License"); | 
				
			||||
you may not use this file except in compliance with the License. | 
				
			||||
You may obtain a copy of the License at | 
				
			||||
 | 
				
			||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||
 | 
				
			||||
Unless required by applicable law or agreed to in writing, software | 
				
			||||
distributed under the License is distributed on an "AS IS" BASIS, | 
				
			||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
				
			||||
See the License for the specific language governing permissions and | 
				
			||||
limitations under the License. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
import posthog, { PostHog } from 'posthog-js'; | 
				
			||||
import PlatformPeg from './PlatformPeg'; | 
				
			||||
import SdkConfig from './SdkConfig'; | 
				
			||||
import SettingsStore from './settings/SettingsStore'; | 
				
			||||
 | 
				
			||||
/* Posthog analytics tracking. | 
				
			||||
 * | 
				
			||||
 * Anonymity behaviour is as follows: | 
				
			||||
 * | 
				
			||||
 * - If Posthog isn't configured in `config.json`, events are not sent. | 
				
			||||
 * - If [Do Not Track](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/doNotTrack) is
 | 
				
			||||
 *   enabled, events are not sent (this detection is built into posthog and turned on via the | 
				
			||||
 *   `respect_dnt` flag being passed to `posthog.init`). | 
				
			||||
 * - If the `feature_pseudonymous_analytics_opt_in` labs flag is `true`, track pseudonomously, i.e. | 
				
			||||
 *   hash all matrix identifiers in tracking events (user IDs, room IDs etc) using SHA-256. | 
				
			||||
 * - Otherwise, if the existing `analyticsOptIn` flag is `true`, track anonymously, i.e. | 
				
			||||
 *   redact all matrix identifiers in tracking events. | 
				
			||||
 * - If both flags are false or not set, events are not sent. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
interface IEvent { | 
				
			||||
    // The event name that will be used by PostHog. Event names should use snake_case.
 | 
				
			||||
    eventName: string; | 
				
			||||
 | 
				
			||||
    // The properties of the event that will be stored in PostHog. This is just a placeholder,
 | 
				
			||||
    // extending interfaces must override this with a concrete definition to do type validation.
 | 
				
			||||
    properties: {}; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export enum Anonymity { | 
				
			||||
    Disabled, | 
				
			||||
    Anonymous, | 
				
			||||
    Pseudonymous | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// If an event extends IPseudonymousEvent, the event contains pseudonymous data
 | 
				
			||||
// that won't be sent unless the user has explicitly consented to pseudonymous tracking.
 | 
				
			||||
// For example, it might contain hashed user IDs or room IDs.
 | 
				
			||||
// Such events will be automatically dropped if PosthogAnalytics.anonymity isn't set to Pseudonymous.
 | 
				
			||||
export interface IPseudonymousEvent extends IEvent {} | 
				
			||||
 | 
				
			||||
// If an event extends IAnonymousEvent, the event strictly contains *only* anonymous data;
 | 
				
			||||
// i.e. no identifiers that can be associated with the user.
 | 
				
			||||
export interface IAnonymousEvent extends IEvent {} | 
				
			||||
 | 
				
			||||
export interface IRoomEvent extends IPseudonymousEvent { | 
				
			||||
    hashedRoomId: string; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
interface IPageView extends IAnonymousEvent { | 
				
			||||
    eventName: "$pageview"; | 
				
			||||
    properties: { | 
				
			||||
        durationMs?: number; | 
				
			||||
        screen?: string; | 
				
			||||
    }; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
const hashHex = async (input: string): Promise<string> => { | 
				
			||||
    const buf = new TextEncoder().encode(input); | 
				
			||||
    const digestBuf = await window.crypto.subtle.digest("sha-256", buf); | 
				
			||||
    return [...new Uint8Array(digestBuf)].map((b: number) => b.toString(16).padStart(2, "0")).join(""); | 
				
			||||
}; | 
				
			||||
 | 
				
			||||
const whitelistedScreens = new Set([ | 
				
			||||
    "register", "login", "forgot_password", "soft_logout", "new", "settings", "welcome", "home", "start", "directory", | 
				
			||||
    "start_sso", "start_cas", "groups", "complete_security", "post_registration", "room", "user", "group", | 
				
			||||
]); | 
				
			||||
 | 
				
			||||
export async function getRedactedCurrentLocation( | 
				
			||||
    origin: string, | 
				
			||||
    hash: string, | 
				
			||||
    pathname: string, | 
				
			||||
    anonymity: Anonymity, | 
				
			||||
): Promise<string> { | 
				
			||||
    // Redact PII from the current location.
 | 
				
			||||
    // If anonymous is true, redact entirely, if false, substitute it with a hash.
 | 
				
			||||
    // For known screens, assumes a URL structure of /<screen name>/might/be/pii
 | 
				
			||||
    if (origin.startsWith('file://')) { | 
				
			||||
        pathname = "/<redacted_file_scheme_url>/"; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    let hashStr; | 
				
			||||
    if (hash == "") { | 
				
			||||
        hashStr = ""; | 
				
			||||
    } else { | 
				
			||||
        let [beforeFirstSlash, screen, ...parts] = hash.split("/"); | 
				
			||||
 | 
				
			||||
        if (!whitelistedScreens.has(screen)) { | 
				
			||||
            screen = "<redacted_screen_name>"; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        for (let i = 0; i < parts.length; i++) { | 
				
			||||
            parts[i] = anonymity === Anonymity.Anonymous ? `<redacted>` : await hashHex(parts[i]); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        hashStr = `${beforeFirstSlash}/${screen}/${parts.join("/")}`; | 
				
			||||
    } | 
				
			||||
    return origin + pathname + hashStr; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
interface PlatformProperties { | 
				
			||||
    appVersion: string; | 
				
			||||
    appPlatform: string; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export class PosthogAnalytics { | 
				
			||||
    /* Wrapper for Posthog analytics. | 
				
			||||
     * 3 modes of anonymity are supported, governed by this.anonymity | 
				
			||||
     * - Anonymity.Disabled means *no data* is passed to posthog | 
				
			||||
     * - Anonymity.Anonymous means all identifers will be redacted before being passed to posthog | 
				
			||||
     * - Anonymity.Pseudonymous means all identifiers will be hashed via SHA-256 before being passed | 
				
			||||
     *   to Posthog | 
				
			||||
     * | 
				
			||||
     * To update anonymity, call updateAnonymityFromSettings() or you can set it directly via setAnonymity(). | 
				
			||||
     * | 
				
			||||
     * To pass an event to Posthog: | 
				
			||||
     * | 
				
			||||
     * 1. Declare a type for the event, extending IAnonymousEvent, IPseudonymousEvent or IRoomEvent. | 
				
			||||
     * 2. Call the appropriate track*() method. Pseudonymous events will be dropped when anonymity is | 
				
			||||
     *    Anonymous or Disabled; Anonymous events will be dropped when anonymity is Disabled. | 
				
			||||
     */ | 
				
			||||
 | 
				
			||||
    private anonymity = Anonymity.Disabled; | 
				
			||||
    // set true during the constructor if posthog config is present, otherwise false
 | 
				
			||||
    private enabled = false; | 
				
			||||
    private static _instance = null; | 
				
			||||
    private platformSuperProperties = {}; | 
				
			||||
 | 
				
			||||
    public static get instance(): PosthogAnalytics { | 
				
			||||
        if (!this._instance) { | 
				
			||||
            this._instance = new PosthogAnalytics(posthog); | 
				
			||||
        } | 
				
			||||
        return this._instance; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    constructor(private readonly posthog: PostHog) { | 
				
			||||
        const posthogConfig = SdkConfig.get()["posthog"]; | 
				
			||||
        if (posthogConfig) { | 
				
			||||
            this.posthog.init(posthogConfig.projectApiKey, { | 
				
			||||
                api_host: posthogConfig.apiHost, | 
				
			||||
                autocapture: false, | 
				
			||||
                mask_all_text: true, | 
				
			||||
                mask_all_element_attributes: true, | 
				
			||||
                // This only triggers on page load, which for our SPA isn't particularly useful.
 | 
				
			||||
                // Plus, the .capture call originating from somewhere in posthog makes it hard
 | 
				
			||||
                // to redact URLs, which requires async code.
 | 
				
			||||
                //
 | 
				
			||||
                // To raise this manually, just call .capture("$pageview") or posthog.capture_pageview.
 | 
				
			||||
                capture_pageview: false, | 
				
			||||
                sanitize_properties: this.sanitizeProperties, | 
				
			||||
                respect_dnt: true, | 
				
			||||
            }); | 
				
			||||
            this.enabled = true; | 
				
			||||
        } else { | 
				
			||||
            this.enabled = false; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private sanitizeProperties = (properties: posthog.Properties): posthog.Properties => { | 
				
			||||
        // Callback from posthog to sanitize properties before sending them to the server.
 | 
				
			||||
        //
 | 
				
			||||
        // Here we sanitize posthog's built in properties which leak PII e.g. url reporting.
 | 
				
			||||
        // See utils.js _.info.properties in posthog-js.
 | 
				
			||||
 | 
				
			||||
        // Replace the $current_url with a redacted version.
 | 
				
			||||
        // $redacted_current_url is injected by this class earlier in capture(), as its generation
 | 
				
			||||
        // is async and can't be done in this non-async callback.
 | 
				
			||||
        if (!properties['$redacted_current_url']) { | 
				
			||||
            console.log("$redacted_current_url not set in sanitizeProperties, will drop $current_url entirely"); | 
				
			||||
        } | 
				
			||||
        properties['$current_url'] = properties['$redacted_current_url']; | 
				
			||||
        delete properties['$redacted_current_url']; | 
				
			||||
 | 
				
			||||
        if (this.anonymity == Anonymity.Anonymous) { | 
				
			||||
            // drop referrer information for anonymous users
 | 
				
			||||
            properties['$referrer'] = null; | 
				
			||||
            properties['$referring_domain'] = null; | 
				
			||||
            properties['$initial_referrer'] = null; | 
				
			||||
            properties['$initial_referring_domain'] = null; | 
				
			||||
 | 
				
			||||
            // drop device ID, which is a UUID persisted in local storage
 | 
				
			||||
            properties['$device_id'] = null; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return properties; | 
				
			||||
    }; | 
				
			||||
 | 
				
			||||
    private static getAnonymityFromSettings(): Anonymity { | 
				
			||||
        // determine the current anonymity level based on current user settings
 | 
				
			||||
 | 
				
			||||
        // "Send anonymous usage data which helps us improve Element. This will use a cookie."
 | 
				
			||||
        const analyticsOptIn = SettingsStore.getValue("analyticsOptIn", null, true); | 
				
			||||
 | 
				
			||||
        // (proposed wording) "Send pseudonymous usage data which helps us improve Element. This will use a cookie."
 | 
				
			||||
        //
 | 
				
			||||
        // TODO: Currently, this is only a labs flag, for testing purposes.
 | 
				
			||||
        const pseudonumousOptIn = SettingsStore.getValue("feature_pseudonymous_analytics_opt_in", null, true); | 
				
			||||
 | 
				
			||||
        let anonymity; | 
				
			||||
        if (pseudonumousOptIn) { | 
				
			||||
            anonymity = Anonymity.Pseudonymous; | 
				
			||||
        } else if (analyticsOptIn) { | 
				
			||||
            anonymity = Anonymity.Anonymous; | 
				
			||||
        } else { | 
				
			||||
            anonymity = Anonymity.Disabled; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return anonymity; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private registerSuperProperties(properties: posthog.Properties) { | 
				
			||||
        if (this.enabled) { | 
				
			||||
            this.posthog.register(properties); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private static async getPlatformProperties(): Promise<PlatformProperties> { | 
				
			||||
        const platform = PlatformPeg.get(); | 
				
			||||
        let appVersion; | 
				
			||||
        try { | 
				
			||||
            appVersion = await platform.getAppVersion(); | 
				
			||||
        } catch (e) { | 
				
			||||
            // this happens if no version is set i.e. in dev
 | 
				
			||||
            appVersion = "unknown"; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return { | 
				
			||||
            appVersion, | 
				
			||||
            appPlatform: platform.getHumanReadableName(), | 
				
			||||
        }; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private async capture(eventName: string, properties: posthog.Properties) { | 
				
			||||
        if (!this.enabled) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
        const { origin, hash, pathname } = window.location; | 
				
			||||
        properties['$redacted_current_url'] = await getRedactedCurrentLocation( | 
				
			||||
            origin, hash, pathname, this.anonymity); | 
				
			||||
        this.posthog.capture(eventName, properties); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public isEnabled(): boolean { | 
				
			||||
        return this.enabled; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public setAnonymity(anonymity: Anonymity): void { | 
				
			||||
        // Update this.anonymity.
 | 
				
			||||
        // This is public for testing purposes, typically you want to call updateAnonymityFromSettings
 | 
				
			||||
        // to ensure this value is in step with the user's settings.
 | 
				
			||||
        if (this.enabled && (anonymity == Anonymity.Disabled || anonymity == Anonymity.Anonymous)) { | 
				
			||||
            // when transitioning to Disabled or Anonymous ensure we clear out any prior state
 | 
				
			||||
            // set in posthog e.g. distinct ID
 | 
				
			||||
            this.posthog.reset(); | 
				
			||||
            // Restore any previously set platform super properties
 | 
				
			||||
            this.registerSuperProperties(this.platformSuperProperties); | 
				
			||||
        } | 
				
			||||
        this.anonymity = anonymity; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async identifyUser(userId: string): Promise<void> { | 
				
			||||
        if (this.anonymity == Anonymity.Pseudonymous) { | 
				
			||||
            this.posthog.identify(await hashHex(userId)); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public getAnonymity(): Anonymity { | 
				
			||||
        return this.anonymity; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public logout(): void { | 
				
			||||
        if (this.enabled) { | 
				
			||||
            this.posthog.reset(); | 
				
			||||
        } | 
				
			||||
        this.setAnonymity(Anonymity.Anonymous); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async trackPseudonymousEvent<E extends IPseudonymousEvent>( | 
				
			||||
        eventName: E["eventName"], | 
				
			||||
        properties: E["properties"] = {}, | 
				
			||||
    ) { | 
				
			||||
        if (this.anonymity == Anonymity.Anonymous || this.anonymity == Anonymity.Disabled) return; | 
				
			||||
        await this.capture(eventName, properties); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async trackAnonymousEvent<E extends IAnonymousEvent>( | 
				
			||||
        eventName: E["eventName"], | 
				
			||||
        properties: E["properties"] = {}, | 
				
			||||
    ): Promise<void> { | 
				
			||||
        if (this.anonymity == Anonymity.Disabled) return; | 
				
			||||
        await this.capture(eventName, properties); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async trackRoomEvent<E extends IRoomEvent>( | 
				
			||||
        eventName: E["eventName"], | 
				
			||||
        roomId: string, | 
				
			||||
        properties: Omit<E["properties"], "roomId">, | 
				
			||||
    ): Promise<void> { | 
				
			||||
        const updatedProperties = { | 
				
			||||
            ...properties, | 
				
			||||
            hashedRoomId: roomId ? await hashHex(roomId) : null, | 
				
			||||
        }; | 
				
			||||
        await this.trackPseudonymousEvent(eventName, updatedProperties); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async trackPageView(durationMs: number): Promise<void> { | 
				
			||||
        const hash = window.location.hash; | 
				
			||||
 | 
				
			||||
        let screen = null; | 
				
			||||
        const split = hash.split("/"); | 
				
			||||
        if (split.length >= 2) { | 
				
			||||
            screen = split[1]; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        await this.trackAnonymousEvent<IPageView>("$pageview", { | 
				
			||||
            durationMs, | 
				
			||||
            screen, | 
				
			||||
        }); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async updatePlatformSuperProperties(): Promise<void> { | 
				
			||||
        // Update super properties in posthog with our platform (app version, platform).
 | 
				
			||||
        // These properties will be subsequently passed in every event.
 | 
				
			||||
        //
 | 
				
			||||
        // This only needs to be done once per page lifetime. Note that getPlatformProperties
 | 
				
			||||
        // is async and can involve a network request if we are running in a browser.
 | 
				
			||||
        this.platformSuperProperties = await PosthogAnalytics.getPlatformProperties(); | 
				
			||||
        this.registerSuperProperties(this.platformSuperProperties); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public async updateAnonymityFromSettings(userId?: string): Promise<void> { | 
				
			||||
        // Update this.anonymity based on the user's analytics opt-in settings
 | 
				
			||||
        // Identify the user (via hashed user ID) to posthog if anonymity is pseudonmyous
 | 
				
			||||
        this.setAnonymity(PosthogAnalytics.getAnonymityFromSettings()); | 
				
			||||
        if (userId && this.getAnonymity() == Anonymity.Pseudonymous) { | 
				
			||||
            await this.identifyUser(userId); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,26 +0,0 @@ | 
				
			||||
/* | 
				
			||||
Copyright 2021 The Matrix.org Foundation C.I.C. | 
				
			||||
 | 
				
			||||
Licensed under the Apache License, Version 2.0 (the "License"); | 
				
			||||
you may not use this file except in compliance with the License. | 
				
			||||
You may obtain a copy of the License at | 
				
			||||
 | 
				
			||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||
 | 
				
			||||
Unless required by applicable law or agreed to in writing, software | 
				
			||||
distributed under the License is distributed on an "AS IS" BASIS, | 
				
			||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
				
			||||
See the License for the specific language governing permissions and | 
				
			||||
limitations under the License. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
import SettingController from "./SettingController"; | 
				
			||||
import { SettingLevel } from "../SettingLevel"; | 
				
			||||
import { PosthogAnalytics } from "../../PosthogAnalytics"; | 
				
			||||
import { MatrixClientPeg } from "../../MatrixClientPeg"; | 
				
			||||
 | 
				
			||||
export default class PseudonymousAnalyticsController extends SettingController { | 
				
			||||
    public onChange(level: SettingLevel, roomId: string, newValue: any) { | 
				
			||||
        PosthogAnalytics.instance.updateAnonymityFromSettings(MatrixClientPeg.get().getUserId()); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,232 +0,0 @@ | 
				
			||||
/* | 
				
			||||
Copyright 2021 The Matrix.org Foundation C.I.C. | 
				
			||||
 | 
				
			||||
Licensed under the Apache License, Version 2.0 (the "License"); | 
				
			||||
you may not use this file except in compliance with the License. | 
				
			||||
You may obtain a copy of the License at | 
				
			||||
 | 
				
			||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||
 | 
				
			||||
Unless required by applicable law or agreed to in writing, software | 
				
			||||
distributed under the License is distributed on an "AS IS" BASIS, | 
				
			||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
				
			||||
See the License for the specific language governing permissions and | 
				
			||||
limitations under the License. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
import { | 
				
			||||
    Anonymity, | 
				
			||||
    getRedactedCurrentLocation, | 
				
			||||
    IAnonymousEvent, | 
				
			||||
    IPseudonymousEvent, | 
				
			||||
    IRoomEvent, | 
				
			||||
    PosthogAnalytics, | 
				
			||||
} from '../src/PosthogAnalytics'; | 
				
			||||
 | 
				
			||||
import SdkConfig from '../src/SdkConfig'; | 
				
			||||
 | 
				
			||||
class FakePosthog { | 
				
			||||
    public capture; | 
				
			||||
    public init; | 
				
			||||
    public identify; | 
				
			||||
    public reset; | 
				
			||||
    public register; | 
				
			||||
 | 
				
			||||
    constructor() { | 
				
			||||
        this.capture = jest.fn(); | 
				
			||||
        this.init = jest.fn(); | 
				
			||||
        this.identify = jest.fn(); | 
				
			||||
        this.reset = jest.fn(); | 
				
			||||
        this.register = jest.fn(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export interface ITestEvent extends IAnonymousEvent { | 
				
			||||
    key: "jest_test_event"; | 
				
			||||
    properties: { | 
				
			||||
        foo: string; | 
				
			||||
    }; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export interface ITestPseudonymousEvent extends IPseudonymousEvent { | 
				
			||||
    key: "jest_test_pseudo_event"; | 
				
			||||
    properties: { | 
				
			||||
        foo: string; | 
				
			||||
    }; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export interface ITestRoomEvent extends IRoomEvent { | 
				
			||||
    key: "jest_test_room_event"; | 
				
			||||
    properties: { | 
				
			||||
        foo: string; | 
				
			||||
    }; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
describe("PosthogAnalytics", () => { | 
				
			||||
    let fakePosthog: FakePosthog; | 
				
			||||
    const shaHashes = { | 
				
			||||
        "42": "73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049", | 
				
			||||
        "some": "a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b", | 
				
			||||
        "pii": "bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4", | 
				
			||||
        "foo": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", | 
				
			||||
    }; | 
				
			||||
 | 
				
			||||
    beforeEach(() => { | 
				
			||||
        fakePosthog = new FakePosthog(); | 
				
			||||
 | 
				
			||||
        window.crypto = { | 
				
			||||
            subtle: { | 
				
			||||
                digest: async (_, encodedMessage) => { | 
				
			||||
                    const message = new TextDecoder().decode(encodedMessage); | 
				
			||||
                    const hexHash = shaHashes[message]; | 
				
			||||
                    const bytes = []; | 
				
			||||
                    for (let c = 0; c < hexHash.length; c += 2) { | 
				
			||||
                        bytes.push(parseInt(hexHash.substr(c, 2), 16)); | 
				
			||||
                    } | 
				
			||||
                    return bytes; | 
				
			||||
                }, | 
				
			||||
            }, | 
				
			||||
        }; | 
				
			||||
    }); | 
				
			||||
 | 
				
			||||
    afterEach(() => { | 
				
			||||
        window.crypto = null; | 
				
			||||
    }); | 
				
			||||
 | 
				
			||||
    describe("Initialisation", () => { | 
				
			||||
        it("Should not be enabled without config being set", () => { | 
				
			||||
            jest.spyOn(SdkConfig, "get").mockReturnValue({}); | 
				
			||||
            const analytics = new PosthogAnalytics(fakePosthog); | 
				
			||||
            expect(analytics.isEnabled()).toBe(false); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should be enabled if config is set", () => { | 
				
			||||
            jest.spyOn(SdkConfig, "get").mockReturnValue({ | 
				
			||||
                posthog: { | 
				
			||||
                    projectApiKey: "foo", | 
				
			||||
                    apiHost: "bar", | 
				
			||||
                }, | 
				
			||||
            }); | 
				
			||||
            const analytics = new PosthogAnalytics(fakePosthog); | 
				
			||||
            analytics.setAnonymity(Anonymity.Pseudonymous); | 
				
			||||
            expect(analytics.isEnabled()).toBe(true); | 
				
			||||
        }); | 
				
			||||
    }); | 
				
			||||
 | 
				
			||||
    describe("Tracking", () => { | 
				
			||||
        let analytics: PosthogAnalytics; | 
				
			||||
 | 
				
			||||
        beforeEach(() => { | 
				
			||||
            jest.spyOn(SdkConfig, "get").mockReturnValue({ | 
				
			||||
                posthog: { | 
				
			||||
                    projectApiKey: "foo", | 
				
			||||
                    apiHost: "bar", | 
				
			||||
                }, | 
				
			||||
            }); | 
				
			||||
 | 
				
			||||
            analytics = new PosthogAnalytics(fakePosthog); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should pass trackAnonymousEvent() to posthog", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Pseudonymous); | 
				
			||||
            await analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event"); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should pass trackRoomEvent to posthog", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Pseudonymous); | 
				
			||||
            const roomId = "42"; | 
				
			||||
            await analytics.trackRoomEvent<IRoomEvent>("jest_test_event", roomId, { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event"); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar"); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][1]["hashedRoomId"]) | 
				
			||||
                .toEqual("73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should pass trackPseudonymousEvent() to posthog", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Pseudonymous); | 
				
			||||
            await analytics.trackPseudonymousEvent<ITestEvent>("jest_test_pseudo_event", { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_pseudo_event"); | 
				
			||||
            expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should not track pseudonymous messages if anonymous", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Anonymous); | 
				
			||||
            await analytics.trackPseudonymousEvent<ITestEvent>("jest_test_event", { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            expect(fakePosthog.capture.mock.calls.length).toBe(0); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should not track any events if disabled", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Disabled); | 
				
			||||
            await analytics.trackPseudonymousEvent<ITestEvent>("jest_test_event", { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            await analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            await analytics.trackRoomEvent<ITestRoomEvent>("room id", "foo", { | 
				
			||||
                foo: "bar", | 
				
			||||
            }); | 
				
			||||
            await analytics.trackPageView(200); | 
				
			||||
            expect(fakePosthog.capture.mock.calls.length).toBe(0); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should pseudonymise a location of a known screen", async () => { | 
				
			||||
            const location = await getRedactedCurrentLocation( | 
				
			||||
                "https://foo.bar", "#/register/some/pii", "/", Anonymity.Pseudonymous); | 
				
			||||
            expect(location).toBe( | 
				
			||||
                `https://foo.bar/#/register/\ | 
				
			||||
a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b/\ | 
				
			||||
bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
 | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should anonymise a location of a known screen", async () => { | 
				
			||||
            const location = await getRedactedCurrentLocation( | 
				
			||||
                "https://foo.bar", "#/register/some/pii", "/", Anonymity.Anonymous); | 
				
			||||
            expect(location).toBe("https://foo.bar/#/register/<redacted>/<redacted>"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should pseudonymise a location of an unknown screen", async () => { | 
				
			||||
            const location = await getRedactedCurrentLocation( | 
				
			||||
                "https://foo.bar", "#/not_a_screen_name/some/pii", "/", Anonymity.Pseudonymous); | 
				
			||||
            expect(location).toBe( | 
				
			||||
                `https://foo.bar/#/<redacted_screen_name>/\ | 
				
			||||
a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b/\ | 
				
			||||
bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
 | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should anonymise a location of an unknown screen", async () => { | 
				
			||||
            const location = await getRedactedCurrentLocation( | 
				
			||||
                "https://foo.bar", "#/not_a_screen_name/some/pii", "/", Anonymity.Anonymous); | 
				
			||||
            expect(location).toBe("https://foo.bar/#/<redacted_screen_name>/<redacted>/<redacted>"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should handle an empty hash", async () => { | 
				
			||||
            const location = await getRedactedCurrentLocation( | 
				
			||||
                "https://foo.bar", "", "/", Anonymity.Anonymous); | 
				
			||||
            expect(location).toBe("https://foo.bar/"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should identify the user to posthog if pseudonymous", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Pseudonymous); | 
				
			||||
            await analytics.identifyUser("foo"); | 
				
			||||
            expect(fakePosthog.identify.mock.calls[0][0]) | 
				
			||||
                .toBe("2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"); | 
				
			||||
        }); | 
				
			||||
 | 
				
			||||
        it("Should not identify the user to posthog if anonymous", async () => { | 
				
			||||
            analytics.setAnonymity(Anonymity.Anonymous); | 
				
			||||
            await analytics.identifyUser("foo"); | 
				
			||||
            expect(fakePosthog.identify.mock.calls.length).toBe(0); | 
				
			||||
        }); | 
				
			||||
    }); | 
				
			||||
}); | 
				
			||||
					Loading…
					
					
				
		Reference in new issue