From 27c62f31bbc648ab36b9351fac51ac83701b8e29 Mon Sep 17 00:00:00 2001 From: Raquel Smith Date: Fri, 15 Nov 2024 13:10:58 -0800 Subject: [PATCH 01/27] fix: only let someone use the dashboard templates if they've ingested events (#26226) --- frontend/src/scenes/onboarding/Onboarding.tsx | 7 ++++++- .../DashboardTemplateConfigureStep.tsx | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/src/scenes/onboarding/Onboarding.tsx b/frontend/src/scenes/onboarding/Onboarding.tsx index 522e28c569a..a4106a69173 100644 --- a/frontend/src/scenes/onboarding/Onboarding.tsx +++ b/frontend/src/scenes/onboarding/Onboarding.tsx @@ -26,6 +26,7 @@ import { ExperimentsSDKInstructions } from './sdks/experiments/ExperimentsSDKIns import { FeatureFlagsSDKInstructions } from './sdks/feature-flags/FeatureFlagsSDKInstructions' import { ProductAnalyticsSDKInstructions } from './sdks/product-analytics/ProductAnalyticsSDKInstructions' import { SDKs } from './sdks/SDKs' +import { sdksLogic } from './sdks/sdksLogic' import { SessionReplaySDKInstructions } from './sdks/session-replay/SessionReplaySDKInstructions' import { SurveysSDKInstructions } from './sdks/surveys/SurveysSDKInstructions' @@ -105,12 +106,16 @@ const OnboardingWrapper = ({ children }: { children: React.ReactNode }): JSX.Ele const ProductAnalyticsOnboarding = (): JSX.Element => { const { currentTeam } = useValues(teamLogic) const { featureFlags } = useValues(featureFlagLogic) + const { combinedSnippetAndLiveEventsHosts } = useValues(sdksLogic) + // mount the logic here so that it stays mounted for the entire onboarding flow // not sure if there is a better way to do this useValues(newDashboardLogic) const showTemplateSteps = - featureFlags[FEATURE_FLAGS.ONBOARDING_DASHBOARD_TEMPLATES] == 'test' && window.innerWidth > 1000 + featureFlags[FEATURE_FLAGS.ONBOARDING_DASHBOARD_TEMPLATES] == 'test' && + window.innerWidth > 1000 && + combinedSnippetAndLiveEventsHosts.length > 0 const options: ProductConfigOption[] = [ { diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx index c2740d598ca..9d30f984a4c 100644 --- a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx @@ -52,8 +52,8 @@ const UrlInput = ({ iframeRef }: { iframeRef: React.RefObject return (
setInputValue(v)} From cf7aaf66a82399694b8b15f5a518af98668bf8e6 Mon Sep 17 00:00:00 2001 From: Surbhi Date: Fri, 15 Nov 2024 17:22:36 -0400 Subject: [PATCH 02/27] fix: password validation correction (#26227) --- .../src/scenes/authentication/signup/signupForm/signupLogic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts b/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts index 1b458e909e0..d1257595c38 100644 --- a/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts +++ b/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts @@ -67,7 +67,7 @@ export const signupLogic = kea([ password: !values.preflight?.demo ? !password ? 'Please enter your password to continue' - : values.validatedPassword.feedback + : values.validatedPassword.feedback || undefined : undefined, }), submit: async () => { From 4ce7e9c7814f5b61961cfae8b985846fd4105bf8 Mon Sep 17 00:00:00 2001 From: Dylan Martin Date: Sat, 16 Nov 2024 00:44:55 +0100 Subject: [PATCH 03/27] feat(flags): dynamic cohort matching in rust (#25776) --- rust/Cargo.lock | 6 + rust/feature-flags/Cargo.toml | 2 + rust/feature-flags/src/api.rs | 24 +- rust/feature-flags/src/cohort_cache.rs | 221 +++++ rust/feature-flags/src/cohort_models.rs | 50 + rust/feature-flags/src/cohort_operations.rs | 369 ++++++++ rust/feature-flags/src/flag_definitions.rs | 38 +- rust/feature-flags/src/flag_matching.rs | 880 ++++++++++++++++-- rust/feature-flags/src/flag_request.rs | 21 +- rust/feature-flags/src/lib.rs | 5 +- .../src/{utils.rs => metrics_utils.rs} | 0 rust/feature-flags/src/property_matching.rs | 43 +- rust/feature-flags/src/request_handler.rs | 24 +- rust/feature-flags/src/router.rs | 6 +- rust/feature-flags/src/server.rs | 4 + rust/feature-flags/src/team.rs | 6 +- rust/feature-flags/src/test_utils.rs | 74 +- .../tests/test_flag_matching_consistency.rs | 9 +- 18 files changed, 1671 insertions(+), 111 deletions(-) create mode 100644 rust/feature-flags/src/cohort_cache.rs create mode 100644 rust/feature-flags/src/cohort_models.rs create mode 100644 rust/feature-flags/src/cohort_operations.rs rename rust/feature-flags/src/{utils.rs => metrics_utils.rs} (100%) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index b99943cc4e5..9a263a87878 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1808,7 +1808,9 @@ dependencies = [ "futures", "health", "maxminddb", + "moka", "once_cell", + "petgraph", "rand", "redis", "regex", @@ -3046,9 +3048,13 @@ version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" dependencies = [ + "async-lock 3.4.0", + "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", + "event-listener 5.3.1", + "futures-util", "once_cell", "parking_lot", "quanta 0.12.2", diff --git a/rust/feature-flags/Cargo.toml b/rust/feature-flags/Cargo.toml index 4cf4016767b..4099fd8ab06 100644 --- a/rust/feature-flags/Cargo.toml +++ b/rust/feature-flags/Cargo.toml @@ -39,6 +39,8 @@ health = { path = "../common/health" } common-metrics = { path = "../common/metrics" } tower = { workspace = true } derive_builder = "0.20.1" +petgraph = "0.6.5" +moka = { version = "0.12.8", features = ["future"] } [lints] workspace = true diff --git a/rust/feature-flags/src/api.rs b/rust/feature-flags/src/api.rs index 4430476d28a..9d6b649719b 100644 --- a/rust/feature-flags/src/api.rs +++ b/rust/feature-flags/src/api.rs @@ -89,7 +89,7 @@ pub enum FlagError { #[error("Row not found in postgres")] RowNotFound, #[error("failed to parse redis cache data")] - DataParsingError, + RedisDataParsingError, #[error("failed to update redis cache")] CacheUpdateError, #[error("redis unavailable")] @@ -102,6 +102,12 @@ pub enum FlagError { TimeoutError, #[error("No group type mappings")] NoGroupTypeMappings, + #[error("Cohort not found")] + CohortNotFound(String), + #[error("Failed to parse cohort filters")] + CohortFiltersParsingError, + #[error("Cohort dependency cycle")] + CohortDependencyCycle(String), } impl IntoResponse for FlagError { @@ -138,7 +144,7 @@ impl IntoResponse for FlagError { FlagError::TokenValidationError => { (StatusCode::UNAUTHORIZED, "The provided API key is invalid or has expired. Please check your API key and try again.".to_string()) } - FlagError::DataParsingError => { + FlagError::RedisDataParsingError => { tracing::error!("Data parsing error: {:?}", self); ( StatusCode::SERVICE_UNAVAILABLE, @@ -194,6 +200,18 @@ impl IntoResponse for FlagError { "The requested row was not found in the database. Please try again later or contact support if the problem persists.".to_string(), ) } + FlagError::CohortNotFound(msg) => { + tracing::error!("Cohort not found: {}", msg); + (StatusCode::NOT_FOUND, msg) + } + FlagError::CohortFiltersParsingError => { + tracing::error!("Failed to parse cohort filters: {:?}", self); + (StatusCode::BAD_REQUEST, "Failed to parse cohort filters. Please try again later or contact support if the problem persists.".to_string()) + } + FlagError::CohortDependencyCycle(msg) => { + tracing::error!("Cohort dependency cycle: {}", msg); + (StatusCode::BAD_REQUEST, msg) + } } .into_response() } @@ -205,7 +223,7 @@ impl From for FlagError { CustomRedisError::NotFound => FlagError::TokenValidationError, CustomRedisError::PickleError(e) => { tracing::error!("failed to fetch data: {}", e); - FlagError::DataParsingError + FlagError::RedisDataParsingError } CustomRedisError::Timeout(_) => FlagError::TimeoutError, CustomRedisError::Other(e) => { diff --git a/rust/feature-flags/src/cohort_cache.rs b/rust/feature-flags/src/cohort_cache.rs new file mode 100644 index 00000000000..68894c19f88 --- /dev/null +++ b/rust/feature-flags/src/cohort_cache.rs @@ -0,0 +1,221 @@ +use crate::api::FlagError; +use crate::cohort_models::Cohort; +use crate::flag_matching::{PostgresReader, TeamId}; +use moka::future::Cache; +use std::time::Duration; + +/// CohortCacheManager manages the in-memory cache of cohorts using `moka` for caching. +/// +/// Features: +/// - **TTL**: Each cache entry expires after 5 minutes. +/// - **Size-based eviction**: The cache evicts least recently used entries when the maximum capacity is reached. +/// +/// ```text +/// CohortCacheManager { +/// postgres_reader: PostgresReader, +/// per_team_cohorts: Cache> { +/// // Example: +/// 2: [ +/// Cohort { id: 1, name: "Power Users", filters: {...} }, +/// Cohort { id: 2, name: "Churned", filters: {...} } +/// ], +/// 5: [ +/// Cohort { id: 3, name: "Beta Users", filters: {...} } +/// ] +/// } +/// } +/// ``` +/// +#[derive(Clone)] +pub struct CohortCacheManager { + postgres_reader: PostgresReader, + per_team_cohort_cache: Cache>, +} + +impl CohortCacheManager { + pub fn new( + postgres_reader: PostgresReader, + max_capacity: Option, + ttl_seconds: Option, + ) -> Self { + // We use the size of the cohort list (i.e., the number of cohorts for a given team)as the weight of the entry + let weigher = + |_: &TeamId, value: &Vec| -> u32 { value.len().try_into().unwrap_or(u32::MAX) }; + + let cache = Cache::builder() + .time_to_live(Duration::from_secs(ttl_seconds.unwrap_or(300))) // Default to 5 minutes + .weigher(weigher) + .max_capacity(max_capacity.unwrap_or(10_000)) // Default to 10,000 cohorts + .build(); + + Self { + postgres_reader, + per_team_cohort_cache: cache, + } + } + + /// Retrieves cohorts for a given team. + /// + /// If the cohorts are not present in the cache or have expired, it fetches them from the database, + /// caches the result upon successful retrieval, and then returns it. + pub async fn get_cohorts_for_team(&self, team_id: TeamId) -> Result, FlagError> { + if let Some(cached_cohorts) = self.per_team_cohort_cache.get(&team_id).await { + return Ok(cached_cohorts.clone()); + } + let fetched_cohorts = Cohort::list_from_pg(self.postgres_reader.clone(), team_id).await?; + self.per_team_cohort_cache + .insert(team_id, fetched_cohorts.clone()) + .await; + + Ok(fetched_cohorts) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cohort_models::Cohort; + use crate::test_utils::{ + insert_cohort_for_team_in_pg, insert_new_team_in_pg, setup_pg_reader_client, + setup_pg_writer_client, + }; + use std::sync::Arc; + use tokio::time::{sleep, Duration}; + + /// Helper function to setup a new team for testing. + async fn setup_test_team( + writer_client: Arc, + ) -> Result { + let team = crate::test_utils::insert_new_team_in_pg(writer_client, None).await?; + Ok(team.id) + } + + /// Helper function to insert a cohort for a team. + async fn setup_test_cohort( + writer_client: Arc, + team_id: TeamId, + name: Option, + ) -> Result { + let filters = serde_json::json!({"properties": {"type": "OR", "values": [{"type": "OR", "values": [{"key": "$active", "type": "person", "value": [true], "negation": false, "operator": "exact"}]}]}}); + insert_cohort_for_team_in_pg(writer_client, team_id, name, filters, false).await + } + + /// Tests that cache entries expire after the specified TTL. + #[tokio::test] + async fn test_cache_expiry() -> Result<(), anyhow::Error> { + let writer_client = setup_pg_writer_client(None).await; + let reader_client = setup_pg_reader_client(None).await; + + let team_id = setup_test_team(writer_client.clone()).await?; + let _cohort = setup_test_cohort(writer_client.clone(), team_id, None).await?; + + // Initialize CohortCacheManager with a short TTL for testing + let cohort_cache = CohortCacheManager::new( + reader_client.clone(), + Some(100), + Some(1), // 1-second TTL + ); + + let cohorts = cohort_cache.get_cohorts_for_team(team_id).await?; + assert_eq!(cohorts.len(), 1); + assert_eq!(cohorts[0].team_id, team_id); + + let cached_cohorts = cohort_cache.per_team_cohort_cache.get(&team_id).await; + assert!(cached_cohorts.is_some()); + + // Wait for TTL to expire + sleep(Duration::from_secs(2)).await; + + // Attempt to retrieve from cache again + let cached_cohorts = cohort_cache.per_team_cohort_cache.get(&team_id).await; + assert!(cached_cohorts.is_none(), "Cache entry should have expired"); + + Ok(()) + } + + /// Tests that the cache correctly evicts least recently used entries based on the weigher. + #[tokio::test] + async fn test_cache_weigher() -> Result<(), anyhow::Error> { + let writer_client = setup_pg_writer_client(None).await; + let reader_client = setup_pg_reader_client(None).await; + + // Define a smaller max_capacity for testing + let max_capacity: u64 = 3; + + let cohort_cache = CohortCacheManager::new(reader_client.clone(), Some(max_capacity), None); + + let mut inserted_team_ids = Vec::new(); + + // Insert multiple teams and their cohorts + for _ in 0..max_capacity { + let team = insert_new_team_in_pg(writer_client.clone(), None).await?; + let team_id = team.id; + inserted_team_ids.push(team_id); + setup_test_cohort(writer_client.clone(), team_id, None).await?; + cohort_cache.get_cohorts_for_team(team_id).await?; + } + + cohort_cache.per_team_cohort_cache.run_pending_tasks().await; + let cache_size = cohort_cache.per_team_cohort_cache.entry_count(); + assert_eq!( + cache_size, max_capacity, + "Cache size should be equal to max_capacity" + ); + + let new_team = insert_new_team_in_pg(writer_client.clone(), None).await?; + let new_team_id = new_team.id; + setup_test_cohort(writer_client.clone(), new_team_id, None).await?; + cohort_cache.get_cohorts_for_team(new_team_id).await?; + + cohort_cache.per_team_cohort_cache.run_pending_tasks().await; + let cache_size_after = cohort_cache.per_team_cohort_cache.entry_count(); + assert_eq!( + cache_size_after, max_capacity, + "Cache size should remain equal to max_capacity after eviction" + ); + + let evicted_team_id = &inserted_team_ids[0]; + let cached_cohorts = cohort_cache + .per_team_cohort_cache + .get(evicted_team_id) + .await; + assert!( + cached_cohorts.is_none(), + "Least recently used cache entry should have been evicted" + ); + + let cached_new_team = cohort_cache.per_team_cohort_cache.get(&new_team_id).await; + assert!( + cached_new_team.is_some(), + "Newly added cache entry should be present" + ); + + Ok(()) + } + + #[tokio::test] + async fn test_get_cohorts_for_team() -> Result<(), anyhow::Error> { + let writer_client = setup_pg_writer_client(None).await; + let reader_client = setup_pg_reader_client(None).await; + let team_id = setup_test_team(writer_client.clone()).await?; + let _cohort = setup_test_cohort(writer_client.clone(), team_id, None).await?; + let cohort_cache = CohortCacheManager::new(reader_client.clone(), None, None); + + let cached_cohorts = cohort_cache.per_team_cohort_cache.get(&team_id).await; + assert!(cached_cohorts.is_none(), "Cache should initially be empty"); + + let cohorts = cohort_cache.get_cohorts_for_team(team_id).await?; + assert_eq!(cohorts.len(), 1); + assert_eq!(cohorts[0].team_id, team_id); + + let cached_cohorts = cohort_cache + .per_team_cohort_cache + .get(&team_id) + .await + .unwrap(); + assert_eq!(cached_cohorts.len(), 1); + assert_eq!(cached_cohorts[0].team_id, team_id); + + Ok(()) + } +} diff --git a/rust/feature-flags/src/cohort_models.rs b/rust/feature-flags/src/cohort_models.rs new file mode 100644 index 00000000000..d1099839017 --- /dev/null +++ b/rust/feature-flags/src/cohort_models.rs @@ -0,0 +1,50 @@ +use crate::flag_definitions::PropertyFilter; +use serde::{Deserialize, Serialize}; +use sqlx::FromRow; + +#[derive(Debug, Clone, Serialize, Deserialize, FromRow)] +pub struct Cohort { + pub id: i32, + pub name: String, + pub description: Option, + pub team_id: i32, + pub deleted: bool, + pub filters: serde_json::Value, + pub query: Option, + pub version: Option, + pub pending_version: Option, + pub count: Option, + pub is_calculating: bool, + pub is_static: bool, + pub errors_calculating: i32, + pub groups: serde_json::Value, + pub created_by_id: Option, +} + +pub type CohortId = i32; + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "UPPERCASE")] +pub enum CohortPropertyType { + AND, + OR, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct CohortProperty { + pub properties: InnerCohortProperty, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct InnerCohortProperty { + #[serde(rename = "type")] + pub prop_type: CohortPropertyType, + pub values: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct CohortValues { + #[serde(rename = "type")] + pub prop_type: String, + pub values: Vec, +} diff --git a/rust/feature-flags/src/cohort_operations.rs b/rust/feature-flags/src/cohort_operations.rs new file mode 100644 index 00000000000..ea4214ccdc0 --- /dev/null +++ b/rust/feature-flags/src/cohort_operations.rs @@ -0,0 +1,369 @@ +use std::collections::HashSet; +use std::sync::Arc; +use tracing::instrument; + +use crate::cohort_models::{Cohort, CohortId, CohortProperty, InnerCohortProperty}; +use crate::{api::FlagError, database::Client as DatabaseClient, flag_definitions::PropertyFilter}; + +impl Cohort { + /// Returns a cohort from postgres given a cohort_id and team_id + #[instrument(skip_all)] + pub async fn from_pg( + client: Arc, + cohort_id: i32, + team_id: i32, + ) -> Result { + let mut conn = client.get_connection().await.map_err(|e| { + tracing::error!("Failed to get database connection: {}", e); + // TODO should I model my errors more generally? Like, yes, everything behind this API is technically a FlagError, + // but I'm not sure if accessing Cohort definitions should be a FlagError (vs idk, a CohortError? A more general API error?) + FlagError::DatabaseUnavailable + })?; + + let query = "SELECT id, name, description, team_id, deleted, filters, query, version, pending_version, count, is_calculating, is_static, errors_calculating, groups, created_by_id FROM posthog_cohort WHERE id = $1 AND team_id = $2"; + let cohort = sqlx::query_as::<_, Cohort>(query) + .bind(cohort_id) + .bind(team_id) + .fetch_optional(&mut *conn) + .await + .map_err(|e| { + tracing::error!("Failed to fetch cohort from database: {}", e); + FlagError::Internal(format!("Database query error: {}", e)) + })?; + + cohort.ok_or_else(|| { + FlagError::CohortNotFound(format!( + "Cohort with id {} not found for team {}", + cohort_id, team_id + )) + }) + } + + /// Returns all cohorts for a given team + #[instrument(skip_all)] + pub async fn list_from_pg( + client: Arc, + team_id: i32, + ) -> Result, FlagError> { + let mut conn = client.get_connection().await.map_err(|e| { + tracing::error!("Failed to get database connection: {}", e); + FlagError::DatabaseUnavailable + })?; + + let query = "SELECT id, name, description, team_id, deleted, filters, query, version, pending_version, count, is_calculating, is_static, errors_calculating, groups, created_by_id FROM posthog_cohort WHERE team_id = $1"; + let cohorts = sqlx::query_as::<_, Cohort>(query) + .bind(team_id) + .fetch_all(&mut *conn) + .await + .map_err(|e| { + tracing::error!("Failed to fetch cohorts from database: {}", e); + FlagError::Internal(format!("Database query error: {}", e)) + })?; + + Ok(cohorts) + } + + /// Parses the filters JSON into a CohortProperty structure + // TODO: this doesn't handle the deprecated "groups" field, see + // https://github.com/PostHog/posthog/blob/feat/dynamic-cohorts-rust/posthog/models/cohort/cohort.py#L114-L169 + // I'll handle that in a separate PR. + pub fn parse_filters(&self) -> Result, FlagError> { + let cohort_property: CohortProperty = serde_json::from_value(self.filters.clone()) + .map_err(|e| { + tracing::error!("Failed to parse filters for cohort {}: {}", self.id, e); + FlagError::CohortFiltersParsingError + })?; + Ok(cohort_property + .properties + .to_property_filters() + .into_iter() + .filter(|f| !(f.key == "id" && f.prop_type == "cohort")) + .collect()) + } + + /// Extracts dependent CohortIds from the cohort's filters + pub fn extract_dependencies(&self) -> Result, FlagError> { + let cohort_property: CohortProperty = serde_json::from_value(self.filters.clone()) + .map_err(|e| { + tracing::error!("Failed to parse filters for cohort {}: {}", self.id, e); + FlagError::CohortFiltersParsingError + })?; + + let mut dependencies = HashSet::new(); + Self::traverse_filters(&cohort_property.properties, &mut dependencies)?; + Ok(dependencies) + } + + /// Recursively traverses the filter tree to find cohort dependencies + /// + /// Example filter tree structure: + /// ```json + /// { + /// "properties": { + /// "type": "OR", + /// "values": [ + /// { + /// "type": "OR", + /// "values": [ + /// { + /// "key": "id", + /// "value": 123, + /// "type": "cohort", + /// "operator": "exact" + /// }, + /// { + /// "key": "email", + /// "value": "@posthog.com", + /// "type": "person", + /// "operator": "icontains" + /// } + /// ] + /// } + /// ] + /// } + /// } + /// ``` + fn traverse_filters( + inner: &InnerCohortProperty, + dependencies: &mut HashSet, + ) -> Result<(), FlagError> { + for cohort_values in &inner.values { + for filter in &cohort_values.values { + if filter.is_cohort() { + // Assuming the value is a single integer CohortId + if let Some(cohort_id) = filter.value.as_i64() { + dependencies.insert(cohort_id as CohortId); + } else { + return Err(FlagError::CohortFiltersParsingError); + } + } + // NB: we don't support nested cohort properties, so we don't need to traverse further + } + } + Ok(()) + } +} + +impl InnerCohortProperty { + /// Flattens the nested cohort property structure into a list of property filters. + /// + /// The cohort property structure in Postgres looks like: + /// ```json + /// { + /// "type": "OR", + /// "values": [ + /// { + /// "type": "OR", + /// "values": [ + /// { + /// "key": "email", + /// "value": "@posthog.com", + /// "type": "person", + /// "operator": "icontains" + /// }, + /// { + /// "key": "age", + /// "value": 25, + /// "type": "person", + /// "operator": "gt" + /// } + /// ] + /// } + /// ] + /// } + /// ``` + pub fn to_property_filters(&self) -> Vec { + self.values + .iter() + .flat_map(|value| &value.values) + .cloned() + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + cohort_models::{CohortPropertyType, CohortValues}, + test_utils::{ + insert_cohort_for_team_in_pg, insert_new_team_in_pg, setup_pg_reader_client, + setup_pg_writer_client, + }, + }; + use serde_json::json; + + #[tokio::test] + async fn test_cohort_from_pg() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .expect("Failed to insert team"); + + let cohort = insert_cohort_for_team_in_pg( + postgres_writer.clone(), + team.id, + None, + json!({"properties": {"type": "OR", "values": [{"type": "OR", "values": [{"key": "$initial_browser_version", "type": "person", "value": ["125"], "negation": false, "operator": "exact"}]}]}}), + false, + ) + .await + .expect("Failed to insert cohort"); + + let fetched_cohort = Cohort::from_pg(postgres_reader, cohort.id, team.id) + .await + .expect("Failed to fetch cohort"); + + assert_eq!(fetched_cohort.id, cohort.id); + assert_eq!(fetched_cohort.name, "Test Cohort"); + assert_eq!(fetched_cohort.team_id, team.id); + } + + #[tokio::test] + async fn test_list_from_pg() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .expect("Failed to insert team"); + + // Insert multiple cohorts for the team + insert_cohort_for_team_in_pg( + postgres_writer.clone(), + team.id, + Some("Cohort 1".to_string()), + json!({"properties": {"type": "AND", "values": [{"type": "property", "values": [{"key": "age", "type": "person", "value": [30], "negation": false, "operator": "gt"}]}]}}), + false, + ) + .await + .expect("Failed to insert cohort1"); + + insert_cohort_for_team_in_pg( + postgres_writer.clone(), + team.id, + Some("Cohort 2".to_string()), + json!({"properties": {"type": "OR", "values": [{"type": "property", "values": [{"key": "country", "type": "person", "value": ["USA"], "negation": false, "operator": "exact"}]}]}}), + false, + ) + .await + .expect("Failed to insert cohort2"); + + let cohorts = Cohort::list_from_pg(postgres_reader, team.id) + .await + .expect("Failed to list cohorts"); + + assert_eq!(cohorts.len(), 2); + let names: HashSet = cohorts.into_iter().map(|c| c.name).collect(); + assert!(names.contains("Cohort 1")); + assert!(names.contains("Cohort 2")); + } + + #[test] + fn test_cohort_parse_filters() { + let cohort = Cohort { + id: 1, + name: "Test Cohort".to_string(), + description: None, + team_id: 1, + deleted: false, + filters: json!({"properties": {"type": "OR", "values": [{"type": "OR", "values": [{"key": "$initial_browser_version", "type": "person", "value": ["125"], "negation": false, "operator": "exact"}]}]}}), + query: None, + version: None, + pending_version: None, + count: None, + is_calculating: false, + is_static: false, + errors_calculating: 0, + groups: json!({}), + created_by_id: None, + }; + + let result = cohort.parse_filters().unwrap(); + assert_eq!(result.len(), 1); + assert_eq!(result[0].key, "$initial_browser_version"); + assert_eq!(result[0].value, json!(["125"])); + assert_eq!(result[0].prop_type, "person"); + } + + #[test] + fn test_cohort_property_to_property_filters() { + let cohort_property = InnerCohortProperty { + prop_type: CohortPropertyType::AND, + values: vec![CohortValues { + prop_type: "property".to_string(), + values: vec![ + PropertyFilter { + key: "email".to_string(), + value: json!("test@example.com"), + operator: None, + prop_type: "person".to_string(), + group_type_index: None, + negation: None, + }, + PropertyFilter { + key: "age".to_string(), + value: json!(25), + operator: None, + prop_type: "person".to_string(), + group_type_index: None, + negation: None, + }, + ], + }], + }; + + let result = cohort_property.to_property_filters(); + assert_eq!(result.len(), 2); + assert_eq!(result[0].key, "email"); + assert_eq!(result[0].value, json!("test@example.com")); + assert_eq!(result[1].key, "age"); + assert_eq!(result[1].value, json!(25)); + } + + #[tokio::test] + async fn test_extract_dependencies() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .expect("Failed to insert team"); + + // Insert a single cohort that is dependent on another cohort + let dependent_cohort = insert_cohort_for_team_in_pg( + postgres_writer.clone(), + team.id, + Some("Dependent Cohort".to_string()), + json!({"properties": {"type": "OR", "values": [{"type": "OR", "values": [{"key": "$browser", "type": "person", "value": ["Safari"], "negation": false, "operator": "exact"}]}]}}), + false, + ) + .await + .expect("Failed to insert dependent_cohort"); + + // Insert main cohort with a single dependency + let main_cohort = insert_cohort_for_team_in_pg( + postgres_writer.clone(), + team.id, + Some("Main Cohort".to_string()), + json!({"properties": {"type": "OR", "values": [{"type": "OR", "values": [{"key": "id", "type": "cohort", "value": dependent_cohort.id, "negation": false}]}]}}), + false, + ) + .await + .expect("Failed to insert main_cohort"); + + let fetched_main_cohort = Cohort::from_pg(postgres_reader.clone(), main_cohort.id, team.id) + .await + .expect("Failed to fetch main cohort"); + + println!("fetched_main_cohort: {:?}", fetched_main_cohort); + + let dependencies = fetched_main_cohort.extract_dependencies().unwrap(); + let expected_dependencies: HashSet = + [dependent_cohort.id].iter().cloned().collect(); + + assert_eq!(dependencies, expected_dependencies); + } +} diff --git a/rust/feature-flags/src/flag_definitions.rs b/rust/feature-flags/src/flag_definitions.rs index baebaa04da3..d62ecc9e0e0 100644 --- a/rust/feature-flags/src/flag_definitions.rs +++ b/rust/feature-flags/src/flag_definitions.rs @@ -1,4 +1,7 @@ -use crate::{api::FlagError, database::Client as DatabaseClient, redis::Client as RedisClient}; +use crate::{ + api::FlagError, cohort_models::CohortId, database::Client as DatabaseClient, + redis::Client as RedisClient, +}; use serde::{Deserialize, Serialize}; use std::sync::Arc; use tracing::instrument; @@ -7,7 +10,7 @@ use tracing::instrument; // TODO: Add integration tests across repos to ensure this doesn't happen. pub const TEAM_FLAGS_CACHE_PREFIX: &str = "posthog:1:team_feature_flags_"; -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum OperatorType { Exact, @@ -25,6 +28,8 @@ pub enum OperatorType { IsDateExact, IsDateAfter, IsDateBefore, + In, + NotIn, } #[derive(Debug, Clone, Deserialize, Serialize)] @@ -36,10 +41,28 @@ pub struct PropertyFilter { pub value: serde_json::Value, pub operator: Option, #[serde(rename = "type")] + // TODO: worth making a enum here to differentiate between cohort and person filters? pub prop_type: String, + pub negation: Option, pub group_type_index: Option, } +impl PropertyFilter { + /// Checks if the filter is a cohort filter + pub fn is_cohort(&self) -> bool { + self.key == "id" && self.prop_type == "cohort" + } + + /// Returns the cohort id if the filter is a cohort filter, or None if it's not a cohort filter + /// or if the value cannot be parsed as a cohort id + pub fn get_cohort_id(&self) -> Option { + if !self.is_cohort() { + return None; + } + self.value.as_i64().map(|id| id as CohortId) + } +} + #[derive(Debug, Clone, Deserialize, Serialize)] pub struct FlagGroupType { pub properties: Option>, @@ -68,6 +91,9 @@ pub struct FlagFilters { pub super_groups: Option>, } +// TODO: see if you can combine these two structs, like we do with cohort models +// this will require not deserializing on read and instead doing it lazily, on-demand +// (which, tbh, is probably a better idea) #[derive(Debug, Clone, Deserialize, Serialize)] pub struct FeatureFlag { pub id: i32, @@ -142,7 +168,7 @@ impl FeatureFlagList { tracing::error!("failed to parse data to flags list: {}", e); println!("failed to parse data: {}", e); - FlagError::DataParsingError + FlagError::RedisDataParsingError })?; Ok(FeatureFlagList { flags: flags_list }) @@ -174,7 +200,7 @@ impl FeatureFlagList { .map(|row| { let filters = serde_json::from_value(row.filters).map_err(|e| { tracing::error!("Failed to deserialize filters for flag {}: {}", row.key, e); - FlagError::DataParsingError + FlagError::RedisDataParsingError })?; Ok(FeatureFlag { @@ -200,7 +226,7 @@ impl FeatureFlagList { ) -> Result<(), FlagError> { let payload = serde_json::to_string(&flags.flags).map_err(|e| { tracing::error!("Failed to serialize flags: {}", e); - FlagError::DataParsingError + FlagError::RedisDataParsingError })?; client @@ -1095,7 +1121,7 @@ mod tests { .expect("Failed to set malformed JSON in Redis"); let result = FeatureFlagList::from_redis(redis_client, team.id).await; - assert!(matches!(result, Err(FlagError::DataParsingError))); + assert!(matches!(result, Err(FlagError::RedisDataParsingError))); // Test database query error (using a non-existent table) let result = sqlx::query("SELECT * FROM non_existent_table") diff --git a/rust/feature-flags/src/flag_matching.rs b/rust/feature-flags/src/flag_matching.rs index bdcd542f098..571fe9c84b4 100644 --- a/rust/feature-flags/src/flag_matching.rs +++ b/rust/feature-flags/src/flag_matching.rs @@ -1,30 +1,34 @@ use crate::{ api::{FlagError, FlagValue, FlagsResponse}, + cohort_cache::CohortCacheManager, + cohort_models::{Cohort, CohortId}, database::Client as DatabaseClient, feature_flag_match_reason::FeatureFlagMatchReason, - flag_definitions::{FeatureFlag, FeatureFlagList, FlagGroupType, PropertyFilter}, + flag_definitions::{FeatureFlag, FeatureFlagList, FlagGroupType, OperatorType, PropertyFilter}, metrics_consts::{FLAG_EVALUATION_ERROR_COUNTER, FLAG_HASH_KEY_WRITES_COUNTER}, + metrics_utils::parse_exception_for_prometheus_label, property_matching::match_property, - utils::parse_exception_for_prometheus_label, }; use anyhow::Result; use common_metrics::inc; +use petgraph::algo::{is_cyclic_directed, toposort}; +use petgraph::graph::DiGraph; use serde_json::Value; use sha1::{Digest, Sha1}; use sqlx::{postgres::PgQueryResult, Acquire, FromRow}; use std::fmt::Write; use std::sync::Arc; use std::{ - collections::{HashMap, HashSet}, + collections::{HashMap, HashSet, VecDeque}, time::Duration, }; use tokio::time::{sleep, timeout}; use tracing::{error, info}; -type TeamId = i32; -type GroupTypeIndex = i32; -type PostgresReader = Arc; -type PostgresWriter = Arc; +pub type TeamId = i32; +pub type GroupTypeIndex = i32; +pub type PostgresReader = Arc; +pub type PostgresWriter = Arc; #[derive(Debug)] struct SuperConditionEvaluation { @@ -182,6 +186,7 @@ pub struct FeatureFlagMatcher { pub team_id: TeamId, pub postgres_reader: PostgresReader, pub postgres_writer: PostgresWriter, + pub cohort_cache: Arc, group_type_mapping_cache: GroupTypeMappingCache, properties_cache: PropertiesCache, groups: HashMap, @@ -195,8 +200,8 @@ impl FeatureFlagMatcher { team_id: TeamId, postgres_reader: PostgresReader, postgres_writer: PostgresWriter, + cohort_cache: Arc, group_type_mapping_cache: Option, - properties_cache: Option, groups: Option>, ) -> Self { FeatureFlagMatcher { @@ -204,10 +209,11 @@ impl FeatureFlagMatcher { team_id, postgres_reader: postgres_reader.clone(), postgres_writer: postgres_writer.clone(), + cohort_cache, group_type_mapping_cache: group_type_mapping_cache .unwrap_or_else(|| GroupTypeMappingCache::new(team_id, postgres_reader.clone())), - properties_cache: properties_cache.unwrap_or_default(), groups: groups.unwrap_or_default(), + properties_cache: PropertiesCache::default(), } } @@ -732,12 +738,29 @@ impl FeatureFlagMatcher { .await; } - // NB: we can only evaluate group or person properties, not both - let properties_to_check = self - .get_properties_to_check(feature_flag, property_overrides, flag_property_filters) + // Separate cohort and non-cohort filters + let (cohort_filters, non_cohort_filters): (Vec, Vec) = + flag_property_filters + .iter() + .cloned() + .partition(|prop| prop.is_cohort()); + + // Get the properties we need to check for in this condition match from the flag + any overrides + let target_properties = self + .get_properties_to_check(feature_flag, property_overrides, &non_cohort_filters) .await?; - if !all_properties_match(flag_property_filters, &properties_to_check) { + // Evaluate non-cohort filters first, since they're cheaper to evaluate and we can return early if they don't match + if !all_properties_match(&non_cohort_filters, &target_properties) { + return Ok((false, FeatureFlagMatchReason::NoConditionMatch)); + } + + // Evaluate cohort filters, if any. + if !cohort_filters.is_empty() + && !self + .evaluate_cohort_filters(&cohort_filters, &target_properties) + .await? + { return Ok((false, FeatureFlagMatchReason::NoConditionMatch)); } } @@ -805,6 +828,37 @@ impl FeatureFlagMatcher { } } + /// Evaluates dynamic cohort property filters + /// + /// NB: This method first caches all of the cohorts associated with the team, which allows us to avoid + /// hitting the database for each cohort filter. + pub async fn evaluate_cohort_filters( + &self, + cohort_property_filters: &[PropertyFilter], + target_properties: &HashMap, + ) -> Result { + // At the start of the request, fetch all of the cohorts for the team from the cache + // This method also caches the cohorts in memory for the duration of the application, so we don't need to fetch from + // the database again until we restart the application. + let cohorts = self.cohort_cache.get_cohorts_for_team(self.team_id).await?; + + // Store cohort match results in a HashMap to avoid re-evaluating the same cohort multiple times, + // since the same cohort could appear in multiple property filters. This is especially important + // because evaluating a cohort requires evaluating all of its dependencies, which can be expensive. + let mut cohort_matches = HashMap::new(); + for filter in cohort_property_filters { + let cohort_id = filter + .get_cohort_id() + .ok_or(FlagError::CohortFiltersParsingError)?; + let match_result = + evaluate_cohort_dependencies(cohort_id, target_properties, cohorts.clone())?; + cohort_matches.insert(cohort_id, match_result); + } + + // Apply cohort membership logic (IN|NOT_IN) + apply_cohort_membership_logic(cohort_property_filters, &cohort_matches) + } + /// Check if a super condition matches for a feature flag. /// /// This function evaluates the super conditions of a feature flag to determine if any of them should be enabled. @@ -1048,6 +1102,172 @@ impl FeatureFlagMatcher { } } +/// Evaluates a single cohort and its dependencies. +/// This uses a topological sort to evaluate dependencies first, which is necessary +/// because a cohort can depend on another cohort, and we need to respect the dependency order. +fn evaluate_cohort_dependencies( + initial_cohort_id: CohortId, + target_properties: &HashMap, + cohorts: Vec, +) -> Result { + let cohort_dependency_graph = + build_cohort_dependency_graph(initial_cohort_id, cohorts.clone())?; + + // We need to sort cohorts topologically to ensure we evaluate dependencies before the cohorts that depend on them. + // For example, if cohort A depends on cohort B, we need to evaluate B first to know if A matches. + // This also helps detect cycles - if cohort A depends on B which depends on A, toposort will fail. + let sorted_cohort_ids_as_graph_nodes = + toposort(&cohort_dependency_graph, None).map_err(|e| { + FlagError::CohortDependencyCycle(format!("Cyclic dependency detected: {:?}", e)) + })?; + + // Store evaluation results for each cohort in a map, so we can look up whether a cohort matched + // when evaluating cohorts that depend on it, and also return the final result for the initial cohort + let mut evaluation_results = HashMap::new(); + + // Iterate through the sorted nodes in reverse order (so that we can evaluate dependencies first) + for node in sorted_cohort_ids_as_graph_nodes.into_iter().rev() { + let cohort_id = cohort_dependency_graph[node]; + let cohort = cohorts + .iter() + .find(|c| c.id == cohort_id) + .ok_or(FlagError::CohortNotFound(cohort_id.to_string()))?; + let property_filters = cohort.parse_filters()?; + let dependencies = cohort.extract_dependencies()?; + + // Check if all dependencies have been met (i.e., previous cohorts matched) + let dependencies_met = dependencies + .iter() + .all(|dep_id| evaluation_results.get(dep_id).copied().unwrap_or(false)); + + // If dependencies are not met, mark the current cohort as not matched and continue + // NB: We don't want to _exit_ here, since the non-matching cohort could be wrapped in a `not_in` operator + // and we want to evaluate all cohorts to determine if the initial cohort matches. + if !dependencies_met { + evaluation_results.insert(cohort_id, false); + continue; + } + + // Evaluate all property filters for the current cohort + let all_filters_match = property_filters + .iter() + .all(|filter| match_property(filter, target_properties, false).unwrap_or(false)); + + // Store the evaluation result for the current cohort + evaluation_results.insert(cohort_id, all_filters_match); + } + + // Retrieve and return the evaluation result for the initial cohort + evaluation_results + .get(&initial_cohort_id) + .copied() + .ok_or_else(|| FlagError::CohortNotFound(initial_cohort_id.to_string())) +} + +/// Apply cohort membership logic (i.e., IN|NOT_IN) +fn apply_cohort_membership_logic( + cohort_filters: &[PropertyFilter], + cohort_matches: &HashMap, +) -> Result { + for filter in cohort_filters { + let cohort_id = filter + .get_cohort_id() + .ok_or(FlagError::CohortFiltersParsingError)?; + let matches = cohort_matches.get(&cohort_id).copied().unwrap_or(false); + let operator = filter.operator.unwrap_or(OperatorType::In); + + // Combine the operator logic directly within this method + let membership_match = match operator { + OperatorType::In => matches, + OperatorType::NotIn => !matches, + // Currently supported operators are IN and NOT IN + // Any other operator defaults to false + _ => false, + }; + + // If any filter does not match, return false early + if !membership_match { + return Ok(false); + } + } + // All filters matched + Ok(true) +} + +/// Constructs a dependency graph for cohorts. +/// +/// Example dependency graph: +/// ```text +/// A B +/// | /| +/// | / | +/// | / | +/// C D +/// \ / +/// \ / +/// E +/// ``` +/// In this example: +/// - Cohorts A and B are root nodes (no dependencies) +/// - C depends on A and B +/// - D depends on B +/// - E depends on C and D +/// +/// The graph is acyclic, which is required for valid cohort dependencies. +fn build_cohort_dependency_graph( + initial_cohort_id: CohortId, + cohorts: Vec, +) -> Result, FlagError> { + let mut graph = DiGraph::new(); + let mut node_map = HashMap::new(); + let mut queue = VecDeque::new(); + // This implements a breadth-first search (BFS) traversal to build a directed graph of cohort dependencies. + // Starting from the initial cohort, we: + // 1. Add each cohort as a node in the graph + // 2. Track visited nodes in a map to avoid duplicates + // 3. For each cohort, get its dependencies and add directed edges from the cohort to its dependencies + // 4. Queue up any unvisited dependencies to process their dependencies later + // This builds up the full dependency graph level by level, which we can later check for cycles + queue.push_back(initial_cohort_id); + node_map.insert(initial_cohort_id, graph.add_node(initial_cohort_id)); + + while let Some(cohort_id) = queue.pop_front() { + let cohort = cohorts + .iter() + .find(|c| c.id == cohort_id) + .ok_or(FlagError::CohortNotFound(cohort_id.to_string()))?; + let dependencies = cohort.extract_dependencies()?; + for dep_id in dependencies { + // Retrieve the current node **before** mutable borrowing + // This is safe because we're not mutating the node map, + // and it keeps the borrow checker happy + let current_node = node_map[&cohort_id]; + // Add dependency node if we haven't seen this cohort ID before in our traversal. + // This happens when we discover a new dependency that wasn't previously + // encountered while processing other cohorts in the graph. + let dep_node = node_map + .entry(dep_id) + .or_insert_with(|| graph.add_node(dep_id)); + + graph.add_edge(current_node, *dep_node, ()); + + if !node_map.contains_key(&dep_id) { + queue.push_back(dep_id); + } + } + } + + // Check for cycles, this is an directed acyclic graph so we use is_cyclic_directed + if is_cyclic_directed(&graph) { + return Err(FlagError::CohortDependencyCycle(format!( + "Cyclic dependency detected starting at cohort {}", + initial_cohort_id + ))); + } + + Ok(graph) +} + /// Fetch and locally cache all properties for a given distinct ID and team ID. /// /// This function fetches both person and group properties for a specified distinct ID and team ID. @@ -1443,8 +1663,8 @@ mod tests { OperatorType, }, test_utils::{ - insert_flag_for_team_in_pg, insert_new_team_in_pg, insert_person_for_team_in_pg, - setup_pg_reader_client, setup_pg_writer_client, + insert_cohort_for_team_in_pg, insert_flag_for_team_in_pg, insert_new_team_in_pg, + insert_person_for_team_in_pg, setup_pg_reader_client, setup_pg_writer_client, }, }; @@ -1485,6 +1705,7 @@ mod tests { async fn test_fetch_properties_from_pg_to_match() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await @@ -1534,7 +1755,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -1547,7 +1768,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -1560,7 +1781,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -1573,6 +1794,7 @@ mod tests { async fn test_person_property_overrides() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -1590,6 +1812,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -1611,7 +1834,7 @@ mod tests { team.id, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ); @@ -1633,6 +1856,7 @@ mod tests { async fn test_group_property_overrides() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -1650,6 +1874,7 @@ mod tests { operator: None, prop_type: "group".to_string(), group_type_index: Some(1), + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -1664,10 +1889,12 @@ mod tests { None, ); - let mut cache = GroupTypeMappingCache::new(team.id, postgres_reader.clone()); + let mut group_type_mapping_cache = + GroupTypeMappingCache::new(team.id, postgres_reader.clone()); let group_types_to_indexes = [("organization".to_string(), 1)].into_iter().collect(); - cache.group_types_to_indexes = group_types_to_indexes; - cache.group_indexes_to_types = [(1, "organization".to_string())].into_iter().collect(); + group_type_mapping_cache.group_types_to_indexes = group_types_to_indexes; + group_type_mapping_cache.group_indexes_to_types = + [(1, "organization".to_string())].into_iter().collect(); let groups = HashMap::from([("organization".to_string(), json!("org_123"))]); @@ -1684,8 +1911,8 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - Some(cache), - None, + cohort_cache.clone(), + Some(group_type_mapping_cache), Some(groups), ); @@ -1708,14 +1935,14 @@ mod tests { let flag = create_test_flag_with_variants(1); let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; - - let mut cache = GroupTypeMappingCache::new(1, postgres_reader.clone()); + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let mut group_type_mapping_cache = GroupTypeMappingCache::new(1, postgres_reader.clone()); let group_types_to_indexes = [("group_type_1".to_string(), 1)].into_iter().collect(); let group_type_index_to_name = [(1, "group_type_1".to_string())].into_iter().collect(); - cache.group_types_to_indexes = group_types_to_indexes; - cache.group_indexes_to_types = group_type_index_to_name; + group_type_mapping_cache.group_types_to_indexes = group_types_to_indexes; + group_type_mapping_cache.group_indexes_to_types = group_type_index_to_name; let groups = HashMap::from([("group_type_1".to_string(), json!("group_key_1"))]); @@ -1724,8 +1951,8 @@ mod tests { 1, postgres_reader.clone(), postgres_writer.clone(), - Some(cache), - None, + cohort_cache.clone(), + Some(group_type_mapping_cache), Some(groups), ); let variant = matcher.get_matching_variant(&flag, None).await.unwrap(); @@ -1740,6 +1967,7 @@ mod tests { async fn test_get_matching_variant_with_db() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -1751,7 +1979,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -1765,6 +1993,7 @@ mod tests { async fn test_is_condition_match_empty_properties() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let flag = create_test_flag( Some(1), None, @@ -1797,7 +2026,7 @@ mod tests { 1, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ); @@ -1854,6 +2083,7 @@ mod tests { async fn test_overrides_avoid_db_lookups() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -1871,6 +2101,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -1893,7 +2124,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -1923,6 +2154,7 @@ mod tests { async fn test_fallback_to_db_when_overrides_insufficient() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -1941,6 +2173,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }, PropertyFilter { key: "age".to_string(), @@ -1948,6 +2181,7 @@ mod tests { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }, ]), rollout_percentage: Some(100.0), @@ -1982,7 +2216,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2006,6 +2240,7 @@ mod tests { async fn test_property_fetching_and_caching() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2025,7 +2260,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2050,6 +2285,7 @@ mod tests { async fn test_property_caching() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2069,7 +2305,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2102,7 +2338,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2150,6 +2386,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }, PropertyFilter { key: "age".to_string(), @@ -2157,6 +2394,7 @@ mod tests { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }, ]; @@ -2170,6 +2408,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }, PropertyFilter { key: "cohort".to_string(), @@ -2177,6 +2416,7 @@ mod tests { operator: None, prop_type: "cohort".to_string(), group_type_index: None, + negation: None, }, ]; @@ -2189,6 +2429,7 @@ mod tests { async fn test_concurrent_flag_evaluation() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2218,13 +2459,14 @@ mod tests { let flag_clone = flag.clone(); let postgres_reader_clone = postgres_reader.clone(); let postgres_writer_clone = postgres_writer.clone(); + let cohort_cache_clone = cohort_cache.clone(); handles.push(tokio::spawn(async move { let mut matcher = FeatureFlagMatcher::new( format!("test_user_{}", i), team.id, postgres_reader_clone, postgres_writer_clone, - None, + cohort_cache_clone, None, None, ); @@ -2246,6 +2488,7 @@ mod tests { async fn test_property_operators() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2264,6 +2507,7 @@ mod tests { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }, PropertyFilter { key: "email".to_string(), @@ -2271,6 +2515,7 @@ mod tests { operator: Some(OperatorType::Icontains), prop_type: "person".to_string(), group_type_index: None, + negation: None, }, ]), rollout_percentage: Some(100.0), @@ -2300,7 +2545,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2314,7 +2559,7 @@ mod tests { async fn test_empty_hashed_identifier() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; - + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let flag = create_test_flag( Some(1), None, @@ -2341,7 +2586,7 @@ mod tests { 1, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ); @@ -2355,6 +2600,7 @@ mod tests { async fn test_rollout_percentage() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let mut flag = create_test_flag( Some(1), None, @@ -2381,7 +2627,7 @@ mod tests { 1, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ); @@ -2402,7 +2648,7 @@ mod tests { async fn test_uneven_variant_distribution() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; - + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let mut flag = create_test_flag_with_variants(1); // Adjust variant rollout percentages to be uneven @@ -2432,7 +2678,7 @@ mod tests { 1, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ); @@ -2464,6 +2710,7 @@ mod tests { async fn test_missing_properties_in_db() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2491,6 +2738,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2510,7 +2758,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache, None, None, ); @@ -2524,6 +2772,7 @@ mod tests { async fn test_malformed_property_data() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2551,6 +2800,7 @@ mod tests { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2570,7 +2820,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache, None, None, ); @@ -2585,6 +2835,7 @@ mod tests { async fn test_get_match_with_insufficient_overrides() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2603,6 +2854,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }, PropertyFilter { key: "age".to_string(), @@ -2610,6 +2862,7 @@ mod tests { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }, ]), rollout_percentage: Some(100.0), @@ -2644,7 +2897,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache, None, None, ); @@ -2661,6 +2914,7 @@ mod tests { async fn test_evaluation_reasons() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let flag = create_test_flag( Some(1), None, @@ -2687,7 +2941,7 @@ mod tests { 1, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache, None, None, ); @@ -2705,6 +2959,7 @@ mod tests { async fn test_complex_conditions() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2723,6 +2978,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2734,6 +2990,7 @@ mod tests { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2763,7 +3020,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache, None, None, ); @@ -2777,6 +3034,7 @@ mod tests { async fn test_super_condition_matches_boolean() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2795,6 +3053,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(0.0), variant: None, @@ -2806,6 +3065,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2826,6 +3086,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2850,7 +3111,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2860,7 +3121,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2870,7 +3131,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2897,6 +3158,7 @@ mod tests { async fn test_super_condition_matches_string() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -2924,6 +3186,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(0.0), variant: None, @@ -2935,6 +3198,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2955,6 +3219,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -2970,7 +3235,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -2986,6 +3251,7 @@ mod tests { async fn test_super_condition_matches_and_false() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -3013,6 +3279,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(0.0), variant: None, @@ -3024,6 +3291,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -3044,6 +3312,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -3059,7 +3328,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -3069,7 +3338,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -3079,7 +3348,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ); @@ -3116,6 +3385,473 @@ mod tests { assert_eq!(result_another_id.condition_index, Some(2)); } + #[tokio::test] + async fn test_basic_cohort_matching() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a cohort with the condition that matches the test user's properties + let cohort_row = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + None, + json!({ + "properties": { + "type": "OR", + "values": [{ + "type": "OR", + "values": [{ + "key": "$browser_version", + "type": "person", + "value": "125", + "negation": false, + "operator": "gt" + }] + }] + } + }), + false, + ) + .await + .unwrap(); + + // Insert a person with properties that match the cohort condition + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "test_user".to_string(), + Some(json!({"$browser_version": 126})), + ) + .await + .unwrap(); + + // Define a flag with a cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort_row.id), + operator: Some(OperatorType::In), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + "test_user".to_string(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!(result.matches); + } + + #[tokio::test] + async fn test_not_in_cohort_matching() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a cohort with a condition that does not match the test user's properties + let cohort_row = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + None, + json!({ + "properties": { + "type": "OR", + "values": [{ + "type": "OR", + "values": [{ + "key": "$browser_version", + "type": "person", + "value": "130", + "negation": false, + "operator": "gt" + }] + }] + } + }), + false, + ) + .await + .unwrap(); + + // Insert a person with properties that do not match the cohort condition + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "test_user".to_string(), + Some(json!({"$browser_version": 126})), + ) + .await + .unwrap(); + + // Define a flag with a NotIn cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort_row.id), + operator: Some(OperatorType::NotIn), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + "test_user".to_string(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!(result.matches); + } + + #[tokio::test] + async fn test_not_in_cohort_matching_user_in_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a cohort with a condition that matches the test user's properties + let cohort_row = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + None, + json!({ + "properties": { + "type": "OR", + "values": [{ + "type": "OR", + "values": [{ + "key": "$browser_version", + "type": "person", + "value": "125", + "negation": false, + "operator": "gt" + }] + }] + } + }), + false, + ) + .await + .unwrap(); + + // Insert a person with properties that match the cohort condition + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "test_user".to_string(), + Some(json!({"$browser_version": 126})), + ) + .await + .unwrap(); + + // Define a flag with a NotIn cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort_row.id), + operator: Some(OperatorType::NotIn), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + "test_user".to_string(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + // The user matches the cohort, but the flag is set to NotIn, so it should evaluate to false + assert!(!result.matches); + } + + #[tokio::test] + async fn test_cohort_dependent_on_another_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a base cohort + let base_cohort_row = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + None, + json!({ + "properties": { + "type": "OR", + "values": [{ + "type": "OR", + "values": [{ + "key": "$browser_version", + "type": "person", + "value": "125", + "negation": false, + "operator": "gt" + }] + }] + } + }), + false, + ) + .await + .unwrap(); + + // Insert a dependent cohort that includes the base cohort + let dependent_cohort_row = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + None, + json!({ + "properties": { + "type": "OR", + "values": [{ + "type": "OR", + "values": [{ + "key": "id", + "type": "cohort", + "value": base_cohort_row.id, + "negation": false, + "operator": "in" + }] + }] + } + }), + false, + ) + .await + .unwrap(); + + // Insert a person with properties that match the base cohort condition + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "test_user".to_string(), + Some(json!({"$browser_version": 126})), + ) + .await + .unwrap(); + + // Define a flag with a cohort filter that depends on another cohort + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(dependent_cohort_row.id), + operator: Some(OperatorType::In), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + "test_user".to_string(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!(result.matches); + } + + #[tokio::test] + async fn test_in_cohort_matching_user_not_in_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a cohort with a condition that does not match the test user's properties + let cohort_row = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + None, + json!({ + "properties": { + "type": "OR", + "values": [{ + "type": "OR", + "values": [{ + "key": "$browser_version", + "type": "person", + "value": "130", + "negation": false, + "operator": "gt" + }] + }] + } + }), + false, + ) + .await + .unwrap(); + + // Insert a person with properties that do not match the cohort condition + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "test_user".to_string(), + Some(json!({"$browser_version": 125})), + ) + .await + .unwrap(); + + // Define a flag with an In cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort_row.id), + operator: Some(OperatorType::In), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + "test_user".to_string(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + // The user does not match the cohort, and the flag is set to In, so it should evaluate to false + assert!(!result.matches); + } + #[tokio::test] async fn test_set_feature_flag_hash_key_overrides_success() { let postgres_reader = setup_pg_reader_client(None).await; @@ -3123,7 +3859,7 @@ mod tests { let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); - let distinct_id = "user1".to_string(); + let distinct_id = "user2".to_string(); // Insert person insert_person_for_team_in_pg(postgres_reader.clone(), team.id, distinct_id.clone(), None) @@ -3148,7 +3884,7 @@ mod tests { Some(true), // ensure_experience_continuity ); - // need to convert flag to FeatureFlagRow + // Convert flag to FeatureFlagRow let flag_row = FeatureFlagRow { id: flag.id, team_id: flag.team_id, @@ -3165,8 +3901,8 @@ mod tests { .await .unwrap(); - // Attempt to set hash key override - let result = set_feature_flag_hash_key_overrides( + // Set hash key override + set_feature_flag_hash_key_overrides( postgres_writer.clone(), team.id, vec![distinct_id.clone()], @@ -3175,9 +3911,7 @@ mod tests { .await .unwrap(); - assert!(result, "Hash key override should be set successfully"); - - // Retrieve the hash key overrides + // Retrieve hash key overrides let overrides = get_feature_flag_hash_key_overrides( postgres_reader.clone(), team.id, @@ -3186,14 +3920,10 @@ mod tests { .await .unwrap(); - assert!( - !overrides.is_empty(), - "At least one hash key override should be set" - ); assert_eq!( overrides.get("test_flag"), Some(&"hash_key_2".to_string()), - "Hash key override for 'test_flag' should match the set value" + "Hash key override should match the set value" ); } @@ -3271,10 +4001,12 @@ mod tests { "Hash key override should match the set value" ); } + #[tokio::test] async fn test_evaluate_feature_flags_with_experience_continuity() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -3304,6 +4036,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -3337,7 +4070,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ) @@ -3356,6 +4089,7 @@ mod tests { async fn test_evaluate_feature_flags_with_continuity_missing_override() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -3385,6 +4119,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -3408,7 +4143,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ) @@ -3427,6 +4162,7 @@ mod tests { async fn test_evaluate_all_feature_flags_mixed_continuity() { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -3456,6 +4192,7 @@ mod tests { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -3484,6 +4221,7 @@ mod tests { operator: Some(OperatorType::Gt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -3517,7 +4255,7 @@ mod tests { team.id, postgres_reader.clone(), postgres_writer.clone(), - None, + cohort_cache.clone(), None, None, ) diff --git a/rust/feature-flags/src/flag_request.rs b/rust/feature-flags/src/flag_request.rs index 771c216834c..1cf64eb879a 100644 --- a/rust/feature-flags/src/flag_request.rs +++ b/rust/feature-flags/src/flag_request.rs @@ -158,8 +158,8 @@ impl FlagRequest { pub async fn get_flags_from_cache_or_pg( &self, team_id: i32, - redis_client: Arc, - pg_client: Arc, + redis_client: &Arc, + pg_client: &Arc, ) -> Result { let mut cache_hit = false; let flags = match FeatureFlagList::from_redis(redis_client.clone(), team_id).await { @@ -167,10 +167,14 @@ impl FlagRequest { cache_hit = true; Ok(flags) } - Err(_) => match FeatureFlagList::from_pg(pg_client, team_id).await { + Err(_) => match FeatureFlagList::from_pg(pg_client.clone(), team_id).await { Ok(flags) => { - if let Err(e) = - FeatureFlagList::update_flags_in_redis(redis_client, team_id, &flags).await + if let Err(e) = FeatureFlagList::update_flags_in_redis( + redis_client.clone(), + team_id, + &flags, + ) + .await { tracing::warn!("Failed to update Redis cache: {}", e); // TODO add new metric category for this @@ -206,7 +210,6 @@ mod tests { TEAM_FLAGS_CACHE_PREFIX, }; use crate::flag_request::FlagRequest; - use crate::redis::Client as RedisClient; use crate::team::Team; use crate::test_utils::{insert_new_team_in_redis, setup_pg_reader_client, setup_redis_client}; use bytes::Bytes; @@ -360,6 +363,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(50.0), variant: None, @@ -402,6 +406,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -426,7 +431,7 @@ mod tests { // Test fetching from Redis let result = flag_request - .get_flags_from_cache_or_pg(team.id, redis_client.clone(), pg_client.clone()) + .get_flags_from_cache_or_pg(team.id, &redis_client, &pg_client) .await; assert!(result.is_ok()); let fetched_flags = result.unwrap(); @@ -483,7 +488,7 @@ mod tests { .expect("Failed to remove flags from Redis"); let result = flag_request - .get_flags_from_cache_or_pg(team.id, redis_client.clone(), pg_client.clone()) + .get_flags_from_cache_or_pg(team.id, &redis_client, &pg_client) .await; assert!(result.is_ok()); // Verify that the flags were re-added to Redis diff --git a/rust/feature-flags/src/lib.rs b/rust/feature-flags/src/lib.rs index 051b3e27697..67659bfcf9d 100644 --- a/rust/feature-flags/src/lib.rs +++ b/rust/feature-flags/src/lib.rs @@ -1,4 +1,7 @@ pub mod api; +pub mod cohort_cache; +pub mod cohort_models; +pub mod cohort_operations; pub mod config; pub mod database; pub mod feature_flag_match_reason; @@ -8,13 +11,13 @@ pub mod flag_matching; pub mod flag_request; pub mod geoip; pub mod metrics_consts; +pub mod metrics_utils; pub mod property_matching; pub mod redis; pub mod request_handler; pub mod router; pub mod server; pub mod team; -pub mod utils; pub mod v0_endpoint; // Test modules don't need to be compiled with main binary diff --git a/rust/feature-flags/src/utils.rs b/rust/feature-flags/src/metrics_utils.rs similarity index 100% rename from rust/feature-flags/src/utils.rs rename to rust/feature-flags/src/metrics_utils.rs diff --git a/rust/feature-flags/src/property_matching.rs b/rust/feature-flags/src/property_matching.rs index 8d12fe6ab5e..84479f13161 100644 --- a/rust/feature-flags/src/property_matching.rs +++ b/rust/feature-flags/src/property_matching.rs @@ -44,7 +44,7 @@ pub fn match_property( } let key = &property.key; - let operator = property.operator.clone().unwrap_or(OperatorType::Exact); + let operator = property.operator.unwrap_or(OperatorType::Exact); let value = &property.value; let match_value = matching_property_values.get(key); @@ -193,6 +193,12 @@ pub fn match_property( // Ok(false) // } } + OperatorType::In | OperatorType::NotIn => { + // TODO: we handle these in cohort matching, so we can just return false here + // because by the time we match properties, we've already decomposed the cohort + // filter into multiple property filters + Ok(false) + } } } @@ -260,6 +266,7 @@ mod test_match_properties { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -313,6 +320,7 @@ mod test_match_properties { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -335,6 +343,7 @@ mod test_match_properties { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -379,6 +388,7 @@ mod test_match_properties { operator: Some(OperatorType::IsNot), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -416,6 +426,7 @@ mod test_match_properties { operator: Some(OperatorType::IsNot), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -490,6 +501,7 @@ mod test_match_properties { operator: Some(OperatorType::IsSet), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -538,6 +550,7 @@ mod test_match_properties { operator: Some(OperatorType::Icontains), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -595,6 +608,7 @@ mod test_match_properties { operator: Some(OperatorType::Icontains), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -634,6 +648,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -674,6 +689,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( &property_b, @@ -708,6 +724,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -730,6 +747,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( &property_d, @@ -760,6 +778,7 @@ mod test_match_properties { operator: Some(OperatorType::Gt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -802,6 +821,7 @@ mod test_match_properties { operator: Some(OperatorType::Lt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -848,6 +868,7 @@ mod test_match_properties { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -889,6 +910,7 @@ mod test_match_properties { operator: Some(OperatorType::Lt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -935,6 +957,7 @@ mod test_match_properties { operator: Some(OperatorType::Lt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -1013,6 +1036,7 @@ mod test_match_properties { operator: Some(OperatorType::IsNot), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1034,6 +1058,7 @@ mod test_match_properties { operator: Some(OperatorType::IsSet), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -1049,6 +1074,7 @@ mod test_match_properties { operator: Some(OperatorType::Icontains), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -1070,6 +1096,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1085,6 +1112,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1118,6 +1146,7 @@ mod test_match_properties { operator: None, prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1137,6 +1166,7 @@ mod test_match_properties { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1152,6 +1182,7 @@ mod test_match_properties { operator: Some(OperatorType::IsSet), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1167,6 +1198,7 @@ mod test_match_properties { operator: Some(OperatorType::IsNotSet), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(match_property( @@ -1203,6 +1235,7 @@ mod test_match_properties { operator: Some(OperatorType::Icontains), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1218,6 +1251,7 @@ mod test_match_properties { operator: Some(OperatorType::NotIcontains), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1233,6 +1267,7 @@ mod test_match_properties { operator: Some(OperatorType::Regex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1248,6 +1283,7 @@ mod test_match_properties { operator: Some(OperatorType::NotRegex), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1263,6 +1299,7 @@ mod test_match_properties { operator: Some(OperatorType::Gt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1278,6 +1315,7 @@ mod test_match_properties { operator: Some(OperatorType::Gte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1293,6 +1331,7 @@ mod test_match_properties { operator: Some(OperatorType::Lt), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1308,6 +1347,7 @@ mod test_match_properties { operator: Some(OperatorType::Lte), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( @@ -1324,6 +1364,7 @@ mod test_match_properties { operator: Some(OperatorType::IsDateBefore), prop_type: "person".to_string(), group_type_index: None, + negation: None, }; assert!(!match_property( diff --git a/rust/feature-flags/src/request_handler.rs b/rust/feature-flags/src/request_handler.rs index 5e0be8faacc..538c6845d2a 100644 --- a/rust/feature-flags/src/request_handler.rs +++ b/rust/feature-flags/src/request_handler.rs @@ -1,5 +1,6 @@ use crate::{ api::{FlagError, FlagsResponse}, + cohort_cache::CohortCacheManager, database::Client, flag_definitions::FeatureFlagList, flag_matching::{FeatureFlagMatcher, GroupTypeMappingCache}, @@ -69,6 +70,7 @@ pub struct FeatureFlagEvaluationContext { feature_flags: FeatureFlagList, postgres_reader: Arc, postgres_writer: Arc, + cohort_cache: Arc, #[builder(default)] person_property_overrides: Option>, #[builder(default)] @@ -108,18 +110,16 @@ pub async fn process_request(context: RequestContext) -> Result = state.postgres_reader.clone(); - let postgres_writer_dyn: Arc = state.postgres_writer.clone(); - let evaluation_context = FeatureFlagEvaluationContextBuilder::default() .team_id(team_id) .distinct_id(distinct_id) .feature_flags(feature_flags_from_cache_or_pg) - .postgres_reader(postgres_reader_dyn) - .postgres_writer(postgres_writer_dyn) + .postgres_reader(state.postgres_reader.clone()) + .postgres_writer(state.postgres_writer.clone()) + .cohort_cache(state.cohort_cache.clone()) .person_property_overrides(person_property_overrides) .group_property_overrides(group_property_overrides) .groups(groups) @@ -224,8 +224,8 @@ pub async fn evaluate_feature_flags(context: FeatureFlagEvaluationContext) -> Fl context.team_id, context.postgres_reader, context.postgres_writer, + context.cohort_cache, Some(group_type_mapping_cache), - None, // TODO maybe remove this from the matcher struct, since it's used internally but not passed around context.groups, ); feature_flag_matcher @@ -359,6 +359,7 @@ mod tests { async fn test_evaluate_feature_flags() { let postgres_reader: Arc = setup_pg_reader_client(None).await; let postgres_writer: Arc = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let flag = FeatureFlag { name: Some("Test Flag".to_string()), id: 1, @@ -374,6 +375,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "person".to_string(), group_type_index: None, + negation: None, }]), rollout_percentage: Some(100.0), // Set to 100% to ensure it's always on variant: None, @@ -397,6 +399,7 @@ mod tests { .feature_flags(feature_flag_list) .postgres_reader(postgres_reader) .postgres_writer(postgres_writer) + .cohort_cache(cohort_cache) .person_property_overrides(Some(person_properties)) .build() .expect("Failed to build FeatureFlagEvaluationContext"); @@ -505,6 +508,7 @@ mod tests { async fn test_evaluate_feature_flags_multiple_flags() { let postgres_reader: Arc = setup_pg_reader_client(None).await; let postgres_writer: Arc = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let flags = vec![ FeatureFlag { name: Some("Flag 1".to_string()), @@ -556,6 +560,7 @@ mod tests { .feature_flags(feature_flag_list) .postgres_reader(postgres_reader) .postgres_writer(postgres_writer) + .cohort_cache(cohort_cache) .build() .expect("Failed to build FeatureFlagEvaluationContext"); @@ -608,6 +613,7 @@ mod tests { async fn test_evaluate_feature_flags_with_overrides() { let postgres_reader: Arc = setup_pg_reader_client(None).await; let postgres_writer: Arc = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let team = insert_new_team_in_pg(postgres_reader.clone(), None) .await .unwrap(); @@ -627,6 +633,7 @@ mod tests { operator: Some(OperatorType::Exact), prop_type: "group".to_string(), group_type_index: Some(0), + negation: None, }]), rollout_percentage: Some(100.0), variant: None, @@ -655,6 +662,7 @@ mod tests { .feature_flags(feature_flag_list) .postgres_reader(postgres_reader) .postgres_writer(postgres_writer) + .cohort_cache(cohort_cache) .group_property_overrides(Some(group_property_overrides)) .groups(Some(groups)) .build() @@ -688,6 +696,7 @@ mod tests { let long_id = "a".repeat(1000); let postgres_reader: Arc = setup_pg_reader_client(None).await; let postgres_writer: Arc = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let flag = FeatureFlag { name: Some("Test Flag".to_string()), id: 1, @@ -717,6 +726,7 @@ mod tests { .feature_flags(feature_flag_list) .postgres_reader(postgres_reader) .postgres_writer(postgres_writer) + .cohort_cache(cohort_cache) .build() .expect("Failed to build FeatureFlagEvaluationContext"); diff --git a/rust/feature-flags/src/router.rs b/rust/feature-flags/src/router.rs index 505f18adfb0..e34ea31a3c6 100644 --- a/rust/feature-flags/src/router.rs +++ b/rust/feature-flags/src/router.rs @@ -9,11 +9,12 @@ use health::HealthRegistry; use tower::limit::ConcurrencyLimitLayer; use crate::{ + cohort_cache::CohortCacheManager, config::{Config, TeamIdsToTrack}, database::Client as DatabaseClient, geoip::GeoIpClient, + metrics_utils::team_id_label_filter, redis::Client as RedisClient, - utils::team_id_label_filter, v0_endpoint, }; @@ -22,6 +23,7 @@ pub struct State { pub redis: Arc, pub postgres_reader: Arc, pub postgres_writer: Arc, + pub cohort_cache: Arc, // TODO does this need a better name than just `cohort_cache`? pub geoip: Arc, pub team_ids_to_track: TeamIdsToTrack, } @@ -30,6 +32,7 @@ pub fn router( redis: Arc, postgres_reader: Arc, postgres_writer: Arc, + cohort_cache: Arc, geoip: Arc, liveness: HealthRegistry, config: Config, @@ -42,6 +45,7 @@ where redis, postgres_reader, postgres_writer, + cohort_cache, geoip, team_ids_to_track: config.team_ids_to_track.clone(), }; diff --git a/rust/feature-flags/src/server.rs b/rust/feature-flags/src/server.rs index c9e238fa8fd..69ff759ddfc 100644 --- a/rust/feature-flags/src/server.rs +++ b/rust/feature-flags/src/server.rs @@ -6,6 +6,7 @@ use std::time::Duration; use health::{HealthHandle, HealthRegistry}; use tokio::net::TcpListener; +use crate::cohort_cache::CohortCacheManager; use crate::config::Config; use crate::database::get_pool; use crate::geoip::GeoIpClient; @@ -54,6 +55,8 @@ where } }; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let health = HealthRegistry::new("liveness"); // TODO - we don't have a more complex health check yet, but we should add e.g. some around DB operations @@ -67,6 +70,7 @@ where redis_client, postgres_reader, postgres_writer, + cohort_cache, geoip_service, health, config, diff --git a/rust/feature-flags/src/team.rs b/rust/feature-flags/src/team.rs index 0fa75f0bd3d..f13cf29094b 100644 --- a/rust/feature-flags/src/team.rs +++ b/rust/feature-flags/src/team.rs @@ -42,7 +42,7 @@ impl Team { // TODO: Consider an LRU cache for teams as well, with small TTL to skip redis/pg lookups let team: Team = serde_json::from_str(&serialized_team).map_err(|e| { tracing::error!("failed to parse data to team: {}", e); - FlagError::DataParsingError + FlagError::RedisDataParsingError })?; Ok(team) @@ -55,7 +55,7 @@ impl Team { ) -> Result<(), FlagError> { let serialized_team = serde_json::to_string(&team).map_err(|e| { tracing::error!("Failed to serialize team: {}", e); - FlagError::DataParsingError + FlagError::RedisDataParsingError })?; client @@ -173,7 +173,7 @@ mod tests { let client = setup_redis_client(None); match Team::from_redis(client.clone(), team.api_token.clone()).await { - Err(FlagError::DataParsingError) => (), + Err(FlagError::RedisDataParsingError) => (), Err(other) => panic!("Expected DataParsingError, got {:?}", other), Ok(_) => panic!("Expected DataParsingError"), }; diff --git a/rust/feature-flags/src/test_utils.rs b/rust/feature-flags/src/test_utils.rs index 32a2016bf75..22f7753d979 100644 --- a/rust/feature-flags/src/test_utils.rs +++ b/rust/feature-flags/src/test_utils.rs @@ -1,11 +1,12 @@ use anyhow::Error; use axum::async_trait; use serde_json::{json, Value}; -use sqlx::{pool::PoolConnection, postgres::PgRow, Error as SqlxError, PgPool, Postgres}; +use sqlx::{pool::PoolConnection, postgres::PgRow, Error as SqlxError, Postgres}; use std::sync::Arc; use uuid::Uuid; use crate::{ + cohort_models::Cohort, config::{Config, DEFAULT_TEST_CONFIG}, database::{get_pool, Client, CustomDatabaseError}, flag_definitions::{self, FeatureFlag, FeatureFlagRow}, @@ -23,7 +24,9 @@ pub fn random_string(prefix: &str, length: usize) -> String { format!("{}{}", prefix, suffix) } -pub async fn insert_new_team_in_redis(client: Arc) -> Result { +pub async fn insert_new_team_in_redis( + client: Arc, +) -> Result { let id = rand::thread_rng().gen_range(0..10_000_000); let token = random_string("phc_", 12); let team = Team { @@ -48,7 +51,7 @@ pub async fn insert_new_team_in_redis(client: Arc) -> Result, + client: Arc, team_id: i32, json_value: Option, ) -> Result<(), Error> { @@ -88,7 +91,7 @@ pub async fn insert_flags_for_team_in_redis( Ok(()) } -pub fn setup_redis_client(url: Option) -> Arc { +pub fn setup_redis_client(url: Option) -> Arc { let redis_url = match url { Some(value) => value, None => "redis://localhost:6379/".to_string(), @@ -130,7 +133,7 @@ pub fn create_flag_from_json(json_value: Option) -> Vec { flags } -pub async fn setup_pg_reader_client(config: Option<&Config>) -> Arc { +pub async fn setup_pg_reader_client(config: Option<&Config>) -> Arc { let config = config.unwrap_or(&DEFAULT_TEST_CONFIG); Arc::new( get_pool(&config.read_database_url, config.max_pg_connections) @@ -139,7 +142,7 @@ pub async fn setup_pg_reader_client(config: Option<&Config>) -> Arc { ) } -pub async fn setup_pg_writer_client(config: Option<&Config>) -> Arc { +pub async fn setup_pg_writer_client(config: Option<&Config>) -> Arc { let config = config.unwrap_or(&DEFAULT_TEST_CONFIG); Arc::new( get_pool(&config.write_database_url, config.max_pg_connections) @@ -261,7 +264,7 @@ pub async fn insert_new_team_in_pg( } pub async fn insert_flag_for_team_in_pg( - client: Arc, + client: Arc, team_id: i32, flag: Option, ) -> Result { @@ -310,7 +313,7 @@ pub async fn insert_flag_for_team_in_pg( } pub async fn insert_person_for_team_in_pg( - client: Arc, + client: Arc, team_id: i32, distinct_id: String, properties: Option, @@ -352,3 +355,58 @@ pub async fn insert_person_for_team_in_pg( Ok(()) } + +pub async fn insert_cohort_for_team_in_pg( + client: Arc, + team_id: i32, + name: Option, + filters: serde_json::Value, + is_static: bool, +) -> Result { + let cohort = Cohort { + id: 0, // Placeholder, will be updated after insertion + name: name.unwrap_or("Test Cohort".to_string()), + description: Some("Description for cohort".to_string()), + team_id, + deleted: false, + filters, + query: None, + version: Some(1), + pending_version: None, + count: None, + is_calculating: false, + is_static, + errors_calculating: 0, + groups: serde_json::json!([]), + created_by_id: None, + }; + + let mut conn = client.get_connection().await?; + let row: (i32,) = sqlx::query_as( + r#"INSERT INTO posthog_cohort + (name, description, team_id, deleted, filters, query, version, pending_version, count, is_calculating, is_static, errors_calculating, groups, created_by_id) VALUES + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) + RETURNING id"#, + ) + .bind(&cohort.name) + .bind(&cohort.description) + .bind(cohort.team_id) + .bind(cohort.deleted) + .bind(&cohort.filters) + .bind(&cohort.query) + .bind(cohort.version) + .bind(cohort.pending_version) + .bind(cohort.count) + .bind(cohort.is_calculating) + .bind(cohort.is_static) + .bind(cohort.errors_calculating) + .bind(&cohort.groups) + .bind(cohort.created_by_id) + .fetch_one(&mut *conn) + .await?; + + // Update the cohort_row with the actual id generated by sqlx + let id = row.0; + + Ok(Cohort { id, ..cohort }) +} diff --git a/rust/feature-flags/tests/test_flag_matching_consistency.rs b/rust/feature-flags/tests/test_flag_matching_consistency.rs index 94f4f67dcdc..c632d28bc15 100644 --- a/rust/feature-flags/tests/test_flag_matching_consistency.rs +++ b/rust/feature-flags/tests/test_flag_matching_consistency.rs @@ -1,3 +1,6 @@ +use std::sync::Arc; + +use feature_flags::cohort_cache::CohortCacheManager; use feature_flags::feature_flag_match_reason::FeatureFlagMatchReason; /// These tests are common between all libraries doing local evaluation of feature flags. /// This ensures there are no mismatches between implementations. @@ -110,6 +113,7 @@ async fn it_is_consistent_with_rollout_calculation_for_simple_flags() { for (i, result) in results.iter().enumerate().take(1000) { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let distinct_id = format!("distinct_id_{}", i); @@ -118,7 +122,7 @@ async fn it_is_consistent_with_rollout_calculation_for_simple_flags() { 1, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ) @@ -1209,6 +1213,7 @@ async fn it_is_consistent_with_rollout_calculation_for_multivariate_flags() { for (i, result) in results.iter().enumerate().take(1000) { let postgres_reader = setup_pg_reader_client(None).await; let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); let distinct_id = format!("distinct_id_{}", i); let feature_flag_match = FeatureFlagMatcher::new( @@ -1216,7 +1221,7 @@ async fn it_is_consistent_with_rollout_calculation_for_multivariate_flags() { 1, postgres_reader, postgres_writer, - None, + cohort_cache, None, None, ) From f5a567f01a730dce04d09a945e47d7f849dd082b Mon Sep 17 00:00:00 2001 From: Dylan Martin Date: Sat, 16 Nov 2024 01:02:43 +0100 Subject: [PATCH 04/27] feat(flags): add support for matching static cohort membership (#25942) --- rust/feature-flags/src/api.rs | 5 + rust/feature-flags/src/flag_matching.rs | 647 +++++++++++++++++++--- rust/feature-flags/src/request_handler.rs | 1 + rust/feature-flags/src/test_utils.rs | 62 ++- 4 files changed, 636 insertions(+), 79 deletions(-) diff --git a/rust/feature-flags/src/api.rs b/rust/feature-flags/src/api.rs index 9d6b649719b..be21c1c37f5 100644 --- a/rust/feature-flags/src/api.rs +++ b/rust/feature-flags/src/api.rs @@ -108,6 +108,8 @@ pub enum FlagError { CohortFiltersParsingError, #[error("Cohort dependency cycle")] CohortDependencyCycle(String), + #[error("Person not found")] + PersonNotFound, } impl IntoResponse for FlagError { @@ -212,6 +214,9 @@ impl IntoResponse for FlagError { tracing::error!("Cohort dependency cycle: {}", msg); (StatusCode::BAD_REQUEST, msg) } + FlagError::PersonNotFound => { + (StatusCode::BAD_REQUEST, "Person not found. Please check your distinct_id and try again.".to_string()) + } } .into_response() } diff --git a/rust/feature-flags/src/flag_matching.rs b/rust/feature-flags/src/flag_matching.rs index 571fe9c84b4..d9332fce4e4 100644 --- a/rust/feature-flags/src/flag_matching.rs +++ b/rust/feature-flags/src/flag_matching.rs @@ -15,7 +15,7 @@ use petgraph::algo::{is_cyclic_directed, toposort}; use petgraph::graph::DiGraph; use serde_json::Value; use sha1::{Digest, Sha1}; -use sqlx::{postgres::PgQueryResult, Acquire, FromRow}; +use sqlx::{postgres::PgQueryResult, Acquire, FromRow, Row}; use std::fmt::Write; use std::sync::Arc; use std::{ @@ -26,6 +26,7 @@ use tokio::time::{sleep, timeout}; use tracing::{error, info}; pub type TeamId = i32; +pub type PersonId = i32; pub type GroupTypeIndex = i32; pub type PostgresReader = Arc; pub type PostgresWriter = Arc; @@ -176,6 +177,7 @@ impl GroupTypeMappingCache { /// to fetch the properties from the DB each time. #[derive(Clone, Default, Debug)] pub struct PropertiesCache { + person_id: Option, person_properties: Option>, group_properties: HashMap>, } @@ -217,9 +219,18 @@ impl FeatureFlagMatcher { } } - /// Evaluate feature flags for a given distinct_id - /// - Returns a map of feature flag keys to their values - /// - If an error occurs while evaluating a flag, it will be logged and the flag will be omitted from the result + /// Evaluates all feature flags for the current matcher context. + /// + /// ## Arguments + /// + /// * `feature_flags` - The list of feature flags to evaluate. + /// * `person_property_overrides` - Any overrides for person properties. + /// * `group_property_overrides` - Any overrides for group properties. + /// * `hash_key_override` - Optional hash key overrides for experience continuity. + /// + /// ## Returns + /// + /// * `FlagsResponse` - The result containing flag evaluations and any errors. pub async fn evaluate_all_feature_flags( &mut self, feature_flags: FeatureFlagList, @@ -746,22 +757,29 @@ impl FeatureFlagMatcher { .partition(|prop| prop.is_cohort()); // Get the properties we need to check for in this condition match from the flag + any overrides - let target_properties = self + let person_or_group_properties = self .get_properties_to_check(feature_flag, property_overrides, &non_cohort_filters) .await?; // Evaluate non-cohort filters first, since they're cheaper to evaluate and we can return early if they don't match - if !all_properties_match(&non_cohort_filters, &target_properties) { + if !all_properties_match(&non_cohort_filters, &person_or_group_properties) { return Ok((false, FeatureFlagMatchReason::NoConditionMatch)); } // Evaluate cohort filters, if any. - if !cohort_filters.is_empty() - && !self - .evaluate_cohort_filters(&cohort_filters, &target_properties) + if !cohort_filters.is_empty() { + // Get the person ID for the current distinct ID – this value should be cached at this point, but as a fallback we fetch from the database + let person_id = self.get_person_id().await?; + if !self + .evaluate_cohort_filters( + &cohort_filters, + &person_or_group_properties, + person_id, + ) .await? - { - return Ok((false, FeatureFlagMatchReason::NoConditionMatch)); + { + return Ok((false, FeatureFlagMatchReason::NoConditionMatch)); + } } } @@ -809,6 +827,31 @@ impl FeatureFlagMatcher { } } + /// Retrieves the `PersonId` from the properties cache. + /// If the cache does not contain a `PersonId`, it fetches it from the database + /// and updates the cache accordingly. + async fn get_person_id(&mut self) -> Result { + match self.properties_cache.person_id { + Some(id) => Ok(id), + None => { + let id = self.get_person_id_from_db().await?; + self.properties_cache.person_id = Some(id); + Ok(id) + } + } + } + + /// Fetches the `PersonId` from the database based on the current `distinct_id` and `team_id`. + /// This method is called when the `PersonId` is not present in the properties cache. + async fn get_person_id_from_db(&mut self) -> Result { + let postgres_reader = self.postgres_reader.clone(); + let distinct_id = self.distinct_id.clone(); + let team_id = self.team_id; + fetch_person_properties_from_db(postgres_reader, distinct_id, team_id) + .await + .map(|(_, person_id)| person_id) + } + /// Get person properties from cache or database. /// /// This function attempts to retrieve person properties either from a cache or directly from the database. @@ -836,26 +879,45 @@ impl FeatureFlagMatcher { &self, cohort_property_filters: &[PropertyFilter], target_properties: &HashMap, + person_id: PersonId, ) -> Result { // At the start of the request, fetch all of the cohorts for the team from the cache - // This method also caches the cohorts in memory for the duration of the application, so we don't need to fetch from - // the database again until we restart the application. + // This method also caches any cohorts for a given team in memory for the duration of the application, so we don't need to fetch from + // the database again until we restart the application. See the CohortCacheManager for more details. let cohorts = self.cohort_cache.get_cohorts_for_team(self.team_id).await?; - // Store cohort match results in a HashMap to avoid re-evaluating the same cohort multiple times, - // since the same cohort could appear in multiple property filters. This is especially important - // because evaluating a cohort requires evaluating all of its dependencies, which can be expensive. + // Split the cohorts into static and dynamic, since the dynamic ones have property filters + // and we need to evaluate them based on the target properties, whereas the static ones are + // purely based on person properties and are membership-based. + let (static_cohorts, dynamic_cohorts): (Vec<_>, Vec<_>) = + cohorts.iter().partition(|c| c.is_static); + + // Store all cohort match results in a HashMap to avoid re-evaluating the same cohort multiple times, + // since the same cohort could appear in multiple property filters. let mut cohort_matches = HashMap::new(); - for filter in cohort_property_filters { - let cohort_id = filter - .get_cohort_id() - .ok_or(FlagError::CohortFiltersParsingError)?; - let match_result = - evaluate_cohort_dependencies(cohort_id, target_properties, cohorts.clone())?; - cohort_matches.insert(cohort_id, match_result); + + if !static_cohorts.is_empty() { + let results = evaluate_static_cohorts( + self.postgres_reader.clone(), + person_id, + static_cohorts.iter().map(|c| c.id).collect(), + ) + .await?; + cohort_matches.extend(results); } - // Apply cohort membership logic (IN|NOT_IN) + if !dynamic_cohorts.is_empty() { + for filter in cohort_property_filters { + let cohort_id = filter + .get_cohort_id() + .ok_or(FlagError::CohortFiltersParsingError)?; + let match_result = + evaluate_dynamic_cohorts(cohort_id, target_properties, cohorts.clone())?; + cohort_matches.insert(cohort_id, match_result); + } + } + + // Apply cohort membership logic (IN|NOT_IN) to the cohort match results apply_cohort_membership_logic(cohort_property_filters, &cohort_matches) } @@ -971,11 +1033,12 @@ impl FeatureFlagMatcher { let postgres_reader = self.postgres_reader.clone(); let distinct_id = self.distinct_id.clone(); let team_id = self.team_id; - let db_properties = + let (db_properties, person_id) = fetch_person_properties_from_db(postgres_reader, distinct_id, team_id).await?; - // once the properties are fetched, cache them so we don't need to fetch again in a given request + // once the properties and person ID are fetched, cache them so we don't need to fetch again in a given request self.properties_cache.person_properties = Some(db_properties.clone()); + self.properties_cache.person_id = Some(person_id); Ok(db_properties) } @@ -1102,10 +1165,49 @@ impl FeatureFlagMatcher { } } -/// Evaluates a single cohort and its dependencies. +/// Evaluate static cohort filters by checking if the person is in each cohort. +async fn evaluate_static_cohorts( + postgres_reader: PostgresReader, + person_id: i32, // Change this parameter from distinct_id to person_id + cohort_ids: Vec, +) -> Result, FlagError> { + let mut conn = postgres_reader.get_connection().await?; + + let query = r#" + WITH cohort_membership AS ( + SELECT c.cohort_id, + CASE WHEN pc.cohort_id IS NOT NULL THEN true ELSE false END AS is_member + FROM unnest($1::integer[]) AS c(cohort_id) + LEFT JOIN posthog_cohortpeople AS pc + ON pc.person_id = $2 + AND pc.cohort_id = c.cohort_id + ) + SELECT cohort_id, is_member + FROM cohort_membership + "#; + + let rows = sqlx::query(query) + .bind(&cohort_ids) + .bind(person_id) // Bind person_id directly + .fetch_all(&mut *conn) + .await?; + + let result = rows + .into_iter() + .map(|row| { + let cohort_id: CohortId = row.get("cohort_id"); + let is_member: bool = row.get("is_member"); + (cohort_id, is_member) + }) + .collect(); + + Ok(result) +} + +/// Evaluates a dynamic cohort and its dependencies. /// This uses a topological sort to evaluate dependencies first, which is necessary /// because a cohort can depend on another cohort, and we need to respect the dependency order. -fn evaluate_cohort_dependencies( +fn evaluate_dynamic_cohorts( initial_cohort_id: CohortId, target_properties: &HashMap, cohorts: Vec, @@ -1221,6 +1323,16 @@ fn build_cohort_dependency_graph( let mut graph = DiGraph::new(); let mut node_map = HashMap::new(); let mut queue = VecDeque::new(); + + let initial_cohort = cohorts + .iter() + .find(|c| c.id == initial_cohort_id) + .ok_or(FlagError::CohortNotFound(initial_cohort_id.to_string()))?; + + if initial_cohort.is_static { + return Ok(graph); + } + // This implements a breadth-first search (BFS) traversal to build a directed graph of cohort dependencies. // Starting from the initial cohort, we: // 1. Add each cohort as a node in the graph @@ -1283,32 +1395,52 @@ async fn fetch_and_locally_cache_all_properties( let query = r#" SELECT - (SELECT "posthog_person"."properties" - FROM "posthog_person" - INNER JOIN "posthog_persondistinctid" - ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") - WHERE ("posthog_persondistinctid"."distinct_id" = $1 - AND "posthog_persondistinctid"."team_id" = $2 - AND "posthog_person"."team_id" = $2) - LIMIT 1) as person_properties, - - (SELECT json_object_agg("posthog_group"."group_type_index", "posthog_group"."group_properties") - FROM "posthog_group" - WHERE ("posthog_group"."team_id" = $2 - AND "posthog_group"."group_type_index" = ANY($3))) as group_properties + person.person_id, + person.person_properties, + group_properties.group_properties + FROM ( + SELECT + "posthog_person"."id" AS person_id, + "posthog_person"."properties" AS person_properties + FROM "posthog_person" + INNER JOIN "posthog_persondistinctid" + ON "posthog_person"."id" = "posthog_persondistinctid"."person_id" + WHERE + "posthog_persondistinctid"."distinct_id" = $1 + AND "posthog_persondistinctid"."team_id" = $2 + AND "posthog_person"."team_id" = $2 + LIMIT 1 + ) AS person, + ( + SELECT + json_object_agg( + "posthog_group"."group_type_index", + "posthog_group"."group_properties" + ) AS group_properties + FROM "posthog_group" + WHERE + "posthog_group"."team_id" = $2 + AND "posthog_group"."group_type_index" = ANY($3) + ) AS group_properties "#; let group_type_indexes_vec: Vec = group_type_indexes.iter().cloned().collect(); - let row: (Option, Option) = sqlx::query_as(query) + let row: (Option, Option, Option) = sqlx::query_as(query) .bind(&distinct_id) .bind(team_id) .bind(&group_type_indexes_vec) .fetch_optional(&mut *conn) .await? - .unwrap_or((None, None)); + .unwrap_or((None, None, None)); - if let Some(person_props) = row.0 { + let (person_id, person_props, group_props) = row; + + if let Some(person_id) = person_id { + properties_cache.person_id = Some(person_id); + } + + if let Some(person_props) = person_props { properties_cache.person_properties = Some( person_props .as_object() @@ -1319,7 +1451,7 @@ async fn fetch_and_locally_cache_all_properties( ); } - if let Some(group_props) = row.1 { + if let Some(group_props) = group_props { let group_props_map: HashMap> = group_props .as_object() .unwrap_or(&serde_json::Map::new()) @@ -1342,7 +1474,7 @@ async fn fetch_and_locally_cache_all_properties( Ok(()) } -/// Fetch person properties from the database for a given distinct ID and team ID. +/// Fetch person properties and person ID from the database for a given distinct ID and team ID. /// /// This function constructs and executes a SQL query to fetch the person properties for a specified distinct ID and team ID. /// It returns the fetched properties as a HashMap. @@ -1350,31 +1482,37 @@ async fn fetch_person_properties_from_db( postgres_reader: PostgresReader, distinct_id: String, team_id: TeamId, -) -> Result, FlagError> { +) -> Result<(HashMap, i32), FlagError> { let mut conn = postgres_reader.as_ref().get_connection().await?; let query = r#" - SELECT "posthog_person"."properties" as person_properties - FROM "posthog_person" - INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") - WHERE ("posthog_persondistinctid"."distinct_id" = $1 - AND "posthog_persondistinctid"."team_id" = $2 - AND "posthog_person"."team_id" = $2) - LIMIT 1 - "#; + SELECT "posthog_person"."id" as person_id, "posthog_person"."properties" as person_properties + FROM "posthog_person" + INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") + WHERE ("posthog_persondistinctid"."distinct_id" = $1 + AND "posthog_persondistinctid"."team_id" = $2 + AND "posthog_person"."team_id" = $2) + LIMIT 1 + "#; - let row: Option = sqlx::query_scalar(query) + let row: Option<(i32, Value)> = sqlx::query_as(query) .bind(&distinct_id) .bind(team_id) .fetch_optional(&mut *conn) .await?; - Ok(row - .and_then(|v| v.as_object().cloned()) - .unwrap_or_default() - .into_iter() - .map(|(k, v)| (k, v.clone())) - .collect()) + match row { + Some((person_id, person_props)) => { + let properties_map = person_props + .as_object() + .unwrap_or(&serde_json::Map::new()) + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); + Ok((properties_map, person_id)) + } + None => Err(FlagError::PersonNotFound), + } } /// Fetch group properties from the database for a given team ID and group type index. @@ -1436,11 +1574,11 @@ fn locally_computable_property_overrides( /// Check if all properties match the given filters fn all_properties_match( flag_condition_properties: &[PropertyFilter], - target_properties: &HashMap, + matching_property_values: &HashMap, ) -> bool { flag_condition_properties .iter() - .all(|property| match_property(property, target_properties, false).unwrap_or(false)) + .all(|property| match_property(property, matching_property_values, false).unwrap_or(false)) } async fn get_feature_flag_hash_key_overrides( @@ -1663,8 +1801,9 @@ mod tests { OperatorType, }, test_utils::{ - insert_cohort_for_team_in_pg, insert_flag_for_team_in_pg, insert_new_team_in_pg, - insert_person_for_team_in_pg, setup_pg_reader_client, setup_pg_writer_client, + add_person_to_cohort, get_person_id_by_distinct_id, insert_cohort_for_team_in_pg, + insert_flag_for_team_in_pg, insert_new_team_in_pg, insert_person_for_team_in_pg, + setup_pg_reader_client, setup_pg_writer_client, }, }; @@ -1750,6 +1889,7 @@ mod tests { )) .unwrap(); + // Matcher for a matching distinct_id let mut matcher = FeatureFlagMatcher::new( distinct_id.clone(), team.id, @@ -1763,6 +1903,7 @@ mod tests { assert!(match_result.matches); assert_eq!(match_result.variant, None); + // Matcher for a non-matching distinct_id let mut matcher = FeatureFlagMatcher::new( not_matching_distinct_id.clone(), team.id, @@ -1776,6 +1917,7 @@ mod tests { assert!(!match_result.matches); assert_eq!(match_result.variant, None); + // Matcher for a distinct_id that does not exist let mut matcher = FeatureFlagMatcher::new( "other_distinct_id".to_string(), team.id, @@ -1785,9 +1927,10 @@ mod tests { None, None, ); - let match_result = matcher.get_match(&flag, None, None).await.unwrap(); - assert!(!match_result.matches); - assert_eq!(match_result.variant, None); + let match_result = matcher.get_match(&flag, None, None).await; + + // Expecting an error for non-existent distinct_id + assert!(match_result.is_err()); } #[tokio::test] @@ -3106,6 +3249,19 @@ mod tests { .await .unwrap(); + insert_person_for_team_in_pg(postgres_reader.clone(), team.id, "lil_id".to_string(), None) + .await + .unwrap(); + + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "another_id".to_string(), + None, + ) + .await + .unwrap(); + let mut matcher_test_id = FeatureFlagMatcher::new( "test_id".to_string(), team.id, @@ -3265,6 +3421,19 @@ mod tests { .await .unwrap(); + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + "another_id".to_string(), + None, + ) + .await + .unwrap(); + + insert_person_for_team_in_pg(postgres_reader.clone(), team.id, "lil_id".to_string(), None) + .await + .unwrap(); + let flag = create_test_flag( Some(1), Some(team.id), @@ -3852,6 +4021,344 @@ mod tests { assert!(!result.matches); } + #[tokio::test] + async fn test_static_cohort_matching_user_in_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a static cohort + let cohort = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + Some("Static Cohort".to_string()), + json!({}), // Static cohorts don't have property filters + true, // is_static = true + ) + .await + .unwrap(); + + // Insert a person + let distinct_id = "static_user".to_string(); + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + distinct_id.clone(), + Some(json!({"email": "static@user.com"})), + ) + .await + .unwrap(); + + // Retrieve the person's ID + let person_id = + get_person_id_by_distinct_id(postgres_reader.clone(), team.id, &distinct_id) + .await + .unwrap(); + + // Associate the person with the static cohort + add_person_to_cohort(postgres_reader.clone(), person_id, cohort.id) + .await + .unwrap(); + + // Define a flag with an 'In' cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort.id), + operator: Some(OperatorType::In), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + distinct_id.clone(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!( + result.matches, + "User should match the static cohort and flag" + ); + } + + #[tokio::test] + async fn test_static_cohort_matching_user_not_in_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a static cohort + let cohort = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + Some("Another Static Cohort".to_string()), + json!({}), // Static cohorts don't have property filters + true, + ) + .await + .unwrap(); + + // Insert a person + let distinct_id = "non_static_user".to_string(); + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + distinct_id.clone(), + Some(json!({"email": "nonstatic@user.com"})), + ) + .await + .unwrap(); + + // Note: Do NOT associate the person with the static cohort + + // Define a flag with an 'In' cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort.id), + operator: Some(OperatorType::In), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + distinct_id.clone(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!( + !result.matches, + "User should not match the static cohort and flag" + ); + } + + #[tokio::test] + async fn test_static_cohort_not_in_matching_user_not_in_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a static cohort + let cohort = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + Some("Static Cohort NotIn".to_string()), + json!({}), // Static cohorts don't have property filters + true, // is_static = true + ) + .await + .unwrap(); + + // Insert a person + let distinct_id = "not_in_static_user".to_string(); + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + distinct_id.clone(), + Some(json!({"email": "notinstatic@user.com"})), + ) + .await + .unwrap(); + + // No association with the static cohort + + // Define a flag with a 'NotIn' cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort.id), + operator: Some(OperatorType::NotIn), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + distinct_id.clone(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!( + result.matches, + "User not in the static cohort should match the 'NotIn' flag" + ); + } + + #[tokio::test] + async fn test_static_cohort_not_in_matching_user_in_cohort() { + let postgres_reader = setup_pg_reader_client(None).await; + let postgres_writer = setup_pg_writer_client(None).await; + let cohort_cache = Arc::new(CohortCacheManager::new(postgres_reader.clone(), None, None)); + let team = insert_new_team_in_pg(postgres_reader.clone(), None) + .await + .unwrap(); + + // Insert a static cohort + let cohort = insert_cohort_for_team_in_pg( + postgres_reader.clone(), + team.id, + Some("Static Cohort NotIn User In".to_string()), + json!({}), // Static cohorts don't have property filters + true, // is_static = true + ) + .await + .unwrap(); + + // Insert a person + let distinct_id = "in_not_in_static_user".to_string(); + insert_person_for_team_in_pg( + postgres_reader.clone(), + team.id, + distinct_id.clone(), + Some(json!({"email": "innotinstatic@user.com"})), + ) + .await + .unwrap(); + + // Retrieve the person's ID + let person_id = + get_person_id_by_distinct_id(postgres_reader.clone(), team.id, &distinct_id) + .await + .unwrap(); + + // Associate the person with the static cohort + add_person_to_cohort(postgres_reader.clone(), person_id, cohort.id) + .await + .unwrap(); + + // Define a flag with a 'NotIn' cohort filter + let flag = create_test_flag( + None, + Some(team.id), + None, + None, + Some(FlagFilters { + groups: vec![FlagGroupType { + properties: Some(vec![PropertyFilter { + key: "id".to_string(), + value: json!(cohort.id), + operator: Some(OperatorType::NotIn), + prop_type: "cohort".to_string(), + group_type_index: None, + negation: Some(false), + }]), + rollout_percentage: Some(100.0), + variant: None, + }], + multivariate: None, + aggregation_group_type_index: None, + payloads: None, + super_groups: None, + }), + None, + None, + None, + ); + + let mut matcher = FeatureFlagMatcher::new( + distinct_id.clone(), + team.id, + postgres_reader.clone(), + postgres_writer.clone(), + cohort_cache.clone(), + None, + None, + ); + + let result = matcher.get_match(&flag, None, None).await.unwrap(); + + assert!( + !result.matches, + "User in the static cohort should not match the 'NotIn' flag" + ); + } + #[tokio::test] async fn test_set_feature_flag_hash_key_overrides_success() { let postgres_reader = setup_pg_reader_client(None).await; @@ -4095,7 +4602,6 @@ mod tests { .unwrap(); let distinct_id = "user4".to_string(); - // Insert person insert_person_for_team_in_pg( postgres_reader.clone(), team.id, @@ -4168,7 +4674,6 @@ mod tests { .unwrap(); let distinct_id = "user5".to_string(); - // Insert person insert_person_for_team_in_pg( postgres_reader.clone(), team.id, diff --git a/rust/feature-flags/src/request_handler.rs b/rust/feature-flags/src/request_handler.rs index 538c6845d2a..5ef43896e64 100644 --- a/rust/feature-flags/src/request_handler.rs +++ b/rust/feature-flags/src/request_handler.rs @@ -97,6 +97,7 @@ pub async fn process_request(context: RequestContext) -> Result, -) -> Result<(), Error> { +) -> Result { + // Changed return type to Result let payload = match properties { Some(value) => value, None => json!({ @@ -329,7 +330,7 @@ pub async fn insert_person_for_team_in_pg( let uuid = Uuid::now_v7(); let mut conn = client.get_connection().await?; - let res = sqlx::query( + let row = sqlx::query( r#" WITH inserted_person AS ( INSERT INTO posthog_person ( @@ -337,10 +338,11 @@ pub async fn insert_person_for_team_in_pg( properties_last_operation, team_id, is_user_id, is_identified, uuid, version ) VALUES ('2023-04-05', $1, '{}', '{}', $2, NULL, true, $3, 0) - RETURNING * + RETURNING id ) INSERT INTO posthog_persondistinctid (distinct_id, person_id, team_id, version) VALUES ($4, (SELECT id FROM inserted_person), $5, 0) + RETURNING person_id "#, ) .bind(&payload) @@ -348,12 +350,11 @@ pub async fn insert_person_for_team_in_pg( .bind(uuid) .bind(&distinct_id) .bind(team_id) - .execute(&mut *conn) + .fetch_one(&mut *conn) .await?; - assert_eq!(res.rows_affected(), 1); - - Ok(()) + let person_id: i32 = row.get::("person_id"); + Ok(person_id) } pub async fn insert_cohort_for_team_in_pg( @@ -410,3 +411,48 @@ pub async fn insert_cohort_for_team_in_pg( Ok(Cohort { id, ..cohort }) } + +pub async fn get_person_id_by_distinct_id( + client: Arc, + team_id: i32, + distinct_id: &str, +) -> Result { + let mut conn = client.get_connection().await?; + let row: (i32,) = sqlx::query_as( + r#"SELECT id FROM posthog_person + WHERE team_id = $1 AND id = ( + SELECT person_id FROM posthog_persondistinctid + WHERE team_id = $1 AND distinct_id = $2 + LIMIT 1 + ) + LIMIT 1"#, + ) + .bind(team_id) + .bind(distinct_id) + .fetch_one(&mut *conn) + .await + .map_err(|_| anyhow::anyhow!("Person not found"))?; + + Ok(row.0) +} + +pub async fn add_person_to_cohort( + client: Arc, + person_id: i32, + cohort_id: i32, +) -> Result<(), Error> { + let mut conn = client.get_connection().await?; + let res = sqlx::query( + r#"INSERT INTO posthog_cohortpeople (cohort_id, person_id) + VALUES ($1, $2) + ON CONFLICT DO NOTHING"#, + ) + .bind(cohort_id) + .bind(person_id) + .execute(&mut *conn) + .await?; + + assert!(res.rows_affected() > 0, "Failed to add person to cohort"); + + Ok(()) +} From 1421cc41bd5d9e69f334e89b9aded8cfc65e2964 Mon Sep 17 00:00:00 2001 From: Zach Waterfield Date: Fri, 15 Nov 2024 19:41:41 -0500 Subject: [PATCH 05/27] feat: add payment entry modal (#25614) Co-authored-by: Raquel Smith Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- ...el-top-to-bottom-breakdown-edit--light.png | Bin 162492 -> 162607 bytes frontend/src/scenes/billing/Billing.tsx | 3 ++ .../src/scenes/billing/PaymentEntryModal.tsx | 44 +++++++++++++----- .../src/scenes/billing/paymentEntryLogic.ts | 8 ++-- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit--light.png b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit--light.png index 78ea79ea3f74550c79004e8ec145f94889135282..25ab8cd06fd020558975f117de59f999c129fa9e 100644 GIT binary patch literal 162607 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%0AvVi5ae-biGGr6c`O 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 GxBd-GW@C5& literal 162492 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%0D?>oB*P<(Y6{e=9z_C%7 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

UP@oFmopW5b?iG=2lrr@ELf(q{@#XFVq|g## z7PohFY|EQb4#J9Uqo>M)n$MpN4D!)c-b0I!Qlaa(7wMW8oaa$y;JQf-BC=)Enl*FN zP9#SZ3qg@!eB_^&^L!T+Oj1y&m!OO9H~vVqtUx!#sfccBaL8jrHpIfhrtja6`uh)W zX#2MD(){O&;})%0y!dCuYoS2EkXzjZHnzFZ*erENTu6xQ-n+zd&PAcQGZ;7laEd*d zr;aZURuUo&+LILZWfEWc4EJ;$FyI94_e&U+Gr!Q#Qfir=8Q1SciLvG6fKw47+MX1c(Jop=YblE(1xRSC)U+Nc4uGnNfmWz*iZ}Xr1Ch4Cp^FyN|Rm=PX# zR@a1$U7|y6hL}Up96Wo5wm1oWuxC{8ib6ig4$vUOjl%D~kt+ zO9dzoTz2gz58=&4%4UXoLkHidaWM#;rpdG1C)QL|LyT%gfrj7y=?o2ReO zA^bQuw{pNDf<~!G<~q-@wUt*fJrcCyckqc5BcpqX^_f3#)>b7((#)8VBfo;}Jk6tb zh`QwlWOozMRHNzo-6<&fG&5xr)+kKay@?L*=8iQfzX+Hkb?4HR@e?{`uFbqb5+PU&dwgm49*cF7?ZUW zd(xss0gvBPjedCl9(618e|SfKtFqd^ycjg7D~c2R9!MUhU>mTKl9Tgd@;Y(8?5t?? z5PM0DtAjzUkkwJ`wV0k}`SOY5$1ANzXx}Bi*XZ*^DTSlz5C(aD@0Xu&|Mhe$)7F_y z>C$Zc?ScvzrnfB-^8w?ih%TbsVanv(2J2+#@^<=bxTqg!m`|S=MVC1o-pCy|M}#1mohQ`QA~fx? zMETG@ch7QZ_3mB0SIZ8mpGuWnO!0E_pFYGN7|7i;sMzJcv2lZNrnsPs8m)` zdimxJj1FIUe@`AUX3T+?+_syb{U4lrJTi_@TLTck@{S04bGk7pc^w;@GIT9yGYNPY z)W83^=xF^i)Pt6298FD3Xdf_Ct>9C&y!5@H(iRvLdW`=W{PJDFq4%GE>M{61yyxCO{kcOT*)j{+<1wl^l4>xa7RBvR*?Yh@0-s-lLghXIO zMBLS@nh<1^GL>^D_}*k|cvo8+8WFM4-X5JE^RpM)MV;p3aVtuQ&Z9lSB-xrT%^@-?s+?7v$`cT4` zc?Ltp{mlOCIBW}a9&OR$>oWU`M_C`H&E?bWZGU)LX3l<*-ToDTBDTUID6{|wFobSgdc)8h4ru2=q{2HQor@jM9H=tDep&*D6k1s z5E-ucPzd|p%^fdUkiYD&VH{!$-YSR`yto?=&?eHjCQGYd7Y`rWO`Kx>v&BSGsIAo` z*MBwhk=!2C>to)oOV=--Zq(?k_&8*XASbL+P?!@Obn-+c8T6KKMcinS^ zZdRM-%<)O?*5ypypLAxoX%^0DqSx2=t1-8jH}L^K?#wvCAI6M*`XxMLxb8BMw(yZPOhbX_ds!uYJiMlp{IYTKiu{}SWWo%>dD z`>i)kjZTc@`1)fAS`fVDcEseZ-Rl)xR#4YcQu6UReI`8;6*;7T4l68C z<*oNph5C$v9(|&QtR{wUl*!vA`~i1eu8000cmd(7qZ{`}WcQ{kJldTZ_dhuFf08%K zer?UPHx^T0ZPMRhnE;y$gmQG)>eZd+ib8j{96sEc>f36Y)L>z07^?b$8dutCYfb#F zqL^95#os>V0J*z&`?I=SRydcPpZIqs0=mZHvF$tRm+riME%845d!=hZ<~x&1QI+4R zIAteV&2srTT8H#Ent$EbzZ2KkpYJEvI!`p=)#vIQW9P=^z~H*=`LAG8R9U-R@~cw) zPqS~U*e2Y}j$_z16N&(dF9yo&iT6|VHR{wS=uz$o%t z`M1X(!jIl&0*rG0puWSf^1O830kmFV`j2R~^h8<3oXpOSH?C^ko}Rv4;87QJKWEm^ zdgIs?$+tV6TlBsW;Q*lK`TMS@LbtvAGBJc`=EqAL=ABz`#j1A6eTVN2@h49GR2}uA`i1+tq;TiOGd}P_t<${Qx5Qn%_VVeb zvsdf2mwaOE#TDz+sH^oYheC@e?~TfqEnn{S?eo4o%^^Cv_r{NU`O3_Ak%7mzyskZ& zG1;a5&uv(D)k<7P^nH!2+r~x(u^H~pTee#}&Cb<7vvrPF<);^QG+fGt*O`(Pai{oP zhce!&=b4$`o{b!ro~GX1(!2d=c-oHAD<(%E{Ia@D0ooVQFa)@_>3zbAUMK{+sKn3q zA5;DAubMPaG^(n~dqrIH=m}$n&8YXY^_bE7(C~#u9lu`09*-@VC@cH>@%ybY1`)?Y zgSLOMm>(n0{^m0F&pK?Kwjf{bSox_iLv2y(RIm4`4L?WtT7_Gay?^gsJfq_ym+zF3 z?F^7uzrM<;thM*mhWGEIE=Lp6OEtIwwzGKLI~zTcIp zmtFrnJY{p^B2S$^uSB0YB51S1&K-9zM=l@kyQgdX*M|7RA&ZEm2vd#!uC-N%bf;bC zV%qGuhEKIum5APn^m}N~*#|=rgs-Gcl*p7w(te=CGO_uL>S9vI*UGlZoq>FshfD_9;E`2ub z)cNH5wUdS#ndq+e?3;QyBf}^$-aYIq-TM!Z4D7d*1?;-BN9s4R6T@r4DuMA$ois_p z6{(?!whFUFv}JioABx>mm!reSpHsfjQ&eHF;ZmcM=uj72SgLhGS}Z>N)G7A4$*9m| z0$$uG>gF4Wh$TU z$A2~buu@IEo+!pP#qcv*+stj%Qd*v#o^nS+!otSYYxC{9ukJGnsrR)Rt}9|KnVLc& zHs|dUm%nz-%3i-CcAPkws<2J2oAj*rk;RL(Kl$88uYnrvn(&jYJE-y>9Oz;%dS={u z$15?5w(B1pzr!WPg}r-&B}WbyLT$#`t2&qfXFPdQzd7ZLW#eGsc~?}98Lmgqy0JKY87> zl!^d@%z1sxGm=+xj|#eQJDazP{eFJarRU%sufLj@ec>2$mmV_Je)WEdv;MOKkE~Iu z7p|48&n`|0;cIuN_Wpl{y%?sN42^`;tD|bq+J(l z^bgL>QlVU7_!k!DG)4d%(BEsjS$LtFmNliij1j=7GH8muKfLvc6Q;PlVzy5>OKps$ z!!_>+?KS+S+NAx!^d3fI+$VhzOXa$PEaIRgx=L`LWB5RANbX-neZ7r|Nz3+x&UoNS zu$%sCA9QW=$cT=1*kHL!2@tQMq5@%l-qWX>K=5&8RkW;{KIES_L*ojEj%^ZEB9jE( z0>_;kZ+?AUQ8Xp>cB2MGMvCTxmb)*VcUD4U;8sJ$yN*kMssT&UnA5`|Vj(CDbe!MN zUZ7BM6jc5T?(t0|C#cxxwsQb7BHU|@N-4%7WHWg%4nmkL&?9p9PPo-7u~Fm4e+EO$ zdrZfLHgx0>f8qTNzijkK0@JS2gbBl>q^5v0lSa)}OG}5iG?qMsZCxdT&f6=;O?k6! z*a4l^m3mih6Wxith($G6t6wtpMof2TSbST(wie< zV>eJh?CQp?W!w^h&qHrFqF<$%b-3|rn9FhDW5+qzeDgtD%9VH={tNBW2R8*zHTeAR+OUbAZ+`pOsf_(l4Jo zHx*VC#uxSoj);JbRw%l6rvM6AKH00wSHxM2EU4gbq2u}uovD3Xoo7Z<^Rydow(mfQ zFo81FlEOgK7!-T2i&=g~VXB7YGj2%vSWlA|dh+Cc+h0F^;9uSj`2jOCWSV0EpA!&@ zL`E+rg^tWpmnq>$F9yO&tv0~ieCc@ zag!h-TflZ1Rqpiq=B2!suU|L^08gK0-Z&%++9kI07sbW@H1QBSfw7=prD;3+E3~4H z0J82iZEI(TC*>F7!S<6m)v$F(hs-!~@eY<&Cntg7c2L(5y&V>WMGsjv`<%DoFOA)M z_H+&MNxglWD*ngMpWLo5*mLFxl6QK2p1gT_dKGGHC1C1E0kuWfFm~76TyVtE@zQX* zg?wvnZ2X(Ixp;8_I(tFgS=5adUtD9MNXi9--8tFW2WB5UiKAD_dp2~3Y-;pb>&`Xy z(T#7$5GJ``0b}P9vg4Te!)RyLnqDqD4;17N4=*zPjvZU-?yffR=;6a?zqGu*@I<_S zzt5HsR0P+JKRhOe%!Z~Q#N_NH&@8e)`Ww;!R5o+t2@YeS5WCJQW@E6L$3hIyRlITS znrNRsL_+h_LZ-*Evx0G1TSs7ngM>P8#9~9=o)VIhbEbW4Xef7Z+W2kJ5eZjA&GlBt zA|uI=XS&-ZqA;j)Yg)+Vapq9oYS>(#2b#h#9v`<~AQceJWE=%rDGwihhbWBf(#evY zp@{<@0JVd(j#Pg*aqh#r0&McqANUnXUG7M(R7p|MpMf4OF0F9SOaj%ReLdUE+ef7h zH_lWBMmsk(tY<}l@4!pZ-S1-R-io0^y+Nsf==c(bpfqHhmG|;{_|Tx%x8Z($9a|TC z3phAf8f$hFkt{ZTIn~x_ZiU1d|M~QIi>g?E>T*Xf3T-t`LF5AoX5;Zp!VIW7pTB&W zse44w@Kwt?FK@e+Re>o5b;w2v#g-o&JiyQ>9-uTad5+S2QT!;kvEeIfe@HeLT5t@p zH_g_S6-JxBgoB?hl!)20SBhgZ#5vS6N5Dx~ zJ_)-unOGx%YLhPsdwa;4HR_ta{w0&i*nT$oYnwG`IVcyUk<8sIYUu_7$Vtcx5PptBmDYVLgWA#HM6^E zfIT59&K~)rek2UA49x7^`}h3$mfMIYg!mHzNl}!*%n6q=;C>@uUSnfpYpau2QeT%5 z99C#FCXOA;>|B7TuPrTalDDjGS&yX(kZl)}l#wRUWMa(_^6h`D?f**sM8s8ZAc!UpjLp z@YJcFd78V$$&_gQy6sKMd=(LwVG%(J)TETwT8tDs(@sW8*1IlUq{S{|mvraPsl2$D zTAl6NV6UmXvZ4W}=5-459k}5e6aF|Kc?`%lpy-lZBQZBjA*gcdS4bj!O5{kJnVW-c zBh8XpyD~2EQ03gQxroL|p5IU&&73`39s?fxW7bZQj?!@CEZjR1W#Eg@@gA<(3H(2H%$PXa%nnu???>T7 zi$@n+gwD?8ucr+hz9TccbL_%Ij-;vqT{#iAef?zGKHzox&xc@pO?qcg2!X=l^gb)0 z-~w?&6b6PeYp1q68 zoKh>4%PMTApI^>#BATsjPvAp_vNKqQbCriuLWivop!HH*T9=euu=B%P%%R&!-P%DM=ff|)NESOu4;}(`EYPrT^OFT}Xx8UyM>4u2^ zBRfI*##a6YWod<_g|)TDs8P|``SP8G2N=zC>C&J{EAR01`A=7n({PuTm$x-FB@@SC z?OMNvRY1c`_kMo&E}9c7eSHTWOLi(@{~Xlk0ogQkb&HoR6a1G%ei1YnmzHJ)W~!21 zoL0^wMWKd#9CH&fH)&IHIHk9UrJ#*~pWs|hS{~dc+e}T#F$xN`XwhStev>$~m6SLy zKT&jY7~0Uh=rzo3z2D_bK;8LySFzk_jvc!mA%=~O4G#~`L@6LWJ3&*@7gES5eGFrY z7>)s9k-&@{e^1?T!Tb|7=CbQJqO)N!0r0D@S|K|04(9+z3^8XoSQd`A z9HV|K{__eKic7>u)Eq;Q=-%n^ix4UcGc(H6S_+2bEXI>st%8JxS3XBfea?R0PHjq? z{yZ?AbqHd)I!8QTT7?j-#+Ob^QRc7u*=(Lfa!IZoKy#8q15k3s9NBR?nN-c|b&xty zRt%%>c=h$J*1ZhbhH!OAVt z-M8~?bg~q-8X6k-a^z)X_Iv+ieM6L!SVnP0(S~rJ!&E9c|Ims;#yATxLSx60KT3S= z;2E33i6BRY#3H}p`D=$quj`4YW+v?<&WAe6eEf3s5CQoPm*V58r`j2Rg|d&qCZuMt z2^U|r(IdkvB?Gj8lpevEj~a9$>8IDPliKYngic~zv}DP^G2&5sK$Xwgf{e$%`Lm56 z745N)BO^F-J@zg>Adg4ne~34kp5jLaPPXGkSW)99Oqh=U$Sm=<&=;T@VvxyNYf_4N zF2K$n_Rr{k#U`CKV8@blt8muV7TGe_(9OyARlGkphz+p#sx^$~P8e^WI5a>Mp*Aq# zXmM!C4-_F}Imm;`*iMPHeTGp`9Sr|Wk6(SW(z5l%3o6&%ujsmUuN(|;u9k==U(Md$ zUg(2u4!N=AXN|ph=GWl#q{B^t-6b28DsHqhbxP6KBCW5$qOwlm%+vIy?9&;K47ywg@e&rW!%OkTX%%a9NP zWVAIKCQq7#QhH<=ad6~I&2Z*NUih)6uB&0C)+8=c*X<9#c+Z({55$%g(pyfn%tNIz zE=~w;dUPV|jq2(RH_B!DozGtRFeq?b;A%4lmN0qU!pVw=Py*hl3F(tL)a9qIU&cu# zoZ6gu*wyCh>p#lPO-x?BYkFtG!HfYFi*C_!b57H_4{#lSW(Y+iMlq~b));Lkrv*QG z^Jcb^Qr3e9f0f_1CaKEN@ggv$T-&^uB1CR1R-YJp#kzPNs8r;lPbHZ2ayl%m?%g}z z{3-j0%(=HneT45zryXQ}aEZL?A3^Zv&U(N>dZ3Sw$BY+cWgRpzXde+c(RJ_?j(iYa zvCVUznQm%#NN!z4CWje!JF|p$Zx1K zeL}*EpFO)*e$~x{ZH6Oo!-hT&A3vTkeL9JqGiS~`9}~lbt9eV8Zl$!&%JcpC)7@w2 zU$GnsadBLTY-h4!JLcn1qu$L8S>5{eYwppzcYB{KaGWN#Z%@t%mO}HumCc(k(IC?= z9Q%cLma&bQzrPI$I$!zT{M5YB=SPXl<%`_)@1_9Lh)@bbuYjW&cf&)U19C?jDFrM) zruFI4I+hW|w>^F|vq@tJl#!D&iYaOu;ngJSP%wa`i1wkn2x*o)&DBl{zIOY|nA>fd z_pc{pY%J4mL$rNp&{U-HV5mYivt0x-rSO3jTfVWcfy`!XuakKy@$-8_=eIAGRR*q) zj*sCMjW}6;cSSwGCrGpQG(pKn)u1+Wrl^Z={sRlEdvg{o+JL4w%Q8)K$S5f6G);04 z(5-U_U}QwWAb1!tnMfIjD&3q}BNizu<|LIsj?+%DedGw|4$@&aY08QV43yY9s=#6v z^DWpADD57;-%8{f2L^?UpH}#_YuD(^df(nPbijZMoGLLfNmxlijVLQw83=*9I5R0D zFK13-^1=NQ8zw88Sym zQs3{){jA|#>s#CUzP5MUUXNRKox^b)`~IJH?{`rbiygNB!+=SEsMa5wn!jggmR}6$ zF>nw$FKi5?7Xti!DRIk}J8^VJ$dFzL6mYJ_t(WcHdxTf5<+wOUFxvzLkO)IkSsp%A zNT{1g_~)B9k*7P+&FC9#gG@k?3Piq%LlNZq@{k4;`K0Ty5e}eTT)TFp(TuB3*%LQx zb%9`S3%X=i0#XN434knUl(L&Mr(eS9GmbV_Ue*H{4(Q*X=Nmp5P-0iw9$|^_99S`p zRr-bY7tnGt6h_c5KFntF8MP)y;XEDro*hdj|I^EOrSs}ln-lPPEhhoD#olM!d@3C} zKU#Vo)Tz^_!-nP|o$|;Ex(Bb-D}ywpw8(FUe%&C83XdM$)_5P+Qk7q?70>nS52Gz$ z@5?_@qI;1>oEL?(TRI{Z2*pLJPjIE%xXUE?t!yW-nr{ott$Kcu-cNd)-#M!ty2y-` zhkxlz#rKr@lYVZsAjOuRpAxxO>c{PA#!dykcWY{t!uMX){6y2G;3?O)cj)~r%PCU^ z9qeni4!f#YOliJ3GO~AJ6!GTcsT0w^J~_WWoD{4fLtr%f$mcuS+J^4f;YXdyABA@n7Bd7O+T8ka!(YrO`L+v8^lZQ%UuP+Q{tfCi zKzjDjAX7$FPF=lvcve&Y`F)R<99eI#;Y}(!%Yk)*8jBTzIDjAqRLAr`{5@GL7&*`> zftY^mcfJw$jM+bUTd7_N6xi%f#t)1P?HhT1usQ@Fd+|GX6qIwlb6v622*vm8*$?lz z+a0l|U12JYVf+o}EGFItZaUkZG$PC?SwtD|LphgvD{T)g2=y`$t?dR6SDA_ijpK9M zSjpkc8E6X%oiH~e~WhP39+PpeqV%vNK}B0zkaC=9(-z+R&!MJC^MO=L=kDSSQ)6h zJ8ymd=@an;2oD!g+mp5h!|<%`q;|~9Z!?`s%h*oAXn0l+Dk~E+G6b2wbExsJwMq*f z54Hw}r-lk>eBLGBc5_O~OR74KC-$~bO$tHAbIHVB>_lO0d*qG)KFv-npbN*34?yBxpB4Id;?&zV5&OOem$=sq%>Uv)YtEdbX=#KERxg|U zLh?dxrPDmdW58i}^tde5qX&s$3pU1n{_RY6f=z09p}NoLyG1>^H1u8YrArSa5S6KX z{)QV;?d~PL>+{9(Q`g>uVPRJWZ>aW>Hy^jGm#8wX>p!!)2A;LFtTZ?F%BgRA65`Ku{c1{)6W2+`!Ie^=tf{mMz=8O>**+EI+ff$x232K z>F9z?pRdU~WoO6##s8DI_scKYu3aUgt&gP$JbvJfjwlu6QyFE>ELw~fF6SE;aqn6t=ATYW?SxNqvDj{;j=-9E4dB=J55e*zh3w-qTySl z+O1tCB`EgPKdBdoGq=?BnV^Rd73vG2d2L_+BXRy;*!0Sj)%zR0^oE?Boq`Z8Jmtd;L^`hyU z(}=nr&ydMcR7GlsmU?|9-LbypT}~vT>Ec4Hp=Kz>Myj*RRj8wLN+2 zRFeQI?>8N_8+X%dwiHf1-UVi*Vdz+XI*5+)k&sYBFIU)fy3TSzpSu*)LP|xFE$Lg6?KH0sJEj+fH8bMqsWXs6VtgUlUl_!jUh?-j016!fvl+wD4zYAta z>q|JQDOGg?Km%Kqkgr5+Ed*WN+H;)TU#7Z1^?}vX3v}o#wV|ci2jxE9mx5GqL?46x zHkdzXhbRT1+H)2abr#z)8ap~#E~{`@192;dS9uD1c%AbRF(gi z|0Juy97^g6X4Q$|it$)vtG}2Rzxg&)wrsTfJXzqMoRcRno6!56z?712i+} zE`2IY%h0eXL@8jHzJAHWnY4UF9)bgivu)?hVfZfxwBx*a6o)~cLwRmH=qa9@I(TqC z2;_+}gh}qmpD9-AFGz3B6*bsI^zR@tnHC(`vFX|Ko%@FV(mZxHI`!iUQYp6Fe3Ox$ zzSa^4z2NUw6+0fEV<9W}VT+zOHZ`3&BOfrxk_G}unTQrH>D#YwOPn>0#t@lW32)rc za4a)(@MrJmmph@0;I65PQEOyl90wBp`To9VZRu{TXM=vqFw_wReV^_6aOju`H&;^( zT-~8iZ~mhNc;1~bQyZGp;nK8$EBGnJ_h>V5J?7?xU3^(jeaY|? z>nMWl#;K~BZRqyj;Lyaxz-uo5!l8s^KhqPs`hb7{593hqC73y&K$3MBA<|WzU5q(| zbsYYXKIR&Yyx77&*tk(}^y%wIr{`h#pnYdt@J-_NZ{E~}Gp(393rZ105+|Q9#1as6 zREm3MNdzZ3$L<7iB{e)8_mD4Vat@2$)<07e-kw#hPpx?UH|3?enPhjIF}308n%s%n`)07hzH<#*jRmJ}fm0JmsV77GWTdEWEyY$l(k1$;nTS1<} zkaM0VC+1h{^!x1q00Mp{L7{YQNzMj zf(F{x=)fS$?jx6%Rg|yEc@`xbTBvLEy&26pvP&aN}it=sE)O1%(Bhqp~64Meli}th4l4k<)5!E*O(l@9$n1m-@Qy_ejT0^Brd2 z{dnEF+x@N&SMxMkt2b`mOfXnIFvygQ=tme-0$Tr&yObL_&CcS;I>;5kYXEw5&@c8- zTE2PxnrQtTgYUBgIT1`t!EqK$($&$Sktx1*@xMbcBP{$<6&Tq8e0>ynfOH#}ImGt_ zxzrE#%bfNpnP+(R>?|jz0W&XdZMncq(HG|PXjLJeR0J)=!eL)3c0xrHh1oIu9ey}K zGDthqQTm?8v$A@n^*`%6?}1x4(kXzI*$*gh>+0$dmh6s-Ixu#<&gv0Kg@p%~#sKo3 zqDHAqoM0Y?&nd6{@TUs*@7%hjGOCWDDQiaM?~oZqE*u2&^EghW2g`qWUidRnDwL-M zVjGoiF4a|}ENbgBwbLc1474hpyYkwj-VMug&)-p2eZCR7GKdMd_KOd_!!?G&-7k?y zwjYa-$#kiJtw}5Uy)qg*_MZhWul7OjLjs!fBHQ*xLuu4Tz*r$7lyxn|2W55 zfDyqZP2K{#GiNf47ahR{JQ1%$o?K3wlsc+rkn>h9Syqx5Lm|@hg|yF@`#hfN^Xq#q zKsnKSU)yqaVHW)AISb~`-_>P6Sd}S7EQ%y3XVw@dB`lzDY`X~iIwD^fT0Qt{_n1+; zjYl`H8Pu=W>d3UTA-`Itc-#)P2$vi@u!C~Pw$YLEI}Yh;*P(l!TF|eReRe9{?p1f- zm<6;C0J`w@80lZV{tSy(1I>!lT{6DILO!si$3Eyb%^-ke1a=jg|Lxt_Z#o{#2z6P&=AmimJJHYoY<;F;l|1RLn3++Pr)zP6o*$9t+tqz}Rk zBv|GKT+vq@6>X+HK6|zhUl|E-aD9?NUqR_%O#E)_^e3>mB&pe6<8D=z-pG+rHfiMF zpwf9Z?MTV~{}pinB39FACX$ws=2NF?({}0TWL8Y&+ac$nv4tADstRF49=QVelAwAl zb{wrBOSgSniCi7DV8P7V5epicSh%p=90fbJZ%09c`}!ov?G01cu-%7mg>gQx!QlzX#I0oYIY=#wb=dZ5IP9epE$rYlC zxK<8XNWtQH?*9cL_^aPIqp&BUbEm!g_A%;iOVM*cUV^*;u@JFH1PcTSTO%F0<;&Yk9)TW;tEX_5q4-|ITK7%x1{^40KJSLC=J9e*NNwsm-sy7&ZkA(|g{1_`qxNY}DwT zO2+f8tu>fi#JqHBn+Fg2-jwS#UgNn+J5fj52l{d!A0?%$dq%AMr!C3s@wIZ_BImA| z&Fb?;|1r`sKL7ID_14!*%l6J07Q5otsl$9A3R{2^M2ELmw>x9fSP=B-1yvn_Ls&w& z^~%Q~@`QeW`%h^@bABPkZoS>~WY6{@zf??8U4CLGNL;^2r!_TY|K-Jng4uR@_aDoP zmnP_7Y89+gqH`Vh9+5(o-|hK?);0}y&kiX&40{r;`Q8HJF{jaTfGDu<_k(RgX1;QL zUGK=%|7r$<<%R=#DxPSVl4MKDCMRp?o0ork&q@oE;4dqpV`Ao?TYDrq8L;>=!!{s) zZoXlvc0hCE@R1`Mp#FGMfg)tr@BRC2%_nZeg-ByYTk&WlY$*?et`{w>&HHmsd#4PJ zyte$~gkc};Pyql9_1T_-UK$a}ySh43nvhYxud93b=#kJfTys%0T+5u$W2*Q*gs;R7 zYwdzpQA5&ef;lb+J7?zxwVQ)275pwta=?c9)fNl_p{o-dyF^Dybx!f=)Ol;xhWdY5 z%V(1!sG#{$UKbyw!eT(x!{)#n$WE5;^+SkWNc(y3+3a>T>GAw6ZzqP;-Q8%f;jXW# zag>6~!G#Qv5zK0QEjSXXC+77P+Xe&}1;EoFY)Rf*L07e3a{{6fi(Z z$=J0_mRkZIfH>vdJNJ3JK96F+JXP{UP$uSWF?fAt_2OBx9$=xJt#uC#8;p9WSN?BW zXmklbKG%fb{LFcA904&z2WwLzTXme2*I1Vg>%NjaOEjLD4jso^N{Ui7&UdtkP>;Wp zZ;~0tS748ORtoI{#I=YXoq+?X!C^OOKv*UN#aJ_t;_k?(d-tw~FwQV4B4QZq8-)~w zG3^TK@tgZbg!ml^;G?oH5}ie%M!(bk>EDWf)V1|tn_)v(KI->&qd9G# zTx4j6|+hH%%>xFx{IYM1sLP{U0jh;HQxysBB^Czaf{4dap_Q8}g8qYw;~Zo=5x%k-a7%OyyNAQU(+epHciu9+j2 zy;M8S;%PeNh*B&qFRr&KMdMsYIyovWifeqQ|&MQ3f{T1yJ={JTek!AA%!LG;G0*uuK-G0-$cc3 z?#d~&E@;Ba5DxOMzx*`5xBBNJ*uXt7c!&mVz#vnJ!I~Y~9(rbCNVbnIme#7IIvh{QTDxE z$d?mt>S|~pKUhBEGXKjcp$4(UD38A@>dSHOs_{Zfi`Ig|W&uUkF5Fe!d|+>1E%E0O z24lx|VT54k&N_3lOCLSj@3&vEcW<+1%CJI?+1hoK@Y|#>XLPohM9sqr(zFdpgsmU> z{n@1sUk{HeTH1Yk386qpEu>!+u}>@>*7tbO-+jSk$-6@vB_PyEsuyx5STp_p`A5)| ziX%AbrYF%?Bk1PctwHRH`6K^-S2av1e6y;J-Vjqnh=qQ5=a1GN#YIJnVJ?AS{eXa> zcE6OnZ60nc23eu0WH6jAQ5$pwkVuyHkEBxcIiQP+Yk9uZ;~S)V4dxxTW&X!-v?r{K zl8poYzRPP**_;bG2^mQ?4uVMPeMXA`lmjN50J=|KMRcl}SrKZA3ru5C8Tl8U=j1Hl z?cw(k*g^zw?ep;*)2L1viiAw#DczRIdW=j{0EScad zG8t`=YP~A2f7h;!1MweJTCC3NuaWaA+FKlGyu9WfSB5s4str-NRlw2?@ixLhy1z8g ztPUMTeq%r*gM)pU!??PO@Y-e{OL~49#l^S>qr5LnpZHYZ)?gRsPjx^kOX6fsv|T%q zbA6}Li{8ICUUPQpAN!mOvu*jti!-qRNA5|!Rj2pyQ8(_{`t8BRi~WA8$M3$*;byNxNK_+CZo|ZIzgo-#3uIetw9zKgaf59*x{bR3h&eeVID_hzvCl#Y$Dxse$&M zSjG6;oI|M>n&V+P<2*w7DPuZ~iiEMnVWv?q<%P zf8+To!_zZFCMSfk7%qC;@{$4kVo{}&_xxZa#bs~436oFZn^RNA9$z3b`8*x321E!* zKuip|Im({|OIP5^BRqZ7gKV8r3VMgw2_ndUE9?bi4!DOePlIWj`!)Xak4NZ<8K7d6 zz#x^HuKv82rj`VLTzyI4!nUzgNutExb+}QOEDHYF+mPqGS%e9o17ovfp9>R5? zp`|6eeqL)YgQtRgi`}cZ-@hKr0Y^MsCD?yadyLueC9$C34?0rn+?xxBky%kZU}grY z9Vw5@4qvpzK|yGc3VeK!o5YR&#h931F0m~Sd>2tGl!8~A{z$BM=~)uGVFRMonPJZR~(-(IMRm% zLxg)MfQfUX5K~l%ii_JGH-6PKQRKB_L|811xc=&(p?4YKY9-EiNOCuLbr4BU=f~02 z)18$D0jvlZL0mZf>#G`W!jtO5J(PYJ`#r$_w(!>ayw$2v z46Au6Ii$-7kC+)7&kuedG11WRTSVcr)7)L+C9E zkQUrE#W1 z=wM0LKbzv=K)?9)TkVRu{+kXMX%cbo^t(xE%voXsbRKC)j_gHD! z&mWxOU}TLsbIiWMKp5E49B53-7=wr}3_L{=xkF5g3;Uq1@zP}3wRM=Tt| zCJpw|n7`=3$wgEf<`Rr4tYG&5A*d)6j|`O-NF5NxFzJ5GH3RsEJ2qJR))wusI3g!U zKS1RoED)F%3tR<#k9@CQyCWhNu3XvD-Drr&w-Y@!XCK#y55p)ST<|CLTz&QK7ViI_ zbuCh{*R`3q)4kx=@92xvvD)j`w0`@cZ5ZG3vB}%p>D{|?4Ucnl`-fjmu{(dybubq> zAlbt|Z^jXO5(ANSjtgksz)S#6_s_JvH5WF83rrQcj5wAqaP%Sa<{&c)Xb%19`|}eJ zx56z6qe-5T5uJOPQhhWAp^Gw2=bu${1}~-Pg&gO20H*3?3aa_>51Xw^b#*ldENO{_ zNWkEf&b#>rN+(-c^Uq4bCUv!GkI1(qu=qv&deH8Vx5a11^)Lo1&rB+$uDjmJ z>;n)7muO(`?Q*`SHDum{ah+8XqDkZz(v|L?3$dL$SCgh7)efmKUlh#xUbUq(4!G`P zOp|u>(-$=+{?+AwnzwZ09GovGhT*$VYcXM-aMlOaeMF)Pq^)e% zV$&oc6X?Y*3;XNyV*8I>x8?e);EF z%}zUd)Hk@m4B$9muC47X+b>I|Oj-W60!>JlT!o2o@s2q9POe8mc6Dw_%3_TAkCvY~ zo4&ND38n4M%F(IT*3Ro509-=z<^lmg$ARDhHf(XO?)emeaHOq0V@G=7-|k}W#K|)vrJ*>NH2t`9WQ15656dgfn3E5e$6qnj z+~joc=cW!_RW`SK6QkvHh#ZRh%d0R?AD&wGe&6Z*!BhGZcB>w3B|=$_~_{k99UO9_-jw4;cb-s&(IK-31c`Aa2NowEM%Z@3S6y>@-yNn-(9r!wvJFKe(<35)~!XS z-h^w;Y##i3n8t^wOl8@)*@I*q$6ZgC8Bnpe&ee5=T;Elnu0>WB7q1UDRWz3L$=`Ut z+PJ6EDzA5TVTzMynDCz0>^c_>ur^Y}Ynis-$N6(T4r^=A8Hvjw6}0u`5GG8P>3v%A z@$>tozN<#RjbZ=g%&#qz*7$Iz^ub&2=J$9&bQkFTGy0y27|U8&;U&ETSd~Lg=g+MCRPROu` z4lk+g)~C6@{6F&j`kisVyWhHhVZ$z-*?GgCtJc0X^u5y)Jc2GQc;dvhX5GELO+#m| z8DUy_e!Uf*M>9pE{UbIO7Jsj<8f26qd7i^4@8qd9dbN*~_4SYBh61H9Y?tO=0=xF zGQbYh0t2piROnW5boI-tHu3Mgzn9(5+s-q(SypDl(9z}h$0$D=d3&Re=c?u#jsMXC zXnq)}`f_q>z}8|9l_fQWt-#qAk zKl9_It(#iTdC8rQMk}6~NxZn0O082>oZfHkKeMeqCzmHskVkd7PXlsvCqCzR|0Ni1 zzGX}sv3P-D0*`xgB)F}tqS?pMm|-spC$Y6z4*wW!E&=6w}ILt#L} zG9_af(|ad=qEX$jc;#Z!0~E&>8aKSzJaK1jdgZ)DY4cXT47_+-M`tU(n!ItD8Sf(s zHm-Ack*@in^zrYsk7Lgm7(4=kgcqQZ-q~OOMb)cs4Nv^54t4D&-*Sw$DSf(Xmr1{0 z4%xNz{nE*wvl^DD6%g?iv3*OX$}E^gqwjr0iSGcfaNW2!_2WP_DN0H75ay$AtCJ7~ zUOoYU5m+|eHaKFpN=>w+C{W|_)?oT4jY+)}(Dm-IRoG7>>K;|KChO~Mc5 zj<0jmikUP*4z%isV~)WKtZ=+%xy1N0UMG`w-ZC;>;wt;-d)eqf&(kpYah5@uod%Cq@{&q2xwIF;mR)l zf|&ea8}yfcec1EAAXTAhF#nma1%k?sufP)mP|w%JnQciyp!b^prlfq4`?n=;loZ55 zeE9_lF;0B_fBG@eb}NvYB~~M^*H$mp)Y0i9*(ql{1zh93tcU&4YU%5H>+A0<`zUCV zOrl*}{cqiSt$%C8(T|%&>X!5TTs+ofJW}j5(nLaAfdLOqCk&o%>ezm>gvBNc?qG5c8@!>v+dt!dx>+F`$pMHkxKTVl(2Sx63qwp`Zjy` z$8tNE8`*6V)0uqwaQ1@i?0>F5mjA>(Nk4RX%eWQVI#nHbgn`zFrfrewrGi$l)7O=u zTz%pmuWw%ZBeOj=B5nI}eBqvs^~*OG>aar($vjT@2*iz2skS9bN5=osDTk$P5YLff#qL=I(6K`I(BF#m6_ zcV6~AaX>ha$#4cQJ=4W*D}%zquQJNVp;@soD4aurdpmtz@GwGpJUu@nx`6lt6jNu*BBa4fYtQqR^%qwr(=b!&fH&fCTzS%x#i=LP&LB^DV>()^R zP2b$_jHySEz?8r>UM&R$O?a6h=1^8Pe>(qp-RJ6x<&!ULD1$usBX?h^DMqZVJ0LTm*$ zO>hCdr{&rTzc<>SB}$?{#YzilikKbVzJEV=&YZs?=)Fzxv2hcfF5S9y3-?r0udwq- zwPA3ix_76DY(@4@i>|l5?8D?A<3l&e^4l9$?AsXeCy{g?A#Eh^U2>w7%D{nJq?v$J zoQ;2V95XdQgt&HL*V7z2V9VujcufM83yV`7! z46~NB7zfBLT-(cO431zgRoR*6YJ}3Cgn0u4eh=6+zl2toZ-#{`(~0R5osrO4+u z0jh%;5pOE_TjsN6nPTzG?O|a_o|AR=yl;EB>F2o0l4hfh>7S*4*_uhuIVIgPNm-g2 zoQb=5JLP0$Ye|-P{hH}P{=dGefjYNUK>8s2oF+1xP*g>Ra51QMV#W*)PL@~j{r=8E zf~~rzN-b~>D8?{7y=2X`pPuZKuF7;8YibG3`)AIhl9E?Eaqb62!_A6{oUE*6)%j!M zBg`ab<1WPYzE_9Yt+aE|&7y~_xIV?<=nIL-y+7wdPl+S& z#D08|Cs+y^9=?0!ZzQMK%YU*&(pCn-BXuaq_qTeubw{nC`s%x1dCn&B(Q$Eq#;D?K zG9d;xMtzVzOxZj4N-Tq>k z;@?iET*BZ<5^j2uwX!P>B=Ec% zUmrO}KK51U(thg*crdku8)0{$n)u*vRkIb5k;))Fy*<)iPzUZ~crwBYGG74!u80w~+ zEZK7N6t*dXS*nIk6i2ZC;0OH!dc|VIbcH~e5*qJ8>d(aE$NkxDkmKQp25d7NKG9D{ zI>k#h%9I&=nwlPNss{bu^e^Q^A|0<|yaYvx-2YH*_ zw8yn43Zn}kSp>;Lfc>anoY$(#F7smh(LZeuG$q~AtI%Y{$A7Q$iNXVVNitXFo>~42 z6)SEXq_W09%m`T5F2i&Nc)E1aqFypG$#}`w=Jb@#%;-1bbZB0niNr6ijhXd}Jw01# zQn^Zcl#rWmV#f>#k@lkdq3$Ers7uF=tZTss#0^iKnb9C|eGT!xfTIjQ0(T2Fc8(S% zzmgGyGzszI;FrDlL2q~oIH4CUTC{xBM$#3Km7Z!)yRJBD`2&;QLpGb7Wa<46k8gUI zg0g;g@1+Z+=je;0<0Dn>cLoVKUUA%gIgy7ssyaqhl_&Sji+lD{#SfW|>Z_g2XB$i1 z>-x1`)n6{5J$u;C?bhR-g|=u)OT4}CLUOy_t3Mq=X7?A)U(vrsS~?q0-h02%V;^iX z_9}jG^h3x`CCXfK=eb$8*3B6ohLMhKq@lxEMlX&VKYniZ(nW4=qgFjLX*$*;Y=GX< z-?YA*z-v_1R3Obs3cBT!H%{?pb@luv8$wLV+U#d_hRC6bD=Tk)jHnuV-p!?SbV z>*eKh3YRkmzZaDsvQ9W>g&;c~85psV00^)dM-Ut!`T#fd zYiZsm4b>3KpFzN5XB&fW^C;Pgg*j8VZZVhs4jON)1!Ea9Q$N7EL644~S_I8Wr*3^J z`}lqxQeWyFHa#r2;nUN{H8sX$4nQ2j@bP0(gTf1ce>%?_j3tbK4`NQW6RzbhkNV&V6WA+N1YVd!8@6SM&C9(5woy`%wBpm$u#6Zja(f#A{(XHd z`>#WXp3)qVEur$tVrEd1gWE#;f!Wx!Gy{~{`!^0!5gYZ<)6$xvEN%aZCX8oha-2sr zH)m$io%{EPh)K4lh?<}0W#Q!Hj|C595sTk?!i09(#pV+14>3UCf3}QLQ?npl3h}Od z%`}i8!ZY4_=)_+4JMkG1o~@R(Ys1LZn{OunipedHABnh~&&k?E>TnLD{AwB?RiVSt}cO0fVk14k2e|Zs~jk{49k=>%gBFw)O_hJsR_(yWcg|od$GFxT%@ZHOvoL z1hi$skX!!^Z+qNJbs{%QNC@Ys7DT*@12v%A=ACKCrIS5!d+}S{I+M>Z3cqnNo##!BF}4BZm!RfQGjJibabqWeamH zJnjkT9(XHSUcBZU^tzt*uAdIEyRt_MlY8U~ButVVp~oTwoM9`PiDR*0j~ zT;ILTt|A&K4F>sQl>urfwqMpMt3*{yi^JD#IYL$rMncg)r6X zzJ!F&1b%#&inKFdF~b1u4Idv@M7NIZhki3DdmKitL2&RD*r6cPMH~i*I5-Ph-ispMLh8~ zKLu}iQ*x8h9?wTNjkSH64e->6OPp~9Q4}n?+%x)dwE0qpzD{z%F;Q>#Xl7GnULJRS zDL#yBC!!Ou=tF;!rbcwkl-J7gf3HB)sdHx;Q_jY{F^h_V2N(x5!+wo4!_gx+uTZ8l zC@mo&!PC_>2O&tN(}f!rR@0^}$Z?nZ<~YubCLxlrdafFYjH;_*XjD8K?{7qiK(dD- zr*SNw=Ev|35WQ$$v*gRvjm-v8(qBJ0eZ4VYHg z3itGMjSXyl*>99MMr*G}`+>vP#_R?Tkm%U3V0DnizOOBti%#zlj@SPk8e*NaUIR;) zKj)95d>2uASF&`jzTCIp(d^?CQM%4@}}8(w=jGeij{-BB=% z9y#(uWm1Q@io9@$NhFdD_{e>zyH9R1o2TM>O@h*}fI`p+q5H$&= z;D-0UX%tzsmpS7B(12}D$W9+Vb=|<-OQ}y0@NoE^%*yK8vnN%lKRQNC@$MU!e!oIP zykFnL@o|dqO@U2ESGo$beDY}0*n9;EodhW0FOUjy1lW-o(*E<2qSGHn3{HP+CQ9$j z3K!JN`tDKYzu76_0YdPtO@2wEytEOD0r8d22nwo9QV5 z&^NUX*VBv2jfK?6-%x*@*-J;s`brMnrtz!}04=mQ=x$_QU0@Qp8$W zIXTh(FL<2t`)E#{!-}5mOm0!@_xfeq8)Lm-b{W8b?ok? zP;w0BRu&^=LBNRX#n&0|;T1g?b)JkVS(`45#U%Yf$PZs~Qvl77T8zn3gv?=6e*0dS zh? z6HDAD%zWhd#Mb*PIg^Sba}`Y421krgJADBAuTJdb1?SJ7r-W@y*wn&hZlG8s9cvnuQjCLlAIzzly=1G4QLR-Al$BjX6Dv;eYuA+*(Yi{5H)I*Nzll6upb$eJ2DE zh-R;}-olHbLjq^VY55Lx!Z~>j)?^<_Tik76T-fr*>69 zbwJTLY{)~*CgU*lt=RPCS-azpZSCxk5-oRixTJMXLlKCo8vKml{AtF2WXZXP1{Pv; z%iCQaJ1p>AFfY%!a|6e7w`}*G^X|TgJ&m22rFsyq99btboLET=s~yymjus^ZyK2{t zTS#&lwv)B~4|_Em5hDQM{HcEq{PS9 zmnGxL&3q+iVdUG8j*f#mD3_C#6b%TChap0@Lz}`1;2(GH)M>?E$4d53`e$PxSH`3w zXrsM&(Q~=>G>0DMaBMX-3uu*a0YJ)A+K;0*ue+-;dYJG*8)GPI{?e9K)m^3o82vA# zWs=|bQqB6`(uwUZst!#GR?c>ro|hJ1_Pa~wN~eFho=5)&{zkST`!?o+yo3EZifk>2 zl*t+2F;Ef<>fyC1jf; z^r87U`$JN*n)W6gw1XpzjZLFS*;|MZ^+fz5#r7th_WCCBc4A#}wz-iG-;cJ!R9&_z z#JQ$m<9a%3!1iSnsX>oX1Xt~k15;p+K?q{^Y*9Oc_UDqHhed`H^F(s844ClCm#0Ct zI9u!+BU9sml{ReHVEN(RrAwP{zF`#Ca0Sy@v-++`^PD`X{Z<_fb#)y5V-jvIIsH%w zkO%aoe|?NDgv}e^jnj_FMnCFqPjY@N*+t8>+;-Yfbu)^8A$wt)5YYbj8l0auXe~%y zx5323gmVaXgj^aXu*bv*am;OVbLRv-CgmkU`URPcK(9nJxkyO%VJKBx+*p!HQCFCT z?%Y`cx$w)cg>|Oce9aEM8Ll>xj(XRuz_&yrgbyHo_wGxtyo5xOJ$qnD_T9DSLT2A# zNl*l_32m_&#^!}XnG$Lfxtd>lq+MmjTcDYczz>xC_7dPXJR2S|3X!W z4aua&u`v=mo1KFLQA-zW)uSGaD46#Jg@dUjm`h_P8Z+e9A+0V;mTdPViT?*%5NI-Y zNyZenQCAgW$ixwBig=0`Cy%!;uc1>%1+(d8dy|ap%!3o*XR6b8n<$e%MCwj)?Ltwy z3M&K{8%$d+%={hIbVkPgAE6=*U8ZFbAz#t*Q&&H(g2Q2t!AH&8sJt+hpd&&8w9LaJ zF2VVuHD#-^$jW?zeL^dbZoiVQAH}3v%juNUt=y5i$C8^)fyuHYI3B)J+YI_KKQ}FTRR$8X@g$a*G3`C0|j=*|oz?mbd zr+yFI6~8^XOP8GEY~f7U{E0e@k1$2ThlYUIg`go#97t;=tqC|_rK|vn^a%)HBFui% z&OM4BJu*~Re@oflpxFvCLL$&3=ALp`=(V_DrJ{5OWjTq@kcw zow#Eu#GI4H?`i9}R4^e%^vHQGhonW;#}3KU8&oJsrC|gQ^zBUfn|>U6yhJsi*LCO! z2~`UYo=6-&=>xlV-MF~9gOGLO+dI!Rt9-awK~WiGtH;(mcMjcq?WjLWQ55*7m%P%l zrRp`VAsQ`4<=>W0`FhI5X|B`UKgF?M`{=!jV7Wqx4kz-`&E3lN_8y1mJOZXcI|+S)rqs&l*KI9*S8|5U$Fw_QK$d8DezkIUwqO;br5|OTvdMWa?bgqXre6wF~-w zhGz(4hdow^g1gmVl7E8smu$DsxitZEPrL18sz#7pEbtr%89{xB4IuOdvzi1j7%?pl ztc!K)&gA8dDbSX2*!M2ytEo*{xP$K^1D|f|KZsQaQLTFg9*~G;26V}dED78+v4>~&Kdu&vM=I5Y;H zce?EI#C)J{(yk2M?{$Z|oQ@iB&)P*JS;$o>weSgy{n{|Ve2{FIi+^T^<53N4aNL5* zYh!lkX{uQb%^Xxv9b-A@5#<8sE%#B!RZ^IK4uA<>R5!OyE*6s}8wjU0&HdYP?I40E z-S|YeJ8Nca8lsq}F{8k7eyKy#RSnP0!|LLO4N8`OcecqcA=6Z@bJ{@F-hzzGUFpsF z!Yxbg*Ll2}a5^e&rJTRb(0R=TZ;Sp>_-Uf4cI&?2OGL`lXM164^q#jKhwb(h4~E{Q zm`OXatl&7LX{GO6x=|s-{hLb>k%7KDlP_QJVW&hG*x=1WLa1h5l1leCLX+cyNM-74 z4tu&iMvn)Dgk13XHW=U4jl$FnoC)BYpAp`sm)R>t%X>w)WX0qbS&Iug*7HPln7-9~ zzgzsDn_9=e#D+(GS+i=@S-)Riq=ka#UeA~|X~Ffr0ae#z4)E*g3-`EsI*0{DPt0n= zmTBMbXKcAD-|hZcjh+XNjPuS=*UnnFY})iWTRy;=?BRvNhqbH!7`%TB%#mhJLzmHy zdZmtA5%;C&{T7R-wbniNT3ZpKN`39BvwcRkT@@QN;TW{!`A%lE!r!QZ^P72Nwpm6Q%o?{C?BB&*X=$yN0QqS!FeC zdhnBQnY8FVlp68L8Z8#`YSV`v$$w!jckeN2hBF8_T)i3!t1C52j~<8DciGlcmFh-a z-I8IKKAkPO^=ye)om)8=P-plm1ySR2j!s@8!JD(m>cks|Fr^HZ;2}@D`3j-drD&$MKbbH`n;8quOt=6vYlw+dkl|?tT@kbS2 zSuFF(kxlJ#@`Iph0h`;tKVxt3Z()^pd3?yJ`*A6~rbi1)eh9wp6dJ!UNX$T>bh=2){rRkXf@yWwM&P~e56$7F8CR>(oJOh zL(*gAfbj(}xm8(du>Q&4C^yHdH-~`DC;|RT5BS!+DU!y)%M2s zaQ(SJ^8UGNgh17 zJ=u|i?2;|6q#rKZVON(Ud%fGj^zc>PS>fwe^$$6!bN=GWH|8VPmN{9Og*?4s<^8bJ zF4dL$j|JFCYCFtwwX#l9t8<7sbjL#DM462L(QAOPm)?Bi#o}##Lcv-UG9$XowsPUW zpW4tm^}gM)wflyp$F=>Ad#gUoGgv2Q{H(ouD33_aarPd&rB=StYD2wumt~wn3v-NW zvVhW+9e~|p1=HTK66`%+q~LHws#EvisHMBrjw+<4*!yaiSjTqVdakRWy7WsqBs*tM zYMGr+P|Ts3v-ixGKT@tS84D2)Ku?IYOB9r{1ixRN2h+3)V4Zu%6?H&YL!C_%CN5t#!ymHVqNX6MHVJBt`p}>lmlLP#-ICP!C@%cK>8{sq-=1M+ zrb=|e;K36oO%jGfWoK^@Yd8jP37%k`T`G51#^qS58)qoN4_eS{v<>)zfXUmHQwZp$c+)`*Bz zpf!|@0$%U)dbIHEfd;54$0?pzyV%FV(B;WoX6XQQXyk^V;iN~;qj>Iq;@JXs_jhPu zi2tO*8r%}`5>QsKg;3n{51#Tz+)n+fv(TW5OzsYC=w}MN3bQEtaIuf6nHjY>{?V!H z?Z3NB)By`(n8rzD;%F$!<_U4mV0%<~xG|rh#xdx>tNlblwJ7=?YC1y95vuvxJkJzC zsP~|mN9MCW&z^lyQ86{Yo@GC9cRC+n%J%c;e{+~no;?=Wy1s*jZ@=S|GjGN|reSRu z$MHoiAyEe|7JhXs4n-$lnpC)S1w{IuH7$hHY7^;F&;_OH%X$(kx~d2wN^Pg8|5dIT zl_#fC`(H((+F6f~F~QybO{rkdAJo})zAkN7xn=(W1K_6W-c$N8kxtMUJ$XV4_6sQU zg+KC+iiZ#L00JqF+_v?y9wWWF;gbtU2TgVTI`X~gD(m}T^F-t$pwkWC1ieY1r;YX! z2`C%trXAtom@YpM7l-(EI+ikfP1sYs&nYS{QC+-IkyE2|rtgU?+ zX2`_o;xhiCsj+@BwbeYOp~7<;xk0i*nw#d+x~Oo5z{RS#(A8y^pz<-=zJ@K4S^ zT9ChC_u=k*M|74vE+|l}Ti&}A$G`jZ$ws37`*%6XAha9;*ve{ABV zs~`$t9DRQnFRfHY5AX=|9p>fq8ytIpm%5(oIhxSo^~JfwL)^J@Du+|an-?SA{#s9| zBB28BrXmK2sHc1d^(&X?ssd@JDyAKD$dunUxC0g-WDW|q`zk5|Gp=u%Po z@bbn3B2QXdeqMm+$DJd{D?oL)a}atNQGcRlTkklyCU&OlF`0sY50LV?Y(HTgb{njY z&FV(54Li~P{qD}r15?+(D%fVc)~rD#%L*=jQ-$6W6=`IJTPx~D3O^*2eVH%- z3{%&e)$~3hA_8pW!9!s%;eV4*&hD(cSa-@hBxSL5C%c$Z1IBwe*F-@6mUN>WCWW0q zt5GWEn7z>%{^&r8&z;Ij1UCg*3Z_J;P)+R!=_+~^wmtmVM-|bX_U1-+q{WUwdp&Pj zq)G${grZE>PVEu#OG~u;xmsFkTRmTPzlzqpv$o9&DbR(z!_3)DQ+s=YDiWy1OjJab z<4466K%0UvGhL1gC3$(2v2jgNQA&dm8(jd7WOfeT>5oWtr<}*dOKXbk7F8&D2XEJG zWZ^sd_7q49L|r77a(9a^Uw-@XvdkLqvKfnXF{e{(Q;|Cr`uSW4_(PuD+t;suptM?m z&o>3Aywbx*PppIG+SP8Y++(p%VT&#E^UNAYkCC1^ zD{82xu4KWCU;Mn8#nPrW2Ml`g?q)5X1Vq9*^scK?0~ z{5S3Uo25+!@AScgibR4|8;}5qk~=JyqG>Q7YuO(eVNrdlaCUv;QkpXXBDCuKep{!z zvAnv%bOdy|P|7roR$3L;u8lzlYi?eQnrL5KNxQ&+^{z`FOv#*THzShjt#CqPvb?*5 z>Eu4q=Yy3$E1i9Gp=Z0JnEdY2c*Ec-{`1dcro7_+L}dzdMSB5$%nQQ=1R4Nkf%y^z z>ZzD54K!T$ftYk(ULH9WY_`2gg{?-^eE)w1)6c`z+J;y12CKH$O zH0Drl1^r5%ufj!+Bj@puM9KLR;EPdui{o(xfe=fznQz+Wn8q_rCAv`9Htk^ZUR4y}a%(H=pbC`CQlg zeZJ50IFI8v<>V4EI_ck32W7ftesquzM|vu2fBTa^XqW9I2AozLHG;JKa< z_fDih-OliRj`gLvZ-@wb-UKPEKo$UC^Yw?nHEx$c8^$53w#ZwIKOY#3l-YrFssAW} zg%l(#PLwj~GD2R$OT0@vrO{0K|NiH|a{kc`Orq$NKtl1r%d0uc_ekadIt5sEx2|4&n-9+#xTV3^1{Jm`qO^%+ z0YWIiukh9D2;q$f;SPbE6l7(5CNTJ$KVW?Ul*4eg42+%wY`20+@gu9wJU6opxH2f_ z&v^L`&_<6W4<2}Bc{7~xZB(qy~ENBD!2 zsO;gP`fZkf^0~zgfrfhIW;isFJUK7|BJT0ZE#C&%OK8OD>X< zRrs2r2B3*>{#EdF2#UhY&{AH$7Qh?`B$&ne8;MoR0!R+P+O2>GBTa#Vr5`jyHja}g zL1A@=FB$l?;+R?|kq&Q945iKdK9Ig0A$q^0Te)w;MwyN~=7NA+0mc~7OhwNdb0scV zy@1CSaGJpleuMHCg&1Z?f$DGECc!+!FC2xh@60o4NvT`_?afuHX)8yytd#kT}34PO> z&SBDe34fQESpAmr;N+9f=yg;b8$_K8TPyhk>~f>CG=mBq!z)d6etigGc)KK z2V8e^M`QFH5-zmAIJ$uz!x!!|I#V+u<><+wfecwNSg>4*;qBPO-In0kKrw_A5(gr# z2F!^@=8L%qdIgWp0J!{UidZFn`gA20iLlGQZz#YXjKfOBOC-G4|sJCjaV>PKNXq8u(}``b+qOsOgAc0*d`(QDoMH6C`d4#NtHP z95vvL|8?_Df3kNC>#X-Q@fI`M*saqgi* z%|NZdW_yW!!wqjn-I{nmRKeChY>(Q*Rc zzzbU)-6Nt@0HzB`AeR^E*831BAlTYLCjs>U0So8na}b;tq`WP#xWXorkU)Q<7o|q} zl4tt%L|JZZ6j;6WtoHNyBkzTOkAJH{h{d?=jgGC1TT)X}Zeac^Fzc&F+n)vyt#r0!J8u6^(jM&KtMrp#SvH z<#KRKSp328Z0+0GlkvgH7PM{-`ma(VxD{v0Budc6fak07GKl9Wr!i?FSWe?4WeN+b zJ?t5fs?K=d0)6{DU^~?FSQ#`$5nz9`l#ru(+hc|AyH~z5=9J?M z6dK6y_c1eDn3{sxD(KCsIj^Fo#)mk~Th=^{oF!r^+8|v%W_xOd|5>lio83j0q?xKR05(iC~Up!NAB^ zmwyUA@z@3XDbLl%^V*Sj{J=s(jet^gVQ%j7t1Hq*Mwoj9vymr@2n6DI8ZzIjic&G8 zR7lMd85R1gBZ+bN@<2a?^dL}ayWRqB`0~n%9}LV& zA(a6M#l>iZwKcLwBRd&6C64%p@?aW!u07?j?Ki|8XJw7nTmh0-<>c3u!>adLu|CFFOEJ3ERjQ^EYJzfAhr%dIrDkq8se zqALLq0-W&DZCk(b3aWju3fT*mi*ySXW}`flAnWBLxBR>2qI;dL6{Sm?s2RUsL4s zh8PEnBsO6ZPY=e5#-G7{vqYZ_Edq>z_;_(l8$;^i<$RI+YQqH%cF^5Q8-B!uI>MCr z`)#mmQAcHUpR7z{61TYl0x6mzV*8)@`tF>Sba0&f5yv@IxQjnOO7_vP$m<^*xs|Jc^#fTByP6-K*~Z;(;U6 z_UMkASib;>{I>;&PM0(^1agTU?m zRV^15NOIfS+g-p324^~!VqW0H9ae0S%Jn5-%=3SW4NA#NO6+ z9{vEt^^R}dB`I6%FddJnBM8gL`ZxsG(SmITH5yL5ASU7C2@25E49}u^v&6o!vI5~z zx_d7?0wE&AEZSu|uopof2CUlXfVPJjkd9loR)AkT?@NCFgnhaQMGQ`Dkz>bhw#0iQ znnNKG7O{2f))Qi4fInfqzisQ*hf`(m3h9V{lSlw74vBk?NHc&mFVc~ z9BMEO_7_r8d<%HYAmu`~T#f`d&juh0!YHy9jG9k`;0W`oCn^X;`gKvPWrr-P8rrJq zZ@`ni{82|7JB++^kGmeBiNRmdB|ibePn9}CMLjqylHw9XUphLOed6)x3tWH7BFMpXe)+&AGwVKnw8-OiG`ecN*$~=@haHTtJvn{>A)mPg5 zfc$Xkg_ZF z8>yI9@#oC@A$Ntmv+wV8eUKtR`RxRyMsqC|_Set;O?!~&A^rL>GP3tKE8Yj$aB@-- zjZAl;#R~ET)1MeVH&hTT2SVb+nS%k~=HouVVhvoayb)BDpkmN+U4#m$3&+U|J9u^j zQ5p(%#ht@x9P%Zzv=qZ9*f_Yj9^AzECnUs7p$%&wV!)mndGs9W;}90`=sHj--gtnv z!Cw}$_vRrI+e_13w!-;>h`1WYjBd$MOA-4Y4&~?v0v0*BaqF z8}1|<9Bls7G}P+GY5a_qa(6VVH<5Q_>uP0c_>vdD`c;uu@Q`7DipPm`hRpZ^%KT@g z=X$pUa30_$CpYqvx?3gr$xxp0m=TAxLDM!* zMl?VUf=dl-4g2&uN_#{qvtO~BrJe>PNn|Htau-R*G-tmoI{9!)@?Mqi!Qrf@t=;TN z3%T0vy?Y(7CD7nK&k=}A*QW7kb2hzu$1W&HD0A^NQRxyo*yR1L!0>@XBG!EYjtBG+ z!y)VunGOa#{2M1w+@N#P2)}N;5&|CdV))xEpaBG8pqXvJOhc1kzltu1}qx< z3C+A#&ykm^qrihJ7uBvJ^~BCETy;mDEu;@PLJT-5Vp<_I85|s50vHTg5PS_E6cdkH zeusoaMwX*fgtx0zP?wMx{NCQG3nCd@<|HM8^9ygzOL(Ei(MWdmK5_}tz#Q`~wBu`P z&Mn-*@~qDY6vdn#Hre{qjEI~2mNt$J?jWa?!R{p{2M8)+(h%0k^XGHDRNdgX8aDs~ zOTTTWzBJ_JPdITh>%MvS(IhQoiIhawdvY{c$Vskc)w1;9vC=|1x*%TwsBRmpDnx*T+>7TFTcv&NntZsL1E$H(7MZ{8>t6Y=+{iBV{Z0*8k)BtZrgHdjiY zV#A4?a=eI#?!23xd3PmoW4&uA>p&t|td6JPa|xLJm2iK03#} zCHc9XSy%2)tfunv_T$-6n%4ov&TmcEckdE(Za!W(rOA7;;)a|3nBtG?Ut6=yhwqlm zof8O+2nmt9z8Q7qbA3@1q3C(2YwpT_uEGtKG}c3cB+!fcDjxYeQT6qXr}|LTffZg2S|h(GWNC`qBQ!Ea2`je}N>?R`R|4>$MH(6r(mkXNLM_NCpv zbEl=FBjm`X`MDIOuTIWpsfMuD>sZ=(IXy;jGf4`Sw#CY5<_Y$awd*b6Zzk@kbp?rD z3d=s@>#P=Lvf-eWf}8=^H^6>iL9i8l$*RULq%{Nh16~rR0RHNJB}+Mmkb^oo*ZwL@ zr`y=Of>RS>Gebl7tW91+?uG^eyfj~aaBY2omL;kM7^6&Lc>*am5)8wIgpVB?{hav~ zauB%5fYFXF249R=a{?Xcg^s^^#6E5_IIM9(BCV~^En3&`6lN)sG#{<=w61o4@Jig# zy72ThN+nGAS;Oq1yC?Q@j=L02;z$C5h*RAeH5fggX8WVziS%pWkP>{?jt z<+6BGA7$G*P-QF`r7%GgYzGqoGkgQc%rO7=IGwGn#?svD)NO)l80u zICs^r>7y5xGZ3gC`)JoC@DdvMF}66S%I<&Z4k(9e)cnybw6nuhSZjW z%gyOEKO0-zYS3Ir$E6-kC?Tv{pc@AYYz)6lBn0Z6mN%uKj0B}un?Ff%Y-FVQ$j*3f zUNJF8964xt;XI=Et)8Kp#&Hjy-y5i5!*`aKrr9~ECtJ9lEEwBD6id2sCr-sWYy`&3 zRisccrWN+SGLl8$!01CHq`)K&M4VkhmWM!&-EaSw!U$A9Ska5TI|FbmMx-Er2XzpP z4HN)-^eX|rp`pN?rKTgcR$b!b;{)m5nS*iM3I_vRx`rWR%!&t2&BXjtN;=nVE-u-Z8>2 z7TJ*TPn_Dl$oSE*$JDbHcn6i90xKTR5-E4bjdo$Fj@Gn7#kr@BE>Fle%R z?J}8^#p~2Wimo$s!TVFy6*eyPzYbW{3OI4DL-MvmJt>Kl(3f}W4$V6MqzCsvqLdQS zwv?TF9(hIFmh;p*1-@yDFeUwY{JG@&b9Bd2$Ud+^AWPBE;rlZ!X^$~lTij&CKpFhR z5-=n2!~Jh{k^&oUJbpY>|7A({Km8MjYfPZX94>BFEnF2`&pCT-lL~9(q{@ZcX08l! zmvX%YU#en7By!__LKHY@>XO}Y7_0Y^6WC_jtc1gv!qq>mAxuxVNh#tk6&Bq}9OeGD z(@X6FBfTl9YUgP*-nfTq&Hbgi(L4t+REw zlTQ(Z_9Zd=&ev^O_pXp`Ch^ZC9{j!gk2e+*pYx)8QUB|s|Iz`aruF|^fSQ_II02doX4?wPpTP^HS#}<0FjZ$>_z+*KqJn4fXNbo zcF_L}@7bmzclYiL%2a}-J=rZ6DxcVjiVTM3Xm6u9b#`*%6$ni>`wDw<@CigB&?vtF zTr5=`Ron?AQ%DzVnLSFsqbNfDNk}Smb;FacU1Ctmbh>|94995NgCI3UMwz9m^Jui| zy}I%StPlXUC{Hb}UX|%2Mopn`aEjkd(yVK)EE(0p_jt%Y$n-s5*7-~A*z9C%XpG=U z=>erg?h;xTGI6&Nsu2TmCLl`TLO63T7gFk+HiA z@|gOr2(@vwv&e4eR^8#lfpH-AQvf719hew#XzklqQ(c`ZBtt@C@p@tI+KMG-aB%#~ zm`u>xBVm4T*#pUM84!8s;6RIeKserk+kXNqWP&h#C>c*F>E%m028J{fs@M!9ogfDS zh_Byc@ZaPvmkoXv{$FyJ+;Q9UXr5a26o3Dz5t>B#E>%N0Wob|yA01*&lV4Q73FAR6 z&xly=$8WB*U-1ET^tD;1;a$lG2BuWuAEL`2)hiv*U8JAqn$EKTXMvRMvOwrM{JgQm zFwYL88;H!%pnyFT4}&ibZ!;^aBk9}CFa%3A=?pg=EY*;IwXg!V2B#`Dwp`reKdA~3 z>XR6<3V{%)2fBR&;;A@r!YQRqP85uh3CBb-v7}!9{&aJIJcl!H9ms5U%B#p=P($QH zr;?W!0m(m#XqQ8HYG{2yEwz)4LrAEtzrP9%V8~1`(UPFtbpN3sko+pbdD~Rym zq!ujv*&eK+t(}7UHaYp6J6v)0JUT;OpWgKu`eUF&C`8aE0S5xDvw%`Ny7pbk4C*l= zpG<&(7{4<_g*-AGfI4EjYGZ8*RTtJT#I0YDf?*NzJPs_-EielS3JSuIM>b=m6v*r` zuMBc2YiOiFy@6L*TnY1L5|uME-!4zbuw^LqMP@dAQ4_h)&+(99E>Gg0usLBWcY>+lqLibuoG=jbs62RE~N%dkORq+-Bsfv&bcrWbLmN-b4+r!z4OG+3wB)28}{MYoxBLv)!+{eow0N44%R+xE!htz{-06+|F z=hC}BA7^yn*jq-Z^E9Y-6%SIFfN8$ky$D6@M? zO|W2fym95)=QzeMk`itbIQ&5sZ9|8H)on5Eto=5U*a!4JJLskiRr6E!%(KaM6#g^T z3FZ<+*BV{%$JTcK>lTG6P345DJd3O(1UZl>2QxuL#>$WhhUd$!r;rP*9W2) z`rkxHAE`N#X}IxO0I>r`koGAFp0qD2V;l7-A5&#(sF%wW>!5NJn5(aKaV zkEIit@>u&QDj=w6(Egf2i98r17znq@`Cj{eGVixQt6^)fvb_Aj+dI`2Uc7WhCA(Vm z?%p455BW{Om-$}ESlqS)fByMEZvhDzmszQgKTNT@aBqPwu}Ny|W_t;+g}yQ|+hrKk z5ppuJRD)Vjgr5BztG=6g!O9ATjLTBaQ~xAE9?So20_VYdRZwS_!zo2#&`m5!wQ+86 z$^t8q;-z7_*w^Eh@uS?xoOn@Ge=*nB&?7FAa?sV)Q`$m*?^Y|G?a*iWyX)(Q$t-u= zq(9C^6FpW`MmUeD!(P(%=rP8zv9wVs+^GgFqs_4|iio!&P2q~vRS2xQsj~j?5>eE11pWx5+3l0iFs!w% z`lI_4!jUU%k)Hwp>71~SmNm34J^D|56QyMl)y%ue? z;m4(HLzV@-8XG(5*mgZ(8Xdi(&EFWel|(ojGkfLv>uHA`p4s+vU)U{i_yl^0pI207 zG%>A&MMl!o!*lby2rHq(aHyZ1TS`iLevwOPR=+gq9iB@{PLE zF~Y+WbaIM}KNygdfWJv`#&zX6IK{=y|Gw(%IiIID+wd1@B!7o+{rB0v7A;BpE5JpB zO8sflmX?D{+Z?;Pro7)q_VoB&y%R74!}s~Eo7p$@zq)rvHo8*U;sbGeW8kiravrvK zr4G{v*K=IT3y+M8U8^L0<7fnyz(D@yOar5so3w^LI2gKSl@_V3?aQGdo^S z45RWG1I_pyfIg<AyC;-??Tmw2sNOAk{QGgi>-)R1Z&lUbmy*DsuKrUW} zFMY_aQ0b!Swkoq17n7o*g1qI_LQ3f$k>k;%lpH031AnG-J?2&?L0)e{jk^E(>1ian8uO%~OWH<0yvzpMB!UA%Lk}_dj{XL` zi21;1k;07h)$7-<;Set)4>5o?KLfem z!tmN69DY$5ZoR+p#O4&RTt7c$Y(lvIUA}x72q}PDx*DDDpXt9K&4Upf@Ga=!Ac!E$ za>i;5E0tyBRaBaR(g5kgr6(~JbafTEVB&$J+vfQuHjwwCWE@2s!NK8#&%1!8{b{QS zm_!Mm#U|qG0#gSe3ijnivyqVK%9Qekiqt$tLK_E;{zKoAPdXJbn1a-|2x`bG{ zwt&dcDx{SGhYu8p6|^%^0Rad9`6ph9kGu8|h-nH>n>2HEm)50sJwL4f{YTHxNXrey z9r5(HkCVhkHIqb6v0!6sHqGpONbYZE&drVT6?G0njfj4vdIdnwN1*hfxU zfi^QJsZNv7eglTps3e+PSSsj^!Gv;jbP15ow{PFj1Lb>|_coKS8DKl|V_F$lNFh5W zte;R0XbE9e5mef;GG}Z!GGe?sa4{6DX9<(CofoCo$XBoZ^D1w+AQ%Iv(;r7(cdhf^@e}5LU1KF0!Op zd8k=<^)cLP5zhv8+xXiE7TwwEgcwjxw0N`Ca>GwqG*IJ?Q?jhCIm|u65YT{>+P804 z)3cqFqJLZi3+hcuMy5F_8?*jN773J7dqQwBx^4N={OaoCY%BH0Rc}x4JAMP>HS@4$aKJ2ggA>C;`uCoJe^WBC z;|%F2;_(uNbcg=z?Cef*^2bk~V#|+vY}!IMD5Q{ryo@~%(l$fXRCEU))!$Fc#t2uB@~NlLhcx*Z@)HbB(p zXTU7^cqD^19|?UEN<=gDb4281qI zM6}&K!9=2>e52*hZ4IssMT{`ule>hVY6nuLwRM8eV>eC27(|`3hKndmVa8ek2HqU6 ztLqxbElx{lW<4&-N?rU3n~g<~m{u^%9P6V$_Ra7i=Su~ZC{A!SV^(a<^w?a%GEEf~ zLe&Sesz&7H2ux@eVk(!FNmOn6#JPl6Sx%~{>$363!WxN;J6hr-`g<((r@)xSV*wC` znJF((GUHVT271lt8M+=YrGbvv)n)zs@eQu#L@l z#yF-!GSkM+F4z9mpO~?t8`GO*#xGkBuDk)ipIT(MWSKm&OQkMUV<$fAqeJp`atTW_LGV++Yh)qp+?P13Q8zV}0 zRGl#uJjeboP3jR1gl)gakMG{T4MTn4OMKSpagCpa>8nmbhk{#<=Z$Fq#Fotys!P!& zSnvNw*WF3j{^^@50BiuHHN7|{%S{(8ZmaM-n&6&P}g}U%E)MK z+O)^F+C)UXGBQ4;E@drz@7LHGX1V{vh>WfCTjFFtF1&%(1N^HD3+Z-f?P6D7Trn5`%YWuzJ8d-n+@dqPcTr-D#OEDPTbu$cy2t#* zH=Yv3D)^wF6)9Kceg3a)f0ZFuJ@m5B&OvYb_w=+QMu8D5BB$fr+$rcpgW5+)My8W< zbsL5ays}lSK4OIh3aSvg?Qr;;MVF?2>*cj&2oFdpD9X`ZhFuVvHgF|NE4hUk892Vs zeZ#*tEHsB@M8xWv zU%MI2%{$KRX@%*|^mG$n`EHI7g#p@Vz#j@7pHL4B+|^*|xqN|!Hi(oBSyw{#5fg-z z>y42j*M{+TVJrn663Y`^~~@%9~ZH!J=lsv)bIB+BU=TT*=D z>zCt)ye^l_++?_yu9ek#D7kZEotb1acgifgtZ5&%t z*%yDL6Sp%mrY_ipxW(wkg--ivSZr3&0_q1kkg#RXBJKf@bf95#w?f=kCW{_EB*o}$ zJQ8eXP&8jah$yaI5U7wy#nKmFvv*{CpY{vA*`>`ae#)eEO?$|_OS0S4)GM5&NWV`n zq9AcyFx{h=Xn6XcS~``Lka#`2_M?(1*g zlbxRHSPD$^9f?c>Ye3XWKg9h&X70=zL#hh*jZG0BEA7?<^`oPrdaL@SWFBTu4a)iM z36A-22!^|&qMbcGk<@|nr_>Nl}e1O*x9 zbWM1@CueC_-ybMg!PDl+zYezE;RsnWHc?B1oL8@2NV>PY+2Vut$a;l+ne-NR8Tqop zEVTUrIywKDgbxkp8a2DzrGGMUqp&_YEzSAMzz$e!*Lm1UKB6D(`{c!Bw(In&sB z;N6SE=PE${AUiwA+uJt3!T$+lEQE1j+8h1s1v`O1tUVlFaGR@m;;zZwTX_5SB|!-l zD%6L7U5C`yl_VIKEoIwG6-Rg8l99)mJnFr;xK&5^0$&4pO?vPV_a(t-YSqh^d+G{q zh1K7=bA;~+o3QX??RQDcjYMSuXSDG3<;#gYdxQITcHMn<_Gw^{AtBii)ccd3j$_s6X+`-hrZP+EUPh{>$!$BBGii346= zz8rU7S+KaPI)fmV>uc&{_YIl;Zkfi9jXk9{&p#G(vPyco=w@}Fx=F4}2GiZK+JFSf zPvNqpIj@e|TaT}LHogDZps8t*AY8DggX(+-3(Q$8Ce3Mo&|LXLq zx#a6=Yq|xNwi7qzkPe^{EwPgUEII&MuWW|5&wAPEDh?PtH0;-iISy|CiSKbfrW7;P=IJ&Rh^rgmehgW|P z=n?&&F&oVehgLeTjIh?g4(u#x7~|2XPt@k-;joPz)R;*J1-`BSSbxRJ5q%wza2-zU zJ?ELhR4AV&Pj*V4y#J7TX13dKgm3gh=*H)^HfJcQ=>@&Qdws`z)V*1@@0#hM%l!$~ zH4*+hyL{5W1oB$NGT81KXZr zWvjjW*FV0h@ryxspz+1&TR-bf#7auwXBi)qV)V{O)2Qv;11i^m8sP-oTnx|tr(5Du3swjvSHJJ-r0k5=AvlU2yGm{ z#gN^z@6><3CP|7or4KDbrR&?RF*e|8L!O{jKE2 z0v_uyHql{B(#D5>i@!AEIWn%x8Ay07DWf6$h46}2=EQ!=wV5=@r*!5Mmh{JbJx zcSdF9&l5iK0-CJz={^9qtyPm*<+-ZKeb zoN`D0C#xL`X5wHXh)cO@jRCIRIeXe|@r8!EI(I;DibWY(6L>Qxr~RAyUo_S9ZUJh= zt2%DK%_6YIjQOI45mG`U$y;*D|c z+}w%H_i{YYT*0N)1AsOcS+yx}a4uga;+pY~zHKD!ryfDJe2{@$@*z1U^cMboASAYd z;aTndm5M>~oUoiLb#juYg3A_&#}X1*aYmjr=cjRN6n*e*R1T#MT$RvT%sHdVPrWzI zNRNcXi~8Q{lwxguI=6P419)RwKV3nu9&<{c^as#M)ZRYP6WL?_w}qhcCxu;>o0n#E zTL)1&kpGvj@AUg&4GPf?+*;!IYvG7r7!biEcni zdD^@Og|x}}M?4o9@@}eKP~4&V_+87u?YWCgA`T&uC|+C3OA3aF~!6VP(-wrO! z%p#^H_yA9X0G)IGc>DJLkE=OS&9USXSN7jG>#MBe@VcSlbRhet5QLi;!JyQ3kEDGM zp5#TYhT2+fWk1h3ygGlAZ*^JXE}zYIY8QTC#6?=>Z+v!GL#NT0tn&TZg%k>2=pC3D@N()UCOR4Sxn|#7>?}H6o_Fs;~%dwS85XOZGx|poVoz zJ^z*)n!p(9L((%dGEO+rQyDt$-gCXR`6VE@0;aQPoj#0d+ya)A_bar3RdOg&Vqf0X zr8LC|&xqs4GCL-L(o1>gi^}4PMtNOOiyaj?_WTI+a75;3_WNL2rG9RI)y9?ea__pj z?9H7Ur;KZX+nq{odNDRRnK&fNR@Ix9%HKWq=dwGrY?bor`DPt=W#2s>9*>l?GJ=!Y z)9a*+ql|imUU>Y?tYDsUsMgJoi=zIO4h@!982YGx#q_h+I!FXU7U5N4B|0C8F{dQ- zt$h^th+NKPPCMVP>5R^KY3Vn0k{hbIj!~6!O^q&{#di_}y#Z=iwWk;fJ4cU6>Kn#j z#C3L77NA0)h`F!wQ(l>7vPfzE){2RZK@gbs-Uh>&o&i+e$BP(;+@B+>?qd^|wB_-|b6a$b&a+A7BF4TC>p- z#rNzgrJdfq%A;u_G>4+8xu24JCbXkqG$IWt$ov10w@uH#Cpk&S6IfO6{ZW z0&IhyCQoXNV?gs+>3y4#{JZH^*!_Im@rdjZ{@fsG|B~j`Exx69@!wK^kyCvGw(9DV zbmGJpA20KX&Q905z@NK!2jp_0rDgFo>0_aV-lEHTa2?+A$ma}w_{o%GPaM|IUCqn! z_BnSPgsmIzj(iLk#Xv)yur6EPC+EUgBLxG_oMSaCw2|w~vWyT};|)=OqXT=Drd!pg zn5v@|V;A@Affbk=*x`{PwnP2yhKmzfyJZTkc3vADG4IcvZ zQs>s$A~I!%`wEyJZ1Ov_dijCBp~~xX@Sh-wHPBrP-W~A~gujvXwH;`)Ad!xbr`*Rx ze(Kcr+Ri1n)#7ZYdGr2CX14dAK8XxXl$Cw@@u3rmUBZa$TXLTl~(s$|>+FaW2 zCn$NsoONbqJ@ZxJht*f-$NT?uDBx3%@h|Cf`X;*IC!p zFwFS7ogS)95^9SkYEm}#b5FliN=zWeQSDo(V)yX_R<1o&)h5X6erbKKF3;%Q`Z>wZ z%A`8Quja(e&($!@-A6lCf~C}~ML?%~;!i&n)rP5dcD54~-hfeWbSz_NSaHkHVK#JW z-+folOCKwUtRJvl>7Cz z%khSs+fR9xm%CKkddb9XqWVkBZCCgzv{g@UU#AkY`-VgstaqSEWNtPE76+ zT^#Ra4K;SbgaqX$Ou|19yGYsKvM$_uD6}Cnz%9-1&6Q%iu@mlnkxic?g@!Tt&u^!@ zAwWINkdXjwdOL*&?o4p71PgmH&a+B6Mr3wpF?Fz{2eWv7GIv_St#h49 zSy@q+XJ`1<7m8wIzpXCqJbU&*+x3fUldt=7`d#61G*z&>={gT1K}-eFj&FRaC7~w7 zc4Xp*%k0qM<-1jI9{ikn@{>SJ-%5IRHstJjPD>^|4T8I1lypR|(s|g@mw~c=%6qwG zIMbXavpb@t_O-{ke$JE(86~A>8ASIzu4OaKa zYbG~G$3?}IU+l47h@22CH62*u=VWI*Y1atbiJ``5(JN9L4I7uyNJKA8vWf?nJJSj6 z$wdH6pK5PAX@EEA$NUsdUohJ0sko&aHVC7%n+tx{XtFvFHFn{vMTl&qE%&8IOa-TU zQ5On0w;IRjc6(Kx_M;9A1>!!-m*F21s!V$9Xo|yO+?w`4@!M4Q8h%o;%oIdN_kDX~ z7;3nWC8q*4I=*9nCA-UKKcO!3LUWDVwGS|ORI)#H?p7RZg7PfBKF8a^mbKh&z8fy+ z%Tyy;d2u3EeG}Sq0gGN=E`)w6EBo_E`C+2rR7hYrw{uhIYVLDBYm$|DYpPwnkub-x z=xzl3vAnE^nT9$`now8tSN2|Zg^Xn9=ZvMUj)DP9jWuJBZc-Ht#9}#V)fWjyDD*vQ zm(}O6E<p=#ClQm`@L*M@j$L zz)#p3S7KE?L1}X?)8rL)WZYQvWpr6OC=%zLkeQUQ_(Xj7OU*i`7?aj!F9VQ;M{^Qt zVkF$v)uL{FFRK8+`z^u8&y8%g*;K4T>%6gfQ2^8#N zyk8H?5V~>;g#rBcII|4%EPN&C2lwm;j-)q22{;s8KD%G#UE!2zcF>!9*InV_;L6u7j1a)nl@Zn`|j=VQ%%16(wZgmG=y zK>Q2v*Bz7OEcmhW&d0mstzDTHt}C9CX5fFZGGpQbU5xjwE_1udr}uFgkNO)^Az7d6 z>4&B%=7gE$61_@7o~>+c76D}fdp!IZiVBkT1j5(fn{gJ&Hu1uyEiR|NNp^XI4^OicNZv`d(o5-N0em0ixY3_2T1MlV_7FN)JL z46Er#GmSq!ROc?ogHtxG}Z((Pwl_qUPs$fnS!wVf>~dE2ue)>5AXlb@W}uYWI& z#2#!&sh#J0D03_+t{L~fl+69LbfMcSsF?X`?|wOsc;zkhSxyS28`b=EMwQ*lTGzPF z(de_Mw$VKOK&isYCYy5bp2rdD-@?qOWTlv2*Om&{_Ewh*Nei6+9hBeCHR|GTYfTrx zuv=ztyl6(cCr7Um&D$%L-G5TQmt6pm?9u%ltpLP){fvF=FGSCsKl$q=)ALI1DBC8# zhk_iIJIK`h1mc3WruI_Y%$wS%V(_FJJ{t6gTIMFlU619z2EiolB9Eu1*=9d$->m7~ zP^4LX#I4rqC~4&4lydLV+;iKG3uXfw8|ODyFFM35-Da5G{ec7GyuXqgl^q{yRvPvC z6;A$&XR-^S$9Jc>Q}}-JwR@n~tv=O#?l;@+cwLv>BN$|NjP+xO$~TgE%70!+`@yFS zPLzqv_LsP#OuRGPll|k(&nLUyJukyGK6aq~vtcXS#RZq$LN^c1ww&6vjZ&rRpMkgC zoCPsFdZsSL4dt^H?Y8b+C&{YC0+pP}2HHZ%WLKjdJA4E7@%2*)@oYZ7*@NldFS0cd zu(%}d?-5`dK&#t>)m2zeB ziM@43$1gzFZ>?Q~E!gq;ex5qDl`N9>o&Q{6fqpnQ%jpuAeq!e5hWfoz0(t9E9HZq` zmjhKeMvK+#{&>JaiB+fb!7IzBf%He)l*b}%O?#u>*E+tetRP8Y9a}jWf{u1>-}OCo zbgFa))vELq+hq-7zP>WrLK&Jcs*ROb7BZNV<*MI0ySc-TcKi)R>63sZ(b?##_mkA) zpZ9(!Yp`J(@8=2pw1d-f2O~`mzw(vxD%DEa595+Ag4KVNs%4(s{5vtdlTl`Qyhu*& zs;sQrwYIaRrSr=w>S5ZK0}nL+aC(ztj1jC?CLGaG8GThJt^tfC|dTVCd4oKawkw0>^}{J%>9V3VRA(rcUsBQ zkfbfCU!kabqWA>AT2|KgJ`ZT;Dh=DaZe;-AHqrg_vRr z!%j0XDUwA$CvnQS163;g40^g@H^u#r_#}pu$g8VsYrj0Bk4;6=Y%qUZ*5QvpLo>n_ zcjfWTn>O@^od05nP_?Tn3vC4}$;0aJ-)(n^miHnQS3n%~BtBA)>=+Sdej9pLS$U6| z41u_`+s=y;`6p4o{!e1B*!#_yUuB9c)7>PcrT1lKnu}OcXsTQv_;BSG-@Xvd-l~mQ z00%pqhet*RfMc(nf-@6G#aLbh&_a}MY_ckEQ1PIOSFef@O1?(Q1}#bEqgVyS`51u^ zRg{k13C{L1wa7JkdRNr7Y03V+PJKJ${nF~1L+>%2%-I>PMF-i~a<)681KsN`Wk}Vu ziEEc4Dcb_&0?t<9FOtMtweP5%L>b&+Ci>l9*IYkXQRu$m<{Qed z-h7C-4KC+zQ%PrzL~LgkFKqf$|EoD?3)|q_sL)*6o+CdXpFNV^m8GxOm3v=9_y<@Y zO))j4CyMUanN3c#FE>dlC)NIx6Dj<7%g&m(SnNk!EI{zjj*+q*Ra@6D|D+tfwLI8!FOl_Gpp&z;nXJ8Xl#~tkOYqxt zS`~q}NB6`+geiu?YI3D_DAFI{f+un$j7yt2AAE%6R2=dep+ z)ZC*)L`AK-TIDo>0{fPfETvW{(aJoaWX@eq4go1N{IrDB!GOhO#pfDouhPu!%ZfnK zyt1SOcf6N17kwUB!i(z#5^)SXbzS3vX%iJdh{6s|9aQY^6W&k0<;QmS{-giA(<Rvqeqcdq| zM9UaH+Z{*>1jIU>wB9gFCl(z_q@cx+iF8+$h2RTgoHCn(%mR+gCaow z_-+5|jU{S#j>J?vbS}MR?-fRAME@{vXQT1Dfmp{~Om;i71kh1|g9dS(#-O zl1+9bWu;_9MnftpE6JXjS%tEbWL0GEy+`(5|Hr56_dVyn@9#PPbKg$qs^j|jcz@pG z^?E)Z&&ROvicYP0qZqF{{Za5(W$?h}y0x?#+*U&O?;<+a5h3XY{?aFq62RBv_*fku zQ$-wBv$z=B<#4XKZDy8%=f>w4K&Wl$N${tZ(S*bZ5%-4wEu@Sg}gy zI$}#$8*`PetUPcHizv2<^qD*sR;Ll1?F+v01fl}X_C|VwWy{wgJL8heQg(w#I!lDwsj2Ml16PD`b@AP( z9UC3JEpl}Ap$W|!Mlr{Y3f;Rf;$!kG>-+Y-c*SC|opaluD@RQFLgJ&E$C%I0_H5rC zs@9Sw3H$l0rlthXJy4r7{M{>SmlMSJEUzximR-m%R@=$4|EWeX14u|u~- z5EO*5i#C@rD+ib6%u;==e3Dsh^|H)e2Lj2<|IO0ckFhgzeG!rlUX=Cl7zBxml(1N> zne>~9?tv+&g++#k6t%-@z0~gtU!=1Kk7>w8D7ef-?FVyK>u3KgOzVj197#!^FFd*S#467KTDQ2#0g%9N?EZmhB%qMm z@2?=|F4EsW%d~vFA@SG7%0MT2PrWOzC3D@!`iG1k3zIWUrp3jv1S!(IE^!Is_vn^> zF55pL=G<=Y0hdpB=UHgnFe=_qxpKv`q{Mdhi#rY(Ck!G$0IT?6Lv{5JmP0C70Vqhj z3GsS&@(esYjPa*Da3d*OOik^AqrBJh#K;y@Xi_~ESaWRGmolp~PHMgV!hSF&Kmrvv zn2_WQbBoQ~9lye#`(G!amMi}j&gQu>?IAN75Y@5;xi{QDeD@vMsjRF#VEi5Kf%60y zRsYj=wz*b_Bq$ZC19;-Tm``Lb+P^Djy>zPVL7WQ5%B!84GJK>@Yf94&5k07_{^5Fo zgpW^coHIzGU>VT?V)qN`>V7UPLQBzxqGoNG@z6HEdu`;V5ADxjt);~84~)lcAtA0f5H6~ zvg^wvdB@x@WM;lprtp8MY3#miw2R4XCi>wcvaU`8QYH(FF$)Xkbf=czzk!>`F$x@% zh9N0;`n&GmPmYapU0v$Ml+4+RC4OiWV|Js1oXJacdPkDFtztW(WJ6%{tmw>tMdX^T9K zYIGXRGRJGq)Sn??0=5?}WMjTK2Tjf+o%NZbOD@i93vEv+20*+|V56#IXC5oN9p8Sm zbi#Q>*)ttd;{6)ZfGpdYz4#ZPX!1% z==V+Ult#K4{y89lj`7arNG4Pkl_5^X(=#(-CM~vbug(U6 zQrZfYZ_#*56U=B;qBhG+vqa>>2X!#z%otO8umT3)L1_{Bqiv?A1+15rrV4C2c6w1T za+m}?;O@YrwJzqdup3n)1KWwRAN`2;-`AxlX_6f>2qCQ7ngCEc0*HLiAZ9AAHYPj z4YeL*?)ODbKclQK@i1PiKi*=*}nD%!_!fheQLgRYi7 z0S_~Vsl}+sm37W`b>ZjA9`Z>Q!VS$JwUwB#w0k=KL{g;C1uv3`xCkh^siZM*zq8rC zPrA}C=J9GOxS1-EB01M8u9PMuPa zkr@~mx%$2c;!lFNR3kG`~L806N`qewmxUzrLlk8*ik~ z-w0$QB^%~VF?#XS{GjxoE+6VPTM3(2ng^PV#oX2x-(3(ylmwJ!-Noa1v|MlMtAk3W zx^r4Q28Lr}nb&T~?b*-3?3rz2b*k}|Chm;K;{3Z#2C{ZoND>i+VCUEp>?GQ!Jl%b( zz|j`hm3069+0iK*lkV=Xg`2!m>-Zpow%r>m&!tvAy$7D3XVXE8u-M*S$}ol{8*Z_M z(e5)MBC>LFtjDhgK37m``v=iP1_evPCj;|5wo6|f6aADk**n@xb?jJNdU~RVmayT|UfjM#*HhUAz--42qTPO`HFGQ01`k&-t59 zht2AucRVVqG@sxx`rt?T0l#5s>U~Gf)aYO<=O2?oBqCND2b1NnXqh}%JMK$e~9u@lGt_BN%)XdrP{L19Pq_OcxvJ zJl;MkWc>`;lX&1^%ENC~7nJHTXPeC%mNoD_yyW)xf(#w_nZXP*XRZ0#NetRb5Jok;|!p?~Bql=4+SWF-Qs? zymy}Nh2#`!YS${>%BJ6?n~#Xjxfi=uVc%-7jAb!d)u|#q`pVv;Cs3pZey8da7AUcA^I^0dL>JU^C_Yd$?pQOr#7!5$pX5Lx#b%Zvts2 zm2*OSTZ9OW6i0FKfScQO=R$#VWuB>S_!d3^!TX2smGlVSIfSp2zc?e>GmihT@nx~3I2H7|ga%wPl2$C^Au7baZX73?nul*+M~&rXP`&;V-s?-WiA}|z)Wh$F3f+T8`+$=uR|1&*sq`N{m$MyzXst{(=V{GuDZ+g1c{Np>l z#nIm^2xbB+1oRC`>7&Pv0s2yLY0@e93t`>NJbcSbRR>y1QYQF0q;;5sqv|Z)jph0N z;kP?Fvm~%=Z`Rjq&b-vjF(Zjf z$ln;sv5?i{_tjs_XL}Wu4OHvK#M`hy&bwhB`kcD1MmcEctWTtRdPz&NuzX6>c-_7s zY$0-Z%OkMeYLNabXdP4s4?ZQQpM!%O94thw;T-smAaY$_ZfR*@^Sq*`*I$L*AkWXw z3cVf^Q_G1{Tu&bpm-2wdn?Y=x-ty;!8kkd;NccW;02jgM{6(2XP80x`*uqd(CTvmaH3sPyHF7YI;* zoh0p6j!Kgiyez7^yCci`T01(7^X(Nf-Aa$|mio{(2@NA$L|>NmVLV7CznjP*{lf=- zuF3DP&&)8UNPYia(_VxbF87?GyVP||D(~uBHqe#a!ZE;}$*l;9$%98rR9kw^#Ke55 zY>XkE8;~>asS1wSah-&QZnI|Ta(_wELa^qVQYkC{C4*vE!@$4=m=z3k!Q=mG><$(B zZZcXCQBhdWT~t<{f?z-3eQeIHt~I#fc=|!63R3^C*4EDn-Ee-|rGy|3Drw|8d2Gy9 zVCc#qa{CKBdGIdKGY;sS#fL|4?R)fWEDYFM8^JyTM}Kl~&>mLNYvU(Na~|bD)Ql_* zPzj)sJC6?r>vXtOUgXz?Vjis$o?t&jLqWhax=KT&%E%!8Ox^U9a)eMw=~e8F4P;NY z>Vn?BZOsp&hyS%mV?!J-(>L7Dg?VJ7IVd;p*x%+8wi=mg+J=AO1_!pkaF7o3uhCuD z6O1fMo1WZ;6gM`y8=o%tZY9(VnvHN7=Ev&m=qr(NM$I0?0i-&WPKP32<6)%Zt6}pg z`Ikr6`((V|I;N~oWN>!nx6j=ZU%O^$8LFVv(2^ndgU{#LGy6M^XN0YU?Y_Ou&K4*= z5PeMi(9NEPfe*aFIo?`TA?R0hBvr2!u&gZ`_r_&BkRlL}Oq|BFUNp3n0 z4cS?-ywI?mBNCPdfLX3~4OCpdx3F~5Gn?OH;EemDAM3FRufAEoR&D8Dwp+XyzZnaa zeX$i?Slh>8@1vK_GwajlHL$L_kO}g9@UBzUWTcm_9MiaAU?{=$qoW|tIa1O=K2w== z&xQ81gFVSBM8)}HDIQv~TO&vXDT2tf?W44@MY1%NW)W}Ia>F|qqaW)Cl) zRj(TH7jvqrZ#kPLhEmyHzwRFxU_GVnZgOob^7)2N6@PHRb)H8`)x6fPQ+lAjfG`2$ zXLV`^s94Zx6Z9CVupPxxRL6%#Wu#NZr=}KwR_4!G{yvtyx}&25>~`D=crK%( zzqGXA@-S=!KnqHl#|k=VPDyUNErgJmws4|v){|5c&RO;!!HZg&95`^mc|_ss0LoR1-Y+|v3VNLk zRo@m^%*(?wx7V+PDst=N?LJo}r5fKTbt}uKC8Qg|QId(UIqS)%k^e-S>F^QmqIEax zp5PvLSvIun-S+LjG`|2Ey?ac#aXu#=sBkyl9_f`Hb!-A8b^E|o6S9VxF#aDbg z=*<>ZAM2j1#U3^fmC!+9)4|(S>-8-yj6&~IGW_G@Nt!pqLw-#Q2&QSTOPgK5+L|;G zs+WF>D!Diba}I>btNr$$?q>BldZ|=raXPVbleMo!Kk1IYmZw+jS|u`9{xG`VB&hl5 zo~vvZy8iC$bX|^&P~Z28T%RpLqf|$^=iscAFzz}@x64-WfA94$+Vb@eW%f6#-Ru7D z-9ClU5wEMp0n=`zPqPwQQ#|NB-Ct{M(;GDi7YdcJKkd=p$1X!DePcJj=3qzB{ZH_A zg8eDFY=Y6Ag9H4AWik+af;{&FC4*Q!R`zt7YLf<>m8nbnj+{I*h4X+b!Hpg92!|)v zRj=b$Qcb|m@$b5Mbnp$+pnH{o%{7;y@hIF8xbQdI zzY8oYCA{t7kxnfhydILvhxMDfWY9L%W2&cwvE)j9%?-SgB9UCf`DPlXlvrU1gOuwS-MS zxB)$Q_f`~cSYul1SI4=L<6%_XT9)v1@G(nS^Ybyy87&PW3yA!Ub~+s@yniI&jR%n6KeXfw}!e6wYU8TRBKFLFR_-{a@q$&%Ms!nWdY+g{%{{2gylou{M^`7&FUphoNq^TGf4Gs^sw=VVaf>k0( zW&e8HzgR#Uf#_9c^-ij)T3UT7$?95K`$`tFBH|{wZkrGp*zU0K$ zHddnE+1%)jey9}8Wn5&gB`^OSuGIH?d#9OwLPEBkM7zJ7E6L2fcpLvm9>ySncbh2N z#1;rd&Jzw3xd)1AxnD?#-(Q{(OEQ*%{WGt=SlHTx&&iHrzZe$65`9o%@jDkfR^N;uN z7-d`kZ0~^=Zj`tJiMZ>zfQu(OKN@d(U7VYuDXiBIFg(?C+WWaO2XjSCx>wegKsz}T zTy_B9{rYw5cdXn(0K{-Gi-R!rwn#X(Z$!q=lEEK)zQ;$G^~~0FS5L~dP-cj_*C;mt z;($xEYDtD1A=uRR&EA9kA>|yDTcL`MldZF;F5yyGZi=!>UQW(oven<{T}%vY0?(JI zC@NB=uzzlXKpsrwKzErPy%W;X=|dxQ*|s;7J-B#zDM<59I(q?ZJ0;;;aYSq>G4^Y0 zsSGjBCP1vsJDt3y)eR--yF4CM)gkLdLs!?rz<|)bOWbcqQiNgwsR575C@;%`inPLb zvkl9me|A!Q`z}sSQ6k|m{sQc1F5|51t+fDW)$$cYl+@ttS$OB+`|zAvs7zm2f%Y z@X@2`+gP24oZnER3c@)lk1bc&>=InI6IE0$T?!YpqAjWhu!=$r0Jenl+#r7Klj3Ip zpzsQc{re*korM*TO*vGvX5XF%@nGUqiTOr1a|C4kX=~qLPrdxLh}UH1L%H_9E0j*z6%TYzU#xFcTl1`MT49)JYHe+8 zWAoG46n2`{)|YyI-$ZHvkcncC?JWdJe||A#Px)V^D~N)s3>Dy-4HnYD6_&p5mrM8Lt;e9gW3TRPcF#zN=1$V z#znc%aii+qTI#Ts{&WOUFxY3r;WbhOtic= z`gE=07RDKTQ_lo$);&=2Fmhj82>JABlugMy5!k|jn0s424P-xf4N%&Z!RH!t7P5nx zl+uXh6TJPUZf2%qy2pcLUr{$cuqefqi-uEVd`DR06W&;P%L1ZXDSa(&Zc)i$#W(xv{d(&f8?!4b*Chwob{$)l`Oh`iykthizukFA{3av_9`M5Ntf|pRxmcWk z!)iY6y(sB&@n9LdjJ4nqzXqd2_U_0yN?IjpS79^5}T@kgBzKOvR%! z>#ly{aHGTRevI=&`0i&kED_ z17|ftA_LJh6#xu-b~G?FVVTs+KR621To*!|!q3pf*}1}v7P%OP)Rr`NUKWcZ2hPrI zv_uvafXZ(Rz~ocLa*4`Ty4#oj8yq!-yz%YqF?xb-`j+0ZUc8pdk99X$S2mH;b%M|x z=xfmMoe3IiDSf;?>Wv!F2-}?FFE)$6jX^_luhJ!=fXV$a4D)1m=+IO*r7|l2HV0ER zlDGab-%t&2ovtEK#DJo`W8N*5An@5dU*=~z)ze@@5 z_h+^Vnm#C}hHeSgREq&)NB`-P27@DpW$>k(7G49x8aG(wf=9qlzbaW|>KYn2D{F7e+#^4E1}GDJKR$d=-@hp>p@xPS(MUR4?>IQB z4-uk2<^Ii|`U{MO{e)Mv+37>n!KpE^u`#jCPcO%Gt5H8L$6O8Fl=ptZVG(dLa}Jp0 ztCAC!o1RKd;SaGJryeH_ELYdo8sZD_tg>#S5`Mgg=w|lZ++5MxLTa%%#Ln^Wk_U&Z z#=gx43Q0^(Ss%+YxD_GH6Q7{Gb0xjf_7(K}3eaaEd+E*{zI6Vz1R#tSct9s61}34v z97u?Za}!+Q-;~5#HN;IneJxD&CW8~R4XEz(ZF?er8H#3Id7p1{lt?yU!tf@_^*fh9 z!kO9UzckG3;C?1xa?;v6ws74Al>U4hdLqk5WbXJZ#Troi-@ZE^-{Y|w&{7@$v)FCV zsBg)1moR1**wCBPevmLRl|sAhM#^-OTY2QC;kn@F{|iEJXf1MhV-EEcfQe2Zacxyi zo$tFw)do=1rS9vxrl3JNqFw>MfzeY?9o{j^Wo;Cqz$yGB#H zo>L59n4g}`03@NSQ(PrVRD)tC`AphhTlJX;I|l~^_n>eTV6Z5^My80Ev*<81ZX2N$* zozl&l`!v1-$&uSI^n3V}!hnM8cU_&qhkGHa5BpfWX4kv2?iReYNlq>ZeZwf_Xgcs+ z*@uq%v)jlpd~p%m;kYo$H};e=`p*9xA^+*qqpevoW`jGWFAi?*ImotJULnN+xcAhl z=RQ78chjmVQ3~!O2U(5aPuSd?K*yt>8?XNveEV^Wk#?kDUpO&mP{Bfn)uX_H*AX zZqVKM>uLf?A}kti*xIsbsvE0Bm0s;Eq>l^^HfA&Y@8V)!CpG(~3CgX7iRvbdO>I59 z$XhvX{rPYRMauB|F&|oHRbG?2Xj-hD5Fnf61h-Fs3nd z7H4qVj|o-I1>Zkt%rMiCE?-z!Y|b$Lc(X6SSSLLt&>ces-(ymCWA(=AMJ~2;J^Xiv z7c#U>P9G{*o`jWMkWQ34=6iY{%=~{8sl4qy1BDB6mhzUyi(K2PA3i32Z^Z2?mM}Qj zlH7Fb%ibA@t7x$mwa{N-$GcWkzLO~WP)5K(k?=R_T2=o}iHIJAV_(`k@;?>>|2-M` zzZjnU*Gs$uVs{eh0{ue4^_Wg}V{W|CPkhph%2LU ztXYEw35(OjL|A<&VXsG1i9CV{p1;GH6^1H@1Z3=dM51V5)doUrVRbp!wkQn6`6S9* zEbfSbZm6$MF*>KDWQ9T-X4~+7N6T`6kFX`4V_|9`HvycD(3?E_F)F4LLPAUEc$#YJ zf?FO(W0H$q54LD~c@PKw2PO5cU~bbjA+`)t4pJVh)R|dX&H(Yu*8k46&h2u(L4x>O z%+Ht!!x$t?kfiH}v$0Tsj=#GLT0U zd0;&TzBuT`i~m9j8JmRI z*7tfj-jr}qxhhSvEl#v)ju19!8o0YFDJfwp%kud&E9(#r5Y!XtC-_Dnm@N|5{}xex zegnV3l=KN>J}t z%-#^o0lTr7uOJbbpFXt6M+RGK6fy_rB9kYlrU)_GD7&(*RTveyXx--Cym9|<1UVQk zkA9lNBvk6&%md0fWYJPd!$YnK?}6t!%6-iO>2V9rq@|8i=iux;=_g}Jr*-KGpVRE*bVxNiY;t%ClaTb<<>3jWF{m-k@~p-stk-{#mBr_l zVge6MI1}Q^L`d9sRCa^A9F8S*&5rL(%#%nF`6&6%IA9zDGA|7c3?TWt19z<$GcUZc)c{fr!6-ZW*#CREQ9dmkW2T2r;&8+%LIx)u>0Lj2FPxHga}Ba52fkVt96CWcip{i!?i*B84y>*7t5(( zCK)HCSWxw-NZ6v@^UtGV(7Ko({n0b?`qFn>Ku{3N?1?e-28aapx%KxJIY(^gmN19z z4F4BrZ;W$Yj)8JsX+J_;FrtR?`v!l=?CdP~JV=*X5cfpug`2spvvUJaR?`GVXzplh z0f->hvmQ$VKo9tZ6quHKBk}`xCAJv$Q>OqQ);}4+QUY>Q_zg6)>OaJHMZ<{g7Lpk} z{Sctzt$=JLDB?E|*9RC3`)0z-%nUjqd=%Ue_y<~KM6nwsgymwN0iM@lavYIl#$!o^Ax7`=L2juF0CDHqW#?uX1W3<#CK7?MtB_!4el19 zn{~(6vdH^k1m5=T+aOkIqz7#{Q+raPB<3;92M+g}!UI<|$rir{jhIw?p_=`1Dmer$ zq9y#`xexLbZsV;9oMus{G0jaL9|sz$b331spErReA&OT{EgFO`;h?db$H&Ll317aR zbp^ZDhfNajEmkg*bdSpv{-;0e%VnIADASVfVL+HX!H67{en`mXOc@2?vmOqCMY7dI z`s}PPX0boovlka;iru*{Wqv7r{BTJkqW!Jjt3!NiCe}yYUaG?7Tfb&Mh%nRb<>pK8 z^E~~+C&S+<>DW(LT3MJ3p#X+qX~`3o3tPACCY!!D+VwtQvNhT+kJ9-MM?=YuQs@5z)_Y!*b@A#yvm{^gqISkJPXCoiYW3 zEN0JoZ$B}fS;Gn^)yyC8?Ab-S8^U)#61;L_rfGN-jI;lbdGyL@+5H)+7X@t`79&`z zmj0>S_lpUqTtK8;uAEZ`+q0z{%(HP1;K?pAHcZpurIW6NJp}~=$-=U6Pr6${YwJ@o zTCV;Uj#H=d+^5zUD;_~uDqR_VcHYO^=N}5jn+WXu^2SDqmRHPq{16igv7P6i`rc~& zoNl9Ev$Ap_Ra>jeWO^m*Aok?0!nP8biv55D&@r6i4Hda{qIbxPx_PYt#T^ zc~Wxn?|lsW#Xnfg6W_f%pOiE@)?iM2?CfCgRo<#M!;rVUSk}+J_b@DMqFbVbS3j4Z zebmp|KRz+>p!BO<$GUPQ&M7O~0Mq1rv+XiC+Ly6ZF6{a(vso%T;RyQFgN$C4eKhm| z7p29N0;YER9r+t(w(l}->92D0W3Q3Sc_1X}%<`stG)@JBuhZ4-7_5@_mS&H8qWWNF zk+_BgMtg2lj%mg+Jx9YSKP)dBQp^4R*!X>YW23=$fE1Zf@D_iJk2^PWdpiTq_s_6@ zNSMSKY%5-M-Cz1+=jaG>;!Tr6XP<4aeOuBM$)I_mS@rY-hB$kq^Rr1rLBSEGZ{Omt zBhW9ht3)ZBiTd@MH~WvamVhuiA^iSbMobVl)!J>>whyesw8%UKprstaznSVrs;;9$ zXRYdbi213G*+pj3KU}1r=+52x+kgqkqT||FUfM6QJS}yOqzZogzkWH|IZ_*x6O2AK z79L3I{hvcODrtUx$>HHaQIUl~x{0=iSMGt4kw9X{CeHY~zh`qB)Z09*chSW~{?_I6 zmo^kzRCIJBEaxw=qJeJ2|PS#d&(>ob`_~z}gy#zYYmm zSI*HWSsi@7Vk)@E>Q#B#@^E*1QlS5yq=Rn}s6uqy77#rIh1eRX3=YvcHniuDhs3L? z@og+G|B<_*t9w9NBz(BNT`wz(Vl|aP^2Ncn@~0H1zy^PHOp4!mPS(lk6Jo$!^862= z0{}zd7w>AXJN2g5f7lYcq9wrJ1cFjEtpCVppQ z5dKAA3+LE$yo$T9btUsQL&*;aagf~}7!cqxywE1Ihe9QaFR0im(RX^~x{?m&Rl+b& z9dGIlWV`%)^6Qs##u^&)8+l~V5`qM>wH3B%s1hOMTs~)P+fA;bpn&L26v7^JIzPh& z-F|<42Yd}L_4i+P`>sMFI(K35`{MuAd_y$|cMrNbcf&l(NK12Xm(R2F}uJSeYR#!0QNtk3Oy!P8Io%!qYb3^PprwB)he z?LBSTNYa&{ygVhAd8rgjhuQR@nX1 zPJgVmXh4Y9Mg!zH*6!S7%gMHKIiW8|(WR^5MlGmgm3;yp%YQaQn>YEKClt&DCE zdosJ|$p_nebm##T$2DF_=Z|GqSCi*ZOrBGho~1svuW>g+FeOi)c3o6bz(4R$&}@A6 z;jo%E>*t{}IJ|R@e}CcM<9IOrx}RsH*Dg8MKwURI6Vhl-&Vt=*+Vg!`Om?%f0OhaA;qZ9Dxm zok_LSqeqVuzFo{>S4+vkc~RHDQ0$4Vp2Ch(yju2uQI#IDRdWcTXojnEF5INXVeUFe zMfiz9>0)|mg&mRii9ST%i_cd5eV*`LSGvKsOf&a1Po?wzL$AjA#Ir&Jo{IQ-8MVQ` zDC_-zV7A{i^wTHzfAjjwD{YYRZed z|7eps#KgWP++cp)aV&8Hi^>HrTHkebDk|5UgTSUtk&J)-Ok}aI)ar899YYVvWRQ%< zpA@F^r?3ZVT&Vlp=d+9Gc+rIm^1>hOCnQ~r&&(TLq_9*_u89tLV&$9la80Up+s!&W zwrocdom~|rM>WZlg1U2t(f8orK@=ZAooiH6R~S)YDz~S;HG5evy-LX0p~3h!oGB$R z`q8}ZT$H;lKK3qBch6R8QPD*8zOb6=!+-7!F1bAoU)x8ccdt+JnXc2*YQ?rFI*bsf z`LA9{i?bR{s@^My2Wy7A%H26tZshxR$9X0_dxppmdl{U$Mv1&|8NW%PC0i-81JWer zaq0skOrAQIIV6?3tLBr$YUBQh7csiu?nszwNaSXtX{c#Yn)>H+bL=O633Ln4g3iH^VY?l+hk*7klCd#9dn{EFJ^xKVbZ@kj_K zNGZnFHZ1Aqm+uFxC)jtLHnKaU6=~!z5T|)W@ni>arm&;D@P%#U~X{_)_6y? zmbm7V++t4I`F5KpJrwTTQMfm_S?adl_yIXZLwXlldi%T*iHPcZwO?QTb6!HN!SZ|g z%a~}sfEq1%gXihtYFZrI&Q8H4fn*A-8P**qj4Z{IeEZo!4;blp^RYbg>qQK49=-zn$P^24i{dCFT&{&vLr^D%I zTc59a^hPscs1#BC@gNb{`~lGy_s8ImZZ($^v#yi-Z*W9!pZ)Dzw06PaxOBFVr-tMs+ma<5lL!p{?) zV2Ln_I$9ck@yeWM^YKxl%jiD7I2kY)jQS|fi zoe|p#ita`36Fi9UN@Ch99D9=G%V67e{{iLKW}Ehp7ld8<7H7oPeUB#cX7JlwXV!Om z6sFTbOITB*&9U^ny`+$SOh=2Ohk7#8xz6~++y3stbb*^BeMQ69BQ-2@=5+i2X?e)< z$KWjQNrlf&L;o;&R>V;mo%m&(Xa4iel-2ff@ck`57rpNl;hnq^1x^Dkc6S}cXDU2= z#b$5c$zMM1GMQQG#3;+y^J(63@bTx0?Kf|N1RGkctZvDZ%>J1g7rNJY+_rYh&84Hm zKJmy#c!;25Jvl2YZ5N4e#X)fcx)6ps;^p}@P66xCY2HsPaoM2)SrgrYf)X-coAnMK z(ZY$@FsG8{YJXdA8#*>YLre3#?Udr^am_cQWlOZZl|Tu zBos3A6Lydp!vH0(FITDN7RgP_qbdr@@+S*SrursJUwqbe=GDAjYT2Er(fMN@*?t2J zY&Z+IwjGRoxkVLD+jM!mUo&qHrTkz&^*yI4ed@rmV~@|5jCIwFRh;_R?RN1L&nXLA zi@xDO!t8-!8Zjl7N;w7Wuvk84yq+cT*PPv7LwANVU9)-athY_7H%Y+Oa zJ&t~75)iP`5h?KHf0<2KZb6LbWOJ=)`m#r+sE=&(CKbAj9ii? z39fL93dpq^cq4g>r>Q3M%6r|wlUznc=e6YCrRC|$+D}G)VPRXIPG~`kVz@idl7Wi~w-sniC%mw|_`y-dtb58OfA{Cz3zrgp_;WqJKIh5t` zC}$F?2${F@10Hl0fsPfP+RC%5tEo*L9R>9s=|Xia6C-^~6JPU~eSU_If~=8k_Vc@M z)EVyfjobHb5J`9h5C5)N{Tf8McJvV-0K-q|)N&R#lMYJfUvaupbgy(H$m)ZgolU-@ zQ`qhIeY<{w+$>&^r01V^^v%a^Oa!p|ZlXd?&BB``T1N5>_238UMBjP;^1%Qv{e z{R&^j@T|496%g0h*w`_V+sE12*}1uYf{_YN5CY6%^-1>bZATOrxR86u4}Iy|DA9EV zFpv8ftVV9V?6>^ay|0!$>H{J!4#vlc6S5aB+}PS!g-{?`2YjYe$B*}dZX~raLr{>w z(L|A?4H~JsWArff5;n*G zk}rFzqAKM%(f@tQ`(UHX=*HRG18k&w-LEtJ6ZW&YrDYit zm4yXzQc@VVOoAs1%02|-xBI>#@kJiCE|{YOLNzFGJhacCTY^waSe_?gwEa|zn(`=1z++~LPb@2+1pbo9{& z4kmJGS>t27j_)QuIJSf6K`f?OlkGV^1m*EIE;z3CgI|>U8N^#LknQo>MP)G(p0=RR@b#0IXIeGs~I zJzZU!u6#_jKj-Hsyn9E;4|9QicGjm)#yGW1@sN--H#g(`KIZ1aSNaABd&m=VLQ){& z5rOanw!Y`$0+=1j2w7R#h3OtCX6CQm-I5#}nWC?I6#$q{z#5B=N0S)mgULQEL z)HtGwqxoc9u#<`a*6+H|(cHX*cUxG;O-l&RD@nny8RGX1U$~}jEaMD9^a+)i%lz=Z zh@C*(sH8DKLJ*bI-rO&>lt6t+m@ozF&(Kn*a$BeeEWM@-#Q+HtOgcRM5LiqYEnnfv zkA*A>kH)AecuzPbY@VGZ9v)-$?;xziI0N82M4k3`@1`!^+~Ha_=%9ayMi4ShOBMQH zPiRT$_U(Ha5I|K5WBGFMBQ|^u9^TM~mTBvRD1$HCy~fLouY9s`iz0fIaG!N`x#59^ z@`m{cT_Gpw<5Fb7>*v`G=?vWP4o#9*dtE0{y!x`Bpdbn}D@^i|larCM4(2k*PAeO$ zckuzZxVcN(kDX&VnL&PDcOTv1^J#pC{>mc9VO11S_Vp_*w_ZFFq)3vJl1RwNCfaj2 zOU_{mj26k-y1;R}>p}r;VGIt$8GI$>J&*{eY=~*hR$`QU`-kgfOoO0XZVX{&M`JB6 zDH*w4jO$G;M|e{9tO19yoGZEDs2GcIXhdjX@W(})3TYh&N6NK|?F0>66(m|CVd%=0 zD~IUm^YZhNUHw`X3T(ukDukhG{j;gaX;TMLnj`H!~;sHpfowl**{YiWFf z)FK=@GN%cjNlHp;%Xk?RN`h0W!+0a&D-o6s+<86~Lov`L&A)n*g7l3@LXaWEJhlo4 zj|gH}!Oe!`H5L((dut107<7Pc9IFHW7{uX9;4UsNe-im!6&vuvmallxBiV*6Kj?85h>p$Ml6+_$S2iX9vZk-or z`c_lJ$<98CP)>Ju0uC7}X!WL~q-5|2hH^BA4y|Cch0H9F*-xB4T~|}%Q<95!^z_41 zctAQ7Mps4molXWSu#pq>oXP8)TJQk004N|gf2K&I12lt2c$p$q__CTvJ<% zCS?>$Hx_Zkf`Yhhm}UAT_VGVNZB@cD(Tp#mQxvMb2RnIP%NlcL4q>x@5*KxwD*%&w zY*w^fSC02QBZ@Arv`w(1*=G|QAN#<)Pd`5PmukhL9HDZbivtQ%di8W@CaFeuB5!X; znfl34kaGxC!6Z@;q;`>#mr@M%fxDx^t-M?$dUHC0B^p5TH zmCv^iA7(1QPU1;P{8-@k^(3nS1y7*+VGqUMY66#&XW2NE z=4p=YKG&sj)9ajut#s%p|Dk=ysZ`;|r4Twwbx9dvhGNyBE`^h9wPnqmqJH0p+j0a? zEI;v1D30B^BkBG=)BMviaxd8hSy*?+zkf@q_`C0c^yx#Ep|WYDkDnVHfUetuKG!O_ zM#*`#WuTBe?y`*i3(*t{K@EG=o=kj1=P}Y`kErWrQWn1pouBKGfwii-d|1}&+-P1+ zsHm)=&ud!scXE{ni`lk^h*?e`4H_fp|;Y)H_ zaS8{I?c5g`Nz5B}sVQk*_22iqE|8p-P8ABh<*Z$t>DTS|9#pNn?Ej}(aOG-L$ zT`=~&_o+Ro$tyD5dV)`R(4AIVyciI9n8|vdv;g(7#!u;wDAl8H86|h;>lR3Q?;Nn~DAMf*DLbHY$; zh4|_%cEWu~q=`(jzh7Ga@pGj4JMV%ve>Z{Bh_CL41LzpDFa`5>Ah#cGcFW&(}$IE(VWwElYLe}5=0HlQERLwp(mBsnK< zX*quBEBqZa{>uCbg1D@=IE)OU6s zW$;Z*OXHLwQ(UB^A^PHk8uL^3`_Iuy(H~+TRSa+tg5g)X`9io@uMgoDnu**$CxfF= z)wfJJj6eS#=&j>2H?tA44G$Yx5*Srzs(*b&OgJ;od%t95#jvA(tjA_4=?K#ES>ogj{d_5X>pCt&d6(N}|H4l}d( zw_y&iW7rsc37-D2?uVrP_3Lk@S!Oq7Rl)iK&m7xUdSYUQ`A1SF?7HCEIW(Dbmj#wU z=L+6~zOL@Rqav!HSlzS%AqRvA@DC(V)Z5;fAR6!Z7wM0U!*Q#MuXar>peO*{8Z+$h z@YdEVF*(*kV7!&MuB!i_VghXhTUL&EE6w=3%kA%zXI(JZcZ6OTq#LlXv{XPUK(z^Z zH26kn3Ht5s6wnY(9;LE7{Z|z9But{BqMm*zj@t#~jEyo-ex!2N95X6U@)a6l5fI3Z zjWr#ui+Mzb?dU!dO-orpS>fd30uL~~^WT$e`xw}=DCd=Y`(#xwfHsQ8EV3k7A3x47 zFJ}~cZZEGyM<3VFXg~?_e1mKgdn7&xsBvc@heI9Z5_2^xnAfdNPo1;kS-V-jbZm%+q`J zJVn?9Dy~3Aai$aS7XbGIG9DC=2%1E9kRh47Fll!G{(XnVZKoFf|K{}x6u{W|FCt$} z31>JM9c+3`b=}u&bl9qxtu^?(@6qXV7yr>a9&Mn`XWzsXP#FJYn6=(8pDTa3db~D3 z!;X`gBQ%jN$4l9hg+?(S|vj5Zh7Ye{u>YJ_G78$I>%a-3*Rv+%hS z?$qs^i2C^ad0}JD@HcOU2L>SjEXI#P;-=4ARm~NEvb=DiUI_uPATJfz4Jo>~tieX& zr`V+^Ny9X4PHOMY&Q1vJCm#DA7E~np|7yGPsG8e$yZle(k2oO z5{T6@2O^Mo0^aS$uaDd`!-hK5jH(M%8x2jN~*c7%^NcE zh6D5IuB)rsf!@%xi9(^gn=}KiQT=ucVc38mn{wDHbC{*l2;|CiS^+~32EN*Y%vhhh(-DK7!6A}$mI(^ z>u}F2B4`k!3O@^(c30Z&BeavKP7je^Ls&K8RhInY(L&@KUAF_Y@|dg&#YtqHA``ehcdj7nS?AHPA_=Dbe(pL&a=A_x1Z4 z4PS@lQ@Zl)qDkMBmuJIB4zJY&=h3HIeA( z;ZcEgiA`GX+seficFyNdEU2A>Cz_;l>XhuFEl~bOj?hQa6DTNP=UvK(GGY}ZPfk93 zv=|6VAVpU=S$`X~+;gJoD5`X8r>l_$C_KnCPmIt#8oE{5rT+v&L_fVZ`~6u*o1~Mf zs#UkQABFbN#;NT^xZv?4p<4wtov182^sU5p_GlmPhqNKw1 z7aQ|&bC;l+zkGSsxVzP_U*j7y&R~Er_ohu&^T`04g!WU0iez0qJ%rx2qW31-Izn#6 z#o4u&xS(o6p~|9xy07s2rS(PiHzY_X-MIk5VYGDo=7$;R_Ktf)$nNfLsHUeUC-HzYovz&pjpej2wKsG6O@+7zsJ^*bC*}mEfbE0)?&(<5QGP0B zYGIZJtGx!lG90$Rq}Fe zsTS7L)5A1&va&L3WVS}3`yY;jt||v#)O+Zx!g>34RUwibgBkFy)l)56$`@|1d1ym$ zhQtdcIV6-2zawr21qQmxQ;!|HcH|+5mnP;UMwV>D7&yWU_H}_luz>dV_0iEnM@UFr z%g`Ez=&3cFoJ)`uLq}ilP~q<6#K3HyXMexKo;R|#WxXG~`j)O9&9?blLyxqooKDjI zosG??Yu83X+6~|!$F(({5p2ojUTy$#Oi!s$0Jjbzvg+d5I|JP6IM>QWe zS>sA$D>paq{@nrIA(SNTG&*X_3@RwZ;mDqKl@K0dU=J$5=;-LQw6s_Ke>jdps|8A+ z2ugG)`@pCemH=?I3bJKL!IOBGl5{mBWbnh&^<$VnaPp}x3S&Gx=i-IW+2$EkWWnL^ z?dw>Ex|e2GuU>V0VN4L9;SY_>NtDbE!xZ@I{CRGZ&~41u$A?GqPr~NenHk(f<+}r6 zp2CiUj09R zI@YF6929aNY2QuTEa&)D&(xRRO8=sgai(Ir)7!%~&wY9l|GCjGKZ7Pf+YD!t;a(_a z*HNIrW&xNfPRqr8m|_09a2I!lpTgV`{5uNm$Ju>`_!KjjXjZ>< zLBRtOpxu&^KQ6KH!E^RBJ$(ZOREtT*84mK&SeXA4`d~;1`*@QdvjyVMDG+4>0*N>V zU@=P>LmFN7kb{4HaS4GjBs3I~-~4Q98l9E?prwVbHo@oTwXx4Yj9T&X(gFekAT@BR z`-8ve1Q=#4eGTFg(z*{-&;Setc-`Nkx;9ydv7qy8Zv^ZPF|sfU41q4oOii^ddrlw} z&F2@>66v;S{-=$Myju={fMKF@Wa{ZO?0IBr=vkF#z6JqMu+ZPfbOQ?4hn+dy`ke-T=|gZ+>CC0WHx*K{OvY;0GcW z=9Y*9hInmRS)+g>uvxaWv{axY>{DL^HuYp@JcE_1)_6|R^+5ATSzA3~N7Wh_9rxte~#c>|n(uz&~zc6w}t7ai&K8B(>7(Y<|p%LGfn zftMa0?~TwZAAhgV%mggBxn=JW!w^XbVc~)!(-3|0bZvfoeW~$Dv}2+LR06tS_B;&x zPx!SAX*oKhTwb%qxy}~tAfm;Lgd%Ft)RfWPebU54+!s#yWgt@`898P>{991ka&wE& zh@6}zMUF|Nvk(hIJw896yu9CiNWX+#@+RnYF7%N=w|E61p*OX7Nl!sqS?9OnCBc*s z^irTI2w%u^$25WVzE)$(UCF;INBx(*8TsnT&utPK8?}3w(WZVE!8QTseMe7DIObVU zrSu{PJNtd_k^R9GGEG}J5>ND&pNIn$Y>|#mI66>t!aCD7a}r_U(I)IJ%2n(^HHYMT z0*to8(SZbidxzgDq@^6EkHIlyZLObsE|hc@80Ga!0)Z#7UXTXeI8@VLI+fvbdYW>- z6#)pFWUrKziQjA=_MnWp35F>uHpv#W=fzdE#ksGiyzP@UeVN?CxREvKRpz9_&GAf1 z%27`pW|WYS@EQv(^^?@U}0qiq+ao}Rs?JF8LQf~JelPmQWNXF-v+c|-=&%US zROibtf9>xt@LTkXRF8~}o$HTtm|}j?YF#|_vu0-kAVS5DN)A*}_N+x=aYg_%fb6G0 zTaJ&jzOLACU)I6o{Q04K`(40~{rG6)0JeJz+ZJ>Q!*OTl;K09yl|~7)<<113X0LjQ zvWf6BY4I`_3{6b1xyB#0-O1SW&lLryr#^4bT&aFsx`Q%owD=PppX0jjdrO>3qXQgf zl}#DiZCcU3erT?G-~%HtARuvLCXo=}p6F`|%78#{w7UIE-E=o^R3Wl09^~RjaaQPm zcG(X3j6gWSbB6?OooDZ#1hp9}HbOwZlQsp}%<0`>fU*xz5_N?qk&Es(8)5p>zm}Upyj=P*(+= zNV-+i*V);bK}B2n;jo|)T~xL*Z!J~@SJqUiiVt82lp)PH$dkO$^zp5 zGNt~jbo+1oyK6c59M)ZHqy?Yvt#hriTN_zz=mf20JF}P9JMX*kTnL3aW;pE8bB`@ES7Zm8K(VZoM6`I!((TNy7~z(t zTUzR+r3wp+WZC6U7Vv)`8v4dy^f8*6jE0$+gN`YK*lI80x22_u7cv8ybuh!Ax(HDi;LzKmpaBQ1?RdC<*` zKDJ&NmvOr`)V_EjjtLvQ@}6qLk*7aN81MSX*gCwmv7=+VqG-+`wuW;XR<;|kAm@&o z$BAfTjGH8MRQbekMHS$`(8G^>@%e^REFcsI8AybGP#L$1VRm}5cJr&T&Db6eCF8v_W8j<+p;p>SFg6g z;3X<=oj10c|2@_wCOH?Q(`s@Rk(N> z{hZy?;nDRM1#Ym{dvfDkaCtg4Wqff2X-~IRPsm^s7#f}9JD$DIyeNU~)oa#heCI3k=E^<`yiVF{ShFKS- z$z}yi>P5SSa$Mk}^urw$xPtIjx^2E;#`~I@E&Hss4<0;7p;XpH>{MQw>A~DnSlob) zaL*Pu{qFsHK1s8K+S=N`th5(e)F0WS9((f%_bWX33;Y6X0)YFVk@cx!ajFfbK?n{y zP_56N{8%hR$H(rHidIKQ^%nO}kK_l)-t|Vtm-!^iqgvNmURj$Ty(T~Ta?a@R9Qn8h zv>shu_4W0oNYNmux!98g;zP{Oj3=ldf(e4Ik`Uw$uJ=4JN&%a^LIidWk(&biK)XQ)^;M%5@*4k--kg%0FwP`MV8c(|ijw1l(N zv6}*$u$tOc=q(=Z2mL^$#;Xp%{R)z2bHryc`iFKB#na0*FF7}~BladTRKS^mMA|d6 zmw}K>7!#dPdcjYoJpOL4mf{#~Y||9H;NUj_bznbC%j09jIh5~FUI>-#oSCjz#vm4F z@?i`P0z(G+Y61{|os1A=(YaSp&=Tbe?!8D9pV_|X(9pt8!-2_9rd>IfbpY7Of9%&W zKX>ji=`6rEE++kYLS@e{KmN6=8J(Wn4t=>0vbG~m^1EA=sc>MmNMN<>Mt|}e_x9CP z1B2bsbtSHhvz@HVQM?;5rkS@{4nUy@Xhdq>ykrjA29xgJml+PQFqd^<1)BhwN)@dW zC76E*>$a(`?w$Df#d_JUA)GRB6`p;OdIy#lT*$A@!<2+BxPxQiKX%*{x&9s3C_OFO zRY#<3EeFSXisFwKD=Eb5$%l0~kEyBMni_^JUB}EUak3Q)*-is|D8iqTApd zCmx0t_hOFzlaX-uW&TM^hB6+Lbgz~`K zMgBr3TgVM1H;c;r5fT=L=FoJeSj1(NJ*3L1xJa}o*4%l%-Ra2|?)BNxNJs~{yAxY- zKs=rYGXYhFw6q&48JOfZQBYVMOL&};5(cP_7=S{}U4k(Slj6&v*5sq|viY9&(fa}^ zNhHd?fs?N@f3jU1-b^eP? zQwJCRW*p=#%R>OYDVp)IvN!Y2SbQMp|k@D1Byt&rN5xyjcJZW4a6!4@1nHL%6>jBev1+`(pmIw z!@e2u9xaQGi}U{3d#sIX!BYD63GwNRpD!MKY*|8*YH*C+>0ipoo(sluuz2Cplb#73gS>=u-x~pm2h$@&wYQ0avGzFFh=qSL{b(OC*tK# z&rN`N3I(l>TNZ>QhjH?15Ts(LJ!&kV5XPWXn<+Vz2XNguxwzm}zXOIozyEN5M~hqF zQZ)T=!$-NDLs4!w^3H3e=3ZrMPHDEgX!d|v#H1`SSC_TdxD82j_gu0-F^W2SelRWT z9rsZXZD(H-$D^Q30@YSkUEOvdN4<}aXTr?ax1;7kLi)6#fv&cxL$O=98?}V?ytuf{ zjfJNTucoKAmhU_r8D;xC_(-9?Qhmyqv|tjbz~~Y4at)*c<;97XM3o>PUte@Vz}zPX zG8(k)yrGcCP9DtZeG}n*rMT}Ay0Wo)G-Konl62gGGthc?0RdpR32ZS8OirPmVouJD zhV{}ve)RO7zkEei##b`%jFErNcm0dAr%Nuoc}#!rNJ|*j+Z(XanZ@WG)c(Z?F3 z-gp0nne5BT(u03IQ)5Y554NdLii!dG)WfJOvLCXO>k{RkC!P{R#CzPT?E3aN>`xb7 zoOS#8)v0iZrT2i!B&%XcUO}O4;Tj1yk>H%R%ACKOVzt+SW9p}lveb`jE>$VgvAI=M zg>KbXN!xb)xRgmfbd3ehFVuGA*1jDB5^f!RvwOwmw?WnU6Oq6BswOQh$Ws}d1DBW< z!bT2*$nq@4@wYR-7{}xDg`MR9xqX&;B5D5sxdkHyJ7|vX?qd@ZKYx6Ga%TQ{ntc21 zvjGZ$EO(V!(d9-T!0PuaKS|#=X$9`ozF2BG@N-Cf*WQc*`jkNUcYgZ0{B}iaT&A`63)W9MrmA^3 IlVTS5AH&TR5dZ)H diff --git a/frontend/src/scenes/billing/Billing.tsx b/frontend/src/scenes/billing/Billing.tsx index fd06e8a6785..5e950359b5f 100644 --- a/frontend/src/scenes/billing/Billing.tsx +++ b/frontend/src/scenes/billing/Billing.tsx @@ -21,6 +21,7 @@ import { BillingCTAHero } from './BillingCTAHero' import { billingLogic } from './billingLogic' import { BillingProduct } from './BillingProduct' import { CreditCTAHero } from './CreditCTAHero' +import { PaymentEntryModal } from './PaymentEntryModal' import { UnsubscribeCard } from './UnsubscribeCard' export const scene: SceneExport = { @@ -82,6 +83,8 @@ export function Billing(): JSX.Element { const platformAndSupportProduct = products?.find((product) => product.type === 'platform_and_support') return (

+ + {showLicenseDirectInput && ( <>
diff --git a/frontend/src/scenes/billing/PaymentEntryModal.tsx b/frontend/src/scenes/billing/PaymentEntryModal.tsx index c4580450167..52092c47d0e 100644 --- a/frontend/src/scenes/billing/PaymentEntryModal.tsx +++ b/frontend/src/scenes/billing/PaymentEntryModal.tsx @@ -1,12 +1,13 @@ import { LemonButton, LemonModal, Spinner } from '@posthog/lemon-ui' import { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js' -import { loadStripe } from '@stripe/stripe-js' import { useActions, useValues } from 'kea' -import { useEffect } from 'react' +import { WavingHog } from 'lib/components/hedgehogs' +import { useEffect, useState } from 'react' +import { urls } from 'scenes/urls' import { paymentEntryLogic } from './paymentEntryLogic' -const stripePromise = loadStripe(window.STRIPE_PUBLIC_KEY!) +const stripeJs = async (): Promise => await import('@stripe/stripe-js') export const PaymentForm = (): JSX.Element => { const { error, isLoading } = useValues(paymentEntryLogic) @@ -34,13 +35,17 @@ export const PaymentForm = (): JSX.Element => { setLoading(false) setError(result.error.message) } else { - pollAuthorizationStatus() + pollAuthorizationStatus(result.paymentIntent.id) } } return (
+

+ Your card will not be charged but we place a $0.50 hold on it to verify your card that will be released + in 7 days. +

{error &&
{error}
}
@@ -58,21 +63,34 @@ interface PaymentEntryModalProps { redirectPath?: string | null } -export const PaymentEntryModal = ({ redirectPath = null }: PaymentEntryModalProps): JSX.Element | null => { +export const PaymentEntryModal = ({ + redirectPath = urls.organizationBilling(), +}: PaymentEntryModalProps): JSX.Element => { const { clientSecret, paymentEntryModalOpen } = useValues(paymentEntryLogic) const { hidePaymentEntryModal, initiateAuthorization } = useActions(paymentEntryLogic) + const [stripePromise, setStripePromise] = useState(null) + + useEffect(() => { + // Load Stripe.js asynchronously + const loadStripeJs = async (): Promise => { + const { loadStripe } = await stripeJs() + const publicKey = window.STRIPE_PUBLIC_KEY! + setStripePromise(await loadStripe(publicKey)) + } + void loadStripeJs() + }, []) useEffect(() => { initiateAuthorization(redirectPath) - }, [redirectPath]) + }, [initiateAuthorization, redirectPath]) return (
{clientSecret ? ( @@ -80,9 +98,13 @@ export const PaymentEntryModal = ({ redirectPath = null }: PaymentEntryModalProp ) : ( -
-
- +
+

We're contacting the Hedgehogs for approval.

+
+
+ +
+
)} diff --git a/frontend/src/scenes/billing/paymentEntryLogic.ts b/frontend/src/scenes/billing/paymentEntryLogic.ts index ebedbfe8b8a..ad2b84d0f80 100644 --- a/frontend/src/scenes/billing/paymentEntryLogic.ts +++ b/frontend/src/scenes/billing/paymentEntryLogic.ts @@ -12,7 +12,7 @@ export const paymentEntryLogic = kea({ setLoading: (loading) => ({ loading }), setError: (error) => ({ error }), initiateAuthorization: (redirectPath: string | null) => ({ redirectPath }), - pollAuthorizationStatus: true, + pollAuthorizationStatus: (paymentIntentId?: string) => ({ paymentIntentId }), setAuthorizationStatus: (status: string | null) => ({ status }), showPaymentEntryModal: true, hidePaymentEntryModal: true, @@ -73,7 +73,7 @@ export const paymentEntryLogic = kea({ } }, - pollAuthorizationStatus: async () => { + pollAuthorizationStatus: async ({ paymentIntentId }) => { const pollInterval = 2000 // Poll every 2 seconds const maxAttempts = 30 // Max 1 minute of polling (30 * 2 seconds) let attempts = 0 @@ -81,9 +81,9 @@ export const paymentEntryLogic = kea({ const poll = async (): Promise => { try { const urlParams = new URLSearchParams(window.location.search) - const paymentIntentId = urlParams.get('payment_intent') + const searchPaymentIntentId = urlParams.get('payment_intent') const response = await api.create('api/billing/activate/authorize/status', { - payment_intent_id: paymentIntentId, + payment_intent_id: paymentIntentId || searchPaymentIntentId, }) const status = response.status From 0e2199c7035d5782388f5fdb608290ce6fd4587a Mon Sep 17 00:00:00 2001 From: Dylan Martin Date: Sat, 16 Nov 2024 06:03:20 +0100 Subject: [PATCH 06/27] chore(flags, etc): add `created_from` property to `feature flag created` events (#26230) --- ee/clickhouse/views/experiments.py | 1 + .../scenes/feature-flags/featureFlagLogic.ts | 2 +- posthog/api/early_access_feature.py | 1 + posthog/api/feature_flag.py | 16 +++++- posthog/api/survey.py | 1 + posthog/api/test/test_early_access_feature.py | 31 +++++++++++ posthog/api/test/test_feature_flag.py | 4 ++ posthog/api/test/test_survey.py | 53 +++++++++++++++++++ posthog/api/test/test_web_experiment.py | 20 ++++++- posthog/api/web_experiment.py | 1 + 10 files changed, 127 insertions(+), 3 deletions(-) diff --git a/ee/clickhouse/views/experiments.py b/ee/clickhouse/views/experiments.py index dc4a3170b93..644445067c4 100644 --- a/ee/clickhouse/views/experiments.py +++ b/ee/clickhouse/views/experiments.py @@ -328,6 +328,7 @@ class ExperimentSerializer(serializers.ModelSerializer): "name": f'Feature Flag for Experiment {validated_data["name"]}', "filters": filters, "active": not is_draft, + "creation_context": "experiments", }, context=self.context, ) diff --git a/frontend/src/scenes/feature-flags/featureFlagLogic.ts b/frontend/src/scenes/feature-flags/featureFlagLogic.ts index 8485d628ed0..875b6f56cf8 100644 --- a/frontend/src/scenes/feature-flags/featureFlagLogic.ts +++ b/frontend/src/scenes/feature-flags/featureFlagLogic.ts @@ -302,7 +302,7 @@ export const featureFlagLogic = kea([ }), forms(({ actions, values }) => ({ featureFlag: { - defaults: { ...NEW_FLAG } as FeatureFlagType, + defaults: { ...NEW_FLAG }, errors: ({ key, filters }) => { return { key: validateFeatureFlagKey(key), diff --git a/posthog/api/early_access_feature.py b/posthog/api/early_access_feature.py index 57885666fde..004725393b4 100644 --- a/posthog/api/early_access_feature.py +++ b/posthog/api/early_access_feature.py @@ -203,6 +203,7 @@ class EarlyAccessFeatureSerializerCreateOnly(EarlyAccessFeatureSerializer): "key": feature_flag_key, "name": f"Feature Flag for Feature {validated_data['name']}", "filters": filters, + "creation_context": "early_access_features", }, context=self.context, ) diff --git a/posthog/api/feature_flag.py b/posthog/api/feature_flag.py index d24ee4499a4..5c1485a6d86 100644 --- a/posthog/api/feature_flag.py +++ b/posthog/api/feature_flag.py @@ -115,6 +115,14 @@ class FeatureFlagSerializer(TaggedItemSerializerMixin, serializers.HyperlinkedMo ) can_edit = serializers.SerializerMethodField() + CREATION_CONTEXT_CHOICES = ("feature_flags", "experiments", "surveys", "early_access_features", "web_experiments") + creation_context = serializers.ChoiceField( + choices=CREATION_CONTEXT_CHOICES, + write_only=True, + required=False, + help_text="Indicates the origin product of the feature flag. Choices: 'feature_flags', 'experiments', 'surveys', 'early_access_features', 'web_experiments'.", + ) + class Meta: model = FeatureFlag fields = [ @@ -139,6 +147,7 @@ class FeatureFlagSerializer(TaggedItemSerializerMixin, serializers.HyperlinkedMo "usage_dashboard", "analytics_dashboards", "has_enriched_analytics", + "creation_context", ] def get_can_edit(self, feature_flag: FeatureFlag) -> bool: @@ -317,6 +326,9 @@ class FeatureFlagSerializer(TaggedItemSerializerMixin, serializers.HyperlinkedMo validated_data["created_by"] = request.user validated_data["team_id"] = self.context["team_id"] tags = validated_data.pop("tags", None) # tags are created separately below as global tag relationships + creation_context = validated_data.pop( + "creation_context", "feature_flags" + ) # default to "feature_flags" if an alternative value is not provided self._update_filters(validated_data) @@ -347,7 +359,9 @@ class FeatureFlagSerializer(TaggedItemSerializerMixin, serializers.HyperlinkedMo _create_usage_dashboard(instance, request.user) - report_user_action(request.user, "feature flag created", instance.get_analytics_metadata()) + analytics_metadata = instance.get_analytics_metadata() + analytics_metadata["creation_context"] = creation_context + report_user_action(request.user, "feature flag created", analytics_metadata) return instance diff --git a/posthog/api/survey.py b/posthog/api/survey.py index 1cd91b881c0..3d13981a867 100644 --- a/posthog/api/survey.py +++ b/posthog/api/survey.py @@ -640,6 +640,7 @@ class SurveySerializerCreateUpdateOnly(serializers.ModelSerializer): "name": f"Targeting flag for survey {name}", "filters": filters, "active": active, + "creation_context": "surveys", }, context=self.context, ) diff --git a/posthog/api/test/test_early_access_feature.py b/posthog/api/test/test_early_access_feature.py index 89d1d7369d0..311fbae3cb1 100644 --- a/posthog/api/test/test_early_access_feature.py +++ b/posthog/api/test/test_early_access_feature.py @@ -3,6 +3,7 @@ from unittest.mock import ANY from rest_framework import status from django.core.cache import cache from django.test.client import Client +from unittest.mock import patch from posthog.models.early_access_feature import EarlyAccessFeature from posthog.models import FeatureFlag, Person @@ -520,6 +521,36 @@ class TestEarlyAccessFeature(APIBaseTest): ], } + @patch("posthog.api.feature_flag.report_user_action") + def test_creation_context_is_set_to_early_access_features(self, mock_capture): + response = self.client.post( + f"/api/projects/{self.team.id}/early_access_feature/", + data={ + "name": "Hick bondoogling", + "description": 'Boondoogle your hicks with one click. Just click "bazinga"!', + "stage": "concept", + }, + format="json", + ) + response_data = response.json() + ff_instance = FeatureFlag.objects.get(id=response_data["feature_flag"]["id"]) + mock_capture.assert_called_once_with( + ANY, + "feature flag created", + { + "groups_count": 1, + "has_variants": False, + "variants_count": 0, + "has_rollout_percentage": False, + "has_filters": False, + "filter_count": 0, + "created_at": ff_instance.created_at, + "aggregating_by_groups": False, + "payload_count": 0, + "creation_context": "early_access_features", + }, + ) + class TestPreviewList(BaseTest, QueryMatchingTest): def setUp(self): diff --git a/posthog/api/test/test_feature_flag.py b/posthog/api/test/test_feature_flag.py index b5a2cfd6d18..2d4745313b9 100644 --- a/posthog/api/test/test_feature_flag.py +++ b/posthog/api/test/test_feature_flag.py @@ -300,6 +300,7 @@ class TestFeatureFlag(APIBaseTest, ClickhouseTestMixin): "created_at": instance.created_at, "aggregating_by_groups": True, "payload_count": 0, + "creation_context": "feature_flags", }, ) @@ -334,6 +335,7 @@ class TestFeatureFlag(APIBaseTest, ClickhouseTestMixin): "created_at": instance.created_at, "aggregating_by_groups": False, "payload_count": 0, + "creation_context": "feature_flags", }, ) @@ -385,6 +387,7 @@ class TestFeatureFlag(APIBaseTest, ClickhouseTestMixin): "created_at": instance.created_at, "aggregating_by_groups": False, "payload_count": 0, + "creation_context": "feature_flags", }, ) @@ -438,6 +441,7 @@ class TestFeatureFlag(APIBaseTest, ClickhouseTestMixin): "created_at": instance.created_at, "aggregating_by_groups": False, "payload_count": 0, + "creation_context": "feature_flags", }, ) diff --git a/posthog/api/test/test_survey.py b/posthog/api/test/test_survey.py index cb124c9b970..ee1cc97a696 100644 --- a/posthog/api/test/test_survey.py +++ b/posthog/api/test/test_survey.py @@ -60,6 +60,59 @@ class TestSurvey(APIBaseTest): ] assert response_data["created_by"]["id"] == self.user.id + @patch("posthog.api.feature_flag.report_user_action") + def test_creation_context_is_set_to_surveys(self, mock_capture): + response = self.client.post( + f"/api/projects/{self.team.id}/surveys/", + data={ + "name": "survey with targeting", + "type": "popover", + "targeting_flag_filters": { + "groups": [ + { + "variant": None, + "rollout_percentage": None, + "properties": [ + { + "key": "billing_plan", + "value": ["cloud"], + "operator": "exact", + "type": "person", + } + ], + } + ] + }, + "conditions": {"url": "https://app.posthog.com/notebooks"}, + }, + format="json", + ) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + response_data = response.json() + + # Ensure that a FeatureFlag has been created + ff_instance = FeatureFlag.objects.get(id=response_data["internal_targeting_flag"]["id"]) + self.assertIsNotNone(ff_instance) + + # Verify that report_user_action was called for the feature flag creation + mock_capture.assert_any_call( + ANY, + "feature flag created", + { + "groups_count": 1, + "has_variants": False, + "variants_count": 0, + "has_rollout_percentage": True, + "has_filters": True, + "filter_count": 2, + "created_at": ff_instance.created_at, + "aggregating_by_groups": False, + "payload_count": 0, + "creation_context": "surveys", + }, + ) + def test_create_adds_user_interactivity_filters(self): response = self.client.post( f"/api/projects/{self.team.id}/surveys/", diff --git a/posthog/api/test/test_web_experiment.py b/posthog/api/test/test_web_experiment.py index 679df4411c7..7b53e2ce0fa 100644 --- a/posthog/api/test/test_web_experiment.py +++ b/posthog/api/test/test_web_experiment.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta from rest_framework import status +from unittest.mock import ANY, patch from posthog.models import WebExperiment from posthog.test.base import APIBaseTest @@ -30,7 +31,8 @@ class TestWebExperiment(APIBaseTest): format="json", ) - def test_can_create_basic_web_experiment(self): + @patch("posthog.api.feature_flag.report_user_action") + def test_can_create_basic_web_experiment(self, mock_capture): response = self._create_web_experiment() response_data = response.json() assert response.status_code == status.HTTP_201_CREATED, response_data @@ -53,6 +55,22 @@ class TestWebExperiment(APIBaseTest): assert web_experiment.type == "web" assert web_experiment.variants.get("control") is not None assert web_experiment.variants.get("test") is not None + mock_capture.assert_called_once_with( + ANY, + "feature flag created", + { + "groups_count": 1, + "has_variants": True, + "variants_count": 2, + "has_rollout_percentage": True, + "has_filters": False, + "filter_count": 0, + "created_at": linked_flag.created_at, + "aggregating_by_groups": False, + "payload_count": 0, + "creation_context": "web_experiments", + }, + ) def test_can_list_active_web_experiments(self): response = self._create_web_experiment("active_web_experiment") diff --git a/posthog/api/web_experiment.py b/posthog/api/web_experiment.py index 81aae23f2da..d90d400404d 100644 --- a/posthog/api/web_experiment.py +++ b/posthog/api/web_experiment.py @@ -98,6 +98,7 @@ class WebExperimentsAPISerializer(serializers.ModelSerializer): "name": f'Feature Flag for Experiment {validated_data["name"]}', "filters": filters, "active": False, + "creation_context": "web_experiments", }, context=self.context, ) From e92e4a8af973ec3568795d7229b622707e0c48a7 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 16 Nov 2024 16:23:42 +0100 Subject: [PATCH 07/27] chore: screenshot test the inspector list (#26229) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- ...ponents-playerinspector--default--dark.png | Bin 0 -> 20552 bytes ...onents-playerinspector--default--light.png | Bin 0 -> 20444 bytes .../inspector/PlayerInspector.stories.tsx | 88 ++++++++++++++++++ .../player/inspector/PlayerInspector.tsx | 11 +++ .../player/sidebar/PlayerSidebarTab.tsx | 10 +- 5 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 frontend/__snapshots__/components-playerinspector--default--dark.png create mode 100644 frontend/__snapshots__/components-playerinspector--default--light.png create mode 100644 frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.stories.tsx create mode 100644 frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.tsx diff --git a/frontend/__snapshots__/components-playerinspector--default--dark.png b/frontend/__snapshots__/components-playerinspector--default--dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e1d088184e1c83c96e8288ad0c74226d3b0b8041 GIT binary patch literal 20552 zcmbq*1yCH{n=Jv75G;fcG(aE(cX!AH5AHs}9TMCLVSwNPg3CZ~cL*LlxD2krJ-FMu z{QkSIcK5wkwY9Hms+yT;x^MUG`+es-=X?{SC@+bHPK=I(goGt6C8msogsg&u^xzK~ zGWY~L#^(ZT9ylmVLXe6FUTz{Gy+V=}d#mc2yfbH}izi8fv_G{SM(^UN7#uvA74+p5 z+E*b7PD{>CT#xs%hGB2m*er3aeo$M=8WxuMVOhwiiRIBZ^3Y8zPG1@HH=_OxN69<9 z_Bk_faduv-6?coDOVR5asUyEXw>u`p>@nCPInw_2ynm1XKix#dp5VI~S)oXY`2Y6C zid%joj56eVvEmDr`i@Z)@*!;*DHi+vDm7U|Tw>yUZYdOc<>6w-$(Wa$`*KmR&Z*I* zG}c=yIUL(+Zd&a*^3BPyBL_!C#GU)r<%!Pj%T1E=;p(lq=9{_?6=BvkHaHM1t*I9; zVu&egJ=QOG_%O)CySNz}NbRd4ij1!Oa~^nqZ1CzdGg)<%K|=aGKFob2NAy+{ozo5V z)XG)I+0F>DzT__w6|JIXOUgSm%<{qBz(5HhhozDtOKsH~k7Jp$aDH=jc5`!lP*`Xk zqhn)ZBOHG-+^dlg*0bq&nT6rgSe&n2b%`iHMCajIPnoHSPmF&laH~VoIZhYKmpmw} z$KiE}hZ_XLiISosV9}epYkTW-@wBb<=BkNwT_mV$xh6LQ`}YFUXIrs?K1qsh50Xej z4wGVMRCH;57Mlu(%$L{#3<5Of#57 zxOPmw>T@wetL!cG^yUJO@E4y5v#^Np@Z9adX$Di8RdsY`o_(r$sxu=@FnE`clESg= zcd<#tf`{(k*f>|m#o%Xm^PJN`UtYerr;!S``?Q3+Kp+4KDGjU0ezIYh${$(BOClW4 zytux)tsR@&P5I9!_T@Da@W>PcNWf=AiwA4xY(};dP6fSd{WrgKF(9i zqoCY~c#FKv7_KZ7xoM;ej3Be(Ee;ELKUub|<0Yi$d9wWQ=m+Iqqx%8l`M8L%Q6r}h z7uJHfi9lGcU}%vjb+nJL{VPGrt(&ykgC`2Eg2HeX*URInh6sFUljrWnB6+uQc@OD? z&*kdzS@wAtNr9JZn0F$_JRINsuD{k$NN;X-r&1x7v0WpMNzd``&K`02BX3nd(}pvu z#YF`X?}bt;+#tt;YjTe>PsElHGSUXCwn
>(XSI+ETLBMhTUaveSrsuD|mhzl>Rv zQzZWs`1;;TOAj6$V&Fi?2W~zfItNd8Zdzt&KA!z;BoWpT@R@(vKaBT^+8ut=5 znU;N&a(gmhgO+}k{?v3(>oZ(su4$PBKg8{FrEFpFdX<1R>*vpvB)jTnx#Y1iF7b{x z1sY6dx5<2@fzp~H;&`htLx?7#Kq z=91EF2G)5~3eR4@PIyyQwQ`daH`*%Kp3%gTLJr$1S8w+|DS=VIOr3saVzw;I! z(n?J3@0Y=1q;oZQXXi`UxBB`dS!xoY9xS_-HltC$QnY?aKZ%Sm@;#orj5h)xRJjOg+#eXStlB2zM&U^+RVUk za6>v=_JrbjDUeE7*;xN}_zXIIyI`-Q2c2 z74*7fWMVSfYl6?t>f%67PH?ZSEycy(M08Cc5E;Yf6LzTUYil<1hi6o*xR?m{upr)q$0KU9m-fx zxmB0pS#0?u18cgRXKl6%wKVu4wYtS|aqBH8SH#rK4(lvf0`EbI4Kz!AxFcnaL|%!cBG``3i9*S zPn(Pnx?*GT88k}bdIj#9A0ee_^~39ux8)&(mq(Gv6pm|=j#Ion$x1MlXEq2gZ*N~Y zxbQ_S5q*t)Z9_wYXH3#{mx3Dek*ghU+n5zk)56h7bx9L97Z(xd?@x*vSYpyxUJMR|D^z3H2y@sP=Qd2Vmo|4OCDKpU1>zkNrX~tU#6L)mH!O|fS7`NI@ zd@)d*dU8_K&`5+d)RH*psglBm*|y|DXJx38@->HYdd<0KX({Rfie#msWDF4-`{A<$ zF=uCDVdLLv8}UDTdM0}0p3}$?OpM($=R<~n{KaR|THM;&*Mp+tjugu!Q-Ri6dmcL*@wm?_G|;}Pt}Z(}TcWn^By;K`uZ_3A&^AIU%5&q;?mWHK!wojtlx(=m9>B-a4x?j=oWHOp*<@Z5 z5}hc=LK~fpEhbMg`S1q z*lz@qKOGw#1xL>iflpRBY-{eZ;p4BpeT#_mF5lmegmPAb1z?Vl-^R}1Z%z?JbY-8d zNc+n1H1gP#g9tR$JZNS6mO8pf=gc20AMQo2Ym22IR?5T0ovF8xkx!pNoN&Jz0m3T$Kk zuB@3h@~-HpUuI_;{6x5f*Q?!kAEhhin$jFoEvDORQAg9kmm>FhBYRhAa@r3skWKuf za|Y1-Tb;JmPphlx>F65mPdXQ0cX3Lpsi`%(^@i`Ad6E*HnD5pNHqYPO)YQ8W5)%u% z9XhUVDd?QZ_4YCZU=mf@?#jgI1Y#07Zj=T?ODH4FC5C2Cwlzrkt}{|oZPlFzcOp;nY6y4d*imNC`Re34|xC#LXY$zkT~^AjODp<-M^fCO_liwu#72v`JR<8YPDIe_2W(r!+ zs?y8L?VS)c50H>5)0rdhA^K-*ls!wZ9jXvrL-`+VzRAjl3J5#`$4FcLCiA|R|KI-p zH6;%|6T&bS{_k$`rieL-W8`z9rHm<`jZlHXG0RX#zt6%=S5(!|$f-5uNKnwwcuXOy zt3mSu4G&#B>CqE#>`EfcHYqCHFo`T>T3s@QcXD!Vyn1@1{tybhCvR|{WD0?O^b#QH z-=wIJ(-nOwNcBjuxW-I{>0`ba#7i;S!qLF}`0Px98-zv(jxnaDm~=siDbXl4V(SaO zLE6pIr!-*Q*s9KN9FU}p%tC%!FaGfUyrH!Tc?k)0N&V`yD*(9ri+614*S(67k(SM_ za~?Gnri@JcJDplwTwD+modv?6#In5`pPSpKPY1X`l~ZZm#!*R0Rw5n(#9`_xI#|4_~YsIaeJmZPG)qP(09lY@&Zfs>6DU}8qW z9~Q{Uw0L5aN_tlPgO=v7e(pqm6JgvUA3kMIp zIf?{ohO+z0;avP(`!9B1Ilg}B%Ow`xaJ-i|}+uq(jXbmM`$uL^->bY%_~7x0xsNW zH;YL}Prqhg%c9?e{xkx1wgf7)A!|sQkCM{CoJYFr^y_G8WA-N$V15Z++SimHo@m;Y z;B!ruvn}i!yi-wDE-0`fjuDZT-I^#V$qSN}w#cjVTD5-&ky235pu$~z!vZyF@{GwV z{KNappnX4`pPyfsndQJD%AQdwV|Z4wZhHDSU6J;ozrVqvk|0@0T>4^P+U8=UQiep` zDgoYntp_;;r{Q@i#k)sr8^=pgBUkALy37Q2Ej>LWAkr6y%S&5q&ef+23O9={5QDie z+qALCDk$*Sy_7Qv^7rQpFqoREJ-5_!ZNGlH4uS?qpjK1VN(u{7tB>$Q-dyvD(}fXp zv2!!OWmIPqN^SW-Na6qz)Yu7CjEs|JVdQH)I^%LN%4gSSrwJ{7kHW#el!pe6vbrWF ztAvBY>qfz$MVRpWxb$Dp~A#S7{$xWH<3j6p(j9?O>1*t zu3yA`$0Xw%>gbUEMIb0G>z;Uwxv;Xega`1HxAz0c*RJKcr&s_*-%K6h!4yCKCWR?_ zHKJ00(+JvZQF#(zwgD7$@Ze>D!D|W3dKVTvI|}-(XEoKakn}%X8YTMldz8Cl zy`^>82Us8Z@|c^0 zV{B}A@#Cb}$erDUQfiHHnWiIuQCg`~?UTVoPI@eg%$LX*4Bm(y_0xX@3r&%ISr06fot&!Ra64IR zLH+Zy+7RW0;3S9nB<=)R>Sou2{L-|2H~XGZy5~vbEeNXdFDzi5(nxZPi`m$fz0~A` z+DtW6)h!oHd;jiwo(fL2wl)CP;g0j|tMg0O^;H5@Rr9UMfdSKjodnIc9hiY~5GqCc z`jJ26Sx84=(drU83`h9II|YS_+1Z`xlcXSpXnXr3DXOu&#IEI_4yV}I*gNh}EHX~T zHdJpA;pQOf&ee^LOewc_3+w3qKNcMwsG|+ctPuN<4;9+67cj_hR@5-9O5`8!7M>tmd^f(~Pmc6h&G*1vs@^#6f9!`RK&N z(J|rb))Lk5`7xJ|2$V;IpuZOkmtR9p&c@q2eIkCiCu(%Ga&(k)HNR#eUL!$EFpR~_ zJhOvi%1v;GAAULS%3_K(>(9=df>LlmJr%L`1|T6}%T0 zH)&m_S?&x|oAUN-ef|#u>rX@U_VlvoUP>OdOT2rBvI@o8iUsM#v2N(`Vufjwi13G5 zztZ1zb^N}fU*lBrRN-Yt$H$I)^Ysfq9XrB7|O zUc?}S=Be&JWT|rbiRKSMm-V_w3|LBZcTN60Hu&c)%0hX+?K4n-Zq`*XfSRXV@{!+g>6f6O zPsZmd+cSo=16f-0Zo@2%&w=^a(I{2Sv|mPz4o&<-Ud-pPshQxJBN6 zZ~5>COFoI8?m|l!Tv5{tigr_y6#k3%6531sBypw#$@7k*XkY?WFxa6VK8Pxh9IX$k zq*77Kp&d^satP44%$$}ygH)LMIG)X;z=j5Pb==RY^{YMm*O&yT}ySwbj>i`e= z-J*g_MBcj2eLtts*}0m-tRGrtsW%k5xjj*2Sr-?R)sc>JHIP!zYayd(seNe%FLq1% zU^|PsiO8u*Nx_2rHrpX&jyu~o;Dl`Kw|Kq8z5)cG$LVdUQ!l}?XBRj6YpRvvA{%l* zSHgzk*)qf_KN*jG`$RjsPH z$yBzGmZpQ`W@f5V;Sv#@*t@vQ+_kkFhZ01G;u0c4M3Ku1S!KDXcQ z!iZ~>lj7s6&CA>LUiQR+czX*|)a>;bvm0TX^$|wMB{j*&$u)c5i~|;kMvi!a7C=>~ ziP?H6>9#)(vA{S3Cud=kK4qj7Iz|W%+83xccCIasfV=ur;`T@+Q+*{NPkGPcb$ao>=YjPHCZeNun0pV z;04FWFTM8WQEX0EKTe{h&&~>Za`EsC4h?;lq5^|t@_?VtGe&9xvRvk_86&RON>j4d z($F##r>C#4RRaL|uuylpy(%Sj21Z8hM(4H>1$^7-pNnqxhx1;K4GotnLnTe5cx)d< zkno&NEXaGfhiX^4`m;w}o!O3$jlG6RQ5iy7qqAEc2hN@l39JDk)IIFr+#bR0B&4n} z@e0;%$Oic;Wqs{uRXNtaBJy}q&9wRyiUsD@X4{W=?=Q^sL!s z&sUbd4c+`aAet|#f@q*O@9hXh_*Gb0ZQuwu~aJ$+& zU&DHO8E_y4g4)+iv%?b6pVZd74u2WWkQgx^EiIK|LK!No%O|EVHZchz zN42u*<+i{F!+)TivdhW7wYtN(G!$txHN|(nz8`5+Ts#mE@aW+~fA)l(w%UrzvpoT; zam-a_h%ZhvU4VR!hN^03d#6vGch$Q)Z~4~&J`Eq{Pqu5c@v=Y>2XOrD@WC9U~ztBc}=@(#t1{M2iGadEyfZ{_>w;bCx*PLn4NzLthYAi?27 zWZ1VWsfqEq*eIytxgej(M0kDvB4q>@GCh zecZP(kp}BYf&ceNUmoeV#jY(ZGW-g zIT2ptnM81z^t3m6G?B4eXG&377I3p+zQzqYx0q)$5*$btww-V(t()=%S=*sumqY#6 zjDv%N*3S>~MSlcr;!klP%{T6<^pRxz*BHK1nm{uGRg#nkNV1#OW+8t?-QJTrq&)g*UFb8Q4`9HBK?~f)fWaYw6PEG)N2{0hV z9T9k+uK3%yJU>6NyqxUj8-QUOy8Xt&9v(XW$ZG29fI{bwcRF*kbf5^|B=>iXvvqSbp>V69Fpa1l>=ebVstKF)=ogH1wHd$HT z6jG2QkHstporwuIz`EgPa{0JnW@cq%XxVDW9^>!nn^u|0$-y8XbR%Bxe<`1rm&e7v zrKYVte?O6;5gFV^VBJd$zCetP9h@A12xF<8&|y41H3eS$$9pa!oS0-%F0ZcP;FSs0I=CrrpOEc^YoP@#G8;)OyIe_qw_E%aZ2$?iT^eomE`>FYAB zAc>irnOUl+*xj{GEDFW3C*QQRv@EwgG0V=TwzXyMKmEB_QN>dNZH?QTYdn~M(;Tdx zPkya+Fy#}#@`=1v<aaG2pP$hPn}&fwK!9Q9_wReg$H9v@j2je6A{xc7Va2+&WQ2sGS;|~{ zQStEr!RsZb%h01>H%Dyjnks!qU*Bj) zhs8{F2^V&CwTh(@ofjEr`MKUJcH3H_o0yN(hXq9q}}($p!`Iy)m2hdJnx9p z5z+rC`)-nJtjeQl&cxjOmnn(Y-CXh3mgR0ZEqENTN3Ikc;(r2%>XRXIBD{ElSiB;H-jAjA$7vd;`@ zY_t&*TYf+e0m9TH3M%}NXAm*Upnh%$+Um;Ml8%GJ(ZR##Dn>9xQ&aq=#Do|dj<(AL3h0EwY8}~S({LYPAlYdS5;}Q1D z54NVKoSPRJ8=@me?|26TaE1F~fxj6d1vhv+@8PuRd2bKMvAT;!t=#Y?Lwozt~ zy&#CgBZw0d7iwkg8?TP&=|M}+Q=u6fw{L5G9rFh0%(~2WTi=5c1^QWN`vzIQD!4Mn z$XHogvgJ<_ zqyPL7I5~;J4r=gN{usL9$nX7>9xR#g%+ur~G0HbMtVTxiT2nsr6mhAy$oj2kvHNGw zrK$F5z5gVNS z&^jOneAEZ|7Ro=vNQu1NS%0qns|KsWDNG zh_Krf`+lpmjX%5iMN9k4YS48$GMqW&^RultxOuYq-*|jT7{C+b?Ej1vH&Tou8fXC# zUE9BlbvO&s>rI9KrTgH92ngVSQH2d#aKdmRy7qQNRkvd&F2Jcg4De5Bv10V;92+U5{+4s>N8sVgQ=Oht0$(V;r;mw}UKt37 zRM{q6d=>ivc~DacE_WhJk+yC}?+mCf9~~V(l5h4HmQ`9ub}b8e;zdUu92OY?nr#0s z2M0$A5$6r4RqPyy3dF-W;TH{!g3loS{^HuscGi6dr-!4-7cXC40tgfzpI90%YeE5i zMax9j-`69r;FE50&m)Px=Yn7SHns=0i;njimDZmC)B6%zXHFelIF#HDK%(p} zlp^o~mCo6_wx6@uDHvb@r6B-`1uxU*=5Bn0YoV=unX#c+s~e7ESP|A4PTFQrVP$Fc z?p<3*$a@@!EHz?cVrHbZA+}fUeg9BXTzJy}0nVQs_FXPx8=Dt6e1pFch+!BPb=+c!EqoPP5fjB&`_k>6{qC(CAxIJ$cW(Zw%FnP1q@kd{WvENt*c zRMHax_-4C@3u{LgB?bAKveZFhBf|y>NlE_xl1njgD&euF3~Vo3GeA)V6c7fuxrf?2 zzWn@+l8NaxP*vIlxUZ&Xva+*leh@fR%!_x_qETopU;boAhx~3ARniXQs?R`tH6R$c z@nt!3Z5Vp|Y{um;5U+~9z9j)T$m~v#Yn-PvWg5hTQ&R(5b*+oKB5k9xc(in2JlG%0 z&$oQ!C;tj(#r|R_-A@veoIZ{L75PD`Fd^n6kiswflP&-vtlGQj6-H8X=v zF3d?y&D@;!ak7-+^t76o-l{}(ul$`4jgHV}N%oX4x07@B#&z89QN@|Ln@)w({X?DW z?w-ZA0MAATt8K#}`hk)1C(+q8&?|8F=7CiRy|U@9Ov_cBgOl@@1{UVAKLn(k3B=gR z>0yJ{`fVP)eo}N3mNd`zC4ccF8LA_!cEI6k58YZ0WS=K`i%(LA<23O0YC3?z2o9w zPy&BQyT-mOTZoc{cDRGM8zPGBbVruw(|q$O~?0?C+^wtVok%P z8=9r9iGI8Bi1O||V1SeY`UWa&Xe|s5%rf$+_>P++G4CFqF2BIO{yEV%YJ58T(4*2X#&inF@ARIyxkc;>Y&p!(37)2nMnCUFqxZl|>08>>e zo6$7v*TLo{(JA4D$NQR30t_YN!_}+pn)YRC`>CS%}{Ldr!I2dLoC7cX&M+D~|87R2^1 zYID*8$q(2p7@##%T*~NW!o}`huRNYptN$GP9!QdSsaWQJ8(h`JD($5wtyG-nW{1_y zvZ@8~@)GigxScY(EywP7!#}VqU}0Q2W~B{cw7E`Z^hmO&hgXxqwe} z?nx~u^dm&fvF<45FtI_^E9|xv+O?qsXVe)hm5iyE${LBEK)flw&s%;U4i?dGEGAS5No!j=Q z+4h8Nf}j!=en;mU&K;#W=18Ro(*}_+i42>mI=?o9!9>2cfpJqnnd`V{f*fR{rL8^t z6l;5jR{LFn7M3iv!_X^9CLLLM`HsCoi~JuyzI0dGsuKPYVP<2a<0?8p4G0cKXY#P7 z%HBdK?YwSqcUhl~a`g&l2&x}~e%j#YZkO=I`7yFVNzt6i8km()VwbygI$XG84WzwN znAEFRu$|pqfW~5(^k4+|czDz~nYIhn7QN#snAFSBZ!iuHqej3@KfgFy+qrcn4@j4T z+VZ+Aj`)Y%;o;-I$;tG(xX9u0d$-S#E3@Ss6zX0H$U#Ut?WPucNXPYN;NCMx*{6dd z0Y(sg0~{S4<7G{ON5Smz2(h+_Fn)AiveZH$2&hg8dw}fTn-AkyAosZ~DlU%|;$9lx zF3oHTR;|4#(<%|9*koV$F(`CguK8&NKfAz;Hd;E5lOG~=HKTWUhyl#CpZd2}DbqJf znpu9<@h-3SY82i$pABHF53H=Mk&1ZRcb)dTUTkr}0SkC?+-(F&-#?x6;IR$(vsz>8 zZw;7b_0nLKNqQGLTG~EPc64_Ga{w1t6)* z+{>O?te95kpO=`kbWDZw#AGO)HUyjiB&tLU5{r^rI5imG%>>`1OG!~j3J8F>jby3x z8!ufnQ@lfdh=~KLr`HIf$U$uW!=oX+*l?`VWo}y#K|FNo?F(!UBcKC9Y38@?^Iiav zksO(keMKpv6Br*U)4B?Jn+0a5^E7F9E+6D_(x=FqMg10|q!IyR1~R8EWz1L9*1BT; z={Be3zCfJ(=Roz`=Kp5|b5Ag1z(D?MWiWTePYxai1d%a&q}1qfD>xDoDR7x!5rtbp%Dg2ff@%7J*I2f$(h&EX`&(p5ZF?_sE~9q z%74}IzL4U7d{;OW{^8gK6>Uld;I7ce1hdLg;k!7$0;f{N3F;t}NK>XuA^m!fxY-CD zgEB*e(O!V>AX1buLqvMVMA82z6nCD|z;NvClcd6Zf&R1lo->Gpq;HhF%<=fx!oE<3%s2p72KuiT5pumWi9!b5LOqQ7!ee1icK{)h`j3eb9 zKmw|X%USDN2X=;m@y_;9Scfq^#s%_Q3uy~eb!YcW45ljpRFSmvFZv{@qkDULfQk2q zNeFPtu6&%_ss^zJSTTU@oNKP#kR3#C@FKlDt0yP!Ty>tSy}#gTlo**4qHPl+gbrn7 zc2<^1aCl5F@GW!CnD0!oz2vUXuIA?CZ20*TcsGpMf$Yr0)Mr&YTRDok>#@19?fKw= zH$6iC9WYpczeryIKK*mCq336KdU{Joh{l(9wgUXvgqv$$;vx=S_OCy=<@XR~;xcN5 zAvJu2q=|%dH@F_ixVo-c6L_ z7Xv+bY3cbRY{zyUy*kem^?e&*_+4FoaECGI2q7hnt*zD4bfwb2kX}*&;A$u*?xd>5 z>SwS)d`=gwWY+^UI$*`2q$KBVFsdkN)U&j7XK-iZ+167{4#BbKDvn^tcm0$>CMqasmB_K9nmCy0TsvF_r{jFyMMix zX*^snm~M?%fk&-rzP8GV&HRO##S}~$F;nu-pn$>sq4vVvB%@#fD3AUWJbH8qNta@d z+uq!A_i&qUa=07a6j@p#U)J%57_{~DJhX8%2V5-?mIea@6x#gknsZZ2-kBL9wch-k zhFEQ!%wO{k_o}1ao|QU!Z+P(2+9=VsQO*QisAJW16PcOobIxt9I zUh38Dn`s{|1H_ynf!T%uw8k6vYpI?Jn3cxB<9=6`D>Zb#w~}a^o10|9KSlWHgxPln zlBYPHK^Qa`u^L@47T!aldup8=3K2>`EXxvBP^{_A+17yGtiNpP-ThNwCJ+A=myrQ6 z^T8Rddkx~DO)pSXOVdh=w3m+_0%>txKeh8EF!j_Hgg97Q5<}1o2qC!|EbqYj3OPb+ z0Mp7sPY>iaHqYEsQl~Z9)BOA`(3S+)XBQV95JF>85Y+wriq1-3qYQfnP=!=vDHqH& z9T_zZ`dgg)ET&dmg2W(HxM--z5c8wX!S^yUGzu7Xj+;F|&^|za>^*B`YRT^L_lwZN zU8(a4`f51%sMoZ@Y#_D9<<1uw!l)Q(BT;52!o) zmw$d4vSDFi?O5ALV3NyFM!M_hB*YU+3WeH6qW}wsonMFH*5)RD-1ka@Bp^%!Bk^E7 zn+@d8`SEe+Mm#S}(Z*)CEpYhtoGuOOqm`8vI)(-Grq?)VU%t#A5ieitD}|ndMxT_3 z!F3W6hw&o4Jg*FlP5Uo4-0aaI z8|`*EHMY0N6zz+pLP8Q35%5EL4&WMTo11eo{B!OE_l}H>WgD0fU|{e_E;$1^*MvQx zoF%5-`rNQWiVE}-yv}*7)Q(!>nab8oSsn@yT<81?9h;S-POm|OD&oc-rvZ-O;TQn0B)8!ZJ74wYoiG;6V ze_^@>B_&v9(Y##-Ja19r9>NGmeRfsLJoXqICC*x(UlamTKVkAPsgH}tYY>Nkg zfg@7s>CBes1EgOwrKPMav^%jrUwPmc!NI{*@Xq1{(O1^)Cx3Sq2rRACLZ3ZEHrRG2 z`puu(3XST7eoyn6ug#u(cX>JF5@d4d|0~uG3bzMC?lz|ORpTKjjJ&f`-sUT=`4Ng}T zCsx_AskFEuhRe9br@6LqzjGx)1DHg{aJBVZ%VMcne=_jxRoGlj{0pmA1Ev6&MV*}S ziqgjlA5lm1nSaZOWum6ZSvp(iR8vxFG1lgx$J{56i;w@FIPQx4PF&m{fL2_UlTF&w zXZnrx4mQ#a!d)@#dK)FYj-(`p8KP)P7LJkMpvv)WBf}Fss-LdRfqPJq)>0Efg@Xe* zJ#}_+a_Ws`ZpFYrM~_xfuCbe`G})Ga6n)SgRmf|Pff(cX-kqsROiGb?v&-yu@esIgewv=xM=BmqED-4G zB_ABFGK_oId#w9Am;v%3oLr>V=*qOg^CWT5d3VJ=Lr=;c0zTZ>!a`qLds+@k7Qo&VN zB1UzZvT{R0FF>5MnLE5sjX`3DvevWVDfJ=s>vVQtW}eP@^aUae$`~2@xKxL{nZy&sw(&3<8$D9Uz|}Rmx(pFC49WS6^_t$61cgQZA0!!5?YMZ~xVx05Bi0o3j>P zobBFIkc@-@T%Mwz;zpP_;Hs2wBKeO~>cH;WFfmH$OuH-AZRh)M6sf49f2WXwxQ$dr zYaFcjYUGC@%|>iONpZ1$`ZvVp@c=eJ{h!et`SqCN7Wd$rUjQlGw$K@Z_qE$t`M2@) zY8m)fega?7v~S(A_$YLEf@ID2XqE)Zw0z*Idf&FdAr0CVqJV|Kkv&0{IZ{Rp*+5T& zba%1t)7m>U0K&K0o&FiY=f9`{GT>X!hI1O=`;2#PzK=U zDN+>{_zCDv2mXr+-|9e)RHe{xbmj$fj4(hA6{8w9=S27KSw7$wcv)4qJtYtL;7n1_ z?m!tSI*kGVq9}z1=#lVM{Q3^CXI=Nj=` zJ32iSLwkXbZ!y(a#@02{tKzWc@c(iZ_{ZLxGLV?YJl9@FcLPZabR-X#cK|Zcp4Zw* z2gDjruZE(cqC{ImwgeEp!3+E53OLf2?d$*Q-m3$;O;@h;$h zhv6jIa60c0VkhaT=m1R`G(&vBF=S5wykso?T9vM?wq?L+qvNqt(|@udga-pZgs29a z@GoEi`?J)+&_Yo|O8Pj|(V?Zc%QbxM2-PP=2p*frW&lCb=cO2ecNpsf)?84~{`a@H z(`O^;34`EX&GxA#B?2=PFsSd6D-8k*F23h+dRCUW*<-L6=vn{gSo|Mn!yt_YWgM{>S>;88EGysiBgvoz9^8xG%&N>Kahpr_5Sl8j7ZUS3cv4Nyw;V4|-?(f)t%{B2iLK+p8d z`Kp-+xxgpTe+8s=bv6+{jpMKOT^szU}uD^rNE0}WXo4#Z= z@QVRuQxY9-vU=v3n3yyf*LG)Iv>3B%Yl-wHKgQ?kaxNwN`D*xTp1-uK3TqMq!?1Y{zQx@lkSs_J$cl?0db;Sg&b8V3%$0p;%fkSi@ zHCO%&H9OtGfX@46kO1&sZXRyHRSKLP#mobs=@yLwW`LHi--sC&#&;h7l%jq4AS5^# zNc@=O`CgJK7sUaf*Z^wHe<(JNPHnU`ppRaX+@oLTEs^SKz_@NofM&nc-nn1 zXFc+BYxK||KR>tvjkbX0@I=JHOUSvcH$3)yUf~7fKtO@u!idNs-6BFYK8(i z=99FAfk7FN{Xi@ER=A~_+DVE4_`wISyX&Kuab4nQ56`dI6Z+oY=>o+Pbc?RqyE)3f zgqSzn@e-#v9~{0w@w)l^`4h-&X=y_UBTo2WGdc12%ryVUhPx6PA4#-lXfV*D^eAvP zT{&+V<=R+T%T-J@BYaXqVhh3!D2tB=aBW*Ah`Hx4UiJh}aKLvcC_t42T@umJI+~iC z0Ao7eS%Q@${(INMsIjXro=uKECMzpzxmnZF%8Fb#lx%a2K2j=GM4_ydwd=lMTIR8} zRvhvG1v@aSgic(J|6b$x57NaD=uyY7n%_S=0u;*nfS%>BmbQ~S5%Hf4X&ZV_S4l)T z!`Y77Kw}+vfezurVD#rk*bwu9#~cJK+N|EKm4}DuFdWcP1UgDYynBGbrLq#!#bqMM zcNu|T*G-n}i@z|im!XGj)I^&B*T`(CSB%Gv)2VKS&eNBI+SWo*9;m#wPWdm74t^{}A)4>p){dW``zr(bf3TI2kseU4b#--U>6bq1u7Elb z&`AP#9W5O=m^)oVu_L}JpULt9ZT3#KR+RHR$ z8LWCk2=2hojTGkQt{j{rr{ho@55`yl*M+~Xnp%f3+rc6!gqE6He(DRT!vC2n&g&iU zvm*N!$k(%p@ZU9~E* zSE~T(!7@#MWp|TnRBwNOo5piEH5~?z_XQCo_eVMIg0ZDxC{EpT`=X{MG9S-r;77Br zR%)AbI65M!DzRs=sa|U7HDQP0+zKKms0QOu;yxih%`eVtxtn`+?|;7Wfnw6-#l3== zbJ7dvR#j9{sQeZd)(7tL^IDlC;YMgv&*<8#<)_Da`T5?6y=IMc&}st7y9Q#zu%MC$$$4bI>!@qsjy7KF~kDd*M70l~sTP z`QLJjv|Ja%S8>Yg;q;z48=Ff`OX#Y;>D|0@x?2H%(F_K;IB=8#pX0T;!111jo|+fK zdH;esSlxgHYV?eu)1buxt}$uK$PuD^ma3*&bel9N6)pwr_^uIsE_Zgc9hLmZE$rZ@ zzO5%M-5zvni6UmX0XyC`GsaAPR(0nh=i61c!fQ$wzvBO zdi}h3&U5)b-{<@NTr#k(mcw2hgB>SeN#BhAaXRc7)I#lA3INYIR439fnU$AS!{tT? zH#9anxbKLCKcax-!zjn(Tc_EDR=*3fi}Mh88fH zUO*jtwe{hBXG%iKVLV>UBOoj-Q>i(CG%?rL4|tRTL?Qw?q8smq|1MU1z_k2EwY9D2 zjkd$%&B@Ajz?0^7%AZcfnN&Ih7;b>vtio(8J*3s@!0ZP=`)&N;*gX&Ej`H>R8pMBa z(L$VwQ?|2mdLm|k`}yBORX{O4z22=p!8@rJ=_i~TCGHm$GhL-pLPHJvg!OmF3)x$D z=WN++$NtHs-HCm9OY=7_tmbQ%CG`l0ZFW`J-?GOv9IT5*8sSEh-Im>&t-phLx#}Z_ zOcp1jgVETMCsa2^d8cNdGSx^K((dmxnHH2Cf*55-=n#E=pwi0GRs|xwY3dXt4gPL$Of~kFm6hFvi!A)u zg7k@ye4NYVO(yd~it+w%))k@?^}@?922;1H@`%l7rQL=_p1Zr7aC)l7yqvzkn#~u@ z^=(pPFZjj8o_aEuT_u&$3`HIurWRa(@2s!jT|a%iDoW1Ksw73`9px#KT|0Rp^P1u9 zeJIhV=%^^s`zhEnq_@5(Phz=DbqZ23~N8h^1(dcbW{;)#-*w?>kuVaR~v084w2&@7)X)j_Mm<>jx6CM*lrZt^kZoHdt@sw%J6vy6Nyi1 z(G`^p(bc8M=N6Glu3i2+zCszCf7-gD`J);T7#0=8MbUKo^_y6~TmBBV=VYA2cc;3< zdyIv$FM-{Wx+~jJ@-)k<&w|Kh{Pg)Xy~{F_*Q#d;?y9z@9+z6@rfOV)sfNerA5t`P zFOX zx;GsViMu|M3s31jsj5)&o-|7+hszSODrv;pAJHudLBd2qlPDv!>Ug!z8?rtGj-`p$ z=Me!Hqr*=Y#f4!9eKJ^lKA$CI#QVlWk>}pGWv$lfatkd`(*{bircM`s2$NS{1Zu(~ z?$Q20@#i21s2I{aH=t&Iclu4-0B)3@_5d5UnaMk9f5T7&)8GfT%OOP;emhie4;FF5 z;-Z7Z%-d>o*_Q07B?Sj(p_gnr6miV+>+siY`Fb7xUl=gV?7Ni3dzf0FT7{sW4-yX4 I`Gj5m2UZ59@Bjb+ literal 0 HcmV?d00001 diff --git a/frontend/__snapshots__/components-playerinspector--default--light.png b/frontend/__snapshots__/components-playerinspector--default--light.png new file mode 100644 index 0000000000000000000000000000000000000000..e9aabac97d7d9b3a1430be8a3249bd9f254b7916 GIT binary patch literal 20444 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 literal 0 HcmV?d00001 diff --git a/frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.stories.tsx b/frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.stories.tsx new file mode 100644 index 00000000000..1c3376a829f --- /dev/null +++ b/frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.stories.tsx @@ -0,0 +1,88 @@ +import { Meta, StoryFn, StoryObj } from '@storybook/react' +import { BindLogic, useActions, useValues } from 'kea' +import { useEffect } from 'react' +import recordingEventsJson from 'scenes/session-recordings/__mocks__/recording_events_query' +import recordingMetaJson from 'scenes/session-recordings/__mocks__/recording_meta.json' +import { snapshotsAsJSONLines } from 'scenes/session-recordings/__mocks__/recording_snapshots' +import { PlayerInspector } from 'scenes/session-recordings/player/inspector/PlayerInspector' +import { sessionRecordingDataLogic } from 'scenes/session-recordings/player/sessionRecordingDataLogic' +import { sessionRecordingPlayerLogic } from 'scenes/session-recordings/player/sessionRecordingPlayerLogic' + +import { mswDecorator } from '~/mocks/browser' + +type Story = StoryObj +const meta: Meta = { + title: 'Components/PlayerInspector', + component: PlayerInspector, + decorators: [ + mswDecorator({ + get: { + '/api/environments/:team_id/session_recordings/:id': recordingMetaJson, + '/api/environments/:team_id/session_recordings/:id/snapshots': (req, res, ctx) => { + // with no sources, returns sources... + if (req.url.searchParams.get('source') === 'blob') { + return res(ctx.text(snapshotsAsJSONLines())) + } + // with no source requested should return sources + return [ + 200, + { + sources: [ + { + source: 'blob', + start_timestamp: '2023-08-11T12:03:36.097000Z', + end_timestamp: '2023-08-11T12:04:52.268000Z', + blob_key: '1691755416097-1691755492268', + }, + ], + }, + ] + }, + }, + post: { + '/api/environments/:team_id/query': (req, res, ctx) => { + const body = req.body as Record + if (body.query.kind === 'EventsQuery' && body.query.properties.length === 1) { + return res(ctx.json(recordingEventsJson)) + } + + // default to an empty response or we duplicate information + return res(ctx.json({ results: [] })) + }, + }, + }), + ], +} +export default meta + +const BasicTemplate: StoryFn = () => { + const dataLogic = sessionRecordingDataLogic({ sessionRecordingId: '12345', playerKey: 'story-template' }) + const { sessionPlayerMetaData } = useValues(dataLogic) + + const { loadSnapshots, loadEvents } = useActions(dataLogic) + loadSnapshots() + + // TODO you have to call actions in a particular order + // and only when some other data has already been loaded + // 🫠 + useEffect(() => { + loadEvents() + }, [sessionPlayerMetaData]) + + return ( +
+ + + +
+ ) +} + +export const Default: Story = BasicTemplate.bind({}) +Default.args = {} diff --git a/frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.tsx b/frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.tsx new file mode 100644 index 00000000000..dc8c712cef4 --- /dev/null +++ b/frontend/src/scenes/session-recordings/player/inspector/PlayerInspector.tsx @@ -0,0 +1,11 @@ +import { PlayerInspectorControls } from 'scenes/session-recordings/player/inspector/PlayerInspectorControls' +import { PlayerInspectorList } from 'scenes/session-recordings/player/inspector/PlayerInspectorList' + +export function PlayerInspector(): JSX.Element { + return ( + <> + + + + ) +} diff --git a/frontend/src/scenes/session-recordings/player/sidebar/PlayerSidebarTab.tsx b/frontend/src/scenes/session-recordings/player/sidebar/PlayerSidebarTab.tsx index 8f2c12055f2..9c69a46274d 100644 --- a/frontend/src/scenes/session-recordings/player/sidebar/PlayerSidebarTab.tsx +++ b/frontend/src/scenes/session-recordings/player/sidebar/PlayerSidebarTab.tsx @@ -1,9 +1,8 @@ import { useValues } from 'kea' +import { PlayerInspector } from 'scenes/session-recordings/player/inspector/PlayerInspector' import { SessionRecordingSidebarTab } from '~/types' -import { PlayerInspectorControls } from '../inspector/PlayerInspectorControls' -import { PlayerInspectorList } from '../inspector/PlayerInspectorList' import { PlayerSidebarDebuggerTab } from './PlayerSidebarDebuggerTab' import { playerSidebarLogic } from './playerSidebarLogic' import { PlayerSidebarOverviewTab } from './PlayerSidebarOverviewTab' @@ -15,12 +14,7 @@ export function PlayerSidebarTab(): JSX.Element | null { case SessionRecordingSidebarTab.OVERVIEW: return case SessionRecordingSidebarTab.INSPECTOR: - return ( - <> - - - - ) + return case SessionRecordingSidebarTab.DEBUGGER: return default: From b562836685e5ef9f7498b8aac67542fe4dbb73dc Mon Sep 17 00:00:00 2001 From: Marcus Hof <13001502+MarconLP@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:35:41 +0100 Subject: [PATCH 08/27] feat(cdp): add brevo destination (#26195) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- frontend/public/services/brevo.png | Bin 0 -> 24286 bytes posthog/cdp/templates/__init__.py | 2 + posthog/cdp/templates/brevo/template_brevo.py | 81 ++++++++++++++++++ .../templates/brevo/test_template_brevo.py | 46 ++++++++++ 4 files changed, 129 insertions(+) create mode 100644 frontend/public/services/brevo.png create mode 100644 posthog/cdp/templates/brevo/template_brevo.py create mode 100644 posthog/cdp/templates/brevo/test_template_brevo.py diff --git a/frontend/public/services/brevo.png b/frontend/public/services/brevo.png new file mode 100644 index 0000000000000000000000000000000000000000..65dfdbac8030abc89fa07c13c877cdfb654b3259 GIT binary patch literal 24286 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 Ntq= 400) { + throw Error(f'Error from api.brevo.com (status {res.status}): {res.body}') +} +""".strip(), + inputs_schema=[ + { + "key": "apiKey", + "type": "string", + "label": "Brevo API Key", + "description": "Check out this page on how to get your API key: https://help.brevo.com/hc/en-us/articles/209467485-Create-and-manage-your-API-keys", + "secret": True, + "required": True, + }, + { + "key": "email", + "type": "string", + "label": "Email of the user", + "description": "Where to find the email for the contact to be created. You can use the filters section to filter out unwanted emails or internal users.", + "default": "{person.properties.email}", + "secret": False, + "required": True, + }, + { + "key": "attributes", + "type": "dictionary", + "label": "Attributes", + "description": "For information on potential attributes, refer to the following page: https://help.brevo.com/hc/en-us/articles/10617359589906-Create-and-manage-contact-attributes", + "default": { + "EMAIL": "{person.properties.email}", + "FIRSTNAME": "{person.properties.firstname}", + "LASTNAME": "{person.properties.lastname}", + }, + "secret": False, + "required": True, + }, + ], + filters={ + "events": [ + {"id": "$identify", "name": "$identify", "type": "events", "order": 0}, + {"id": "$set", "name": "$set", "type": "events", "order": 0}, + ], + "actions": [], + "filter_test_accounts": True, + }, +) diff --git a/posthog/cdp/templates/brevo/test_template_brevo.py b/posthog/cdp/templates/brevo/test_template_brevo.py new file mode 100644 index 00000000000..839dabbc5a3 --- /dev/null +++ b/posthog/cdp/templates/brevo/test_template_brevo.py @@ -0,0 +1,46 @@ +from inline_snapshot import snapshot +from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest +from posthog.cdp.templates.brevo.template_brevo import ( + template as template_brevo, +) + + +def create_inputs(**kwargs): + inputs = { + "apiKey": "apikey12345", + "email": "max@posthog.com", + "attributes": {"EMAIL": "max@posthog.com", "FIRSTNAME": "Max"}, + } + inputs.update(kwargs) + + return inputs + + +class TestTemplateBrevo(BaseHogFunctionTemplateTest): + template = template_brevo + + def test_function_works(self): + self.run_function(inputs=create_inputs()) + assert self.get_mock_fetch_calls()[0] == snapshot( + ( + "https://api.brevo.com/v3/contacts", + { + "method": "POST", + "headers": { + "api-key": "apikey12345", + "Content-Type": "application/json", + }, + "body": { + "email": "max@posthog.com", + "updateEnabled": True, + "attributes": {"EMAIL": "max@posthog.com", "FIRSTNAME": "Max"}, + }, + }, + ) + ) + + def test_function_requires_identifier(self): + self.run_function(inputs=create_inputs(email="")) + + assert not self.get_mock_fetch_calls() + assert self.get_mock_print_calls() == snapshot([("No email set. Skipping...",)]) From 04f656bc67bb20976ef929ac2901e50f79618ea4 Mon Sep 17 00:00:00 2001 From: Georgiy Tarasov Date: Mon, 18 Nov 2024 10:46:17 +0100 Subject: [PATCH 09/27] fix(product-assistant): planner nodes didn't output tools (#26225) Co-authored-by: Michael Matloka --- ee/hogai/taxonomy_agent/nodes.py | 15 ++++++++++++--- ee/hogai/taxonomy_agent/test/test_nodes.py | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/ee/hogai/taxonomy_agent/nodes.py b/ee/hogai/taxonomy_agent/nodes.py index 06d3b29df1a..ef5c1953b99 100644 --- a/ee/hogai/taxonomy_agent/nodes.py +++ b/ee/hogai/taxonomy_agent/nodes.py @@ -75,10 +75,8 @@ class TaxonomyAgentPlannerNode(AssistantNode): AgentAction, agent.invoke( { - "react_format": REACT_FORMAT_PROMPT, + "react_format": self._get_react_format_prompt(toolkit), "react_format_reminder": REACT_FORMAT_REMINDER_PROMPT, - "tools": toolkit.render_text_description(), - "tool_names": ", ".join([t["name"] for t in toolkit.tools]), "product_description": self._team.project.product_description, "groups": self._team_group_types, "events": self._events_prompt, @@ -121,6 +119,17 @@ class TaxonomyAgentPlannerNode(AssistantNode): def _model(self) -> ChatOpenAI: return ChatOpenAI(model="gpt-4o", temperature=0.2, streaming=True) + def _get_react_format_prompt(self, toolkit: TaxonomyAgentToolkit) -> str: + return cast( + str, + ChatPromptTemplate.from_template(REACT_FORMAT_PROMPT, template_format="mustache") + .format_messages( + tools=toolkit.render_text_description(), + tool_names=", ".join([t["name"] for t in toolkit.tools]), + )[0] + .content, + ) + @cached_property def _events_prompt(self) -> str: response = TeamTaxonomyQueryRunner(TeamTaxonomyQuery(), self._team).run( diff --git a/ee/hogai/taxonomy_agent/test/test_nodes.py b/ee/hogai/taxonomy_agent/test/test_nodes.py index 920dfacfb85..1a5fe25d8bf 100644 --- a/ee/hogai/taxonomy_agent/test/test_nodes.py +++ b/ee/hogai/taxonomy_agent/test/test_nodes.py @@ -22,7 +22,7 @@ from posthog.schema import ( from posthog.test.base import APIBaseTest, ClickhouseTestMixin, _create_event, _create_person -class TestToolkit(TaxonomyAgentToolkit): +class DummyToolkit(TaxonomyAgentToolkit): def _get_tools(self) -> list[ToolkitTool]: return self._default_tools @@ -36,8 +36,8 @@ class TestTaxonomyAgentPlannerNode(ClickhouseTestMixin, APIBaseTest): def _get_node(self): class Node(TaxonomyAgentPlannerNode): def run(self, state: AssistantState, config: RunnableConfig) -> AssistantState: - prompt = ChatPromptTemplate.from_messages([("user", "test")]) - toolkit = TestToolkit(self._team) + prompt: ChatPromptTemplate = ChatPromptTemplate.from_messages([("user", "test")]) + toolkit = DummyToolkit(self._team) return super()._run_with_prompt_and_toolkit(state, prompt, toolkit, config=config) return Node(self.team) @@ -180,13 +180,21 @@ class TestTaxonomyAgentPlannerNode(ClickhouseTestMixin, APIBaseTest): node._events_prompt, ) + def test_format_prompt(self): + node = self._get_node() + self.assertNotIn("Human:", node._get_react_format_prompt(DummyToolkit(self.team))) + self.assertIn("retrieve_event_properties,", node._get_react_format_prompt(DummyToolkit(self.team))) + self.assertIn( + "retrieve_event_properties(event_name: str)", node._get_react_format_prompt(DummyToolkit(self.team)) + ) + @override_settings(IN_UNIT_TESTING=True) class TestTaxonomyAgentPlannerToolsNode(ClickhouseTestMixin, APIBaseTest): def _get_node(self): class Node(TaxonomyAgentPlannerToolsNode): def run(self, state: AssistantState, config: RunnableConfig) -> AssistantState: - toolkit = TestToolkit(self._team) + toolkit = DummyToolkit(self._team) return super()._run_with_toolkit(state, toolkit, config=config) return Node(self.team) From 23bd1a010f17ea3c6e9f14abab01f04e1c655ba4 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Mon, 18 Nov 2024 11:05:54 +0100 Subject: [PATCH 10/27] feat(max): Summarize insight results (#26172) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- ee/hogai/assistant.py | 78 ++++--- ee/hogai/funnels/test/test_nodes.py | 4 +- .../test/{test_router.py => test_nodes.py} | 0 ee/hogai/schema_generator/nodes.py | 1 + ee/hogai/schema_generator/test/test_nodes.py | 4 +- ee/hogai/summarizer/__init__.py | 0 ee/hogai/summarizer/nodes.py | 95 +++++++++ ee/hogai/summarizer/prompts.py | 17 ++ ee/hogai/summarizer/test/__init__.py | 0 ee/hogai/summarizer/test/test_nodes.py | 196 ++++++++++++++++++ ee/hogai/trends/test/test_nodes.py | 6 +- ee/hogai/utils.py | 1 + ...app-max-ai--empty-thread-loading--dark.png | Bin 11029 -> 11018 bytes ...pp-max-ai--empty-thread-loading--light.png | Bin 11160 -> 11131 bytes ...ax-ai--generation-failure-thread--dark.png | Bin 44264 -> 44368 bytes ...x-ai--generation-failure-thread--light.png | Bin 43409 -> 43454 bytes .../scenes-app-max-ai--thread--dark.png | Bin 68501 -> 72858 bytes .../scenes-app-max-ai--thread--light.png | Bin 65884 -> 70204 bytes ...i--thread-with-failed-generation--dark.png | Bin 16149 -> 16222 bytes ...--thread-with-failed-generation--light.png | Bin 16249 -> 16322 bytes frontend/src/lib/lemon-ui/icons/categories.ts | 12 +- frontend/src/queries/schema.json | 27 ++- frontend/src/queries/schema.ts | 11 + frontend/src/scenes/max/QuestionInput.tsx | 2 +- .../src/scenes/max/QuestionSuggestions.tsx | 2 + frontend/src/scenes/max/Thread.tsx | 184 +++++++++------- .../max/__mocks__/chatResponse.mocks.ts | 16 +- ...ilureResponse.json => failureMessage.json} | 0 .../scenes/max/__mocks__/summaryMessage.json | 5 + ...esponse.json => visualizationMessage.json} | 3 +- frontend/src/scenes/max/maxLogic.ts | 66 ++---- frontend/src/scenes/max/utils.ts | 5 + package.json | 6 +- pnpm-lock.yaml | 8 +- posthog/demo/matrix/manager.py | 1 + posthog/demo/products/hedgebox/matrix.py | 5 +- posthog/schema.py | 12 ++ 37 files changed, 596 insertions(+), 171 deletions(-) rename ee/hogai/router/test/{test_router.py => test_nodes.py} (100%) create mode 100644 ee/hogai/summarizer/__init__.py create mode 100644 ee/hogai/summarizer/nodes.py create mode 100644 ee/hogai/summarizer/prompts.py create mode 100644 ee/hogai/summarizer/test/__init__.py create mode 100644 ee/hogai/summarizer/test/test_nodes.py rename frontend/src/scenes/max/__mocks__/{failureResponse.json => failureMessage.json} (100%) create mode 100644 frontend/src/scenes/max/__mocks__/summaryMessage.json rename frontend/src/scenes/max/__mocks__/{chatResponse.json => visualizationMessage.json} (99%) diff --git a/ee/hogai/assistant.py b/ee/hogai/assistant.py index 37a171bf036..df200ae869c 100644 --- a/ee/hogai/assistant.py +++ b/ee/hogai/assistant.py @@ -5,6 +5,7 @@ from langchain_core.messages import AIMessageChunk from langfuse.callback import CallbackHandler from langgraph.graph.state import StateGraph from pydantic import BaseModel +from sentry_sdk import capture_exception from ee import settings from ee.hogai.funnels.nodes import ( @@ -15,6 +16,7 @@ from ee.hogai.funnels.nodes import ( ) from ee.hogai.router.nodes import RouterNode from ee.hogai.schema_generator.nodes import SchemaGeneratorNode +from ee.hogai.summarizer.nodes import SummarizerNode from ee.hogai.trends.nodes import ( TrendsGeneratorNode, TrendsGeneratorToolsNode, @@ -26,6 +28,8 @@ from posthog.models.team.team import Team from posthog.schema import ( AssistantGenerationStatusEvent, AssistantGenerationStatusType, + AssistantMessage, + FailureMessage, VisualizationMessage, ) @@ -123,7 +127,7 @@ class Assistant: generate_trends_node.router, path_map={ "tools": AssistantNodeName.TRENDS_GENERATOR_TOOLS, - "next": AssistantNodeName.END, + "next": AssistantNodeName.SUMMARIZER, }, ) @@ -160,10 +164,14 @@ class Assistant: generate_trends_node.router, path_map={ "tools": AssistantNodeName.FUNNEL_GENERATOR_TOOLS, - "next": AssistantNodeName.END, + "next": AssistantNodeName.SUMMARIZER, }, ) + summarizer_node = SummarizerNode(self._team) + builder.add_node(AssistantNodeName.SUMMARIZER, summarizer_node.run) + builder.add_edge(AssistantNodeName.SUMMARIZER, AssistantNodeName.END) + return builder.compile() def stream(self, conversation: Conversation) -> Generator[BaseModel, None, None]: @@ -185,33 +193,47 @@ class Assistant: # Send a chunk to establish the connection avoiding the worker's timeout. yield AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.ACK) - for update in generator: - if is_state_update(update): - _, new_state = update - state = new_state + try: + for update in generator: + if is_state_update(update): + _, new_state = update + state = new_state - elif is_value_update(update): - _, state_update = update + elif is_value_update(update): + _, state_update = update - if AssistantNodeName.ROUTER in state_update and "messages" in state_update[AssistantNodeName.ROUTER]: - yield state_update[AssistantNodeName.ROUTER]["messages"][0] - elif intersected_nodes := state_update.keys() & VISUALIZATION_NODES.keys(): - # Reset chunks when schema validation fails. - chunks = AIMessageChunk(content="") + if ( + AssistantNodeName.ROUTER in state_update + and "messages" in state_update[AssistantNodeName.ROUTER] + ): + yield state_update[AssistantNodeName.ROUTER]["messages"][0] + elif intersected_nodes := state_update.keys() & VISUALIZATION_NODES.keys(): + # Reset chunks when schema validation fails. + chunks = AIMessageChunk(content="") - node_name = intersected_nodes.pop() - if "messages" in state_update[node_name]: - yield state_update[node_name]["messages"][0] - elif state_update[node_name].get("intermediate_steps", []): - yield AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.GENERATION_ERROR) - - elif is_message_update(update): - langchain_message, langgraph_state = update[1] - for node_name, viz_node in VISUALIZATION_NODES.items(): - if langgraph_state["langgraph_node"] == node_name and isinstance(langchain_message, AIMessageChunk): - chunks += langchain_message # type: ignore - parsed_message = viz_node.parse_output(chunks.tool_calls[0]["args"]) - if parsed_message: - yield VisualizationMessage( - reasoning_steps=parsed_message.reasoning_steps, answer=parsed_message.answer + node_name = intersected_nodes.pop() + if "messages" in state_update[node_name]: + yield state_update[node_name]["messages"][0] + elif state_update[node_name].get("intermediate_steps", []): + yield AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.GENERATION_ERROR) + elif AssistantNodeName.SUMMARIZER in state_update: + chunks = AIMessageChunk(content="") + yield state_update[AssistantNodeName.SUMMARIZER]["messages"][0] + elif is_message_update(update): + langchain_message, langgraph_state = update[1] + if isinstance(langchain_message, AIMessageChunk): + if langgraph_state["langgraph_node"] in VISUALIZATION_NODES.keys(): + chunks += langchain_message # type: ignore + parsed_message = VISUALIZATION_NODES[langgraph_state["langgraph_node"]].parse_output( + chunks.tool_calls[0]["args"] ) + if parsed_message: + yield VisualizationMessage( + reasoning_steps=parsed_message.reasoning_steps, answer=parsed_message.answer + ) + elif langgraph_state["langgraph_node"] == AssistantNodeName.SUMMARIZER: + chunks += langchain_message # type: ignore + yield AssistantMessage(content=chunks.content) + except Exception as e: + capture_exception(e) + yield FailureMessage() # This is an unhandled error, so we just stop further generation at this point diff --git a/ee/hogai/funnels/test/test_nodes.py b/ee/hogai/funnels/test/test_nodes.py index d7b42f7a872..59ba48ff6fa 100644 --- a/ee/hogai/funnels/test/test_nodes.py +++ b/ee/hogai/funnels/test/test_nodes.py @@ -33,7 +33,9 @@ class TestFunnelsGeneratorNode(ClickhouseTestMixin, APIBaseTest): self.assertEqual( new_state, { - "messages": [VisualizationMessage(answer=self.schema, plan="Plan", reasoning_steps=["step"])], + "messages": [ + VisualizationMessage(answer=self.schema, plan="Plan", reasoning_steps=["step"], done=True) + ], "intermediate_steps": None, }, ) diff --git a/ee/hogai/router/test/test_router.py b/ee/hogai/router/test/test_nodes.py similarity index 100% rename from ee/hogai/router/test/test_router.py rename to ee/hogai/router/test/test_nodes.py diff --git a/ee/hogai/schema_generator/nodes.py b/ee/hogai/schema_generator/nodes.py index f6e41c69027..6470c52c4fe 100644 --- a/ee/hogai/schema_generator/nodes.py +++ b/ee/hogai/schema_generator/nodes.py @@ -101,6 +101,7 @@ class SchemaGeneratorNode(AssistantNode, Generic[Q]): plan=generated_plan, reasoning_steps=message.reasoning_steps, answer=message.answer, + done=True, ) ], "intermediate_steps": None, diff --git a/ee/hogai/schema_generator/test/test_nodes.py b/ee/hogai/schema_generator/test/test_nodes.py index 961bd88de22..25f82e43d44 100644 --- a/ee/hogai/schema_generator/test/test_nodes.py +++ b/ee/hogai/schema_generator/test/test_nodes.py @@ -54,7 +54,9 @@ class TestSchemaGeneratorNode(ClickhouseTestMixin, APIBaseTest): self.assertEqual( new_state, { - "messages": [VisualizationMessage(answer=self.schema, plan="Plan", reasoning_steps=["step"])], + "messages": [ + VisualizationMessage(answer=self.schema, plan="Plan", reasoning_steps=["step"], done=True) + ], "intermediate_steps": None, }, ) diff --git a/ee/hogai/summarizer/__init__.py b/ee/hogai/summarizer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ee/hogai/summarizer/nodes.py b/ee/hogai/summarizer/nodes.py new file mode 100644 index 00000000000..8d5e8a406f4 --- /dev/null +++ b/ee/hogai/summarizer/nodes.py @@ -0,0 +1,95 @@ +import json +from time import sleep +from django.conf import settings +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.runnables import RunnableConfig +from langchain_openai import ChatOpenAI +from django.core.serializers.json import DjangoJSONEncoder +from rest_framework.exceptions import APIException +from sentry_sdk import capture_exception + +from ee.hogai.summarizer.prompts import SUMMARIZER_SYSTEM_PROMPT, SUMMARIZER_INSTRUCTION_PROMPT +from ee.hogai.utils import AssistantNode, AssistantNodeName, AssistantState +from posthog.api.services.query import process_query_dict +from posthog.clickhouse.client.execute_async import get_query_status +from posthog.errors import ExposedCHQueryError +from posthog.hogql.errors import ExposedHogQLError +from posthog.hogql_queries.query_runner import ExecutionMode +from posthog.schema import AssistantMessage, FailureMessage, HumanMessage, VisualizationMessage + + +class SummarizerNode(AssistantNode): + name = AssistantNodeName.SUMMARIZER + + def run(self, state: AssistantState, config: RunnableConfig): + viz_message = state["messages"][-1] + if not isinstance(viz_message, VisualizationMessage): + raise ValueError("Can only run summarization with a visualization message as the last one in the state") + if viz_message.answer is None: + raise ValueError("Did not found query in the visualization message") + + try: + results_response = process_query_dict( # type: ignore + self._team, # TODO: Add user + viz_message.answer.model_dump(mode="json"), # We need mode="json" so that + # Celery doesn't run in tests, so there we use force_blocking instead + # This does mean that the waiting logic is not tested + execution_mode=ExecutionMode.RECENT_CACHE_CALCULATE_ASYNC_IF_STALE + if not settings.TEST + else ExecutionMode.CALCULATE_BLOCKING_ALWAYS, + ).model_dump(mode="json") + if results_response.get("query_status") and not results_response["query_status"]["complete"]: + query_id = results_response["query_status"]["id"] + for i in range(0, 999): + sleep(i / 2) # We start at 0.5s and every iteration we wait 0.5s more + query_status = get_query_status(team_id=self._team.pk, query_id=query_id) + if query_status.error: + if query_status.error_message: + raise APIException(query_status.error_message) + else: + raise ValueError("Query failed") + if query_status.complete: + results_response = query_status.results + break + except (APIException, ExposedHogQLError, ExposedCHQueryError) as err: + err_message = str(err) + if isinstance(err, APIException): + if isinstance(err.detail, dict): + err_message = ", ".join(f"{key}: {value}" for key, value in err.detail.items()) + elif isinstance(err.detail, list): + err_message = ", ".join(map(str, err.detail)) + return {"messages": [FailureMessage(content=f"There was an error running this query: {err_message}")]} + except Exception as err: + capture_exception(err) + return {"messages": [FailureMessage(content="There was an unknown error running this query.")]} + + summarization_prompt = ChatPromptTemplate(self._construct_messages(state), template_format="mustache") + + chain = summarization_prompt | self._model + + message = chain.invoke( + { + "query_kind": viz_message.answer.kind, + "product_description": self._team.project.product_description, + "results": json.dumps(results_response["results"], cls=DjangoJSONEncoder), + }, + config, + ) + + return {"messages": [AssistantMessage(content=str(message.content), done=True)]} + + @property + def _model(self): + return ChatOpenAI(model="gpt-4o", temperature=0.5, streaming=True) # Slightly higher temp than earlier steps + + def _construct_messages(self, state: AssistantState) -> list[tuple[str, str]]: + conversation: list[tuple[str, str]] = [("system", SUMMARIZER_SYSTEM_PROMPT)] + + for message in state.get("messages", []): + if isinstance(message, HumanMessage): + conversation.append(("human", message.content)) + elif isinstance(message, AssistantMessage): + conversation.append(("assistant", message.content)) + + conversation.append(("human", SUMMARIZER_INSTRUCTION_PROMPT)) + return conversation diff --git a/ee/hogai/summarizer/prompts.py b/ee/hogai/summarizer/prompts.py new file mode 100644 index 00000000000..bf2272d9d4c --- /dev/null +++ b/ee/hogai/summarizer/prompts.py @@ -0,0 +1,17 @@ +SUMMARIZER_SYSTEM_PROMPT = """ +Act as an expert product manager. Your task is to summarize query results in a a concise way. +Offer actionable feedback if possible. Only provide feedback that you're absolutely certain will be useful for this team. + +The product being analyzed is described as follows: +{{product_description}}""" + +SUMMARIZER_INSTRUCTION_PROMPT = """ +Here are the {{query_kind}} results for this question: +```json +{{results}} +``` + +Answer my earlier question using the results above. Point out interesting trends or anomalies. +Take into account what you know about my product. If possible, offer actionable feedback, but avoid generic advice. +Limit yourself to a few sentences. The answer needs to be high-impact and relevant for me as a Silicon Valley engineer. +""" diff --git a/ee/hogai/summarizer/test/__init__.py b/ee/hogai/summarizer/test/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ee/hogai/summarizer/test/test_nodes.py b/ee/hogai/summarizer/test/test_nodes.py new file mode 100644 index 00000000000..b0e8cdcd37f --- /dev/null +++ b/ee/hogai/summarizer/test/test_nodes.py @@ -0,0 +1,196 @@ +from unittest.mock import patch + +from django.test import override_settings +from langchain_core.runnables import RunnableLambda +from langchain_core.messages import ( + HumanMessage as LangchainHumanMessage, +) +from ee.hogai.summarizer.nodes import SummarizerNode +from ee.hogai.summarizer.prompts import SUMMARIZER_INSTRUCTION_PROMPT, SUMMARIZER_SYSTEM_PROMPT +from posthog.schema import ( + AssistantMessage, + AssistantTrendsEventsNode, + AssistantTrendsQuery, + FailureMessage, + HumanMessage, + VisualizationMessage, +) +from rest_framework.exceptions import ValidationError +from posthog.test.base import APIBaseTest, ClickhouseTestMixin +from posthog.api.services.query import process_query_dict + + +@override_settings(IN_UNIT_TESTING=True) +class TestSummarizerNode(ClickhouseTestMixin, APIBaseTest): + maxDiff = None + + @patch("ee.hogai.summarizer.nodes.process_query_dict", side_effect=process_query_dict) + def test_node_runs(self, mock_process_query_dict): + node = SummarizerNode(self.team) + with patch.object(SummarizerNode, "_model") as generator_model_mock: + generator_model_mock.return_value = RunnableLambda( + lambda _: LangchainHumanMessage(content="The results indicate foobar.") + ) + new_state = node.run( + { + "messages": [ + HumanMessage(content="Text"), + VisualizationMessage( + answer=AssistantTrendsQuery(series=[AssistantTrendsEventsNode()]), + plan="Plan", + reasoning_steps=["step"], + done=True, + ), + ], + "plan": "Plan", + }, + {}, + ) + mock_process_query_dict.assert_called_once() # Query processing started + self.assertEqual( + new_state, + { + "messages": [ + AssistantMessage(content="The results indicate foobar.", done=True), + ], + }, + ) + + @patch( + "ee.hogai.summarizer.nodes.process_query_dict", + side_effect=ValueError("You have not glibbled the glorp before running this."), + ) + def test_node_handles_internal_error(self, mock_process_query_dict): + node = SummarizerNode(self.team) + with patch.object(SummarizerNode, "_model") as generator_model_mock: + generator_model_mock.return_value = RunnableLambda( + lambda _: LangchainHumanMessage(content="The results indicate foobar.") + ) + new_state = node.run( + { + "messages": [ + HumanMessage(content="Text"), + VisualizationMessage( + answer=AssistantTrendsQuery(series=[AssistantTrendsEventsNode()]), + plan="Plan", + reasoning_steps=["step"], + done=True, + ), + ], + "plan": "Plan", + }, + {}, + ) + mock_process_query_dict.assert_called_once() # Query processing started + self.assertEqual( + new_state, + { + "messages": [ + FailureMessage(content="There was an unknown error running this query."), + ], + }, + ) + + @patch( + "ee.hogai.summarizer.nodes.process_query_dict", + side_effect=ValidationError( + "This query exceeds the capabilities of our picolator. Try de-brolling its flim-flam." + ), + ) + def test_node_handles_exposed_error(self, mock_process_query_dict): + node = SummarizerNode(self.team) + with patch.object(SummarizerNode, "_model") as generator_model_mock: + generator_model_mock.return_value = RunnableLambda( + lambda _: LangchainHumanMessage(content="The results indicate foobar.") + ) + new_state = node.run( + { + "messages": [ + HumanMessage(content="Text"), + VisualizationMessage( + answer=AssistantTrendsQuery(series=[AssistantTrendsEventsNode()]), + plan="Plan", + reasoning_steps=["step"], + done=True, + ), + ], + "plan": "Plan", + }, + {}, + ) + mock_process_query_dict.assert_called_once() # Query processing started + self.assertEqual( + new_state, + { + "messages": [ + FailureMessage( + content=( + "There was an error running this query: This query exceeds the capabilities of our picolator. " + "Try de-brolling its flim-flam." + ) + ), + ], + }, + ) + + def test_node_requires_a_viz_message_in_state(self): + node = SummarizerNode(self.team) + + with self.assertRaisesMessage( + ValueError, "Can only run summarization with a visualization message as the last one in the state" + ): + node.run( + { + "messages": [ + HumanMessage(content="Text"), + ], + "plan": "Plan", + }, + {}, + ) + + def test_node_requires_viz_message_in_state_to_have_query(self): + node = SummarizerNode(self.team) + + with self.assertRaisesMessage(ValueError, "Did not found query in the visualization message"): + node.run( + { + "messages": [ + VisualizationMessage( + answer=None, + plan="Plan", + reasoning_steps=["step"], + done=True, + ), + ], + "plan": "Plan", + }, + {}, + ) + + def test_agent_reconstructs_conversation(self): + self.project.product_description = "Dating app for lonely hedgehogs." + self.project.save() + node = SummarizerNode(self.team) + + history = node._construct_messages( + { + "messages": [ + HumanMessage(content="What's the trends in signups?"), + VisualizationMessage( + answer=AssistantTrendsQuery(series=[AssistantTrendsEventsNode()]), + plan="Plan", + reasoning_steps=["step"], + done=True, + ), + ] + } + ) + self.assertEqual( + history, + [ + ("system", SUMMARIZER_SYSTEM_PROMPT), + ("human", "What's the trends in signups?"), + ("human", SUMMARIZER_INSTRUCTION_PROMPT), + ], + ) diff --git a/ee/hogai/trends/test/test_nodes.py b/ee/hogai/trends/test/test_nodes.py index 334d321f5ae..03c2ac85ea7 100644 --- a/ee/hogai/trends/test/test_nodes.py +++ b/ee/hogai/trends/test/test_nodes.py @@ -14,6 +14,8 @@ from posthog.test.base import APIBaseTest, ClickhouseTestMixin @override_settings(IN_UNIT_TESTING=True) class TestTrendsGeneratorNode(ClickhouseTestMixin, APIBaseTest): + maxDiff = None + def setUp(self): self.schema = AssistantTrendsQuery(series=[]) @@ -33,7 +35,9 @@ class TestTrendsGeneratorNode(ClickhouseTestMixin, APIBaseTest): self.assertEqual( new_state, { - "messages": [VisualizationMessage(answer=self.schema, plan="Plan", reasoning_steps=["step"])], + "messages": [ + VisualizationMessage(answer=self.schema, plan="Plan", reasoning_steps=["step"], done=True) + ], "intermediate_steps": None, }, ) diff --git a/ee/hogai/utils.py b/ee/hogai/utils.py index 74e12ee2d75..60fa74fc230 100644 --- a/ee/hogai/utils.py +++ b/ee/hogai/utils.py @@ -50,6 +50,7 @@ class AssistantNodeName(StrEnum): FUNNEL_PLANNER_TOOLS = "funnel_planner_tools" FUNNEL_GENERATOR = "funnel_generator" FUNNEL_GENERATOR_TOOLS = "funnel_generator_tools" + SUMMARIZER = "summarizer" class AssistantNode(ABC): diff --git a/frontend/__snapshots__/scenes-app-max-ai--empty-thread-loading--dark.png b/frontend/__snapshots__/scenes-app-max-ai--empty-thread-loading--dark.png index eedf3e01916a0813e55301444130f3eacaceb829..8c043460ab552ad771655d67b65d3dbcc75af4c8 100644 GIT binary patch literal 11018 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 ) } -const Message = React.forwardRef< +const MessageTemplate = React.forwardRef< HTMLDivElement, - React.PropsWithChildren<{ type: 'human' | 'ai'; className?: string; action?: React.ReactNode }> ->(function Message({ type, children, className, action }, ref): JSX.Element { + { type: 'human' | 'ai'; className?: string; action?: React.ReactNode; children: React.ReactNode } +>(function MessageTemplate({ type, children, className, action }, ref) { if (type === AssistantMessageType.Human) { return (
@@ -105,7 +86,7 @@ const Message = React.forwardRef< } return ( -
+
{children}
@@ -114,14 +95,41 @@ const Message = React.forwardRef< ) }) -function Answer({ +const TextAnswer = React.forwardRef< + HTMLDivElement, + { message: (AssistantMessage | FailureMessage) & ThreadMessage; index: number } +>(function TextAnswer({ message, index }, ref) { + const { thread } = useValues(maxLogic) + + return ( + + ) : message.type === 'ai' && + message.status === 'completed' && + (thread[index + 1] === undefined || thread[index + 1].type === 'human') ? ( + // Show answer actions if the assistant's response is complete at this point + + ) : null + } + > + + {message.content || '*Max has failed to generate an answer. Please try again.*'} + + + ) +}) + +function VisualizationAnswer({ message, status, - previousMessage, }: { message: VisualizationMessage status?: MessageStatus - previousMessage: ThreadMessage }): JSX.Element { const query = useMemo(() => { if (message.answer) { @@ -138,7 +146,7 @@ function Answer({ return ( <> {message.reasoning_steps && ( - {step} ))} - + )} {status === 'completed' && query && ( <> - +
@@ -178,36 +186,55 @@ function Answer({
- - {isHumanMessage(previousMessage) && ( - - )} + )} ) } -function AnswerActions({ - message, - previousMessage, -}: { - message: VisualizationMessage - previousMessage: HumanMessage -}): JSX.Element { +function RetriableAnswerActions(): JSX.Element { + const { retryLastMessage } = useActions(maxLogic) + + return ( + } + type="secondary" + size="small" + tooltip="Try again" + onClick={() => retryLastMessage()} + > + Try again + + ) +} + +function SuccessfulAnswerActions({ messageIndex }: { messageIndex: number }): JSX.Element { + const { thread } = useValues(maxLogic) + const { retryLastMessage } = useActions(maxLogic) + const [rating, setRating] = useState<'good' | 'bad' | null>(null) const [feedback, setFeedback] = useState('') const [feedbackInputStatus, setFeedbackInputStatus] = useState<'hidden' | 'pending' | 'submitted'>('hidden') const hasScrolledFeedbackInputIntoView = useRef(false) + const [relevantHumanMessage, relevantVisualizationMessage] = useMemo(() => { + // We need to find the relevant visualization message (which might be a message earlier if the most recent one + // is a results summary message), and the human message that triggered it. + const relevantMessages = thread.slice(0, messageIndex + 1).reverse() + const visualizationMessage = relevantMessages.find(isVisualizationMessage) as VisualizationMessage + const humanMessage = relevantMessages.find(isHumanMessage) as HumanMessage + return [humanMessage, visualizationMessage] + }, [thread, messageIndex]) + function submitRating(newRating: 'good' | 'bad'): void { if (rating) { return // Already rated } setRating(newRating) posthog.capture('chat rating', { - question: previousMessage.content, - answer: JSON.stringify(message.answer), + question: relevantHumanMessage.content, + answer: JSON.stringify(relevantVisualizationMessage.answer), answer_rating: rating, }) if (newRating === 'bad') { @@ -220,8 +247,8 @@ function AnswerActions({ return // Input is empty } posthog.capture('chat feedback', { - question: previousMessage.content, - answer: JSON.stringify(message.answer), + question: relevantHumanMessage.content, + answer: JSON.stringify(relevantVisualizationMessage.answer), feedback, }) setFeedbackInputStatus('submitted') @@ -248,9 +275,18 @@ function AnswerActions({ onClick={() => submitRating('bad')} /> )} + {messageIndex === thread.length - 1 && ( + } + type="tertiary" + size="small" + tooltip="Try again" + onClick={() => retryLastMessage()} + /> + )}
{feedbackInputStatus !== 'hidden' && ( - { if (el && !hasScrolledFeedbackInputIntoView.current) { @@ -292,7 +328,7 @@ function AnswerActions({

W3`3#=QAI#c9R2K_PAOEtN`NmDaWo4I=IA#N1t+;#<9< z>8Yi|f$6g{g{4k(%f!R47A0)Fy!`lQtLw|ysdqgj@uR!(qmOQK_4oIOEWa;yI&r9y zd1GT^j!<05tna(R!Wd?rdf)L~Fj6lr;ru`M<^NEBWgGfrbV}eZww~C&aY_3;RLTI< zw=%jp3e{TY`0FWOBZ$isI^ZpgAk0hC-N*e`#;|gqJ)x$irr`#j3OOEVMM1#{w6LI3 zLyHrLo25z*Y`q*amSEo}K>QOA5j#!ASpsX|gCh_K&_V`X_AjGu5lR|H4ZyKndKnpaqtGPujy%zQsG66_% z&uuRP7qgN%cH}K70HLGzO!(j_G`KLW!rHRaF}=fAR%GtS?^%0}6AET32^?H>qjpkT zJ0>NC=`@A~L}20KjskMw{(}<3;$gc8SU7jMRsIRnDZR|a`2Bi+YOnoO5?5J`ETpa$ds)Vecy(#GnR~_VN zAyk}K?}_O&q5lK!BQ4yAI zSUNm?90#Uv^F5TZ?H~q3d`ok4KTFFJ;fv`VAFsy2>@w`$1u4Y|Ym1^ZjP9D7*VG0V zi(DZc)q2jbgLpX~MB@Shtf!8;jfstu%5epF3e7!M7up)jF4?Tfr_xJeL>3^&3v~cl zXr^fdS^K3wCDl80V#JeyBPBHAIo;Qpxfw|VUVxjX%D zpR)Y?fZq0t;FX0xBS>K%g`8oVj9YN3Fy9kFXLzQUu+!K<8!*8asV^DSkj@man*d>; z1%iQ^udk=wT+_(MkZ>0r*3;djuAd639uv0lEJ827x$9=HtmoPpr~`yB(iEs5knfX8jLSL(d9fJ?PY_#1Z6JlBnL9l0?g1G)29 znoC^NJ6Fg8d;P37-NS0@X#Et2(V5)`x7}Z8e*ytqJvXjn6otq}P36mR{|gP^4LpF- z&Ha%(lr2-n&+R0&gbzJq0yJmNCwgR66Rn+Q+Zg@VO)NXvv3kgUf`sCkw>>xrA znxcn*sN0p5q=1FnKT#7a>oEdbS y{_POKJgEB7#o#9ZPJxJV0V&{QcDhLE} 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 literal 11160 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 diff --git a/frontend/__snapshots__/scenes-app-max-ai--generation-failure-thread--dark.png b/frontend/__snapshots__/scenes-app-max-ai--generation-failure-thread--dark.png index 84a2a7828cdd505539313bc2566214e0560aed93..69db9b395eca7e1753006333ab17af3432eba4db 100644 GIT binary patch delta 24828 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 adxsO07F}-7%XREOKu`OoR?#)bsQ&=gRfIeM delta 24723 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 diff --git a/frontend/__snapshots__/scenes-app-max-ai--generation-failure-thread--light.png b/frontend/__snapshots__/scenes-app-max-ai--generation-failure-thread--light.png index 43ad8593f41e85fd16ecfb526dca2e5c9fb15853..4a9c5c33c2c4b0d97e2f248f00d4f00d481a1c6d 100644 GIT binary patch delta 23692 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 B$Fu+d delta 23647 zcmb@u1yq$=yFa>=t$-j(2#SCblF}uuAR^se(hbthYk-u9h{PfVq(ziQN*W}k8>Ks? z>pr;m_nou%|NEai?iqKDJ;nxE>#aHG^ZaVA%I>pa-Dh8uTzHFh7KK7h3tyf2O!-q5 zNj9`OgPm8Rvy=K!)>KbTbC>sgL!Y3F#3qRvG~g=wG3QLDT7iA4LH_A)8S1^R$T z`0snQJ;WEjQT=$PL4-wbJSLJB?`q58$boJC_OLS1YekmUtlhocvHc}qoAJYk4<9=^ za`N)7j#r(mjFv@6rS3PD)YOQk9nN>BmpLPg54xR^X&U3u4;Vc);TXmDHO(@i!u z-f7V)GxXRWV6Kq%VRQGkGgVr6ntEFs8O=d;&HHrm4$mXG+gU z@JR-Q$7*c(Wpq+L=>An=KS@AHXc4o$xryLhyjWOVY-etsk)54iR8;A;m)GD$Fmy}a zXXTZsd*6Yi>R}x<9r}BrmAa$jW^*_lFBexQ*HPmQBsw-$#C^k;`E_FAc&VdVM1_-p z|5`$&FBQpxu)(iVCt*)46Pd&2d;Z8P?AbFR)ETTAs7Zq#mk!TgeKKAjOfooIb#jc9 zMeEWKG%pS2n{_1UDk`oo7mwQx=1o^W$E>cdW~|@;HD4|PZH0w}$HvA|BtnUm z(<>?}JXEKrr{NeQ+PCt(N%S97AkX=Co>l9RetYcfZ1QoK#!11vCo3zx>IVA)cerdQEJ#xX$Ml`%UD+@+8(8lm^cm4C{&%Tx6Dbue=1dwhGs&KLB z^IECu#%hHV^YiGiFm|iH4=-Q7^!4@q_3Kx8dHMdn2U?~tSHJ4b8v+Mm?7BF9w{Zf; z`&KD83xVT73eH$rtOqWljASO=Jj+a47 zZ;F>WRNi0*e}j5-*oSBD=jPQ@9&?Tnb9kE`(9t4>NtzEGoE`ZHQke` zY-MSgCL24muwZFvxv;pHt@PscHTJS_0r9&Zb-Z0^8CSetguFbS{Ya>F?wx8sSCMFj zthqX~OoPSO6ZKi)dL%HrZF4KX|Lp{vaVBn3$UCNfPr9qn5B8 zDv&hVgK77rq=buyCr|sWl*z&Na(#h`o!!Ydrd(rFQx4YHn3xG{&=n9QU-c?yb_A^L{Y5z@VxPGaE9~EE^Q{B)Jrs( zn3FIO`Un1#n??S=XShI>a6-_N! zK~Y>do#RZa0f_~5xoGx7$`IW zI(`d}4f~f10#(_+ZepL#W?1`la&eDVoU1D?OE(RCHezC88uwfkni-??zjQ;d$oiV& z{M!dgNanBFOCq?qxH9tcRX#@^j~}l^GHdfY&E1TU!Z>?Y?SlqoRExBWqo{773sl~%-}`(rFPi> z+Z0+_9u`8vaPeT`y@P{9e&?)$f?xhOdPVT7@bAV4osqj*s>cDOzP*)pHD;5 z(jwo!rJdSoMFr!lV{}tDPF%`L_`b3kxeNJ0Q{b z`nj?qr}#D{#pvF>>aE58#+TQ`+S40c>Jy25H$Fs#XEpfZ#7FrW&W)DspgGOXVqoCl z;2_6)v+v%$gZ|5Dhd?2%Z)l*Ur6ndIu^aueRpW=VaDqGUg7;I%8^1lH98KiTHSe{3 znbY!1{D8B7P0&kBR04O!$%Si|1b^+`9Qi{Uvp-iK*%@^$b6sT#ZzdxrpPZO*vwKz_ zIXlKInW9R~(Di^|gG64PRHKmv_2RbTBT~9Az zU-uoh2^P7Ee84xCEj_j?2|}JObpiNLNmy7|MuuxIziAM#^o@PQ&Z~co?a|jbK1biK zH{s#6NWt{{y!%uW{@6!slNaS>Qleb#e{B75XQIQEP*&~+(4gnNrHYo>Zn$pu{{8y^ zbWkjhO^l#>9v=ECRxd4A^UlhsfYV%Od%Qr|moIs|O_aZM>D8f7z_V>{Z|6W; z|C;;0WaFcfMd03pBa0z=k?|t-^wS-hcX_$UZ$Q91?qy_a>oeO;Xo3IOa&!0)ZtN!{EVd;cl;PvS8C)DY` z!|VBzb8LV9boGzhPtN@Q@$1b;XK?@g$Ma{PzWsi&VQHW+e*g639$el#6BTuJm;u5e z6&EgCxPAL}3_j`azbe4n3ZkR*efXG}mj{>XYlg0#{`+0Q+fR@)S}y|wn>mMZe!sK8 z?;P9R7J7R6xt>hI&APEMVP@twcrXnO4ULWIA3nTf2uGvmfBbl4WpywUYp157@_5H^ zX{^E%>Oai&a5{Nm*A=pzobGh_(5vh<@Uh|HgT5SXBJt*F2NDvJpk%nLNEY31+9JQt z_X&Z!Hg~^x@uI!GJv%!);BIGU=ciAfLKpPfecbT!+U9IW$G2~J`T00lSPFwyv+eQU zzkkQa$9H#kUoGEkhsIU13a0@e$ji-LSXt?_wa`l>E*p1e{b02!oql0sx&?|A=_2Oo z`Pd#e?Bk){T>*%30S9MsxR@0YSA^SJtvV5QtjgZs-$#x&6X8aNi)>OXV#o=EAqc$h zZ6qpMQ|WymBO^1@9)F#HpvF5pGcz!mK2znJEj!14Vr_V_==xu$CH{))2oOyw0T7>` z@2H_M0A&b|?9Ny3{=YYJix1&tjI^g`Lf~Ylr=s@r^P`}kfaecrMW*KBA7;)vVTv0 z+{h`#HVp4Z)H~h=hv1_8xBIUqSh-|*d3a)?quE&V^YUg|(THTr;93W^G zosv(<$)dF3d%L@TU}7!`(4UUSlRk{7yU*`=e*AOwx(z+X=DK=E=j_GPKcZ0o*ERX) zpK;H^$ozi&wanW{Nl97sD?h9vzmFbs?sQ3aF70nE8a2H9?n-p}-nM6_Yf&TLw5{BI zb0F&6xpTzC!~!l$kBZ3z-8!qQ@6GO`FT|3ky~u*q&JXuTmBXcvVCPYX=s_JtgP(g$De|OVK$QqdHe!&q0Q1ddv1 zm&U7*A77t7KYtMxi3jPHNb&QU>sLK}jK)lwjPv^SJeM~+MCg{VP-_!4rzPj*HO?7W zBTLdVe6G@Ra(I<@pQkS{c+16$AU;6B?%)4IT=C4AGuL@-1t0&o8(f?mYqt6Quv7~r zs9r62ixsIlbkNcw-7Ggb@LV0M0CXgA|2_>JopfqfWL8lx%w$-=QLHc~2DLBbMUJ?H zh4seq&!7qfjl3~Yol+$wC8sMC5X;GKqX>P_xAt}l9%~IbxmQY=TpS#R#I=k4x&5xu zsG(Bt0~cTxP~2C>Dy)o+rxq8jtgR6*Sfv1*=LERS+hC0)JSYT!$0h6O=_yU~CSCC) zxP53S#@*1)4mmkK@;=zM&$T{_GACcV2xIf<)2FL!k5C5@t8fWt&z_|a@zGIG`1*k= zC@2Uz1bqi~e zlcQZcunc9e_Ql2g&!4XexL8X`UC39QjwMWzb_ZDV;?fOU8=K{yKkb)?xVO&wdiYKd zbvGXDtR5U3>@4!g&BkeJy^M2;;iEUuB0x0SyP3X0({xj^_>ODhIo zJX~gIsJy1;H9N%bh0^4TLunlP5llMW z^H|g5LDAY}qQ#+-rt5 zHUPY*fZ*77GabJpwt)FRLIHD(6e{Cdna5UEZmwPbM_tela`h@0O`(sGn4a;PYzX=G z?b~PIM`U~)0s^s`mv$C+4BLN!NL-o7&m{oKFI+g{Pjb)KTky$*eV+9XUSy z@Zq+AK-rTgC}cZlU|^uaa|a4zUw=OwKW6YMIe7&f6|l|h)D#FEkH*T~(P%VP8H@<| zl`B^$C=#Ngip{?#1EUIRfBh)VaQ~rV&qRGNU~3?GP!EA0sO4zY4+nuXLzn2~aD2FT zOFHtl?iVg@?ufyU3iPi42u(GG$;Ki)Vb^;HURPCB`T3nI%b=dRPu~lDK>ec*11qap zq>xhPTk>ZwU*gKk%g?ZU`$v;5uchRAOX`|<$9`gG9O=-hyL#>v0Cz>qw*7E-%>6{b!_A}eSts)N%0j#viAn|MJ@tvKApj>v5L z+}vD1Kmh10u4C?IgLx)~&-yhjEHXiB;$%95a-$H+a({wJasEJoM#}sQTq)N{tiQj% z0{h3w#!vt`&(h{WW2rpeU*wWKB``-jF!XJ~ys{6&*))rV}(_238eJ9ZP%wue=twEDW*I_Ypy>#i)&icB6t3k2; z7pLZ~t~X`zgS@~^m`|72+n)qk{=9Nw-tR5;f7bf<_V%`J#>J5d2ndY1C@U!qFawr} z<+30+P_wXL$d4bPw-b}Oh#am60rRLMJ&kMUlG z5sDQIZxdlCIrsYWhjW!u+P=Q#FMVI1u|2cF^~l20Dd0vFF`0=eveVO};?e>?^ATBo zgl7zJV#Eh>e| zEzJA)U=^tf9;_c6+ynd%M`>$sH(ha^o|vdPG~0!h3Z_J@7D|=B~(Zs|AX1|=AoHcrVvN0PetHav_`Bg z)HbHt(>IrGPQx*!Lzd@*RFwd z<@2-V+?JKMv%sx|$9R+-2z$3Gy?=RI1n^@uwJ)Wm_O1rDvi)(*DbKDwgGnEh3_ZK? z02$>*eGSF~_;ad1o`CurJqyqCa()X_ZaD|E&$zg_rKP2K0aqm=Zm-?7p`oE*5>{d& zB53?1bAFX>3kd0uD93)8*o|l$AMchPc$#5p{T^`uh5!uMKM^ZQhP_!os{oaH_xzCMsLT5*Aq{BqRXW zXJKT_%Fe#d_UK7jnI}kBqDj$g24^WRk=naj%&h1b(kAg!Q>Oq_;jHSy#lthrd+(s= z#EE~_GhtQheXpX-T#D^vSF55LdfE3usa@cBu=L?m*1FMAq@uD?n3s14sy7G)aGS*W zQB7+F{Qj?JtD=eB9qD_>9H}P8N@GeZsQBDiI5{~@?T0J9Jzb1+b;1Oben|*c;N`h4EZqgK!s(~zq1C-(=ZW9Pffi@%Jr}U zH%ZY!Y#cc`syaDZ4Y|&nS5-+p<@?$)D4C3m3>4yzx@E9NB@}z0p>l9?4&Fco-}|VK z%br*&j(2%+?t2P6K0qf+#HmWnUQddkvQ0;*4~+ZqaC6r;HiAJRFFLO(@>_s2#GdsK!@!{u0IQwAgY_3z?E#4E>BMkfXpja5&XU%4+ztk;F_I0q%A}FqQu>m<->(ovzXeTS5DYIzX!fQLQTg<~0Go zLksSriqb-%1nq$C{s8^kWuh+d&6_t&ma49W$01 zsPdOCT=?R#WvQg3Yb!)rT2-%|!igi}|*ZS4mP0w|)@+Ac?vlL}AJRg8?yDSaBOxPLoTO-PcX*& z408R!-d-R&g5+A3Qcr`UU3&?(RTi1W`p+Bhkhe-bbHL)F@UkoQZyJmrT zSXI?YrgAzkd1UveKU5?uT)os#umpg@0L%u+vOgIrLPbpt{q5QF=eb#VMpPE|6t6S>!t}ne0bT}v0?ClyMW3LfEta0T0NVHR9g0Cu^Tnu-Vi>73pz!@ zs@u9n)@T(*-7*&&adE%r&&6b9TI&J{Rli~NQWK>|3&)_*-UrLY(A(j}6kO&Cckh0E zgWQttDKoXSBn8ZA-24V+#`Z!l6D{q7IULob2lZS905gG3w#INTf=9zzb;v*sjW?@(ipmXD6rk7BQZMNe`y>xfgmeyFo8e|Df@6W~RttS}Ms9hIwnFg_Z8s zEx#8pIIcVp7Y8oemMD_w-an3vCu-V(l4!TP_ES<)vUU0`DV^RXhVp9OKAjJ{|C6hX zIRV#b$zS1xjoPg%jsZ@{Qq6|p@!VNC+M7+}B-EI+o*I=lsu8Ey^_}8OAB1;+=i;<9 z5avoU`idH$g6O6`%@`R$49XpHV1MtD2qcUwnV#M+E>H%oAwY9k}4SY7J zJ#S<*2@Vc$xwwOiY}sIUfqn#7!29HA2h9wAjLA4aqNDZ38@W2AH5D}1Q9r~f-BmX4 zjTW(L zZjN>#$7BR2v$;R(ona{gVc_QBaj;`Gy9pB$rlpvuDDY0Zk&;vO!=j7E8}l4+_G(Zu zQCu+D=etsaD^qSF`0m9nZb`E7{JlLrTr4c@C_4qR|3lKOJ=oL*(o}n^^HC=VA0SR# zC4#wq9?$i+mI=TAZ#BzP{Rv*b1rp}lAU4+2fXNuYGy3e=Ssa|;bn@DKi`3N1$;`hc z$?)9`c`=Zjva_>yH>OtRF7E;E!~})Qyz^aJ8m-OFtxuo-Ztg zR{;SJ<>VrzQkgY4i}gG5hKQ|q_!3h)+}&~#^j?ja@y*H4U+%j=%ZDltIMp#Fp#g#E zbSl{Z>brjZ`W87}0WMH7Z*E;EeBDrqi{s;UgVm4U?x%j%5}F~zMWnJ5EpjTKqfqh~ zpb;@MaB_AJ47fopCkUirVv^1n0H-`YE)MkerHKg#@RD2(pe!979UW{fg7wD>tpjY~ z8IjM!|DE116pBkoT%r&h03Y|;TLv(!m$v_@$xg(+Zka})Z4!xtlLzGR?QkEsmtdfv zXThR@#%$u`#I?!6$Y=?NXx)sCjs^{8a9{xV8xO4I!Hf;vr=45QKnj7_7K1;swpQY@ z98<*io_^u$Qw&H=C*cT#%QR zb_7Y~^Jie)3`|T$i-SO>!I=R*3BAB;WrS}lvqnJLeYQMWg|pggt5+T1q}buG($56F$5X0CJkg_L4i0X2p~T?3`1(>ysmAMa6CxL`73e4?E)U zJ**+Si5u5RpJ661vqtJlLsmKwOUz%r@uF_{vcU?z!>t)M^=szq_5@h*KH}Tz!!xMA zEOzx=Jpk#jTC+jy0j*1X1-TW~0@`v2U^h2+cl?jfAd_)06)xYNC{hLWI8{38RAL?` zVb#;o(0~z$j)*WZH7&C2Wi%}lO}Yck6KWNF_`OmuaC&G%Bv-CP#K#N4f(Rs}1LDSE z2lm?E)bWYf=syX&ykgHZ(h@~YOX2Gq9=EqdA0Y)G0A0+%!67Ilgzhi^ zx;{|u?kFeM4lLmmwnu)a=jZ1Kf+r{_$jWL5dJ=dmy*&Q^7v&>w^*<;d?4L8!#pw~W z@0y0;1o&aJ!-m$@xA}@i!|PgFvWtp%=;-|28KPRq$;gh^Ly@_-i=w%zI>*p;j{0DT z&*2bf5Sg2s2LN*l43w0W&B@Nj0jgL8b~-0q98`B!*422|F-_=-9@FLdZ(ZAiCAkS( zJ48+nyX8gr`1vc3wuh0z!opSu50H^$&LmB3(!PFtS&>LpTf5A(EoN=)vFVH3dgaj- zkr8Zlz7ntMb{%R-@#Cp~wJ=d2f!0@O%xxz#KYt>WDlZoyRRakGLH7+B z*=}%<;b*UnsX!?-sA}lgSWpZ;X+vA%fg(P$2Tu~JA9|LLj}M^u5(@}l3(VlXfyNS^ zBb%wxP+zaAqQX{2L`=*vET1SmnxoB|6Z5EO&Bbw~#6B=EkV_Vz5j5hV;bDmKAP`{E z)YjIo^g?4xvP9)i*Vfj0dwKONmOIVANlm@wDv*B~YSN}<{9^I*JzJ zpMS-6L3D6(!bWcLl`nNv(&zI@gdY?hB8(UDJ!G3Ac5CC7-xb+!m_GN~ztXKQ%I-Es zPjJiQ1oZ-w!o%z8qURaBwYV>C>r@AaAa#-CO9NptGNN|WZU+HS7_d7)2oMC7S(|lu z8cwrBxm19RWWmgDYh#AC+R>4ln`;(4I6R!)uMD46Rju!%4SN`kuntDA@}4?H)=|Gx zPG7i_+W%*E50CpVZD9|(4ClC>r3wh`aKMUO23|!*H%ARMH5agifq;=-KXG;deUwW! zducdTnuL{=71BwN0P8A4{+Zh5G%&eM>6=vhOjUsuAXBb zoV5A4C-J#~)K~5kRp?pK+~(4*Z8kg8INXhSbz`BS1hRjX(Z4GN!8$C+?wSDzwCJeN z8zPY{)8#miR%Y$C?S|*be8{X9}WDC65h2^yNUyq(0fTHW%;%^a^U) zaV~O{tzU)sP)(Y3)mKaxhJ_92FJhUbh%3pO%lXg0=Mcl9v>zv^B8h6p6t;sYY(aJ> zN%5vx=w+|XP(z1{qI4QL8_mO3HgtUM@3d*;YEB;#^TsL;>MQ4yaS*O?u(9nO92Pp0 zYMa8SdlB+BigW*VCK3ZBqAdRMo>h6ga;&NOiWCiLS1ktS|XWa*$hN= zb>kZzEH5wXyH8))o;85w4>caBJU%09C3ej$GbScxs#2*{KZ~i2i0w#8YpcvQ=GVV8 z0#-Tn0l~%p(g^zfK_ht1^f!$FG4rkY(Uz2xlLK%AG_24n_LEzpCi;G&_In$UZJGs- z1?nN2Yufj#2~t{3%~KacZ*jR=8bbNf9EgzWEc9QHZBBM$OwBVoa=x4HUmIz78J6+V19soz&;{&Do;<#hhjCyqELn4(Y} zR{^^nj*N`R#obXu{cNvDJdZi z5YPh3mZS0cS*dyVKXW||4M`JJm*uSO>%_&}Tb@#6=xb`e|R3->^~8b}*bg@Ie9 zuCAV4ZUUax%F1y)i9Y1rl!>P2<}?%(9>Yg~C$drI=#+A>vAv#u1a>kgKmZ`oIC#s; z$nx`N&pv|d@b)bc1;xj)c<{&ISAIUe()aJD7IUkFy>>q-G=dQIpYl*2ea^TT7$o`o zOMvXIsQ4Xf3i?tSX|1v(4wRLj_Ba87;k+W{rM+`G#bf*+-<=xmV71H`i)Cw)Qc(CT zBSVFu!uxaW<8{7}>&P?zPK6*R%IR_uk&(wh{(*DPGD}9M-X2wI(+*Vte3rpp-r3m+ zK?4p>V<>XKX8)}8%If}(I7xg-e-@LZB@0}=$yYk%M!yUFZOX)v7g!avvr@ygI{tUu zneh3Kf|gj525JyL9P#6zGpHY$od>zE*T0H|UV^kpK_SpwJfRaMV_>z6-t~*PmIzY}Zw{kxVMms91A2LzRu51M3 z_r1KlKp+R>KVxj}zr}5k)4a{};$jQ)ClC(+e!HxU4EFX$cnV~UjOaj8jJD_fdz!Jn zouxre8HKXk2G<57>>+eDl%~kVzsf_8#D$p%|EK2&$c4y+8p$96cna7(GknGUaZk%Ns~tC zzrcGd_7}1_&`Tk_V-F=Ie^y`OSdDV;#R)>85wM!A|2 zoZomkV*uiMfOuPnspihvKJ)W`DnbL`Y0mQ^-d_oTUF0qfYQJVAysxg#*Bu=Z!EM$a z2OVoc;A5oX@9GJo-u@KWhnR42(PA-))O7Xlzp?o|U*{_!VM26p>D#CU%5-+$zIely}fDe>`$bMG!t=1gQ%aNZH$PSmRzE1WSYHb482&pkjx}G$ zM-oE0Lsak{@O%dNz)$wREpD&lCKBG!(G1xb+&@m)=RAjmhX=p7;-6GFMvC3r`!0!P z6z{{ZgUZgB!AvzYA^E9T0~s5L;DDv2l&Lc7@mfCOd04ClxQ`*27Qt=}DK}@P;3;%I zd$~o9x|tE00E8;Ixh^| zHK$DdXY^4mx~DdJ-ltC*Uz`~7*Z;{X%W^9!ybTQvA)-gZto2^c9V9Q%(X6el8(xve zzIju#Qh#*T|KgKk-3ShuVDPkofdWk&U8Ag-ulYMKUScuvl8tX-w1qGA$zV!7B??NBwsyXLMR!JmNg z=?v?*zJ3~n>DGqT%7c$!%SffZao5z+vNSNLjwKcyb9??WG!$`laY>{9*45JtEjDZY_2tqo4=l3IHnKWv*jC}dI z+r7@O4nB7!I`u#d>#(350@{OqA7-S0F7U@AcW`nt9@~c$2QxEs3X+n7jsoDLoF?;q zZw{tg=f%@j1}y+G*uxO|htGl%QuL?|B&v-2|8=!6JiIP^hvb&{)B2U?@uncmY| zu20lM7zvn)rluz3gtOIhsQzG8(a6{Uqc$TWV{L5>Fee0Db9Bp!_%PNX#R-GfnkXW| z#MIK>&T{kST`%EMw?+I!nWRzG-Mu~Ujb=Ik1p0Z#&0VR|VD~TtK~Nu3d@z3vkZ+)^ zL)it@Q`$sdbjxN0dl!S%4H5JKNMnX?S;VJ0fsQn#K+q|$o>B2_ak~0 zT1L1dl8cb(0Mxy);b7{`6d^U(t@1k`o!&4)KnnY1I_pznFx`F_e7Yo_>`TmMKXHGv z3Mf0)6(e16gaLTGnuN8{>Hn^UdT-b=qyQ zPhDm3KQiO4KiSt_Fo`}3kG=I&CUS)=79TqyBQ$ISXJ_tBK{~p|_V!noDU&{VOv^Zc zaWOEOlAJt1lMx!zAQ$oWEo=pWB^aA#;U}u7uActaa@aM#;Fr{83lWyzqzn>Qh6${{ zcfI_3(@O+0itSGQN9LG5J9YMY$>nhQBI6w4iTKy+_`)_uuIh%rka!PyncJ2t{DuvtJ`qNX0T;_)S zi_w*m>R(9C=P zmq7xAqGDoVW*S?ylOPu=B_##HbEq1COTbvCq!BgP`UbH-RaY%IB;xD5dvGT7)KBNJ9{f-{4GH66!G@i<=vdHYx7Os`^`L$oaTAP}pxvkWI zkHMY|4-XGuj6k+!Xc34<>EF9|hO!u<_ptogPYtU6D&%C`=ODx#HqKlM^9*Fo{A=UK zlJux8ZI4p%O#;o(-RRzNCB_KAYB`yiXb2^PECI6)Xm01qRLw#JXJTk+;+y&t8;T^k zTQoEPoe9E2^FF}bp`0(T5sYoP5r+1t;9hO_$0w>%JA z32qplG(B6*D2u&T^qk5@Lr4%WDoyYp+u830J!E1-}W1 zu|XCaZXC9n7*q*d`Ig>!d99Bc5k`v|WHg;xp?^A|0q(YjhG6tiN3{T{DX{1+_!hf+ z)9-vR8?)xnj54)Nql(cB>~ktz?T6PMi=rT-kz2lT!L#il6gDrfLwLS1-G7#v%kGh# z3%I}+-l;IULSD>v}II23m1tE zv^MbkqrEKOFGpLpvL)R$H=hHw4P5|Oe7K_{lniZOdkKJL0c^?w`?dtOj5RbsBCiCx16+5d`(_$| z2N>J|10ZAP@!h z%gO22n_JS*{fD6GM@L^>*|CP~pzUx`PH?a^boRow*rq=xqu&cLBjNf^%hO7&@CYd!4Daa;hN*+Y3AaX#HN zusv*tj*E_o0o}HXYZT%Q?4`H3z|g*uslrHm`b2LxL;u@^~p=HBXRHEQ&58&V%5)}1nCwoUE|*W@%G#c9H{iDtG@qE|0^ENh`}LI z=TCRNA*knU&I>BA)dB(~prg+T5TE|-=rryB^=80{W8b?7*g^JV-wa?q$+?yPUEsIY z)KZ*jWljJK4*kUJsoF@IjLH71vv(6eA*l1uA5;lG+?z#yk)NiQzvjR5dK~6s@~JWf z)k$~zN%cF1vR2#M!pW=jrx%vs*N~hWp*wb(5#IMb$99!#$S3QK<>r(~^*-Jo@P;4r z9uD?7T_w~uyyD|eQFGz{%1)bgjrU7tKCtLVNYR(V3l=}DK8Cj=C@tKak{qwcpFi(f zr4|@wI0VYm-aghb8+w1Dv znzGVEq*oqT7J9<0>1PpgSw)7jkNe6?H_KcXdt2ACvTw+Fc`I=;xl;(HzGB-$Oxx~B zTdbcUh{0x!n=Pfj^C4jjb&E`fY;VZCQIQ4Iu<~;QQ;WoR;c%NLLT6EK2~bXN%C%ig zi9LAxyq3YjQ))<$Z;mkK`e&84i#FMOUb|Sb-6PDPph?PinEO0ISgS_X2i9-I>WAt* z7Re}lBvI#e?3uLLrzMoS*Lgv(BUq2cJ0wQRCqed0!t^^8HMR4Y{=P44caQz4A)8r@ zi+2r$;(%eeA2ySl#;liOlg`0vA)r4r!EJGDX|o8HSVwd7wC&zZlPfuYbm7C-;4d>P zg^meLzAA_*FGSR?z9YeZuxwF+oCwQy>)FW^6c*kh65BX~!a9BYG7bXb4y!L6n#_pA zC9_VLGLKos6~9$$-`Z(^xDp3jW&8CL*Lst32cx)Tp>Wsr?<6ioW*w+5_IXdSd8v#G zW6V~b+_RWx4oZelwCBzOa_mK+Z2CPpl_@e;DHDx&jt+H*n3cVgT)bL5RCoh4!-y7hzcl|M2E#zU@U^ty$Hw?+#FXmgIgi)zF54ZF3izzueU|P|B917Ie%X#Y zIL7oXZS=gzX&|*UelmSE%3jFxSNw#~R>M~8!ogWo0qp6(Fi-ZPI$Gs72^Ie(eZ&y- zW+WhDBp{VOXyuN=Ug+L~lZ$C@nAfcGdG3LZjxLF=uun>&yk^#wCXYb8_wIJib4&s%Djv*pALT^69gg-36Mgmv zN%YAcjaizT?;4&wT~-|Sd5feg(DPVh^_B#SCOtf6*lWR9r=+}rjcm2oI(khcVGxNQ zZCJ_8HC(oh6J;itFk4qE6FCm5hypUvFR~qObqzw(?t?Qw$*TAPFgX<#S2MVOV8fwvWU^>uHdEQs-`BGSYU9>N; z{mxePq5JW%739FU`#zb;w?^rcy&NI)*-+U4=6B5JtYu@vY@oJA5M#=3_QF*vxK&Ko zX7oj<@bT_sXtdx5tt+p?>>p%51+N2k`nL$2;N^D^y^Sw<2cD!fz_i> z5j^Ubco404^kEfRlu93=PP0& zwl=|{j&R#P(4R?wjE;`NyWi2lX3Pi-GoR;lLtbc{4Av%f*^CO%sAz>025c@ZK8gWHQI-d=9$Dmy_ zgRnSbU7RF+&_rdAn*+5Bv*^d3>#EhB?LR~GjT%8IO7DtnDwRkWU}v{a^!YN_?Rco4 z-W?Rg99w)L;@J1K1pf6u`f-%cJE|DF;@NU5h9iv#ltlypDrs9n5964=5uW5 z*C+Q`tvIc|AfrvMg^7)vg%Pkw??U#b``>hRNuN}x=<9b_+X3jDYj~Y19SQp`Hsf8* z@MAs|7jMS>V4uI3C>ahco0j8-Oev%kK;aW<==B@r7#a-Jyc-#%eyU-Pjht&}K#+I{ zm)_cO)W{t}bT!RPdNX0LTUkbWV-!}gdbDZka>ZF`oz4dns)lG`IpS2raIgj2rfwT*#-t~t+ zKFMAugrG14H6ZI^IrIQYQV6h!xu}s%?Dv`)U%x6moch44AYWNV=631%wAdv*fbm2O$ZQBWzr7xm{1 zY$&*#7TKVKzn0+WHc8TLKe};u&QrX88B_IATzvdM&4?HV>YXYAo4B6bSNasT(iyw5 zjaMdaA@o%H?x6Rp_q#ZfKWRMzGR|EUSL`0!hMf)h5YM&K8)JoZCA4}C1B0LXg$xn- zrWM-S$_FzliQn7hV4zl8eO6DNhdm^^;CG+u`#{}nV&lwA9K>`$fJ5i5_WTI#vmdvC zEGkib#q$g#?EA?f>BMf}4O!V?hv8{&76%gIQdiNQ?5?X-YK8V;n`!n=_toZRcx;a` zgM)&l7Z!-X(sCqUjB(z!u1Fs9F27!u0tByja0XY0GuDTP*-~4?bvk8Z*4WMJQB{^| zri8yHGgq5aiwviP+O13cxFZ9fKgyFP9=_RWL41&w8$v^YkL`mR9%;1k5j4ke9@WhT zNmpE@^l@mc@2?GJ`;6_6fx5f+9H1oD8k;Irc2$$9gpYqQiH6K_Soz`PokytDJk$+Vca_faF|bza{; z`jNigTV#TD>g)PoHv_@@ImgAgo8p{kbMh-YS7jA3GU_fhYK(Gl?8w(17`7T5a4P!r zDI=rgC=_urqkvtq?uXHxal5)$72OL)^prkVv{bX%?R<9&vmQf3kK$J_Y$ zT451KT1VK-Gex?zWDPE`$u{ON)ECT4G$R$B>gHd=FGs z5~rDjadq-n>ek=G3G(vVAr|_4_eh^$pUQ_sbd_Jz<;_DHI{CEE#hBDL>vBc2ExBhx zE?22tA-#4j#F;!idM#p6Lp>;2&(r3UaoqrCA8b-R<5g-lAgI85&j~5>6EX@W--KOb>Z>k`<9bIK0Hiza! zLtqXp5bC~ z9tP8273LW*o0o~cY%U^(j5h@OdWWZb-m&@UzVr1{H|GaiTyb>b zxKuY!+G3xN6KFjKwf;V2Uw%G!$3Yhh?>@3Ua9J+03x(_>QuKNL5Nel6%fm(b^)jrj zSIP7(a*?q-e&;@FE-ozO8P8LNVAIrfq^cH@ZaxUmAHFc!Sa!5KsW@}}5vT_Jde`rD zb8Y5}oi3>i$ZEotWG}M3_4fF(3XiRk3c8rbiAghDJ#lH`MH$Opokc$IA?Cyf`#Bd% ze2yN3A{0W&$wj4QWfmU{1~*cbG8LhwLmr+|3==sRHGn}3N_I1YN;+6-)j0I-M_{fz zDTmYAP~lS?lH0VcL6L1Qcf&4@|H_5&9S8KEZx$L~=JN8|WR3Pqou2{y56XXaNvFhP zvb!27QE~|t$l^;+p^YVexkN;@#lbp6lq|%Jghbba`J97WpYw~3gO3IiN=#(T?O;1T zsrH3+=+JgYW_NTkWdGZbK4U{Ey!jXT77Ts)(VCYrNZlotIj{Wv+`GJfeKInctz*pTLgxThCM9JzCxE;rL4nQM8S~>hYytX) zw5BZBN-=f>-IjOtiC<~h>{m;W2Uxtfnks$o9_-iUhkT>I&EeEmziO_oSHkJ>fa*Wd zJN>writf?l12aX)-9TXeRYXMZdr3V2bj4Qva^v=aTgi==-ns6oDGN?rK)vJsorM0q z{~P!0|5DcZEi(MCqtCxTjr`N+{r};Z|L=!9-8;SJ1e;#pBboD(Mn)-0neQ#M#($ok zT+o$8|>G84o{qI~y@8<(mGQCC=#w#n(VfZXWetp=S*R|5=Q5nAjfQmcXkJW_yTJ{G|_I;uy(rnQ$e54gmYiFB1WKYd>RtT*|G zo7U--WPtftsb^q)JC$anH^+Aq;SyJTQ&seEp!oC-v>>&zd3b~$5P8_4-7}u}ng(oY z#dHXZb}GlAg=1=xSBGOMk`{LP&7=GKH*4KxYJ)Q5~ z(WfR*!8zBiKQgzmw6sDe9&kh}@6}3Nx*_!8BkT&cw(hZVI{jP+34B)qgfv~|I-y&< z;+p+(hnm{LMm9&&KkCWLSitvrBZ~- zZG;+^N)*av%;uz!GAa~m=duxY$ZbNATNA3urZRgHQHhj_l91SvggM_id!Oey&vX1S zkC`#cyzg4;{jGO>Ki{t&4kc^nrI%%S>QZZby;GwK1pVCI2+Okk!tBfJ@aB_q`~JGw z^Ji)Gy|er%zwq^L$3D+q`>67L-pzKo7+U6cQLIZxFFUgETE$rO<_-KKI^TJ<$?jXi z4390H9^{a6MczUm2P78(INR@cOO!oTlFc02?*7(-mp>7GK}P z|GYt8A2}M4AJTY%WAlfywUkVLH5(kM@t&(rquf$yZtTrXZ{2>eU*dPK^Ab!o-8`p^ zr0p5u-h%SWrMd=A z>5iH;&g=eu7sr@%Dyx`*S8GeShbnt7+1!fm-ATkbt@i^DGN72ssWFz#Y}GE8ws94G zX!YMW-sU__JF|XSG=Gc{3r`dLP?`Z2pg;)rG?rk?0wJ%r#ZZwTuwj{~<4HSlVg^QR z?EScp#{hprkX6f~)hBO0HkIa77x5TqC)kx{{EF2VH9Q_(^;%N7Yh5>;NU}6tb&149 zG9wBJkJk;)VO(4s;@luL`D7+iFb<+1ba2J=?tBFU=$AG1()*Hc!$$Kj`MV{0^Za|J zr>7Bq0$YKr@4;wC&BEamc6NzP@7yj5V@&iqAw>ZMgqbPBbe8X9YS1zN@?L@*e70>c z)i(ktX+c3j6q}8Wrn=X|-=H!GpKU}q!@b!FF36Fgo$6BYeB)$({`;bg1Garppsx|g zq0;=W>70jd7qB_q7!zceefs1_R=8eTdg5c|5vauJ{%t{GJRnKw{A>VrxPEif717OCo| z(ba&hn1&PFr+%Th76TZ7#>j|b^Ah#$k+WMJn16jSg9IJir$ZwBzB$aH%hfIKT2<8q zqT_(LULRCAY)KIjKgm679-6SH(yLv^)5rW5iv1Wz-fUya@iA`TSad`<7W6H(nY zj8paP#9cg^&3-*wT3TPuL#w#NG?aziC=CDzpg+!!6zi!Cq_eUy{LSeJ=te}EB?wF- zza{XwsxnV9T0kY{>(9A(tNikE2a%`k?Rll8ZG%|9AWiZYq*B6AQ2_3-Weww!>Fn30 z5=*R=?*07I0JhxI$z`4q3c@PbWdFW>**)(=HzAZ`?CMSK2Mi%w;kQT|aG+3NV0WTY z8(tsq@X(0~AG{LgyeJBmMeYXD+{))&U5E^*m_C4vCzm}`>PnMfuOBeY8i3t?j;)8f zIk8?j0R>6UcpC$P8So_fL{Vw!s!MA(%Jbu4;KKcmu$=GTznhIWOCxlGqfck;ODV*7 zD}iqLMk`HiXq9NgetrT1q~iyND)}?IvhwNRUl002GPr4^VA%P5pQMI#o6Hpz`-eSO z!_{Ut0&h$W4WIS)-a&<=u@<&C33)Nh{jz{O)*Z<`Wo)$Yw@3ZRxELK7u~(C-uC4|P zfggYYpjAtV-p)>G(O7Ky!HDg;!gwUugAzR_V(`6V@*q-&L^Z zm#8^$!f12KFDFsI@poav*0*D5N;0OVG= zk+_U!9WP#Ja3>&&r)n$VY`^vw{Uj@fzV&3x8AU8|bNUU}z0dV@(`HwrAvM?Z8I36r;v}oOECw#XWU5T_kC^FxFA| zRS@AqAuCwtrXbT`_Q}dfMpaLKZ(8M6GC{PI!|wt_-{)?wIuPw2oKEIH*?6lxEl&i`d z9W=T&MGfP#wq)3BkJUeQEW}9~H7nCvt?IBW!=__mSw^|ch4}weGM`)$cdu#)X5UW_ zCuPa@V;<>?1vRa%FA%p(xlLP45EF^rG+pED{&<9V?6XR-n&WM>W4luhC$h`G`1u= zs&fuk-v||2sihz(pb*!*&<@k($aR-M!{uo{?wy9!`IlY4O^s1Fjcrx5+Pwx-Cp!NZvMyoW zs!N&n+E2!D;*+#7>(~aL=TdW`yeqG9eB>-TVxJIx3R0GN2Q@o%?0SaO)rT#v#?p+T zb}OGNV)h|H!O`!a2d6%p<0>yzrrzi_ZPDb2Y7#p4kug2!966NMJw)3eia(e4E$l;$ z(Kg5!HIAGq@DUYIc=(6>^0<5%S^t@ff$8;}?+fDTsTPDj{oTjk^+>F*6$?dyf>pYWs|Ikz}<8i`|(@Utvfh7?ijQa3# zQELWCZb_`%;loVn_~r#m_Y{WZhkD4!R~Tg4chlG03=p|b&ItX=%uqS*eaE2{n_V`?$&hOLKcQ=$%<3VA6cnG3XMe3{gU+?o=_)vbJH*+Hdxu$}}shfm52H%s~{r0doMYhEADVyM|{C=ayF zv^-_?u@C=9IK6wJE#V~**N{H?oj*z6Dth6OFu$q{@B%;oJ7@XNqtBTC9d#%pB)Ah3pCIy- tQ8D?y{Ij4WG)08G_|MI^{a+jNi_ACbhVEUS&4(!no9zx(BHP%Pl6~LFc2|h(ktJ(L7|Uee4M}3iZfs-h z`@W53nD6QHJg?{V`}xCbhWkGExz9P*b-l0m^}Z64E~M06h-IWWB0mpL|clvh^1Dov4QPljJF^7xY2!AeMazTPJ!F21=I`k~I1 z7~pMt^}*TZ>(Exsefq+(c5jDq8d_SxU>k1(y(F{=YJd^jDe0 z9FomqiEHjcJy0sq9vfniJz+E2*IVvWD9X3$6QF!i% z&@K6r>F>2$Q6NXyD|d>|uCtp&$@<_}t6yNg&lV3yMs`V2Y+V+OPGqHmF>=wpgw?s9 zq~njiTQ?A+#kMh_>_WVPvPrL=#(hJqwAIx{jHD8MA$&K~XoS-=zFbo0mMyluY;EQ= z*03KV=RNejLTYoGu_bx|P7SkkB^U9CQushD%J56jL zwoJUCBqTKyo#u+GrB4)E<4LJzA|f17nB*%%)(nTFk2 zpqf@oyKYis|HJ3cg2Od6X=xJzM%B>H@?xr(b8*F7(`hKy9l!p%J#x=CAu}*zKSmE{ zGgQ_VA43%2%C$EQJd2S#+xc6+>DM@k7=%vGPBwO;4v%ceD(sK(o6?Reb5~f$jBeeI zv1B!?u<3v%iC@2dz4@bzeslY+toHuF7q{7cjEUbqS9j|CB4byEG%+Ve&ZOQ>Wt5!c z0?rIS;d!D!J;@iGjC$FJ#mnY*i!enQiIseejHHn_mfcQChX@7<*@!Y^khn9d32My4 zdc02hoBp%4HJS}=*l4w0PyFJ#GgnZSfbbB9k0rg|+d??xl1kSZ(hok3^B5THz!(R# zfv3}7yB3IVeUTY(Hsoxdn85szXrxj5!2W=HcHgIx?Y`gNh7)%GCq~Vv(8x>|PXWlc z`C_QT*DUu)7|Ek~Hov_rK5n&M==*r3{mEvvnI7D7k`OYMhB9^^+U=3Gyr0mJlhVEL zj^vn%rFSzz2=(T8l#wLd_bAu8-fMZyPrukRU@~yE()G3S30sxJXtpJq;omlXPj$xC z*s7*GtMB6Pu(QfJJy(pnxBi_u)1Tm6X6)wJ1`O)8Qp|Nxw-G*M(>65So=GZn^d*m- zUD!WgEMT|dE`lbWJ2ECBf?oc~lVF@*4=WpT5x03(UFRvZno+;$v-Hl-pIXRva&6e? zd(@2wE1iW%IoFwQ#JCo`57pRWH^%IX#H%zh?2lJL%LCsloQCfERKQ2g$``r@`cnf> zeVH$lu3Nv~z-m=YEc8OtB4!6h#U|_xg7YaN+dJZCM`fF@B2-hVYrY-DJ|+>$^icEc z$wca!Q7lal!S`8Bf+)^T)-mmoYz1oKHZ*P+)@sw?v;LGegIVz#X4K0#B+~g&jgg%# zwWLS#8spnZ7kV35{=|>0Ah1#M?HNADy;-eeX?`1ZCaFtS_LGZF+1z zOP?xNhbcLJ{`{HYL--_xOY3PqcbXBfk=vf>^IQDyntkx+5|fHZMflJQxs#nUGWMgj zU1Ts#8Nb}Yk{P63=XJ@{ZBEs%VPR*d=h*fbA~~_YT5jD_=&K1YP>o$^Bu+}J zib+{d20;NH+i{liVc*qKC!_)lM-dnA=G6ssphEQm_+;U@z9Ga{8goL8u;D==V&zU| zper#b#(!s-k>nUJ;5|KMx62(5o)&O&h2zQd=N^lHSt~D+Qt>bQp}I1Rf_z|8?|+lu zgXusU1$k!454@XbW_skjdybEcIG&7GIX>sk8DFn`Gj=Vfk0 z=~WrYIRqUUeRNgV#r3Lay*5X82dHs};y2zp8oCElHqxcA-kYam^B--pLnK$fyc zdl8Ff{)+bOaCn}2EyvSxol^VmFAtFJc~|7aT1ZZuM}DY~3->0$deY5`vw4fbE=9$} zV7MpW;8A2(SisQJ>(y#WmXZ&4pZ@=L$YqYeV zl9F(Ze&J$^xr`ZamP4%1>#j`{yl(ciNfa%`dEA8f=l{n*3rIDldlDA4riH2G`J*ch&0f;#JqWnA7BgaeDTG7((U;~S! zS~*^@V3WKRyd|e9AR_Y1samgaW&)dgtq764TQ~qo}KNW1Q6t@@r$2i_PzXhIkRY zo&`K(RLqdL?d=}3z=J+y1cNiKX*Vy^TJJLpsV25*4%ce`bw#?aj^07<*nTiZ?sO*g zXt$@_J{E>qP*Wlo_MSZNs1Y#rHjwDMD0k^n)L4}YcmR08tXA70DpHuB2WK-(Lo#om zK$e0w{(AL}D&1I3P0dZd9=aA7>?Ta*$zz>ydU+pu=dFwW2sj=lEG#@0 zOw8Tf*+rYlJhkN0N;v3{3Y5ylXA0`k<1yQ_cf_2=Cd!rZRgQ7YcQ`Ne%hY)erwu?s zenZ%O(fl)Q2-;YOP9KQo+P8k7a%z~aV|J#I4~t5zdU!md9Xik-gc&sRJc)y-k?#^{QzH)s`j4qneeo-OrL&f$rNSg+_Xw1aFi+o}`>N~a?#?V~#}n*x zaFi6oisr3JJ(DxpGf}I2>|}*%`EdT)$3chM zdC&UMAE=mYu1ZQuit<$zF=0%|!8yeIctx_VuWJ_D*QYr~zGcvO(_d3l)4?H<<|h;5 z;&{an6MtdB@L7tepJ@*pHiU+R?11^9&0DX@<+T3U%$}7JyreJx>I!ON1S)Y%Z3^)9 zTpM`>b`lJStKN4QB$`vpH|+aV=`3yGVpO=!w_$<&EStLvFy5KBPxx_gkM0i>OsVPuC|l$>+0wfnZ(w*FGi2aM3GW6UH|cX-5dAbjM0wq6We_sjZE3biraND>~fm3 zr03pJG6E+v2z7$cA!|2x&mb|=XKmU_qQ4 zB;*nY2(ixPi(Sr>4Wq@?6CPCxR89+b%p%!DRYiT4B(9o^2!rnIzYgTryRb`TQ2f0~e#gaRn}G0Dk^;C+@Ke5+oV zBu7(4xapgti{+zp`@WgbbOKmhYF4SIMiL;a7%In=_a$|%Umk)32(vXHWO&|xR}B(p zvUr0YUT+FNJelp0tL!_$oNdqKWkNUD7`$fZR?jCEoNl0dg!F6e_Io*k{F5TjEEzBm z=~rznt=(qT59g0R#r7^0vEjpZaV-JTl^+M$PCHFGswS+_f79+C)uH6}lQ+qgG6PPi zC+;0t7019UvJgegQy<%jUg$5i0}x)0;16HsvNq!O&L8iFm(rf!z#=rSas3H+i)PST zPD2cu)a&+oViH*rQZmhYD~;G4kF&@&Y8N-8&;OK2Oz>=jW9)NY!3!L=Lg!1&?_F;q z5N6r1+Nagh{~TogfZPrYjxz(05}MtIYz9n`)!sOcbAIK&8!Ohj+@MrEfRQq1OJ*b# zc;806%+?m+Vnk=LiDF{~Z@}F{K8#sy-|$Oi%-8qCfK5jnRf#Cr{$1=#gYjj6G}4dy zpwk|yvzc(hUIkqD@AIu5&Tye81Dus&BbYIl zkQnLt??xL9v%~227{{@1D(dQg^~|6X)MnroS2KOV@tI+b&&Pq~%a<XsonIUadY3Ir-z1W@^_y%OO{+E8d z0EV62hF zza{k>HT%=3Nul6BT@QCg7tL5@5{JNk3>L&!TI&_*!*S3^6|C2Z56rs( z37gyGMYGafO_kj~#1S&bs)@~f$VLMwYkEf9X)RxwEwC5A#g1&yEJnwjYgYVl;X3SX zIohh+%zgdyYDuGS*U~4)I3wjJ!Hf(H>*Li>%g;8mfYW01JYo~(Dr^sS!?m>AMq~|J z4gDqth&Z49JdP%Ztz2D%DPSbXu3v@0mMFmI#W`Mn62N@GnlHx0zpL_bTr4=*tS_8E zNlgTc3YIug@}nKZ%pk0&r>R4_GB_Lc_zdZlACF}6Jr?ci?}~{nu#nQ%?E8*-7+5cd zxNt}np5(5WL?=CjVQ-xyb;&rMYW)Isd-sGrQ1_Z*>hRf$bjgZqtucQHI7f>cdX&r!OviK+H3)D?(`2nW`Ljv7Ewh^sekEcLzCd(MIbBhAeXi>1nl zi|hG48?SAV9y!2yOR!uqfD(}n=JN5}QPgZwEHqkFW8WqW2bwW(7NQZ1(6w=GK{6qzjX>JhQ2qoa7; z%THb1NzooY*n!5fw$vLd3LS;pxi05AD#x&FpG2q2hsDOm)^FB9-Lu@@(K!9;Rl2nIWlBn;Qn&q0 zX|F1$p)%V6Za@4wqx?6I^?rfM)iV0R;S!@w7b&v6O=dc}vRAF#W&}}vjNBQ4@V@J| zvQT5iIvM-lhaNlvzZ^<s(gQad=-#} zwZ`HX zn){~al_txTtB)ud>_i3l`HdSa3{Xu0Rm7(9G*W|xJ;2Y%hhhCFZr{3fytjPg+lD1c ze&>hIjUp+B5nfUnjn!OqBD+)?cktnE&wCzK9lTS)moLhlzn6PniWC`D%L>RSkZ&($ z*5Cfws;v!aSA<$uSYKp)t~#5OogMf^R2e>0Hm_Hx_I@y1T?*_6k2u&5Q)34{=I6P7 zS=mk+pTc=(wtcR!Jp7zCF@^`WxH3u8SR1|-v3alB zn?gr7D}Rix0poi9?Ab)6{fqK%-@vMRZVW=2iIxV5sbaPb=JUKNPlvFUFpW)+7#YVB zP`VqV<=#uNkNI>xNZx;Zph$s)Ea-IpfL?fpn5n4nr@ zyW2(Np9~qlP%732|2BvhOsrLj%Bm+_FQHB^VAUF_d^AkK<{0awU4_2*rh^RGHr=}1 zohk}=&=*=-GZVFxDWa-&6A~>p_pXgQNJ`cMj(J6l2{tGV(kaGp3*ZgNU{9=_KkBri&G_C%8Q(ux-h?aX(=BNbA9&fAjQrCh)O!|8L#i-EQ&Odm zW)Sdqk4xdQy9zJzqZhyS^$K$p>A7q4^rP$1+=02G_8A^CzdELbZ9qT|80bzFr>q&% z-MVrx&{Mw9O{{drO?IbpB?#1#I%>@t9zM%&4ba0f>aEWr%@uXv*lK6U&24pVZlE2K z!xU{;=Loj=>E!m2Zi-pf8^8x^;{&0nL0%|abYcp4I!XjR`qY>BN3}Grq*Aa*+8`qD-j$BLoI@f`P z>DCVwPS}3)Qcf-|^%{R;Pz~r5ta`IM+!91q0WNGax5bn=)>k?57S}^C_=Ltw`jwJb z_B3x1h*UAh8xMa#fUh>4}AM%mV)2<^WYrim^P#0QeojUvc@F)xv*D_z6bdg zcVSb|#4L>sSkT+b(Y`VnU0nm-Z!Z0KHEX4)`GJa+1>~57Umu-O#J=^Ct?N&#$9KX0 zhF)PEEVPb^zw^RzqTZj?WW`{9VoEWJYaLAt|d zKb_45N)~s0u%{%4p3^hDPJhg>Vh*t|-~F||3foyg%H|Rbsn^(V(1PUQ0RZ7$olWib ziGpUr9)G^_L~z{^_nv$oa^uFAbCfz`Emh9AS5Xnna!y_1#FI%>((qT{5r(J z|GB641udreHld`*FfZ$`k+XLQ&RyC;b!2<~#5}vxDKc%eE=(cRXMB4`MyDcRh459IxtFzHwuWt0kIE`uqGy%j$JTMx&E*N!XM_Y+Oop z@#ginzVRR{*YWZSfRx|W343-@f!Ik|#Qpg!w{25ei`UUzu=IQo3PI4B?0Ott-ba;MtK z^4|3dY5&29bEhX_HZ&-&_2ca9?4{%-@LgAi9@$;T*l3X=s%~t&mf<;{MiotYP5K&4 zL+@Ys*(ymEX_?*T*ZHvi^6w#093h-yFT5I;sagO0~nkmcOb>J0EXWH3R)C^iC1X@25QH4(hWJVR~Nn z&MXY1KOxH7yllwv+3gw`)9P^(+%#;FmhR=(VBRMcZ6MeNBcxca#8m6UuQ@gyG;jvf zXq}Q?g26OCAj0FE?~aMnt0YE|2KBuZxe=9>m31-XA|37(jN|FscXXsV9Ak8FeT}JY zUmcVPq{lUX5e8dqe2WxBWY^HQ&3mcJUyu5IC;{q@?=Y(cxSQ|(!JwOwN(%Zm`c6*K zG-FSZb7;TZf!od27C-GqwLr4=H_Hw6{NA*}$}-VD{;c+1>rWVL>YMph={c-p+rLVPeOh^4}4xi zY>5d#HZ?dL{QKbW3Yk_&thxDX9Yp~iez#gINamb_!E}diq02@sC@3jKL!sb>#l@rF zL0Gn!zEyaXKQXk#HHmR4g;&Q_DV(qE*DoKL$p*st&;gYLN>GoN2+x*C`#aI#uc(=w zlXKcLp+!#$UXc^z@hbFesKUp9a--m&pomxz<$=N8N@-~5^8{aGVp>R@-LI?te8(gD z!u2|Cl`_ogzD#6T*pG3D^)Uv_sOF^vOZ1;G7n}kT!>9Uh7Tf3FmZ+4?L22b3HeR*Z zeI{CPe9~QOvE1>acn!^KDhs9zy`pq4r$lo4n%|(ndS++wP*hjI2(I)JV8ki@GW}bv z@~svIbXw`rO$bDGzE^$Yk1%u+46b*2K%kzrcY7*Glje=@w@5jE+jSi5X$7P-FDP;Sr8NW&np*8WwvRNw}1P z^cq~alF>$Y_mb!xalC^w&z(DZbhrA=CC8c13!VqmK6nExB_(CK^xwX9de$q-`Zh~q zwWAC!k8l6)z5FUy@^&X2(9<4FH7Ht*i~rrzY;aS>^aX1s-iS7)UAsLgnN(0KKC6ZS zatX8@7Xxs|6UYyYgTdKOv7h8$2Gw!9Vg9>^<^Tl&>VOXfjsEk}UNsKK6?es7q~3!2 zGsWnp5HEm5|8tFT{KI9ok+XiUeO7XpQsH55z&jLqy73|PRMee7?N9ThA5k0qvV9=LNYEe#hq?y}@!80*t%atIhMFIANz0vZ`Y!@KsBQ{g$RFoKqM}alvL#9di9W+e0LZr%yit`Ke zz!T2CBOzPOmpli1^tGa5&x}#vhNO9Ni_J(?fO0@6iScEyH%!meojkXCUny#Wn&0P% zx;Y-3@==jjgb~rzKxu!8V!!G^jv%t`j0ZhXG59dH9?hkiME1GL9-q-bAb{6BYYBZI z!-k}}1?nvr!SqCa$Rr~@J~es70#Hw&M4I~L&9{k{yoM420s)6VI6i%%Ra9(KQBk8; zRC{KJ;A&P;Q3(yQ8ngsp@^R2HC`?P;5f{2!u>5CQVX+Qt>*;zZ4ueTuV`Brgaj%3) z6n?NkJK%V)Q;0{xBj1;O0@evmxShQ8*%8K!@e;=s7Dz(E|FAa~t(%VkY`2}r4g3by zx_mTA(1_N>#^V`A5ENKYT`AfJ*UVztU-MO6;&2eF*A29@!+>VZZlF%BS7Zz?He`no(p$|bS>zu%lWZVyO%owY{m3?160XYCT`1$w#d>Sas z%gyy(?k^>!WS32wY%nM{sXqX??=O^I|J9)U+wZ8Wk)#Tx-HGw>e8DxV(MAD$O?Vvj zd$PngbNS9vw|Ad{H-5Hy9tP`7NKZdS7uB{TmHuv1OOpr$iTh>ZdC&J3uIGQ88!ncY zm-jEoX|b`1pOCtJTbo?idV>HUI{=g&$$huI*GKDp_YEDtIAOJdX_6|PA(ZF%L5gFA zq27lB0e=YrNB?$Vu;fYo0)sct|C8UJ_KB!3{~of zM&OVBr!2@UR^v|?F{$@LnxRVn86zEM^P@_YxIqLQ4c2>e9D0-*pEgmax~Q(2RDAFH zW#PU)rcxXAN5z+F@Z>e<1GojzBn1>^F9*_Iklxj};6K`xtcqi3tmD z|I=Q0>@IYxXFP;={|2EC-Y>!Nif|}g4|#7IXdi!~`g%}9MW^8i5R#hG?6BjwyZdeh z3gpt@p#S>y-PN@es$J*=`EN{kxLx`LuaFR~IzkmvV{QI%l`g#T`m;y#s zOW5)}V)^OuUemWX4@iWy(w+Fh{&~I+S8iOhES;NM_-ph-Lwbc7%(z%rz-R;T z*z<^?|6;?Z{|`>(kv5VJ(}UtTKaEt_`nIWj|9f$Q{W=VGAt|<(2NbRvol6YN2O_%$ zeLV8vrXYF(4Gd9Va2DoRYkq=3=R<1g)+(&M(~y`8*Mvmy%jH-0Jy^vYe`^jbkJCS;13aF0^Ii z>)hI57|1cnLfhg=O`lC1m8az4Hy`?#_H_@bYshh%E0yExj~Vs2D$7@*;-zClli&)Q}w(DFV70DD$g>D-F@>loujLob%`zX(Z4c) zwc@K+pIU6hlI7{)Ja()xC|(32|L04J1ghUZp`Y1rtzV=|NWK1j8Q0p+XCX{_x$*Ud z>pX3DfV0WB2ZbmOfM#BOveL$~pI>*YXZ5PjX(+|rcwqJL2*2p>&dG71{SgUgbF*#S zmTzMjzdNlWm}6+#mAnDkxDRsO^k@y-EINcVCnCEJ%uDTt?$JGfhyg~9iK z@2Eas_HQD=p&|6+;i?(B@SwgWxMV+7oznTsjSv2iYWkl4(K<~N$3$;gu=y3N1R~Gj z;ABM(rvq=BcCn$%*II@!Y>(Q%eOqu`l_vc<`AhsqU7Ay9D|f}Nc`%K9cyzcH{FS$a zv6J{B2?^{iWduLkD*i4%|MUE3fv?`-LXd;Ky)N!yM}r+}zEm{%FN`lx)>*|;DaD)b zr95=PVUGq0@88G9YD94LJKVo-d;4h~s5;N~L9v;pr7)pfv%84 zDM0rePxSSZp_ZG{tm=yJF79%N*mbYa_E}o_w5Ei2yj@o1qYiGh6M{)-q^~@mvF5dE zbg?3`n2&ibY|BMavm!$4L-2>|79ePSkMc=!7+mfbv)dZauWIb=y_eIcagZ1!3$mn# z{9UW?38y5Gm3?`BC3IljH8t`#5Svs3SLLhFWd*6kIabY-;T0>M7&e$9(ew5+ugXVt z;G);(wzgc_3T^Oy9J&+?vK3GZJxJVTz2=WCMW4Zt-tcvQyR;)a;=c%L~128NBYI9Ea$ zoqt{HP2|JC&!0bGv+XbbkSgSSpxSZUHO`e2FGTR7KO7#`ylyYkfhVhR+xr`X;8VGG zyXB>bh+XfLj#m|W{>r6GAQrQsrAiP8P89^=X`IE!$jj8!JyL-Ua|7z+<)hb}E3H`N zz`sWwstk+UW7v~8Yc+F7-@G}3oKR{&k-D`NwzYLnC2nVT$1;e8jm=5q`VJ)p3m3*t zH-yG2-XNmWLd0OU*ucO50d~f{fx%AY9)c5Xcn^#vH0q?A=x|TOVPtBsz@fO4c6z!` zQ?tFS>^XP*5K~fur?I9^`KU#uoxoRMTZKcu{CuiIvhN78A(7m#q0en`>FKwF?|o5o zN-_!?KRn=Ef_X2WYX;O||Buhzr+!?_9cz`g-sF zt+M=@rwPHFI=JGUXIj{}9{(XcEnhGVBGyvn6Bj(+srnA*6DleycRvcaVnT2%mw{Nv z_kPM}x`j;g!(xz1bI@5-cE-0-3iwU3hkl zamm0a5|@{Qo|n44FF>V5&VeR15IcMi%yF>E?rGUth4jO*V%oHlus`JSquv?FF0`1_vi^1syB;1^i_GRl4ZtAoKenfade4t#D=oMighl0n)ax zZ$6Dz>P_x$8h$S0?@@@f1ilT4`S}eE z53|CPN0PI%Z&i=K7P%f08~pFci7=hwoVhq6m2yTM804QQE8F&b2o4r;pvg>+Uv;aE zRC?WE$*-y#r_QLw^id;3Z`=3bBu@myB`#z}$CWC`E9h01W;h8#6(^E~-I-oqB3*Dg zGcb{XhqFV!On^h>C*$)VQYtrhHngHW4b(6 z9UXT+#86700D&NXb&p9wL7r7zc^RIfs%4-;uCR;^Qk7jjy<(e4^`YMk64cp`w0_cD z9rEYTp9aFu0XcV=FG#J)W7-|v^My-Y6+j0VevNL@y@iV_ru-D=-;r-A4HpM{Gz|l0-)Eu60P?LTa z6gTwe&(7{{K%V%?EjLIa?Fx#S&i7#kp@A?kT>viOWB%k^D3)qMKK|u#e%|g&j!PWI zg5Dj}{bxB8@-=CKN#)N=*si;`+=x-dR7ta332m)5iD}OftrWUIG(7yNt21O(PWg)Q z)|9npW!ICV!!m$NbWqjyl^$DLk?c?iC(D)gkJ@=N05ZNdhjcht)Z0OUP{t|7D~UCz zPb1A*^{EXf+D%i_)zq}Q%0G?hfiy~$`2Z0!$)r4pHHimos82%#H`7G`pQ{2A3vT@vuIqa+*2rjBALl@X1x>k zAkU5<$bZp4{AmJooNs-Gq!{Np(KMX=uFCZ6BB38rEOH#CWM9ExI$wDEA4Dg2XYI4LziFS*N6gJGHHP z0;x}Rx7A{^b#v&2>k>ijvj;vCKTUD20CHw6CywopJIikN*7|jHNFRIss}t}+E2Tgu z4w_WzaKmzV0$Mr7a>!c)1{ka31&CY(kf@3=|JnywrZ2^3RZ2kr0IW;XgVg81FDvC} zCLXnrgH$l)f82K7z`WZK$V=WtUARupee0HdJ_0+vjS);NHO&?*d-eKZ}DSO%Xs|K?%VmK7NskrX1K`ZIFf@0k7CT zTd)b}L>QudcKdpi@e&yi`=xstvIdEgo8XbgE;{h}VfsgkK8~>XbJY^i#wV)5cc8?k z6nTBP(Z~)|<$!#ZoFm%OavcY`wEkA3WE7N4OaL;V?2M3<&onu9_wz{$niM26ec;mv z&(ve)Tz2jG0qMv1f9R5vQ$#8u-DE=>(CUgWj>?}X$r83sF{kr(Ii-Zm_z9<;B(s3s z-$t8&QG@JQg#;gx8dL`Ja41zakw_vXWwf%i4|oX=VKC3ze=y1aH4Pm~#*j;x-2*g* zvAlfF3)zf5?%GNkb4-a0VE(Z+wrEhl;xc%)JjNxOt4cfz7_W462dyNHzWd2;1I2mj z@C?n_TUY53$y64o1ae_S+_$;0%OF*QL4ep31`3VBZgLkudIOYlgdgnw`NoF?BC~=4rklxur^mm3|LV$kfNVNXE_$~w>sf%~ z>HGN2SV;yZ*vbWPz!d?jZ7-_+R*idB&#ddY+OqFdb4&fk8yDOe$>XYis7h_eZ?kDA zyNwGdJ(>b{L=-P2(uRbF${aQ~&i;-JkBX8^OFY}|>S;RNQ091&IyX$Ya5{0nR>5;c z?@~nD&OYOVcC{Kr;ylYl^)8Ut$cH5g7}?OWO;iuyi(02g%B^uI;w}y_PlHl(D@Tsq zWy#6Olc%JM3k&Iu#h;<#rWYQ`cPhGE#ahQ1_v}slZLcZ^Jw-Y%blhq!$;m3jEAt;e zSXm44&2aa5(scS>Qm{bHZMC)>dg_Fcd})=AQeO=}K(L6pH4K}aGoAqCUHF!fw8mAy z6sp=i)5{x>Jguq^vPQ{=$@t;b>gUyy&{!aPajaISY}y)khEB`vlhmmR`+d_ng3#tE z(QnV0`gDGUZ&l=A0Fdr?Oy8^<@EVhsTCIb+ypW8~mJ5&<$t7=ZOg$#~J6Y8!>NAp@ z5kQ(Tv?eYw@Wr__DtiKH@@DR%@Ey{My9YgiAv9FC8cD{k$q6s~ve#p?y*4k4d6&Wd ze1H4nAUH!1aZ_|LDCoosELb_{@$qbOX{`T|eGz8-8N7;J`R_KYXS;xWm>%&+*Vp$0 zQJXaA)xa?v^vX??xkeE!OM!~x?C97?KCFJTL57>VE<27{B#d3kqSw)TqCW8SH)vY} z46DrUgep+sJoNJfsLvX?Wu4)-3<^-p;?Oh#*>t8G_YH`N*4G>hjlJq+CWK-PQ-I(hilh+ed6Is(k39h^Sc{%!Y@%S_Vj-T3Xg-$qtjudXTLL@ zQI5w+na~8Nqc>s4D&9B2(6}v(pl_arSx@WA=A# zQb5rt*D#P^n@BU$@0ItW2C6v_(i1SeXOCw$!ju^9tUY+4^d#7RmrKQWZknvx(X`%U zy8&3)g-FKzmC;$q3_55B%T{c*-%r`2f9rM#jS%W^4M=l|+gd7oYG3@Z;4^fz3|WSz zcAA{B3(5Go;Qpdy2ybb!LC41!?^t8e+0lwB*uVxL2CRTce*gQ*JX}0-+MdWox%fO& zEVnM|9zx-9=o4jl;#%_3^&yUX&egxguga6dm(4vdaXcrjd|V+|QtY`ZFrZtkUtzzv zAS6eW5H2ln4y+B3eJN4h&nD|TxOH(iaJa5h&MZL1XjMqhtk$NbNY2~APy*6z-e%Nx zY6u*SJA&$oBgX@HGqM}M*G8tx%od4dCouxM3j_(fITy!;n$jE$(nL^&ORvsp?A!Lc zMrlLi{s~C2d~_`W+D4XdqBaE`ft-?d*NXT9%wt~l-v+vEh4A^h!Y#JGo|7XUc9*25 zVv0?VmvC$%scKDmomi)4zCv);#}tTp5b55gG_>);P+Qz?@ZQr35R_j3<1?w)9%_(p zcjTER2G|j5`sBkhp)a?CuZuf*G?$w}r^Phpf4;t>Pe_Z8KUw#d3*7083}tJm1}ogO z*(s}?H?f65$pp3yVM0Fy%i`Cx$GVK1zj(Df4rKaGv$ranoB^TfDd;ovgYYXH!TP1< zo5xxKg{nr+%N<>TQiNaoyhsayFo_w@{fLaIQP8 zTJAv|cJ|V~MxAct>6yJLbr=zdm%hv_894H1n?C*6rt}E~AQzGjwt!~YG;n(qaGXGH zLPT6a$mYGbTW z?szMJ;}>WH4W>Cg!4EL3f>t;hbI??HPFSbnc+8VIn8u{ugHHb2H;*BPjep{nzFc=@ zj$dPyt06R-XD8jDzw@OCleps~6Yl0&#~rpWQu7~pAziZvHIA>E(++wnc2B7SbKqMc z_~5@zliA~344bQ^wn10Z)n;??n-9byFO{_n3_Fe%p9+}OuNQmE*?jJ;c~%I=bqO`0 zj)v==J2=(vFBE7y`4Bp+m7>2KE|y?%#LWmmyWR|t4RiB5jLStkr};+EWGipJ>p^W% zbNr%$FvR&jWwzr*W@l=4$+HB^b>MyCGDLs_?f2kwkA_7G0D z!>jiDBYGMRckC6EBTsx5tdXdLGOsNnsP5mob*s)>wJ-68jNPy3bcjVNZ2^^?%>(@Q z(06LKhaOYS90HF6@af|5@kY**WdgFYXV7vUTmAe(0lfgrTpPSZw$U%}-Ygb$9D#l* zZ;4YqqY2Qeyk zv0ql@awh~dAoW^9uL!4hpHZ@?t1`-0)QgNHEVB8{EGM09j{%hnbPP?WRu(2s_%A%2 z1q$X`$MH>2Q2~t_-o73$=;i;E`JWVv{~HROi0lITXe?eXU~Br0H}*{`&5VxM!C$$v zHB5DN;&$NPc3#0<6Tn_QefkvdbQi6g_6f!u^*hPz4OY(w)c#dV%mY>{{x!P+Q6~@r zoGvdK$Pu<6ch6Klj;uZsJnnX|ez{k=*qu9f@ZHsCGC-YS_FxdM zr$#5=fIlOP&wCEdMpd7pYl%(uRHUtFWJBQmkT^K^XFy5`T2t1sh3$1XF^k1H5!6L#Sl~P_yH_?#W%JPMpLZHDJEeq+k!kztVC=5l9QF8q2 zyzJ2a{-SQ@U$1fr6-Liw^~2w?2g=?&hc3^KL$&+OP%AcDA>E{lRz0D8QT0#R_B(z= z{?$zyx;0s+5FJ(2KMdiT=9{Fycl&IvJIVOU9Ic^;!W&l3&JGoD0atzWpG0*)W&Yy= z17~M@yFi?w_M*pUc^)(AMkUXp>kb)qEf*CJTUM!TUDpwI~RNFG5-F>J#2UQ_!WGHgBT-jjK1IIl$zAOAASPq?0dzz-1@QUBI^ zWqGjzcac+t*L(V=P>CBBH13x1qjon=FxY#JGYOcn^#kD?WxE&f3M}uM)b{ZBrm5V~ zf-;+*7I`1iIWrtV3Tv(fbv7L%50B3@GcJaP&4kA!WRO08BA78yy#nE`$o>02y)C|T z3&@y|(=r-$`~b&|@Nhfa-fy3k03hH73ja5ht)?A62ui4xAAy7j07Xg;CUJF;6=Q2$ z%bmZ_^XYl7^_r%dHu)zUtd|2J8K^3{O9&K$GN_ENhxD7BK~P&JsWMWZz7#c6JPZM~ z)M27Q`9?KDd~n9hnth_$eI3D-F6}81NcaUzqM+NX(F$9&j-tNtaO;#vSOo?<5GdW7 zVK-D3LSudu4wny`=hHh%8qV{6!SPG`#X~m`a7p~U_f|#~(5m!`1~o1pY0MuH1Ml87 zxpnKO_Zs2$?b{D-CWq_FC8Re(-ng@{uq`piIBo4Zhp`4x8JQeEyJrC7ajA^`aE{dNN-r~X<%EhSMt)=!2#VC$(<;D(=Miub0UcL*piDTe9|q87(kpY+qw!d=H8W|xRxenztQv~9&#GpwK@TPsoU|^A6QXS%kU@U!mn0} zdS8FaFjWl1{czt4wjEWM1AkJWwN6hv*uRMqNFUV|wfm${u}> z+Mx0nLq|D(V$wa>RbjwtgpZ zhVlEktxq`%n5^m0?sOuERlNIQ2iw~vhPh=?)Jq7R()TnoQ&}3jS=00L1{F4+9PU)P zxmXsu5F z`ga4<)6?VQwW0geNylKxnqUf)rQVX?|k z%+00dt9-cwB_>j0wi6n4FhBHgQ65y>12ld$4jM1( z#m9X87*8F$$Fdb8JXQ|X<9}0y(DWa@;`sH0HV4lxF;Zk3|BRk*k1%y=D&t2uI2l7K zMVB{1qGgp2yWHO-=h4hWA!3>~XkJ@(-tHJ+qW?mlH1_>>j$gY>qurM{X%XF`3Ckiw zL)RlEk7XEprJ<#z7a5tdvT}QK**pn4F{a7gh+K1Ipzw7PK89U}&XseoP&nTA;KtT^ zSAp3TW|JJkr6Awvt&e?nIwdR~_o_me5rh#jb zZ*O6>3k(#9H8OMy$-gKLE@!DR6>ArJ6lvs?EX7%tg~vx`aTnVT*T(7|_t5(EPj?(0 zr`K`B-=>$`_R~pXlknjfXlu*S?V{7c>PiR9XL~?fVtVL+5ue+-H~6^S9J3vVxw|mB z*8Ml+GujgDFTs4yL!R&wv|L=52srSK#hK?SCd)S`)=XO@+4wGMKJv| zrm9!^b@4&oe(6wNnKLr0eJ4yaNBb+rpc>_(tn7$rY#M`1fxZg#!!%TGzwcY=&+6g2 z)ecGHq_17QPKgK&b&n$S|1Zh^O4wGtK%?oX?=Y32`RA09qT+`mL#5?`d~44rXi36M zz3x&-?Sb0?XwvFj(yNk4B)1rO{QykP4S`wn1%phX^6T^i)Cjn(`cu*TQuL zD7H%ez6dL;4zWhg#XJkC!}FL$@C*{bHcnix(6pA4QuE*9UNFtE zxSZquX+A!oOPH=JeMKZl%p((S^|Ry|<8)y4AUE$r$BDbw-xIi4&C4k%-MB6xX+DvC zC=(z7HT+h114Y|w7d*6|FJ$e|)#vw1GwK+39cWKZg3Hj7za*(Yoz?UAH2JNYjwazO3I6>cJsl+x7bvmh#un zC8ea+79v-!;E==`z)l9gz<+Gl{M+(oxP<5Fil#f5jBsn{gN!h%^{*D@X9f7_2w|FQ z{@y6m?%0Yqexi5D<9N?XY6We5L`1ee4b`~jJztwq)cF?0bk_XwYQKNLfF7~yyvu8h z%0s$Hpx{Xr2-2?7^=DsJjb5KbqK?O^WJC-PI~5eBBWvk}f+ku=-Gex^ss?6yh!#c) zH?Llm&-iW~@%*MjG&?J>v8l5KGl7y_O~QS_xa|WgTNE>6kf_DZ$Q$_#*V#r41Uh$B zRa9_3OKvV{W2kaSX#Dc>?h(igX|BEE)+-QpR4-7&lMw}MRr+3dZY=hk>Snl3eYY&f zeE9NZor<4Hz-I5AL2=!5HNO637zj~lnT^=922Xpv0$m;A@3xzQ?#?}e-{V8LjkXu~ zjcYv~PfIiF6d+5Llltf)7occQ$Yc>^jWeGOH^TM(URjDg-dSJzvy?Pv$m5i}CPV;> zF}(=E$sR`~N{ik?rpEg}R|>AOJVcE;GZp!+c;!%+>3{c_-OHl~zC)*{6QCc7uN2wy8^e8@$57n4Q?J_Fak&@5jn{*Ql7LZQY(xaE z-P5NP9v$hHEouyJL=(`?T7M}J0V3XK1$FsJ;?|956C?kcX`L#qb**I?vtOH(>?X#> zBtAaZXr;NfvoA*^_gE+x)aTmRrang6bg>z4Lt(F^O4mwU{j1C>hA zBO`T8N!*j9;^WY<%%Z5jrrTDf`+LM|%NA8DtG|>KOvow^17g>Mr=eoc0|p%GQ4VJ= z?(TteyJaBgfKu=%pim`Esf$9h=*LwXan#Hrr5XI-22?EJl z1rqn%Y1_(1H9gxH<2Sr76HuT~0H$bCIDWL$1fxq7&ufaY-$g*}W&O-o$*$)Qt79~oW&Gy#pZH|3bHNxo>B_u@rHh5;yNN-M?m3*El|(ll?v=0{ezACuU%Nne&Ji>e-LCy0@jRot#F{%9bK9r#@W7{~*@l^>MpBA5(hc%kk<&`Iw^03?-_P1?TiWRQoNtZrt&zVr+~pk3g+5xu=IkUe=PD`_j+ zV@dN?dm^b!z@Xc zX7Cz3dHDO)^8>^4PRhjmz3&i$x!~!w^US|(lj|CrFi{zbWc%}dxm62KcfKuk%VlJzb$0+|d z&`0TTd9Ka)?K&h-BdB=vZGU`x20V2F;yzaF?VAP}*6JI!zH&N_@Pm%uF&rg%Tp6kP z;+Tc{mAxb~%`X|W)0%ZE?Nb~W{@yanalFR-_sDD#wkmOFYhP)s+-AIFsn~0M%o2}) z)pX_tL~d^Fz|Rk9Vps?StawqE^e+nDf?3(RUn{$)690X$k0r1Pk&^J-GnoJz#V}Yu zepTPnv7mEU=NqIwyOQK?VTq6DF$macon7o!xN&aZDP%aAmA=D#a+u}ny7``(Pd8V8 zs-s`%#N~(oq>P_D)_+KlXh#0Uv)HlmqcF=(KYR>!y(gD1VyqM-RLCZ&>M{w3RGCx9 zzjH0o)n2y8lB7PBgf1W~ARQ*Z8I^bQBJH+&rg=aE5A7WoVL~<*%tz0XC{05R zEw1&|BPW_@=Wu>5D3VTi1cc)OJ0bUDV&iczAsfx$aoqIUwE>kS10}ok52NXXShjh6 z&yApo)U!(Tp4Uq)xoP-0LaYTHgU#n|a&tAYmR5ZB%&xEIj|5}&P~Pz0_CKWkY|*|S zH;j95S$~lWr0x$<#zy(ZzY=9@t0)79U$tGjg9ldwCwGip%9lb=$@J*zS&Sj;o3HYo;)fNq>(dj?+Ca;14GkygR@5tK1Yo*7&EHJW2FC( zL!H=lv+qv`k!%#BjPKUG9Vk)2Y97qh$TKKrgCfCJ7ZQE+XZCygfg1NGs8>Sf=3hgd zfC&x(%u7?ho8^#drp!}alZq7vw?R+6%$Du^t+4m`)X{y!_22>#*9WuyW7ayRb;WGy zm3~Ma%>lB!+un1}bV5jQ2djH7xLD1c$!>$tWzhMF;2V|EAy)JI_-%j|xxn`ewlP5- zd`XG8KBhE_te!%~G#wZ|1Y%Uz3}3v!1O^6#l0W$VU9SKcE$Zjk(mi>S{Jz*xjbQGX z9qrqerBRt5G_V+>f6VGBE~a@Mfq>Z?Me{8WVGgRj{JG}mRClEfoKE;BnQp+4wikb; zstl_avJ&82XUC>7zEic24QbE3d)3B5;LWuV1XeH8=GQhY40c>o3j&qAM2+!E~` zAJ8H`+B?XQNHo8Ci4%IX2l!k>+dT)s_(1P8bKrFE_VNjQ9^VXpvAVSDSNe7_^b#!i zoTgMU-u%~iHOb6nIoOq=#C#QR504V>TYv(8tn*pDqOwX{RFp%P%9srFejwFJ!WtVI8oCC7 zln!L&xQe%`mrC9m%-b+dg)>Z6BaSgAt1T zTJqSr2adv!1gX6Qv2=K*SZX{A_@#xi*Gym=zmFV$wIoeDPgMK?DNf&p!?3d>fQLI) z92Y+X?4O=EwyaO#@B#B-olU#6M}Mom_gAH2;^OXK2Wq=WdSMQOqR@;G*~X@DkaPj- znNwOvzF>xr(OMx5fa|28pzzurTI0z;ONR0??xMp;>&}CyS$^=><@;_xclfpqGtYIX zNaT*aQ2$Wzm)Z5}ZbQ<2@TH}(?Cfk=mf3|;VwShJwhK)8D{SB2rS&`QN-0Mmnl!cg zL&=?x4mxFyzj|cOZ&NelSLXV2`Xv^7Oh<4w>40u(xgm#(;4v<7d~`kqaFOAY+94}J z>tmUe-P=B;Ivpgp+E1a)mh@h4%TRLAum25+TL#^xhdm^)jV~-P!XaSN@QOJq25EEl z%Dx$7og^&F!=!t=yYG=k2G4>1Jz*A&4x<-#{Iwi^d*y86&UFaqH!QfIu{2b{vocv-cFFCMH*|46pC3k7J=j73?4h%gO2Kl=Jy>$5q^#gttR# z+RDYa0vCtR^Lm#AohNEc${b_T(^19&0gr;~$iMh(!dOBL^Y}DNo+>Nns%B9l4i2dD z=#3XQp!csOOCIST%zmmD1Qnd=_OZCPH$afMKzhx3N&rJX0!t|ww24%ETV@Vl328_$ z09h|F%Qu}oiy)^tK`pI*@cfC~B&SwYTzWyYuTSq?xlnSDk5mOpEKlM540B~O$6+kzE+h-o0`lLd+0CwQjkA)O0))b;=ieXeu+k-f$P&lHE3bA(y-LNX7a2n^dP+4d0N`@$Wc+zzE+#yPI+ew%CQrd zH|}M{WW7Y*y_dbewZ)?iRjB(M+yqjkY>iU@Tus!S*Gu9O6K&cknzghv_tz!Nawu|& zT>);`H~vNL?T@KyevB#06K(A{^2YITqu1_sc6R%CnT`Ez9qeGOv^2Xa`kM|`elr*r z86i(>zTOEvr~CZ6X#Qx1qT z-GvpVd7Rwl(k`^#e$JaLGFs)7YWtp7?5sZM~?ctG63Z!$HLsTURz!3O5_&fLO+ zJrfh9KR?%UcmAaR<^x5FeraqRFc@5JN$oBoq%cMV=o6o;{oiaNN1FcGZQ`6*lb++$OXlQs_8>jz1 zqYLQJ!B}szQ|shdgeCB%u(Pu&AS*bo%TTy>HZ;uUd7VBMh1otA3lKEGVU;;5Qb)7IuNFLw~wDrMBk5Vjt$?4RS0}Rzyzw}a70E1UXg!l z?UytMhk(*n4dl8#6h@lJrOlyNsoCtlcu$C*i8l9u-2Dj zQ=rRtL(oMtC3Qf)v@cVe1Vc^|h9mXcqzMy94(-hrppmOW=JfZ=!-5whVZefVij%5w zus7Qk-iP5*P-KZCVbNy$OhHE!qVXD@CMcH$Pg*shg*|!*ayZ!h`-qU26go!GRjl{ zSVDpelT*mOBqAe*l{421QG8}&3#%^%8IaqjUfcFW{zPjtaMm$OiA7p+u+?Xu1#S({ z44j;GqUBy#60nT+_U?bO;_DA0f z7UHlVLUkT6-kAS{oD@gAo?;G+v7P}tF8XcN-ml^O6J#CeQMr9ho)IB#5ip!)Al z4rPB|pZDs76aM<;7$Fgb49y0ox9MUS#O$)Ia-Z8bMp(@GMIiTFxnf%FCB?@VG`giz zY@?Dc=AasYK;WtxK!)~=@*SO+HcB91V9^qX-2F#XfzzPsnsvk)!Tp zQ^>G-fm%rjGR$&?vpK{|-nt5l!C!oh1&6?L{D_prNXR4#?N!baiT_t7_6Yt zQumf2r>PHppviRoacW(90er4qr|#*J9`WqjTHt1%H9vn36W-gT!geW~xrYBbzd_NH zgIVHZCuW$DShg|={np1Uz0HG)@kXoMb&Sj{JoNXI;4KeIGNw_g`P4LF(u9)}fd}TR zt^5GD8OYYL+1Tin!vzK*OW`tQ^}4>T*yjc1_V+{8v4a4QVHCH>ZL>ApZz=HAk3w)T zXtSlg01LC##+VRf5h4|3RKbz*V1P1p=g7pyFw!J`7)ZAPiJl13HEVROe55^;)syP( z?T*#|9AK+o0WUNjy`!g>2uNlThcSKP&#tbVU^CuvUq1;0#zSMMW7tUhGpBx?oWxX- zcn+QF%xZJp&qiGlcBeQhnH!qayte&Z(yNoES^Ytq&+z^1(bI3LaCWC-?_~kjzvE68 zO`v9Uy8VHiIgy;%`y9D?21!X!^M4%w>|QR(-~RIo5$uj0xCnB6m+KYoo>h$wqUs7f zJv>syeQOR0%$V_CqM4)~s+rarkAkamVN4`i;ias+3h27NjVjNTR7p?6tp3A;gVm{G z)JZ63Ur%ORe~a2jx1&xm2`A=YV|A=!yJZyDn(OHYg4)4be*F-King#?T2}QzSzS?# zQTKM4?`d9q$8EZ6=M#j7^KUZTpR2geI)ZaH%yY#2E<}JXS(w#b&Lvz50xVOgI zA&1=^fIF6K%20==khR-xJ1f9(e9@Et_Y5qM24l*>R_G99dTftP08de15*Ewv3R){F zEqRZAV73X6I(AleoP=cVw@pMJ9qrNs063n{M3H!Qab^4XJZSk0sVCvY5IpgHbKm-U zmk)dV`nQh(MKRHLn?!%H?k(cvrxDOw7W_hCFxZc80e;4P`ANd8!|(}3AbWfJJ7A93 zWmGHfV>XSiP1>6u_nuliYO|5OeIih;6kaCNnKX)z?U`OXLBlgLLM*fLCtISKh89D* z0kzor`a5t-3-Kq~#dCT-M@zZCb)rv`Vm7S{Jvfl;>87RvLAxGLU4IvHKes6cQUcHf zwOyZ94Uoc8o8tr-HHPaZHMUd3#kD4Y(5|yNS!|!05idQjjqw>qR-<_#MK zH0D(+T)LntG}lQXt?tx^vwh92KYoN8OmR`YjXnyJ^!qVGcyN(^b=EA#Q$t;$TYFKA1l~ zB6*r9s}Pkg+SM!<>+1*OzpfDf@cw#7`P(4Y-zufQ=Ncn?hV{6s;M8+^Nt*p0@AbZL zUAde+I4U{AzO;FdCA2!FI?mGl57JS&4225}kixy~JaT@~urVBY6i0$--MOEYB9gDf z|9fr@PM0_VAz2bT5j$K6ojZ|3D?D=8xn}@>~avq>^3$| zepSAoisfU`3D1MZGnD*Uo@k(^nQ!M;ko&3@^t6swWnSsou7Sby5!ALYnA`Ibr=nj6 z4W%S`Zn~Lz5RHFdztU%2FS~sG(vIv7fvYSN#;IEUrHlO2Rg@`R&ELn%9RKzf7bxyR zY7g@baSMq}3V^u5V7>xtj$2$j*U30E`VuVGry~Ln1U_e%_oQWy_eGOm03t`m2^3qn zk&mGV6+cyste8e}eX*^r#S7(qhN=t_MUI;%XXycFaGQ81M;9lZ!Ba6Mc& z4g*@99sb)JAlQ8ENv=L4G;k%VgY(Ic9OiAg~ySAxex=n6s3T>->ZbXaSMp=ds!eY2RUR;6Qu`$FoHa}SG zZW>nWNkj(RJoWxry*X?=g%p##Au1*1^a#Iye2qrb_o#fGiK*Oq>Z8Qsic^ZnQ_GeB z;RB#i2s(0-ov#EI8MWunk8&%^;&2PYI!ksrxMOJ96cUVfhr#G~E)2PI4?>Q=OO!bq ze)ssiYd}HC4A!gp{79QZqb&P7+63Q$gvb>p8ATBAdp{yl8FvG= z^_l$Z-F3gPJMmIvZ01$zak6?&FyFcVn?Qs7`C`sdyoEE?!P6;|>0lf0Hb_Apos#)C z?q|&ug0@U3S(y`HeD%c*{Gf%}(E`rdCwPE6?8H3hh-9luCWN7{2E8YQnL${pJi#V2 z{9UBIc*xVdE;xq71 z0FY-PJHT933VPJBzH|>^u$arhM`m~hpqgfC01P&?xBr$A5^|BH!+e-h85jX71U}&3 zW68Q$aQ^8ce@=ygqmoA85$M<|HT0(@7@@pGolzMaKd>z}OgWuO|}!wvGfKuZiIeW&1^j#e{(8ZH2g2ry8^#j&v&b90&Z{SygCXxXdpcr!7rv&C`>^9tX)7qSB! zhmeBcDNxt33J+$IuQRRh@evgYfiu@--`1w_Sv?bzHGYBn2HSA+@~Y&hivsthYVvwC z0K|o3YiP;u?NN zb;ymWNuzr`OviT6pAP^~(>Js%OA{#OQ6%oIvH7m-IxmAQ}q>}Hg(s!ny!ihk%k z;eub!qwZ!j#o6aXN0+ZPCtfF!WV)#d;9KzbNJ+?I=YB!OC+DAVv;o1Jyt?Mnh;YDLuX?%M9QT8E?K9w58`%lxOYa;`2Hxv;omX-&_o z<1nY%_I(p51APD1=aVi*ouBjZo`N^D~(Gfr-4)*rlp}4++`Q zB{Lga6oV9!cy?i-%472+UH5!!FVfq>!h&6mAqA@_$gfDe3D~8k@ayQqF7G_UIp!M(2UWhWQ)An$gzC-r} z?mx8iGm>60<9Saq6OH~?)VbPt?WU@|{c=egbZaPUIQ;ZzFIm*ruS3riAmHgjU)3J+ zcWHKk-UD}6*Bq_tuW*BuVWd>x(JBCalDNOa@h=Ej0K&Gl#|Q43pk9~XVCFdT2@O}u zc(n`ASX;|t=od7H;|~woRc&$ZR_&(z8C_Nssr#+eHA~;_q&86c=u?ZoX(ZinmD4c* zv(68kN`Y!caDu|dCTrNRe0dam9+zWk#Gk8%M-v|Hq9v{6FUI!Wez)R*sewT*d1FU^ z|8NWY-QW5Nvp`uzD-!f}H?7nLf40uNa~tu`FiIS9?JMalHX2jW9c%CH{S3g6D3dB? zi6D!^50~@#_|~SDeU=B7zGukm^Ut+Sn&({R32b#YF2&68DI|`Z>Vd9NjkW)B#*)ICqq z$kSCzlU@NG8;IAa+S8yjvT4KVe4b(naq;e>1pxjc!pNaq6VsBX?}0<+Gn5P?T>rEB zefBJ37Tw$v-@&)dn&!X-ib2A8YaNn04kd@=Q9IkahbP5qxx=Ywbgjew6rf}j7^J}6 z)5gE%1mkf%V64QdV?)Y{JMeposYf#1E8gDy82?vp|8Y z#BDGpuQWJTp_L0|AMLG+c^qWN#0aqb0GCT)G78AA2JK5nZ`CR}fb{LPY zv#l^|gU|+=dw%?!GWx!?=nZa%HI84vWMviTA8zww6BoU__3d9c%D}|($NF4tA{@sX zjxH|SSx~L-nHqEj?2i{S;TXdD?#F)f-)Aw zO^2V^iCM+1kLfWwYG=B||t$7pofy1zViObLqOcxlthwj(q%m{g_Cu zc1cE11?LUdxb`P30SlIN(ZS)CEVn;z!R;G5jYD>Q!QvUnHV-LXc?fsZuR9NZ3^1^4 zjf|?;*!~bAS3nI@BS!jG)yh6#oJzFwA|+T`$aEHDWS?GbnV#k!pA93q-RWg?U-NDe z@*`9b?G1$0jg3(s7scJ~uP{F@^4aEOozo;G@jI%?W421v5&*gKS?fn`|) z1){`ZnseLpW5P<&8_Zh!iIfpW`&lel9_hL~uAc6bh34*n7|PSFc00Vw68b-C>YvbU z2l#VjGA5ZUEHr0ud92i4JJ0aX#w;Q z+xs-@`u4l)8u z1at1zFpRL0oD!l;iP~56B21mo&o#gA2v5QWxkM1+&^|yu^8Y zVUXuE-92@GXQ@~*tVpeZ3=m$S2Q75r(6`j`BKXVC`^vs6e_HBW%m$dWvD%?!K6_FTD<-Ck7imfM_`a?fP-ZeFWKMU26koL z8!RE1H$cy_bqkxN%ru?pDhrYv5L>;0=Cww1MHmH5l>AxSTjSE@sIy#LXD2NaENHX3 zP>nexMuj6lr$S3qI)`4FBhUl^1+AnC*sA_FumXlv%={!H=;KnQcn*Bp3C>GT$=^K`PHa0xOsq^c0P(Wd7Tjtusk+*K z!TNtMPx1Ne*sLEZmw}!Lh|0|CpASXve$2L<-pOHKIFw(vyyytim20;5BP>aqjBxX z!q#@goaKq3;TS-=RMP~{wjVPCYEBg25(X95qPbMgCnpYpYtwSvRU{gnrJ9BowHx~# zCi65ScQ|16pe-{qvvA|-5?a^3Eu2@pFj(0s4By4bz&;6v z^~JlB6U;Jztw|jfs=?vre$SOVk8gIZ;%V1RsK6i1zvlZDBMdSq7|h@^DcmZm`cb0m z)k|EEfe_6*pz8r7;05Of9+?S@RFnKqF^H3v&0DY=0hQftPTx)P#M z(DU@!v%w{gz5L6CG6Vv5LdgyD5||!?@z-}m#+oF$l3WUaVkB48OAq<0DFUkpAlPYA zh`PbFHTb7P@2e^;es=b3Vj0xYFtjk(Q)0>dYp5wGg0>fUSwg}7qKn09Vm|C>eO2Zx zJ+hO~`iF|FQ0kN`j-CE#i4wfga z9{nY_KA&qJ548_s_0~kpVs?Nr4{+qf>Eib=x7B6a{Jgt9jfj9h^X2W=H{{a za$yI^sCcOT9{}BRLr2zsV|o&JO!5bp(MIOrUF(ZwVOMzQe$}bHp}2$~mXVnTzWGUn z%bf=9&%2W?(YZi-12%Q0hdbNReh|p-(c#c7Uq3%_hg7_D0n8Yb>tNiBGC_SuRxMGC zdc<5sZr2C#R$QXe)xUF4#I2q-+e)ZI3lT@Md zQcYgRbkDFYy!ppev8x|2(rX`22Htliei*r|DEz!=k}kH|o!zjC9}a={-JqDcCJ+Pe zl`|YSKQJhBu14IO=fIxPYin(RL!tz)Vgw5y4Nc-Ogs5nCp2tI7PSC;WJSl#a17mMIk^KY+9{Z z1$&*N?sU{DrS>|i>Cz5??V!AqJYD{Gh|oV^j6|R^^hU4W)@4^i2h}OyKd`=aFoyTV zMB!_lq=_a^PxIN;(z+9OxF?Ij-D-b<#6!lXRZq=p4J~dRF!(JVGaPZ7cf7*Rp*Hs- zgceEw+QzB}pm9N2IbZ>NaaNG}LkDsXU<%rUmf}AZm5^xp@q?HJ1Zb%D)8k22B|Ygs zTS7)f9y;&u%1JZ*T5JoNa<5GhdA^#tGK?Z&;nK_h7|jh3P}nLEd0F-BIRt}lNN^uV zmp$XNRJ8CmFej;^qDMO`4gPatds*KT$=Q8*W))er2 zYM&;6)7ivpg63oW;^(Djgwh?;VWccTP#3V*{0q3;zhf5B{P<)b?XN;K(=875J9p}3 z?*1MLeWL}ePWwBGU1|#ejtncLmV5NZZ7=_l&*ONAmtMcxOJ${>X6IFhUOrmVSA2R{ zdJD?}(pyRdU};@}AmFezKnMt}0eczG!DJ>tm*G5J88r9Y&8>+13sCWN(=A#~5CJ$7 z#!pHhu<=rpg9;RKPgS2)`feuxm=qj9UIBnQ_zC85p#HoLi+Z)i0G(6FtBYgVB$32r%eUgtbd-;C=c-IYS delta 28089 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 delta 26204 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 Py;TEUBb^+rb65WZavE!^ diff --git a/frontend/__snapshots__/scenes-app-max-ai--thread-with-failed-generation--dark.png b/frontend/__snapshots__/scenes-app-max-ai--thread-with-failed-generation--dark.png index eccd3471a1f511423f11f72e4e6e794278b48601..e22dc0db8701991d86a8f5012a0370ed6b0fac5e 100644 GIT binary patch literal 16222 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 PE+Q?V@TMGU^!~pAa)( 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 diff --git a/frontend/__snapshots__/scenes-app-max-ai--thread-with-failed-generation--light.png b/frontend/__snapshots__/scenes-app-max-ai--thread-with-failed-generation--light.png index da0efa6c70d732c85004dbc02fbd7c3375fa723d..483b9a3ff881e10234ce0d8e43362f82a962b083 100644 GIT binary patch literal 16322 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 literal 16249 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 diff --git a/frontend/src/lib/lemon-ui/icons/categories.ts b/frontend/src/lib/lemon-ui/icons/categories.ts index 879673b1c94..1f07cd24ec2 100644 --- a/frontend/src/lib/lemon-ui/icons/categories.ts +++ b/frontend/src/lib/lemon-ui/icons/categories.ts @@ -52,9 +52,18 @@ export const OBJECTS = { 'IconGearFilled', 'IconStack', 'IconSparkles', + 'IconPlug', 'IconPuzzle', ], - People: ['IconPeople', 'IconPeopleFilled', 'IconPerson', 'IconProfile', 'IconUser', 'IconGroups'], + People: [ + 'IconPeople', + 'IconPeopleFilled', + 'IconPerson', + 'IconProfile', + 'IconUser', + 'IconGroups', + 'IconShieldPeople', + ], 'Business & Finance': ['IconStore', 'IconCart', 'IconReceipt', 'IconPiggyBank', 'IconHandMoney'], Time: ['IconHourglass', 'IconCalendar', 'IconClock'], Nature: ['IconDay', 'IconNight', 'IconGlobe', 'IconCloud', 'IconBug'], @@ -183,6 +192,7 @@ export const TEAMS_AND_COMPANIES = { 'IconPageChart', 'IconSampling', 'IconLive', + 'IconRefresh', 'IconBadge', ], Replay: [ diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json index 805533b1f5c..2b74ea5a304 100644 --- a/frontend/src/queries/schema.json +++ b/frontend/src/queries/schema.json @@ -1089,6 +1089,10 @@ "content": { "type": "string" }, + "done": { + "description": "We only need this \"done\" value to tell when the particular message is finished during its streaming. It won't be necessary when we optimize streaming to NOT send the entire message every time a character is added.", + "type": "boolean" + }, "type": { "const": "ai", "type": "string" @@ -6296,12 +6300,16 @@ "content": { "type": "string" }, + "done": { + "const": true, + "type": "boolean" + }, "type": { "const": "ai/failure", "type": "string" } }, - "required": ["type"], + "required": ["type", "done"], "type": "object" }, "FeaturePropertyFilter": { @@ -7618,12 +7626,17 @@ "content": { "type": "string" }, + "done": { + "const": true, + "description": "Human messages are only appended when done.", + "type": "boolean" + }, "type": { "const": "human", "type": "string" } }, - "required": ["type", "content"], + "required": ["type", "content", "done"], "type": "object" }, "InsightActorsQuery": { @@ -11687,12 +11700,17 @@ "content": { "type": "string" }, + "done": { + "const": true, + "description": "Router messages are not streamed, so they can only be done.", + "type": "boolean" + }, "type": { "const": "ai/router", "type": "string" } }, - "required": ["type", "content"], + "required": ["type", "content", "done"], "type": "object" }, "SamplingRate": { @@ -12837,6 +12855,9 @@ } ] }, + "done": { + "type": "boolean" + }, "plan": { "type": "string" }, diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts index 4ea06bcbb8f..2697ecc4b95 100644 --- a/frontend/src/queries/schema.ts +++ b/frontend/src/queries/schema.ts @@ -2478,11 +2478,18 @@ export enum AssistantMessageType { export interface HumanMessage { type: AssistantMessageType.Human content: string + /** Human messages are only appended when done. */ + done: true } export interface AssistantMessage { type: AssistantMessageType.Assistant content: string + /** + * We only need this "done" value to tell when the particular message is finished during its streaming. + * It won't be necessary when we optimize streaming to NOT send the entire message every time a character is added. + */ + done?: boolean } export interface VisualizationMessage { @@ -2490,16 +2497,20 @@ export interface VisualizationMessage { plan?: string reasoning_steps?: string[] | null answer?: AssistantTrendsQuery | AssistantFunnelsQuery + done?: boolean } export interface FailureMessage { type: AssistantMessageType.Failure content?: string + done: true } export interface RouterMessage { type: AssistantMessageType.Router content: string + /** Router messages are not streamed, so they can only be done. */ + done: true } export type RootAssistantMessage = diff --git a/frontend/src/scenes/max/QuestionInput.tsx b/frontend/src/scenes/max/QuestionInput.tsx index f39eb4d1132..55ea5371230 100644 --- a/frontend/src/scenes/max/QuestionInput.tsx +++ b/frontend/src/scenes/max/QuestionInput.tsx @@ -25,7 +25,7 @@ export function QuestionInput(): JSX.Element { className={clsx( !isFloating ? 'w-[min(44rem,100%)] relative' - : 'w-full max-w-200 sticky z-10 self-center p-1 mx-3 mb-3 bottom-3 border border-[var(--glass-border-3000)] rounded-[0.625rem] backdrop-blur bg-[var(--glass-bg-3000)]' + : 'w-full max-w-192 sticky z-10 self-center p-1 mx-4 mb-3 bottom-3 border border-[var(--glass-border-3000)] rounded-[0.625rem] backdrop-blur bg-[var(--glass-bg-3000)]' )} > } + center + className="shrink" > {suggestion} diff --git a/frontend/src/scenes/max/Thread.tsx b/frontend/src/scenes/max/Thread.tsx index 8a2f299a312..a4fa9132987 100644 --- a/frontend/src/scenes/max/Thread.tsx +++ b/frontend/src/scenes/max/Thread.tsx @@ -1,4 +1,5 @@ import { + IconRefresh, IconThumbsDown, IconThumbsDownFilled, IconThumbsUp, @@ -11,91 +12,71 @@ import clsx from 'clsx' import { useActions, useValues } from 'kea' import { BreakdownSummary, PropertiesSummary, SeriesSummary } from 'lib/components/Cards/InsightCard/InsightDetails' import { TopHeading } from 'lib/components/Cards/InsightCard/TopHeading' -import { IconRefresh } from 'lib/lemon-ui/icons' import { IconOpenInNew } from 'lib/lemon-ui/icons' +import { LemonMarkdown } from 'lib/lemon-ui/LemonMarkdown' import posthog from 'posthog-js' import React, { useMemo, useRef, useState } from 'react' import { urls } from 'scenes/urls' import { Query } from '~/queries/Query/Query' -import { AssistantMessageType, HumanMessage, InsightVizNode, NodeKind, VisualizationMessage } from '~/queries/schema' +import { + AssistantMessage, + AssistantMessageType, + FailureMessage, + HumanMessage, + InsightVizNode, + NodeKind, + VisualizationMessage, +} from '~/queries/schema' import { maxLogic, MessageStatus, ThreadMessage } from './maxLogic' -import { castAssistantQuery, isFailureMessage, isHumanMessage, isVisualizationMessage } from './utils' +import { + castAssistantQuery, + isAssistantMessage, + isFailureMessage, + isHumanMessage, + isVisualizationMessage, +} from './utils' export function Thread(): JSX.Element | null { const { thread, threadLoading } = useValues(maxLogic) - const { retryLastMessage } = useActions(maxLogic) return (

)} - + )} ) diff --git a/frontend/src/scenes/max/__mocks__/chatResponse.mocks.ts b/frontend/src/scenes/max/__mocks__/chatResponse.mocks.ts index 3bd38eb1e62..dffb3cfa056 100644 --- a/frontend/src/scenes/max/__mocks__/chatResponse.mocks.ts +++ b/frontend/src/scenes/max/__mocks__/chatResponse.mocks.ts @@ -1,17 +1,23 @@ import { AssistantGenerationStatusEvent, AssistantGenerationStatusType } from '~/queries/schema' -import chatResponse from './chatResponse.json' -import failureResponse from './failureResponse.json' +import failureMessage from './failureMessage.json' +import summaryMessage from './summaryMessage.json' +import visualizationMessage from './visualizationMessage.json' function generateChunk(events: string[]): string { return events.map((event) => (event.startsWith('event:') ? `${event}\n` : `${event}\n\n`)).join('') } -export const chatResponseChunk = generateChunk(['event: message', `data: ${JSON.stringify(chatResponse)}`]) +export const chatResponseChunk = generateChunk([ + 'event: message', + `data: ${JSON.stringify(visualizationMessage)}`, + 'event: message', + `data: ${JSON.stringify(summaryMessage)}`, +]) const generationFailure: AssistantGenerationStatusEvent = { type: AssistantGenerationStatusType.GenerationError } const responseWithReasoningStepsOnly = { - ...chatResponse, + ...visualizationMessage, answer: null, } @@ -22,4 +28,4 @@ export const generationFailureChunk = generateChunk([ `data: ${JSON.stringify(generationFailure)}`, ]) -export const failureChunk = generateChunk(['event: message', `data: ${JSON.stringify(failureResponse)}`]) +export const failureChunk = generateChunk(['event: message', `data: ${JSON.stringify(failureMessage)}`]) diff --git a/frontend/src/scenes/max/__mocks__/failureResponse.json b/frontend/src/scenes/max/__mocks__/failureMessage.json similarity index 100% rename from frontend/src/scenes/max/__mocks__/failureResponse.json rename to frontend/src/scenes/max/__mocks__/failureMessage.json diff --git a/frontend/src/scenes/max/__mocks__/summaryMessage.json b/frontend/src/scenes/max/__mocks__/summaryMessage.json new file mode 100644 index 00000000000..011565dc126 --- /dev/null +++ b/frontend/src/scenes/max/__mocks__/summaryMessage.json @@ -0,0 +1,5 @@ +{ + "type": "ai", + "content": "Looks like no pageviews have occured. Get some damn users.", + "done": true +} diff --git a/frontend/src/scenes/max/__mocks__/chatResponse.json b/frontend/src/scenes/max/__mocks__/visualizationMessage.json similarity index 99% rename from frontend/src/scenes/max/__mocks__/chatResponse.json rename to frontend/src/scenes/max/__mocks__/visualizationMessage.json index 5fed25c08bf..cabfe93ca1c 100644 --- a/frontend/src/scenes/max/__mocks__/chatResponse.json +++ b/frontend/src/scenes/max/__mocks__/visualizationMessage.json @@ -64,5 +64,6 @@ "smoothingIntervals": 1, "yAxisScaleType": null } - } + }, + "done": true } diff --git a/frontend/src/scenes/max/maxLogic.ts b/frontend/src/scenes/max/maxLogic.ts index 0ff61094dee..04f36c6cd1c 100644 --- a/frontend/src/scenes/max/maxLogic.ts +++ b/frontend/src/scenes/max/maxLogic.ts @@ -4,7 +4,7 @@ import { createParser } from 'eventsource-parser' import { actions, afterMount, connect, kea, key, listeners, path, props, reducers, selectors } from 'kea' import { loaders } from 'kea-loaders' import api from 'lib/api' -import { isHumanMessage, isRouterMessage, isVisualizationMessage } from 'scenes/max/utils' +import { isHumanMessage } from 'scenes/max/utils' import { projectLogic } from 'scenes/projectLogic' import { @@ -13,6 +13,7 @@ import { AssistantGenerationStatusType, AssistantMessageType, FailureMessage, + HumanMessage, NodeKind, RefreshType, RootAssistantMessage, @@ -28,12 +29,14 @@ export interface MaxLogicProps { export type MessageStatus = 'loading' | 'completed' | 'error' export type ThreadMessage = RootAssistantMessage & { - status?: MessageStatus + status: MessageStatus } -const FAILURE_MESSAGE: FailureMessage = { +const FAILURE_MESSAGE: FailureMessage & ThreadMessage = { type: AssistantMessageType.Failure, content: 'Oops! It looks like I’m having trouble generating this trends insight. Could you please try again?', + status: 'error', + done: true, } export const maxLogic = kea([ @@ -48,7 +51,7 @@ export const maxLogic = kea([ setThreadLoaded: (testOnlyOverride = false) => ({ testOnlyOverride }), addMessage: (message: ThreadMessage) => ({ message }), replaceMessage: (index: number, message: ThreadMessage) => ({ index, message }), - setMessageStatus: (index: number, status: ThreadMessage['status']) => ({ index, status }), + setMessageStatus: (index: number, status: MessageStatus) => ({ index, status }), setQuestion: (question: string) => ({ question }), setVisibleSuggestions: (suggestions: string[]) => ({ suggestions }), shuffleVisibleSuggestions: true, @@ -149,9 +152,7 @@ export const maxLogic = kea([ ) }, askMax: async ({ prompt }) => { - actions.addMessage({ type: AssistantMessageType.Human, content: prompt }) - let generatingMessageIndex: number = -1 - + actions.addMessage({ type: AssistantMessageType.Human, content: prompt, done: true, status: 'completed' }) try { const response = await api.chat({ session_id: props.sessionId, @@ -173,21 +174,15 @@ export const maxLogic = kea([ return } - if (isRouterMessage(parsedResponse)) { + if (values.thread[values.thread.length - 1].status === 'completed') { actions.addMessage({ ...parsedResponse, - status: 'completed', + status: !parsedResponse.done ? 'loading' : 'completed', }) - } else if (generatingMessageIndex === -1) { - generatingMessageIndex = values.thread.length - - if (parsedResponse) { - actions.addMessage({ ...parsedResponse, status: 'loading' }) - } } else if (parsedResponse) { - actions.replaceMessage(generatingMessageIndex, { + actions.replaceMessage(values.thread.length - 1, { ...parsedResponse, - status: values.thread[generatingMessageIndex].status, + status: !parsedResponse.done ? 'loading' : 'completed', }) } } else if (event === AssistantEventType.Status) { @@ -197,7 +192,7 @@ export const maxLogic = kea([ } if (parsedResponse.type === AssistantGenerationStatusType.GenerationError) { - actions.setMessageStatus(generatingMessageIndex, 'error') + actions.setMessageStatus(values.thread.length - 1, 'error') } } }, @@ -205,47 +200,28 @@ export const maxLogic = kea([ while (true) { const { done, value } = await reader.read() - parser.feed(decoder.decode(value)) - if (done) { - if (generatingMessageIndex === -1) { - break - } - - const generatedMessage = values.thread[generatingMessageIndex] - if (generatedMessage && isVisualizationMessage(generatedMessage) && generatedMessage.plan) { - actions.setMessageStatus(generatingMessageIndex, 'completed') - } else if (generatedMessage) { - actions.replaceMessage(generatingMessageIndex, FAILURE_MESSAGE) - } else { - actions.addMessage({ - ...FAILURE_MESSAGE, - status: 'completed', - }) - } break } } } catch (e) { captureException(e) - if (generatingMessageIndex !== -1) { - if (values.thread[generatingMessageIndex]) { - actions.replaceMessage(generatingMessageIndex, FAILURE_MESSAGE) - } else { - actions.addMessage({ - ...FAILURE_MESSAGE, - status: 'completed', - }) - } + if (values.thread[values.thread.length - 1]?.status === 'loading') { + actions.replaceMessage(values.thread.length - 1, FAILURE_MESSAGE) + } else if (values.thread[values.thread.length - 1]?.status !== 'error') { + actions.addMessage({ + ...FAILURE_MESSAGE, + status: 'completed', + }) } } actions.setThreadLoaded() }, retryLastMessage: () => { - const lastMessage = values.thread.filter(isHumanMessage).pop() + const lastMessage = values.thread.filter(isHumanMessage).pop() as HumanMessage | undefined if (lastMessage) { actions.askMax(lastMessage.content) } diff --git a/frontend/src/scenes/max/utils.ts b/frontend/src/scenes/max/utils.ts index 6c6d77204f5..0bfa5757863 100644 --- a/frontend/src/scenes/max/utils.ts +++ b/frontend/src/scenes/max/utils.ts @@ -1,5 +1,6 @@ import { AssistantFunnelsQuery, + AssistantMessage, AssistantMessageType, AssistantTrendsQuery, FailureMessage, @@ -22,6 +23,10 @@ export function isHumanMessage(message: RootAssistantMessage | undefined | null) return message?.type === AssistantMessageType.Human } +export function isAssistantMessage(message: RootAssistantMessage | undefined | null): message is AssistantMessage { + return message?.type === AssistantMessageType.Assistant +} + export function isFailureMessage(message: RootAssistantMessage | undefined | null): message is FailureMessage { return message?.type === AssistantMessageType.Failure } diff --git a/package.json b/package.json index c8b74b26479..9be82875a40 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,8 @@ "typegen:check": "kea-typegen check", "typegen:watch": "kea-typegen watch --delete --show-ts-errors", "typegen:clean": "find frontend/src -type f -name '*Type.ts' -delete", - "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build", + "storybook": "DEBUG=0 storybook dev -p 6006", + "build-storybook": "DEBUG=0 storybook build", "dev:migrate:postgres": "export DEBUG=1 && source env/bin/activate && python manage.py migrate", "dev:migrate:clickhouse": "export DEBUG=1 && source env/bin/activate && python manage.py migrate_clickhouse", "prepare": "husky install", @@ -77,7 +77,7 @@ "@microlink/react-json-view": "^1.21.3", "@monaco-editor/react": "4.6.0", "@posthog/hogvm": "^1.0.58", - "@posthog/icons": "0.8.5", + "@posthog/icons": "0.9.1", "@posthog/plugin-scaffold": "^1.4.4", "@react-hook/size": "^2.1.2", "@rrweb/types": "2.0.0-alpha.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad4f940271f..0579185ebe5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,8 +53,8 @@ dependencies: specifier: ^1.0.58 version: 1.0.58(luxon@3.5.0) '@posthog/icons': - specifier: 0.8.5 - version: 0.8.5(react-dom@18.2.0)(react@18.2.0) + specifier: 0.9.1 + version: 0.9.1(react-dom@18.2.0)(react@18.2.0) '@posthog/plugin-scaffold': specifier: ^1.4.4 version: 1.4.4 @@ -5426,8 +5426,8 @@ packages: luxon: 3.5.0 dev: false - /@posthog/icons@0.8.5(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-bFPMgnR3ZaNnMQ81OznYFQRd7KaCqXcI8xS3qS49UBkSZpKeJgH86JbWXBXI2q2GZWX00gc+gZxEo5EBkY7KcQ==} + /@posthog/icons@0.9.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-9zlU1H7MZm2gSh1JsDzM25km6VDc/Y7HdNf6RyP5sUiHCHVMKhQQ8TA2IMq55v/uTFRc5Yen6BagOUvunD2kqQ==} peerDependencies: react: '>=16.14.0' react-dom: '>=16.14.0' diff --git a/posthog/demo/matrix/manager.py b/posthog/demo/matrix/manager.py index 08f45ef163e..8c69ef06a8d 100644 --- a/posthog/demo/matrix/manager.py +++ b/posthog/demo/matrix/manager.py @@ -137,6 +137,7 @@ class MatrixManager: ) for cohort in Cohort.objects.filter(team=team): cohort.calculate_people_ch(pending_version=0) + team.project.save() team.save() def _save_analytics_data(self, data_team: Team): diff --git a/posthog/demo/products/hedgebox/matrix.py b/posthog/demo/products/hedgebox/matrix.py index 1ae9da06c1f..5990f7a7442 100644 --- a/posthog/demo/products/hedgebox/matrix.py +++ b/posthog/demo/products/hedgebox/matrix.py @@ -98,6 +98,8 @@ class HedgeboxMatrix(Matrix): def set_project_up(self, team, user): super().set_project_up(team, user) + team.project.product_description = "Dropbox for hedgehogs. We're a file sharing and collaboration platform. Free for limited personal use, with paid plans available." + team.autocapture_web_vitals_opt_in = True # Actions interacted_with_file_action = Action.objects.create( @@ -882,6 +884,3 @@ class HedgeboxMatrix(Matrix): ) except IntegrityError: pass # This can happen if demo data generation is re-run for the same project - - # autocapture - team.autocapture_web_vitals_opt_in = True diff --git a/posthog/schema.py b/posthog/schema.py index 6680ac5a4b3..1f4beabe0b8 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -247,6 +247,14 @@ class AssistantMessage(BaseModel): extra="forbid", ) content: str + done: Optional[bool] = Field( + default=None, + description=( + 'We only need this "done" value to tell when the particular message is finished during its streaming. It' + " won't be necessary when we optimize streaming to NOT send the entire message every time a character is" + " added." + ), + ) type: Literal["ai"] = "ai" @@ -850,6 +858,7 @@ class FailureMessage(BaseModel): extra="forbid", ) content: Optional[str] = None + done: Literal[True] = True type: Literal["ai/failure"] = "ai/failure" @@ -1047,6 +1056,7 @@ class HumanMessage(BaseModel): extra="forbid", ) content: str + done: Literal[True] = Field(default=True, description="Human messages are only appended when done.") type: Literal["human"] = "human" @@ -1443,6 +1453,7 @@ class RouterMessage(BaseModel): extra="forbid", ) content: str + done: Literal[True] = Field(default=True, description="Router messages are not streamed, so they can only be done.") type: Literal["ai/router"] = "ai/router" @@ -5536,6 +5547,7 @@ class VisualizationMessage(BaseModel): extra="forbid", ) answer: Optional[Union[AssistantTrendsQuery, AssistantFunnelsQuery]] = None + done: Optional[bool] = None plan: Optional[str] = None reasoning_steps: Optional[list[str]] = None type: Literal["ai/viz"] = "ai/viz" From 3b2f77da6b39c23889401c3b56429ab8023dd8f1 Mon Sep 17 00:00:00 2001 From: Oliver Browne Date: Mon, 18 Nov 2024 13:58:59 +0200 Subject: [PATCH 11/27] fix(err): add issue name and description (#26200) --- ...errortrackingissue_description_and_more.py | 22 ++ posthog/migrations/max_migration.txt | 2 +- .../models/error_tracking/error_tracking.py | 2 + ...75c285bc510766c175b1b8c4e4002e04ff503.json | 21 +- ...f1997fc9cf1fb3436d742e9374ad4f2d55614.json | 27 +- ...f68cd3acdf4dabc1eff87ae7bce49cee9328a.json | 79 +++--- ...c165376f43116b85921c62b36b1b8e85562b0.json | 248 +++++++++--------- ...491f908b5047e86b13fbff22cf8f58e85cc81.json | 47 ++++ ...9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89.json | 35 +-- ...3d0e39f01b19b243d724b09f3ce6617d03dc7.json | 21 +- ...8686c4393f6420e61b6b141143974ff362213.json | 90 ++++--- ...873bf6d1d43884cd628df5b36978dd761b025.json | 35 +-- ...ab521aa6f393027c399a0c40139f5f8a0a45e.json | 22 +- ...13132c3e7bf297834cd42228b35bf3e424dd7.json | 18 -- ...8dc46c18f4950a7951d2c412dcba4d13fb56b.json | 101 +++---- ...554065b71152389f98d35532c6b332d5a4c9d.json | 20 +- ...4711bdfb8cf78e362ccda8bc14e92324d51f8.json | 34 +-- ...d687eb545ee9d4ccbb8b69c958a357d49f687.json | 23 +- ...b59cc00f3125413f4032ac3647a6b5ee1a632.json | 35 +-- ...ec3544acd0228776b8535f22438db59002e1f.json | 28 -- ...074995829d1372fe8ec1fd683f9524bcebb8b.json | 43 +-- ...a76bd8a7d96d73983a0c408f32f17da5f483b.json | 22 +- ...52ea79485e403b9e17b6c37259ea0612065ee.json | 35 +-- ...52345454cd3323568c4bef5b8480380287068.json | 248 +++++++++--------- ...93c27fdf4d88145cd7eaf4bbd39e49a7452f6.json | 26 ++ ...856c4cbd8beb519df8212212017dda9d06c51.json | 76 +++--- ...29c948a291ea8218bbbb4e25cd1ad36dbe9f4.json | 26 +- ...af30c682288988fc6f102e8a063be97c3e51c.json | 60 +++-- ...f6c959ba804dab9c1e5ba39979d19782582ea.json | 81 +++--- ...21c0eae35356f7b92e969a12a839b41cd360a.json | 25 +- rust/cymbal/src/frames/resolver.rs | 6 +- rust/cymbal/src/issue_resolution.rs | 48 +++- rust/cymbal/src/lib.rs | 46 +--- rust/cymbal/src/types/mod.rs | 68 +++-- rust/cymbal/tests/resolve.rs | 6 +- rust/cymbal/tests/types.rs | 4 +- 36 files changed, 978 insertions(+), 752 deletions(-) create mode 100644 posthog/migrations/0519_errortrackingissue_description_and_more.py create mode 100644 rust/.sqlx/query-2a1514685491269ca61a0a898d7491f908b5047e86b13fbff22cf8f58e85cc81.json delete mode 100644 rust/.sqlx/query-44eb698252059821770eaaf5b8213132c3e7bf297834cd42228b35bf3e424dd7.json delete mode 100644 rust/.sqlx/query-ad528f712bdaf75a82293018e3dec3544acd0228776b8535f22438db59002e1f.json create mode 100644 rust/.sqlx/query-e0c6790eccd2e7505d86ed570f093c27fdf4d88145cd7eaf4bbd39e49a7452f6.json diff --git a/posthog/migrations/0519_errortrackingissue_description_and_more.py b/posthog/migrations/0519_errortrackingissue_description_and_more.py new file mode 100644 index 00000000000..f3faae82726 --- /dev/null +++ b/posthog/migrations/0519_errortrackingissue_description_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.15 on 2024-11-14 17:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("posthog", "0518_survey_internal_response_sampling_flag"), + ] + + operations = [ + migrations.AddField( + model_name="errortrackingissue", + name="description", + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name="errortrackingissue", + name="name", + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/posthog/migrations/max_migration.txt b/posthog/migrations/max_migration.txt index 54603fe73b4..6a1c8da5c16 100644 --- a/posthog/migrations/max_migration.txt +++ b/posthog/migrations/max_migration.txt @@ -1 +1 @@ -0518_survey_internal_response_sampling_flag \ No newline at end of file +0519_errortrackingissue_description_and_more diff --git a/posthog/models/error_tracking/error_tracking.py b/posthog/models/error_tracking/error_tracking.py index 982f21e4fa3..7e42f55cf9f 100644 --- a/posthog/models/error_tracking/error_tracking.py +++ b/posthog/models/error_tracking/error_tracking.py @@ -17,6 +17,8 @@ class ErrorTrackingIssue(UUIDModel): team = models.ForeignKey(Team, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) status = models.TextField(choices=Status.choices, default=Status.ACTIVE, null=False) + name = models.TextField(null=True, blank=True) + description = models.TextField(null=True, blank=True) class ErrorTrackingIssueAssignment(UUIDModel): diff --git a/rust/.sqlx/query-075421be22b51c50eb74ac1156175c285bc510766c175b1b8c4e4002e04ff503.json b/rust/.sqlx/query-075421be22b51c50eb74ac1156175c285bc510766c175b1b8c4e4002e04ff503.json index a2cb4e3a0a8..35683fb0fb9 100644 --- a/rust/.sqlx/query-075421be22b51c50eb74ac1156175c285bc510766c175b1b8c4e4002e04ff503.json +++ b/rust/.sqlx/query-075421be22b51c50eb74ac1156175c285bc510766c175b1b8c4e4002e04ff503.json @@ -1,12 +1,15 @@ { - "db_name": "PostgreSQL", - "query": "UPDATE cyclotron_jobs SET last_heartbeat = NOW() WHERE id = $1 AND lock_id = $2", - "describe": { - "columns": [], - "parameters": { - "Left": ["Uuid", "Uuid"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "UPDATE cyclotron_jobs SET last_heartbeat = NOW() WHERE id = $1 AND lock_id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Uuid" + ] }, - "hash": "075421be22b51c50eb74ac1156175c285bc510766c175b1b8c4e4002e04ff503" + "nullable": [] + }, + "hash": "075421be22b51c50eb74ac1156175c285bc510766c175b1b8c4e4002e04ff503" } diff --git a/rust/.sqlx/query-085d682315a548d578f63bb48d2f1997fc9cf1fb3436d742e9374ad4f2d55614.json b/rust/.sqlx/query-085d682315a548d578f63bb48d2f1997fc9cf1fb3436d742e9374ad4f2d55614.json index 972b51fccc5..9329bd2f2da 100644 --- a/rust/.sqlx/query-085d682315a548d578f63bb48d2f1997fc9cf1fb3436d742e9374ad4f2d55614.json +++ b/rust/.sqlx/query-085d682315a548d578f63bb48d2f1997fc9cf1fb3436d742e9374ad4f2d55614.json @@ -1,12 +1,21 @@ { - "db_name": "PostgreSQL", - "query": "\n INSERT INTO posthog_errortrackingstackframe (raw_id, team_id, created_at, symbol_set_id, contents, resolved, id, context)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n ON CONFLICT (raw_id, team_id) DO UPDATE SET\n created_at = $3,\n symbol_set_id = $4,\n contents = $5,\n resolved = $6,\n context = $8\n ", - "describe": { - "columns": [], - "parameters": { - "Left": ["Text", "Int4", "Timestamptz", "Uuid", "Jsonb", "Bool", "Uuid", "Text"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "\n INSERT INTO posthog_errortrackingstackframe (raw_id, team_id, created_at, symbol_set_id, contents, resolved, id, context)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n ON CONFLICT (raw_id, team_id) DO UPDATE SET\n created_at = $3,\n symbol_set_id = $4,\n contents = $5,\n resolved = $6,\n context = $8\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Int4", + "Timestamptz", + "Uuid", + "Jsonb", + "Bool", + "Uuid", + "Text" + ] }, - "hash": "085d682315a548d578f63bb48d2f1997fc9cf1fb3436d742e9374ad4f2d55614" + "nullable": [] + }, + "hash": "085d682315a548d578f63bb48d2f1997fc9cf1fb3436d742e9374ad4f2d55614" } diff --git a/rust/.sqlx/query-14332a535d61ab0144d1f4dbb1cf68cd3acdf4dabc1eff87ae7bce49cee9328a.json b/rust/.sqlx/query-14332a535d61ab0144d1f4dbb1cf68cd3acdf4dabc1eff87ae7bce49cee9328a.json index b489060b996..c1b847f8824 100644 --- a/rust/.sqlx/query-14332a535d61ab0144d1f4dbb1cf68cd3acdf4dabc1eff87ae7bce49cee9328a.json +++ b/rust/.sqlx/query-14332a535d61ab0144d1f4dbb1cf68cd3acdf4dabc1eff87ae7bce49cee9328a.json @@ -1,38 +1,47 @@ { - "db_name": "PostgreSQL", - "query": "\n SELECT id, team_id, issue_id, fingerprint, version FROM posthog_errortrackingissuefingerprintv2\n WHERE team_id = $1 AND fingerprint = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "issue_id", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "fingerprint", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "version", - "type_info": "Int8" - } - ], - "parameters": { - "Left": ["Int4", "Text"] - }, - "nullable": [false, false, false, false, false] + "db_name": "PostgreSQL", + "query": "\n SELECT id, team_id, issue_id, fingerprint, version FROM posthog_errortrackingissuefingerprintv2\n WHERE team_id = $1 AND fingerprint = $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "issue_id", + "type_info": "Uuid" + }, + { + "ordinal": 3, + "name": "fingerprint", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "version", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int4", + "Text" + ] }, - "hash": "14332a535d61ab0144d1f4dbb1cf68cd3acdf4dabc1eff87ae7bce49cee9328a" + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "14332a535d61ab0144d1f4dbb1cf68cd3acdf4dabc1eff87ae7bce49cee9328a" } diff --git a/rust/.sqlx/query-229c28c25aec24180c29e6ed636c165376f43116b85921c62b36b1b8e85562b0.json b/rust/.sqlx/query-229c28c25aec24180c29e6ed636c165376f43116b85921c62b36b1b8e85562b0.json index ffda6f4b70b..04f6c0838ae 100644 --- a/rust/.sqlx/query-229c28c25aec24180c29e6ed636c165376f43116b85921c62b36b1b8e85562b0.json +++ b/rust/.sqlx/query-229c28c25aec24180c29e6ed636c165376f43116b85921c62b36b1b8e85562b0.json @@ -1,123 +1,133 @@ { - "db_name": "PostgreSQL", - "query": "\nWITH available AS (\n SELECT\n id,\n state\n FROM cyclotron_jobs\n WHERE\n state = 'available'::JobState\n AND queue_name = $1\n AND scheduled <= NOW()\n ORDER BY\n priority ASC,\n scheduled ASC\n LIMIT $2\n FOR UPDATE SKIP LOCKED\n)\nUPDATE cyclotron_jobs\nSET\n state = 'running'::JobState,\n lock_id = $3,\n last_heartbeat = NOW(),\n last_transition = NOW(),\n transition_count = transition_count + 1\nFROM available\nWHERE\n cyclotron_jobs.id = available.id\nRETURNING\n cyclotron_jobs.id,\n team_id,\n available.state as \"state: JobState\",\n queue_name,\n priority,\n function_id,\n created,\n last_transition,\n scheduled,\n transition_count,\n NULL::bytea as vm_state,\n metadata,\n parameters,\n blob,\n lock_id,\n last_heartbeat,\n janitor_touch_count\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "state: JobState", - "type_info": { - "Custom": { - "name": "jobstate", - "kind": { - "Enum": ["available", "completed", "failed", "running", "paused"] - } - } - } - }, - { - "ordinal": 3, - "name": "queue_name", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "priority", - "type_info": "Int2" - }, - { - "ordinal": 5, - "name": "function_id", - "type_info": "Uuid" - }, - { - "ordinal": 6, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 7, - "name": "last_transition", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "scheduled", - "type_info": "Timestamptz" - }, - { - "ordinal": 9, - "name": "transition_count", - "type_info": "Int2" - }, - { - "ordinal": 10, - "name": "vm_state", - "type_info": "Bytea" - }, - { - "ordinal": 11, - "name": "metadata", - "type_info": "Bytea" - }, - { - "ordinal": 12, - "name": "parameters", - "type_info": "Bytea" - }, - { - "ordinal": 13, - "name": "blob", - "type_info": "Bytea" - }, - { - "ordinal": 14, - "name": "lock_id", - "type_info": "Uuid" - }, - { - "ordinal": 15, - "name": "last_heartbeat", - "type_info": "Timestamptz" - }, - { - "ordinal": 16, - "name": "janitor_touch_count", - "type_info": "Int2" + "db_name": "PostgreSQL", + "query": "\nWITH available AS (\n SELECT\n id,\n state\n FROM cyclotron_jobs\n WHERE\n state = 'available'::JobState\n AND queue_name = $1\n AND scheduled <= NOW()\n ORDER BY\n priority ASC,\n scheduled ASC\n LIMIT $2\n FOR UPDATE SKIP LOCKED\n)\nUPDATE cyclotron_jobs\nSET\n state = 'running'::JobState,\n lock_id = $3,\n last_heartbeat = NOW(),\n last_transition = NOW(),\n transition_count = transition_count + 1\nFROM available\nWHERE\n cyclotron_jobs.id = available.id\nRETURNING\n cyclotron_jobs.id,\n team_id,\n available.state as \"state: JobState\",\n queue_name,\n priority,\n function_id,\n created,\n last_transition,\n scheduled,\n transition_count,\n NULL::bytea as vm_state,\n metadata,\n parameters,\n blob,\n lock_id,\n last_heartbeat,\n janitor_touch_count\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "state: JobState", + "type_info": { + "Custom": { + "name": "jobstate", + "kind": { + "Enum": [ + "available", + "completed", + "failed", + "running", + "paused" + ] } - ], - "parameters": { - "Left": ["Text", "Int8", "Uuid"] - }, - "nullable": [ - false, - false, - false, - false, - false, - true, - false, - false, - false, - false, - null, - true, - true, - true, - true, - true, - false - ] + } + } + }, + { + "ordinal": 3, + "name": "queue_name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "priority", + "type_info": "Int2" + }, + { + "ordinal": 5, + "name": "function_id", + "type_info": "Uuid" + }, + { + "ordinal": 6, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "last_transition", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "scheduled", + "type_info": "Timestamptz" + }, + { + "ordinal": 9, + "name": "transition_count", + "type_info": "Int2" + }, + { + "ordinal": 10, + "name": "vm_state", + "type_info": "Bytea" + }, + { + "ordinal": 11, + "name": "metadata", + "type_info": "Bytea" + }, + { + "ordinal": 12, + "name": "parameters", + "type_info": "Bytea" + }, + { + "ordinal": 13, + "name": "blob", + "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "lock_id", + "type_info": "Uuid" + }, + { + "ordinal": 15, + "name": "last_heartbeat", + "type_info": "Timestamptz" + }, + { + "ordinal": 16, + "name": "janitor_touch_count", + "type_info": "Int2" + } + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Uuid" + ] }, - "hash": "229c28c25aec24180c29e6ed636c165376f43116b85921c62b36b1b8e85562b0" + "nullable": [ + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + null, + true, + true, + true, + true, + true, + false + ] + }, + "hash": "229c28c25aec24180c29e6ed636c165376f43116b85921c62b36b1b8e85562b0" } diff --git a/rust/.sqlx/query-2a1514685491269ca61a0a898d7491f908b5047e86b13fbff22cf8f58e85cc81.json b/rust/.sqlx/query-2a1514685491269ca61a0a898d7491f908b5047e86b13fbff22cf8f58e85cc81.json new file mode 100644 index 00000000000..970ef472668 --- /dev/null +++ b/rust/.sqlx/query-2a1514685491269ca61a0a898d7491f908b5047e86b13fbff22cf8f58e85cc81.json @@ -0,0 +1,47 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT id, team_id, status, name, description FROM posthog_errortrackingissue\n WHERE team_id = $1 AND id = $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "status", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "description", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4", + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + true, + true + ] + }, + "hash": "2a1514685491269ca61a0a898d7491f908b5047e86b13fbff22cf8f58e85cc81" +} diff --git a/rust/.sqlx/query-2bd3251126625d8dd5143f58f4f9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89.json b/rust/.sqlx/query-2bd3251126625d8dd5143f58f4f9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89.json index cfcbdd6288f..1bdb0efcc34 100644 --- a/rust/.sqlx/query-2bd3251126625d8dd5143f58f4f9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89.json +++ b/rust/.sqlx/query-2bd3251126625d8dd5143f58f4f9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89.json @@ -1,18 +1,23 @@ { - "db_name": "PostgreSQL", - "query": "UPDATE cyclotron_jobs SET state = 'running', lock_id = $1, last_heartbeat=NOW() WHERE id = $2 returning queue_name", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "queue_name", - "type_info": "Text" - } - ], - "parameters": { - "Left": ["Uuid", "Uuid"] - }, - "nullable": [false] + "db_name": "PostgreSQL", + "query": "UPDATE cyclotron_jobs SET state = 'running', lock_id = $1, last_heartbeat=NOW() WHERE id = $2 returning queue_name", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "queue_name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Uuid" + ] }, - "hash": "2bd3251126625d8dd5143f58f4f9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89" + "nullable": [ + false + ] + }, + "hash": "2bd3251126625d8dd5143f58f4f9c4bbd0c3a17b7ea65767cf5e7512e5a6ea89" } diff --git a/rust/.sqlx/query-2ca9ea5e8706bba21b14d9a349f3d0e39f01b19b243d724b09f3ce6617d03dc7.json b/rust/.sqlx/query-2ca9ea5e8706bba21b14d9a349f3d0e39f01b19b243d724b09f3ce6617d03dc7.json index e69786b54b2..affa061018e 100644 --- a/rust/.sqlx/query-2ca9ea5e8706bba21b14d9a349f3d0e39f01b19b243d724b09f3ce6617d03dc7.json +++ b/rust/.sqlx/query-2ca9ea5e8706bba21b14d9a349f3d0e39f01b19b243d724b09f3ce6617d03dc7.json @@ -1,12 +1,15 @@ { - "db_name": "PostgreSQL", - "query": "UPDATE cyclotron_jobs SET state = 'available', lock_id = NULL, queue_name = $1 WHERE id = $2", - "describe": { - "columns": [], - "parameters": { - "Left": ["Text", "Uuid"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "UPDATE cyclotron_jobs SET state = 'available', lock_id = NULL, queue_name = $1 WHERE id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Uuid" + ] }, - "hash": "2ca9ea5e8706bba21b14d9a349f3d0e39f01b19b243d724b09f3ce6617d03dc7" + "nullable": [] + }, + "hash": "2ca9ea5e8706bba21b14d9a349f3d0e39f01b19b243d724b09f3ce6617d03dc7" } diff --git a/rust/.sqlx/query-361eb26d51d253242a8af33e45d8686c4393f6420e61b6b141143974ff362213.json b/rust/.sqlx/query-361eb26d51d253242a8af33e45d8686c4393f6420e61b6b141143974ff362213.json index 7a0918905c0..8ea73c5d641 100644 --- a/rust/.sqlx/query-361eb26d51d253242a8af33e45d8686c4393f6420e61b6b141143974ff362213.json +++ b/rust/.sqlx/query-361eb26d51d253242a8af33e45d8686c4393f6420e61b6b141143974ff362213.json @@ -1,43 +1,53 @@ { - "db_name": "PostgreSQL", - "query": "SELECT id, team_id, ref as set_ref, storage_ptr, created_at, failure_reason\n FROM posthog_errortrackingsymbolset\n WHERE team_id = $1 AND ref = $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "set_ref", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "storage_ptr", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "failure_reason", - "type_info": "Text" - } - ], - "parameters": { - "Left": ["Int4", "Text"] - }, - "nullable": [false, false, false, true, false, true] + "db_name": "PostgreSQL", + "query": "SELECT id, team_id, ref as set_ref, storage_ptr, created_at, failure_reason\n FROM posthog_errortrackingsymbolset\n WHERE team_id = $1 AND ref = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "set_ref", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "storage_ptr", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "failure_reason", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4", + "Text" + ] }, - "hash": "361eb26d51d253242a8af33e45d8686c4393f6420e61b6b141143974ff362213" + "nullable": [ + false, + false, + false, + true, + false, + true + ] + }, + "hash": "361eb26d51d253242a8af33e45d8686c4393f6420e61b6b141143974ff362213" } diff --git a/rust/.sqlx/query-385e94f4adab0f85174968f6eee873bf6d1d43884cd628df5b36978dd761b025.json b/rust/.sqlx/query-385e94f4adab0f85174968f6eee873bf6d1d43884cd628df5b36978dd761b025.json index 5c6b66d3f87..89a968bc010 100644 --- a/rust/.sqlx/query-385e94f4adab0f85174968f6eee873bf6d1d43884cd628df5b36978dd761b025.json +++ b/rust/.sqlx/query-385e94f4adab0f85174968f6eee873bf6d1d43884cd628df5b36978dd761b025.json @@ -1,18 +1,23 @@ { - "db_name": "PostgreSQL", - "query": "\nSELECT id FROM cyclotron_jobs WHERE state = 'running' AND COALESCE(last_heartbeat, $1) <= $1 AND janitor_touch_count >= $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - } - ], - "parameters": { - "Left": ["Timestamptz", "Int2"] - }, - "nullable": [false] + "db_name": "PostgreSQL", + "query": "\nSELECT id FROM cyclotron_jobs WHERE state = 'running' AND COALESCE(last_heartbeat, $1) <= $1 AND janitor_touch_count >= $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Timestamptz", + "Int2" + ] }, - "hash": "385e94f4adab0f85174968f6eee873bf6d1d43884cd628df5b36978dd761b025" + "nullable": [ + false + ] + }, + "hash": "385e94f4adab0f85174968f6eee873bf6d1d43884cd628df5b36978dd761b025" } diff --git a/rust/.sqlx/query-42e393046a686e6a69daa920dc2ab521aa6f393027c399a0c40139f5f8a0a45e.json b/rust/.sqlx/query-42e393046a686e6a69daa920dc2ab521aa6f393027c399a0c40139f5f8a0a45e.json index aa1ff7e7cf3..890675aa24d 100644 --- a/rust/.sqlx/query-42e393046a686e6a69daa920dc2ab521aa6f393027c399a0c40139f5f8a0a45e.json +++ b/rust/.sqlx/query-42e393046a686e6a69daa920dc2ab521aa6f393027c399a0c40139f5f8a0a45e.json @@ -1,12 +1,16 @@ { - "db_name": "PostgreSQL", - "query": "INSERT INTO posthog_eventproperty (event, property, team_id) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", - "describe": { - "columns": [], - "parameters": { - "Left": ["Varchar", "Varchar", "Int4"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "INSERT INTO posthog_eventproperty (event, property, team_id) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Int4" + ] }, - "hash": "42e393046a686e6a69daa920dc2ab521aa6f393027c399a0c40139f5f8a0a45e" + "nullable": [] + }, + "hash": "42e393046a686e6a69daa920dc2ab521aa6f393027c399a0c40139f5f8a0a45e" } diff --git a/rust/.sqlx/query-44eb698252059821770eaaf5b8213132c3e7bf297834cd42228b35bf3e424dd7.json b/rust/.sqlx/query-44eb698252059821770eaaf5b8213132c3e7bf297834cd42228b35bf3e424dd7.json deleted file mode 100644 index 8d5f49a0735..00000000000 --- a/rust/.sqlx/query-44eb698252059821770eaaf5b8213132c3e7bf297834cd42228b35bf3e424dd7.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO posthog_errortrackingissue (id, team_id, status, created_at)\n VALUES ($1, $2, $3, NOW())\n ON CONFLICT (id) DO NOTHING\n RETURNING (xmax = 0) AS was_inserted\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "was_inserted", - "type_info": "Bool" - } - ], - "parameters": { - "Left": ["Uuid", "Int4", "Text"] - }, - "nullable": [null] - }, - "hash": "44eb698252059821770eaaf5b8213132c3e7bf297834cd42228b35bf3e424dd7" -} diff --git a/rust/.sqlx/query-4b24f800767bc20852115e7406f8dc46c18f4950a7951d2c412dcba4d13fb56b.json b/rust/.sqlx/query-4b24f800767bc20852115e7406f8dc46c18f4950a7951d2c412dcba4d13fb56b.json index 1f374d8084c..515f058fad9 100644 --- a/rust/.sqlx/query-4b24f800767bc20852115e7406f8dc46c18f4950a7951d2c412dcba4d13fb56b.json +++ b/rust/.sqlx/query-4b24f800767bc20852115e7406f8dc46c18f4950a7951d2c412dcba4d13fb56b.json @@ -1,48 +1,59 @@ { - "db_name": "PostgreSQL", - "query": "\n SELECT raw_id, team_id, created_at, symbol_set_id, contents, resolved, context\n FROM posthog_errortrackingstackframe\n WHERE raw_id = $1 AND team_id = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "raw_id", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 3, - "name": "symbol_set_id", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "contents", - "type_info": "Jsonb" - }, - { - "ordinal": 5, - "name": "resolved", - "type_info": "Bool" - }, - { - "ordinal": 6, - "name": "context", - "type_info": "Text" - } - ], - "parameters": { - "Left": ["Text", "Int4"] - }, - "nullable": [false, false, false, true, false, false, true] + "db_name": "PostgreSQL", + "query": "\n SELECT raw_id, team_id, created_at, symbol_set_id, contents, resolved, context\n FROM posthog_errortrackingstackframe\n WHERE raw_id = $1 AND team_id = $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "raw_id", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "symbol_set_id", + "type_info": "Uuid" + }, + { + "ordinal": 4, + "name": "contents", + "type_info": "Jsonb" + }, + { + "ordinal": 5, + "name": "resolved", + "type_info": "Bool" + }, + { + "ordinal": 6, + "name": "context", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Text", + "Int4" + ] }, - "hash": "4b24f800767bc20852115e7406f8dc46c18f4950a7951d2c412dcba4d13fb56b" + "nullable": [ + false, + false, + false, + true, + false, + false, + true + ] + }, + "hash": "4b24f800767bc20852115e7406f8dc46c18f4950a7951d2c412dcba4d13fb56b" } diff --git a/rust/.sqlx/query-54d9afe6952f92b753fbce2c4e8554065b71152389f98d35532c6b332d5a4c9d.json b/rust/.sqlx/query-54d9afe6952f92b753fbce2c4e8554065b71152389f98d35532c6b332d5a4c9d.json index 2ff58c66714..6bbfb17e16a 100644 --- a/rust/.sqlx/query-54d9afe6952f92b753fbce2c4e8554065b71152389f98d35532c6b332d5a4c9d.json +++ b/rust/.sqlx/query-54d9afe6952f92b753fbce2c4e8554065b71152389f98d35532c6b332d5a4c9d.json @@ -1,12 +1,14 @@ { - "db_name": "PostgreSQL", - "query": "\nWITH stalled AS (\n SELECT id FROM cyclotron_jobs WHERE state = 'running' AND COALESCE(last_heartbeat, $1) <= $1 FOR UPDATE SKIP LOCKED\n)\nUPDATE cyclotron_jobs\nSET state = 'available', lock_id = NULL, last_heartbeat = NULL, janitor_touch_count = janitor_touch_count + 1\nFROM stalled\nWHERE cyclotron_jobs.id = stalled.id\n ", - "describe": { - "columns": [], - "parameters": { - "Left": ["Timestamptz"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "\nWITH stalled AS (\n SELECT id FROM cyclotron_jobs WHERE state = 'running' AND COALESCE(last_heartbeat, $1) <= $1 FOR UPDATE SKIP LOCKED\n)\nUPDATE cyclotron_jobs\nSET state = 'available', lock_id = NULL, last_heartbeat = NULL, janitor_touch_count = janitor_touch_count + 1\nFROM stalled\nWHERE cyclotron_jobs.id = stalled.id\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz" + ] }, - "hash": "54d9afe6952f92b753fbce2c4e8554065b71152389f98d35532c6b332d5a4c9d" + "nullable": [] + }, + "hash": "54d9afe6952f92b753fbce2c4e8554065b71152389f98d35532c6b332d5a4c9d" } diff --git a/rust/.sqlx/query-78f54fcebc11e2411008448281e4711bdfb8cf78e362ccda8bc14e92324d51f8.json b/rust/.sqlx/query-78f54fcebc11e2411008448281e4711bdfb8cf78e362ccda8bc14e92324d51f8.json index d70d4c9d33a..44118c74052 100644 --- a/rust/.sqlx/query-78f54fcebc11e2411008448281e4711bdfb8cf78e362ccda8bc14e92324d51f8.json +++ b/rust/.sqlx/query-78f54fcebc11e2411008448281e4711bdfb8cf78e362ccda8bc14e92324d51f8.json @@ -1,18 +1,22 @@ { - "db_name": "PostgreSQL", - "query": "SELECT COUNT(*) FROM cyclotron_jobs WHERE queue_name = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "count", - "type_info": "Int8" - } - ], - "parameters": { - "Left": ["Text"] - }, - "nullable": [null] + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM cyclotron_jobs WHERE queue_name = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text" + ] }, - "hash": "78f54fcebc11e2411008448281e4711bdfb8cf78e362ccda8bc14e92324d51f8" + "nullable": [ + null + ] + }, + "hash": "78f54fcebc11e2411008448281e4711bdfb8cf78e362ccda8bc14e92324d51f8" } diff --git a/rust/.sqlx/query-917e3d14c15558a1e0bb1d7015ed687eb545ee9d4ccbb8b69c958a357d49f687.json b/rust/.sqlx/query-917e3d14c15558a1e0bb1d7015ed687eb545ee9d4ccbb8b69c958a357d49f687.json index 188cd0be389..6f3e42a0a8b 100644 --- a/rust/.sqlx/query-917e3d14c15558a1e0bb1d7015ed687eb545ee9d4ccbb8b69c958a357d49f687.json +++ b/rust/.sqlx/query-917e3d14c15558a1e0bb1d7015ed687eb545ee9d4ccbb8b69c958a357d49f687.json @@ -1,12 +1,17 @@ { - "db_name": "PostgreSQL", - "query": "\n INSERT INTO posthog_eventdefinition (id, name, volume_30_day, query_usage_30_day, team_id, last_seen_at, created_at)\n VALUES ($1, $2, NULL, NULL, $3, $4, NOW()) ON CONFLICT\n ON CONSTRAINT posthog_eventdefinition_team_id_name_80fa0b87_uniq\n DO UPDATE SET last_seen_at = $4\n ", - "describe": { - "columns": [], - "parameters": { - "Left": ["Uuid", "Varchar", "Int4", "Timestamptz"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "\n INSERT INTO posthog_eventdefinition (id, name, volume_30_day, query_usage_30_day, team_id, last_seen_at, created_at)\n VALUES ($1, $2, NULL, NULL, $3, $4, NOW()) ON CONFLICT\n ON CONSTRAINT posthog_eventdefinition_team_id_name_80fa0b87_uniq\n DO UPDATE SET last_seen_at = $4\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Int4", + "Timestamptz" + ] }, - "hash": "917e3d14c15558a1e0bb1d7015ed687eb545ee9d4ccbb8b69c958a357d49f687" + "nullable": [] + }, + "hash": "917e3d14c15558a1e0bb1d7015ed687eb545ee9d4ccbb8b69c958a357d49f687" } diff --git a/rust/.sqlx/query-aa595eaf28c1f4b872c278be407b59cc00f3125413f4032ac3647a6b5ee1a632.json b/rust/.sqlx/query-aa595eaf28c1f4b872c278be407b59cc00f3125413f4032ac3647a6b5ee1a632.json index 51fb1b01812..244f029a6a4 100644 --- a/rust/.sqlx/query-aa595eaf28c1f4b872c278be407b59cc00f3125413f4032ac3647a6b5ee1a632.json +++ b/rust/.sqlx/query-aa595eaf28c1f4b872c278be407b59cc00f3125413f4032ac3647a6b5ee1a632.json @@ -1,18 +1,23 @@ { - "db_name": "PostgreSQL", - "query": "SELECT vm_state FROM cyclotron_jobs WHERE id = $1 AND lock_id = $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "vm_state", - "type_info": "Bytea" - } - ], - "parameters": { - "Left": ["Uuid", "Uuid"] - }, - "nullable": [true] + "db_name": "PostgreSQL", + "query": "SELECT vm_state FROM cyclotron_jobs WHERE id = $1 AND lock_id = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "vm_state", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Uuid" + ] }, - "hash": "aa595eaf28c1f4b872c278be407b59cc00f3125413f4032ac3647a6b5ee1a632" + "nullable": [ + true + ] + }, + "hash": "aa595eaf28c1f4b872c278be407b59cc00f3125413f4032ac3647a6b5ee1a632" } diff --git a/rust/.sqlx/query-ad528f712bdaf75a82293018e3dec3544acd0228776b8535f22438db59002e1f.json b/rust/.sqlx/query-ad528f712bdaf75a82293018e3dec3544acd0228776b8535f22438db59002e1f.json deleted file mode 100644 index 1f2ff6b9069..00000000000 --- a/rust/.sqlx/query-ad528f712bdaf75a82293018e3dec3544acd0228776b8535f22438db59002e1f.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT id, team_id, status FROM posthog_errortrackingissue\n WHERE team_id = $1 AND id = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "status", - "type_info": "Text" - } - ], - "parameters": { - "Left": ["Int4", "Uuid"] - }, - "nullable": [false, false, false] - }, - "hash": "ad528f712bdaf75a82293018e3dec3544acd0228776b8535f22438db59002e1f" -} diff --git a/rust/.sqlx/query-b420ccc79fa7847f65246adf76a074995829d1372fe8ec1fd683f9524bcebb8b.json b/rust/.sqlx/query-b420ccc79fa7847f65246adf76a074995829d1372fe8ec1fd683f9524bcebb8b.json index ed79a7102f5..8a40f0f253f 100644 --- a/rust/.sqlx/query-b420ccc79fa7847f65246adf76a074995829d1372fe8ec1fd683f9524bcebb8b.json +++ b/rust/.sqlx/query-b420ccc79fa7847f65246adf76a074995829d1372fe8ec1fd683f9524bcebb8b.json @@ -1,23 +1,26 @@ { - "db_name": "PostgreSQL", - "query": "SELECT COUNT(*), queue_name FROM cyclotron_jobs WHERE state = 'available' AND scheduled <= NOW() GROUP BY queue_name", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "count", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "queue_name", - "type_info": "Text" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [null, false] + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*), queue_name FROM cyclotron_jobs WHERE state = 'available' AND scheduled <= NOW() GROUP BY queue_name", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "queue_name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] }, - "hash": "b420ccc79fa7847f65246adf76a074995829d1372fe8ec1fd683f9524bcebb8b" + "nullable": [ + null, + false + ] + }, + "hash": "b420ccc79fa7847f65246adf76a074995829d1372fe8ec1fd683f9524bcebb8b" } diff --git a/rust/.sqlx/query-b8c1b723826d595dca0389d729fa76bd8a7d96d73983a0c408f32f17da5f483b.json b/rust/.sqlx/query-b8c1b723826d595dca0389d729fa76bd8a7d96d73983a0c408f32f17da5f483b.json index 8f201d80503..7733c346c4b 100644 --- a/rust/.sqlx/query-b8c1b723826d595dca0389d729fa76bd8a7d96d73983a0c408f32f17da5f483b.json +++ b/rust/.sqlx/query-b8c1b723826d595dca0389d729fa76bd8a7d96d73983a0c408f32f17da5f483b.json @@ -1,12 +1,16 @@ { - "db_name": "PostgreSQL", - "query": "INSERT INTO cyclotron_dead_letter_metadata (job_id, original_queue_name, reason, dlq_time) VALUES ($1, $2, $3, NOW())", - "describe": { - "columns": [], - "parameters": { - "Left": ["Uuid", "Text", "Text"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "INSERT INTO cyclotron_dead_letter_metadata (job_id, original_queue_name, reason, dlq_time) VALUES ($1, $2, $3, NOW())", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "Text" + ] }, - "hash": "b8c1b723826d595dca0389d729fa76bd8a7d96d73983a0c408f32f17da5f483b" + "nullable": [] + }, + "hash": "b8c1b723826d595dca0389d729fa76bd8a7d96d73983a0c408f32f17da5f483b" } diff --git a/rust/.sqlx/query-c6ff00fcbbc77c8f5c1b3fe2f3352ea79485e403b9e17b6c37259ea0612065ee.json b/rust/.sqlx/query-c6ff00fcbbc77c8f5c1b3fe2f3352ea79485e403b9e17b6c37259ea0612065ee.json index f6ad8e4e892..608008e09ad 100644 --- a/rust/.sqlx/query-c6ff00fcbbc77c8f5c1b3fe2f3352ea79485e403b9e17b6c37259ea0612065ee.json +++ b/rust/.sqlx/query-c6ff00fcbbc77c8f5c1b3fe2f3352ea79485e403b9e17b6c37259ea0612065ee.json @@ -1,18 +1,23 @@ { - "db_name": "PostgreSQL", - "query": "SELECT group_type_index FROM posthog_grouptypemapping WHERE group_type = $1 AND team_id = $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "group_type_index", - "type_info": "Int4" - } - ], - "parameters": { - "Left": ["Text", "Int4"] - }, - "nullable": [false] + "db_name": "PostgreSQL", + "query": "SELECT group_type_index FROM posthog_grouptypemapping WHERE group_type = $1 AND team_id = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "group_type_index", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Text", + "Int4" + ] }, - "hash": "c6ff00fcbbc77c8f5c1b3fe2f3352ea79485e403b9e17b6c37259ea0612065ee" + "nullable": [ + false + ] + }, + "hash": "c6ff00fcbbc77c8f5c1b3fe2f3352ea79485e403b9e17b6c37259ea0612065ee" } diff --git a/rust/.sqlx/query-ce036f16a37a41b9dc5a164de0b52345454cd3323568c4bef5b8480380287068.json b/rust/.sqlx/query-ce036f16a37a41b9dc5a164de0b52345454cd3323568c4bef5b8480380287068.json index fe174820c3a..d996dae8bd4 100644 --- a/rust/.sqlx/query-ce036f16a37a41b9dc5a164de0b52345454cd3323568c4bef5b8480380287068.json +++ b/rust/.sqlx/query-ce036f16a37a41b9dc5a164de0b52345454cd3323568c4bef5b8480380287068.json @@ -1,123 +1,133 @@ { - "db_name": "PostgreSQL", - "query": "\nWITH available AS (\n SELECT\n id,\n state\n FROM cyclotron_jobs\n WHERE\n state = 'available'::JobState\n AND queue_name = $1\n AND scheduled <= NOW()\n ORDER BY\n priority ASC,\n scheduled ASC\n LIMIT $2\n FOR UPDATE SKIP LOCKED\n)\nUPDATE cyclotron_jobs\nSET\n state = 'running'::JobState,\n lock_id = $3,\n last_heartbeat = NOW(),\n last_transition = NOW(),\n transition_count = transition_count + 1\nFROM available\nWHERE\n cyclotron_jobs.id = available.id\nRETURNING\n cyclotron_jobs.id,\n team_id,\n available.state as \"state: JobState\",\n queue_name,\n priority,\n function_id,\n created,\n last_transition,\n scheduled,\n transition_count,\n vm_state,\n metadata,\n parameters,\n blob,\n lock_id,\n last_heartbeat,\n janitor_touch_count\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "state: JobState", - "type_info": { - "Custom": { - "name": "jobstate", - "kind": { - "Enum": ["available", "completed", "failed", "running", "paused"] - } - } - } - }, - { - "ordinal": 3, - "name": "queue_name", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "priority", - "type_info": "Int2" - }, - { - "ordinal": 5, - "name": "function_id", - "type_info": "Uuid" - }, - { - "ordinal": 6, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 7, - "name": "last_transition", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "scheduled", - "type_info": "Timestamptz" - }, - { - "ordinal": 9, - "name": "transition_count", - "type_info": "Int2" - }, - { - "ordinal": 10, - "name": "vm_state", - "type_info": "Bytea" - }, - { - "ordinal": 11, - "name": "metadata", - "type_info": "Bytea" - }, - { - "ordinal": 12, - "name": "parameters", - "type_info": "Bytea" - }, - { - "ordinal": 13, - "name": "blob", - "type_info": "Bytea" - }, - { - "ordinal": 14, - "name": "lock_id", - "type_info": "Uuid" - }, - { - "ordinal": 15, - "name": "last_heartbeat", - "type_info": "Timestamptz" - }, - { - "ordinal": 16, - "name": "janitor_touch_count", - "type_info": "Int2" + "db_name": "PostgreSQL", + "query": "\nWITH available AS (\n SELECT\n id,\n state\n FROM cyclotron_jobs\n WHERE\n state = 'available'::JobState\n AND queue_name = $1\n AND scheduled <= NOW()\n ORDER BY\n priority ASC,\n scheduled ASC\n LIMIT $2\n FOR UPDATE SKIP LOCKED\n)\nUPDATE cyclotron_jobs\nSET\n state = 'running'::JobState,\n lock_id = $3,\n last_heartbeat = NOW(),\n last_transition = NOW(),\n transition_count = transition_count + 1\nFROM available\nWHERE\n cyclotron_jobs.id = available.id\nRETURNING\n cyclotron_jobs.id,\n team_id,\n available.state as \"state: JobState\",\n queue_name,\n priority,\n function_id,\n created,\n last_transition,\n scheduled,\n transition_count,\n vm_state,\n metadata,\n parameters,\n blob,\n lock_id,\n last_heartbeat,\n janitor_touch_count\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "state: JobState", + "type_info": { + "Custom": { + "name": "jobstate", + "kind": { + "Enum": [ + "available", + "completed", + "failed", + "running", + "paused" + ] } - ], - "parameters": { - "Left": ["Text", "Int8", "Uuid"] - }, - "nullable": [ - false, - false, - false, - false, - false, - true, - false, - false, - false, - false, - true, - true, - true, - true, - true, - true, - false - ] + } + } + }, + { + "ordinal": 3, + "name": "queue_name", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "priority", + "type_info": "Int2" + }, + { + "ordinal": 5, + "name": "function_id", + "type_info": "Uuid" + }, + { + "ordinal": 6, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "last_transition", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "scheduled", + "type_info": "Timestamptz" + }, + { + "ordinal": 9, + "name": "transition_count", + "type_info": "Int2" + }, + { + "ordinal": 10, + "name": "vm_state", + "type_info": "Bytea" + }, + { + "ordinal": 11, + "name": "metadata", + "type_info": "Bytea" + }, + { + "ordinal": 12, + "name": "parameters", + "type_info": "Bytea" + }, + { + "ordinal": 13, + "name": "blob", + "type_info": "Bytea" + }, + { + "ordinal": 14, + "name": "lock_id", + "type_info": "Uuid" + }, + { + "ordinal": 15, + "name": "last_heartbeat", + "type_info": "Timestamptz" + }, + { + "ordinal": 16, + "name": "janitor_touch_count", + "type_info": "Int2" + } + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Uuid" + ] }, - "hash": "ce036f16a37a41b9dc5a164de0b52345454cd3323568c4bef5b8480380287068" + "nullable": [ + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + true, + true, + true, + true, + true, + true, + false + ] + }, + "hash": "ce036f16a37a41b9dc5a164de0b52345454cd3323568c4bef5b8480380287068" } diff --git a/rust/.sqlx/query-e0c6790eccd2e7505d86ed570f093c27fdf4d88145cd7eaf4bbd39e49a7452f6.json b/rust/.sqlx/query-e0c6790eccd2e7505d86ed570f093c27fdf4d88145cd7eaf4bbd39e49a7452f6.json new file mode 100644 index 00000000000..a0513cd7b42 --- /dev/null +++ b/rust/.sqlx/query-e0c6790eccd2e7505d86ed570f093c27fdf4d88145cd7eaf4bbd39e49a7452f6.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO posthog_errortrackingissue (id, team_id, status, name, description, created_at)\n VALUES ($1, $2, $3, $4, $5, NOW())\n ON CONFLICT (id) DO NOTHING\n RETURNING (xmax = 0) AS was_inserted\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "was_inserted", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int4", + "Text", + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "e0c6790eccd2e7505d86ed570f093c27fdf4d88145cd7eaf4bbd39e49a7452f6" +} diff --git a/rust/.sqlx/query-e842f1ed33747bde4570c6d861d856c4cbd8beb519df8212212017dda9d06c51.json b/rust/.sqlx/query-e842f1ed33747bde4570c6d861d856c4cbd8beb519df8212212017dda9d06c51.json index 145fe9bf7bc..de7157b9b0a 100644 --- a/rust/.sqlx/query-e842f1ed33747bde4570c6d861d856c4cbd8beb519df8212212017dda9d06c51.json +++ b/rust/.sqlx/query-e842f1ed33747bde4570c6d861d856c4cbd8beb519df8212212017dda9d06c51.json @@ -1,38 +1,44 @@ { - "db_name": "PostgreSQL", - "query": "\nWITH to_delete AS (\n DELETE FROM cyclotron_jobs\n WHERE state IN ('failed', 'completed')\n RETURNING last_transition, team_id, function_id::text, state::text\n),\naggregated_data AS (\n SELECT\n date_trunc('hour', last_transition) AS hour,\n team_id,\n function_id,\n state,\n COUNT(*) AS count\n FROM to_delete\n GROUP BY hour, team_id, function_id, state\n)\nSELECT\n hour as \"hour!\",\n team_id as \"team_id!\",\n function_id,\n state as \"state!\",\n count as \"count!\"\nFROM aggregated_data", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "hour!", - "type_info": "Timestamptz" - }, - { - "ordinal": 1, - "name": "team_id!", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "function_id", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "state!", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "count!", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [null, false, null, null, null] + "db_name": "PostgreSQL", + "query": "\nWITH to_delete AS (\n DELETE FROM cyclotron_jobs\n WHERE state IN ('failed', 'completed')\n RETURNING last_transition, team_id, function_id::text, state::text\n),\naggregated_data AS (\n SELECT\n date_trunc('hour', last_transition) AS hour,\n team_id,\n function_id,\n state,\n COUNT(*) AS count\n FROM to_delete\n GROUP BY hour, team_id, function_id, state\n)\nSELECT\n hour as \"hour!\",\n team_id as \"team_id!\",\n function_id,\n state as \"state!\",\n count as \"count!\"\nFROM aggregated_data", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "hour!", + "type_info": "Timestamptz" + }, + { + "ordinal": 1, + "name": "team_id!", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "function_id", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "state!", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "count!", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [] }, - "hash": "e842f1ed33747bde4570c6d861d856c4cbd8beb519df8212212017dda9d06c51" + "nullable": [ + null, + false, + null, + null, + null + ] + }, + "hash": "e842f1ed33747bde4570c6d861d856c4cbd8beb519df8212212017dda9d06c51" } diff --git a/rust/.sqlx/query-eecef0ce664dfe65dff4452d92a29c948a291ea8218bbbb4e25cd1ad36dbe9f4.json b/rust/.sqlx/query-eecef0ce664dfe65dff4452d92a29c948a291ea8218bbbb4e25cd1ad36dbe9f4.json index 78ca221cb2f..a54bb9565ea 100644 --- a/rust/.sqlx/query-eecef0ce664dfe65dff4452d92a29c948a291ea8218bbbb4e25cd1ad36dbe9f4.json +++ b/rust/.sqlx/query-eecef0ce664dfe65dff4452d92a29c948a291ea8218bbbb4e25cd1ad36dbe9f4.json @@ -1,12 +1,20 @@ { - "db_name": "PostgreSQL", - "query": "\n INSERT INTO posthog_propertydefinition (id, name, type, group_type_index, is_numerical, volume_30_day, query_usage_30_day, team_id, property_type)\n VALUES ($1, $2, $3, $4, $5, NULL, NULL, $6, $7)\n ON CONFLICT (team_id, name, type, coalesce(group_type_index, -1))\n DO UPDATE SET property_type=EXCLUDED.property_type WHERE posthog_propertydefinition.property_type IS NULL\n ", - "describe": { - "columns": [], - "parameters": { - "Left": ["Uuid", "Varchar", "Int2", "Int2", "Bool", "Int4", "Varchar"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "\n INSERT INTO posthog_propertydefinition (id, name, type, group_type_index, is_numerical, volume_30_day, query_usage_30_day, team_id, property_type)\n VALUES ($1, $2, $3, $4, $5, NULL, NULL, $6, $7)\n ON CONFLICT (team_id, name, type, coalesce(group_type_index, -1))\n DO UPDATE SET property_type=EXCLUDED.property_type WHERE posthog_propertydefinition.property_type IS NULL\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Int2", + "Int2", + "Bool", + "Int4", + "Varchar" + ] }, - "hash": "eecef0ce664dfe65dff4452d92a29c948a291ea8218bbbb4e25cd1ad36dbe9f4" + "nullable": [] + }, + "hash": "eecef0ce664dfe65dff4452d92a29c948a291ea8218bbbb4e25cd1ad36dbe9f4" } diff --git a/rust/.sqlx/query-f074766d1fc32df17f92667f412af30c682288988fc6f102e8a063be97c3e51c.json b/rust/.sqlx/query-f074766d1fc32df17f92667f412af30c682288988fc6f102e8a063be97c3e51c.json index 6139be53026..4f91e01e690 100644 --- a/rust/.sqlx/query-f074766d1fc32df17f92667f412af30c682288988fc6f102e8a063be97c3e51c.json +++ b/rust/.sqlx/query-f074766d1fc32df17f92667f412af30c682288988fc6f102e8a063be97c3e51c.json @@ -1,31 +1,37 @@ { - "db_name": "PostgreSQL", - "query": "\nINSERT INTO cyclotron_jobs\n (\n id,\n team_id,\n function_id,\n created,\n lock_id,\n last_heartbeat,\n janitor_touch_count,\n transition_count,\n last_transition,\n queue_name,\n state,\n scheduled,\n priority,\n vm_state,\n metadata,\n parameters,\n blob\n )\nVALUES\n ($1, $2, $3, NOW(), NULL, NULL, 0, 0, NOW(), $4, $5, $6, $7, $8, $9, $10, $11)\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Int4", - "Uuid", - "Text", - { - "Custom": { - "name": "jobstate", - "kind": { - "Enum": ["available", "completed", "failed", "running", "paused"] - } - } - }, - "Timestamptz", - "Int2", - "Bytea", - "Bytea", - "Bytea", - "Bytea" - ] + "db_name": "PostgreSQL", + "query": "\nINSERT INTO cyclotron_jobs\n (\n id,\n team_id,\n function_id,\n created,\n lock_id,\n last_heartbeat,\n janitor_touch_count,\n transition_count,\n last_transition,\n queue_name,\n state,\n scheduled,\n priority,\n vm_state,\n metadata,\n parameters,\n blob\n )\nVALUES\n ($1, $2, $3, NOW(), NULL, NULL, 0, 0, NOW(), $4, $5, $6, $7, $8, $9, $10, $11)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Int4", + "Uuid", + "Text", + { + "Custom": { + "name": "jobstate", + "kind": { + "Enum": [ + "available", + "completed", + "failed", + "running", + "paused" + ] + } + } }, - "nullable": [] + "Timestamptz", + "Int2", + "Bytea", + "Bytea", + "Bytea", + "Bytea" + ] }, - "hash": "f074766d1fc32df17f92667f412af30c682288988fc6f102e8a063be97c3e51c" + "nullable": [] + }, + "hash": "f074766d1fc32df17f92667f412af30c682288988fc6f102e8a063be97c3e51c" } diff --git a/rust/.sqlx/query-fd6745e4ed7575699286d9828c9f6c959ba804dab9c1e5ba39979d19782582ea.json b/rust/.sqlx/query-fd6745e4ed7575699286d9828c9f6c959ba804dab9c1e5ba39979d19782582ea.json index 698578f7287..791e4ca7135 100644 --- a/rust/.sqlx/query-fd6745e4ed7575699286d9828c9f6c959ba804dab9c1e5ba39979d19782582ea.json +++ b/rust/.sqlx/query-fd6745e4ed7575699286d9828c9f6c959ba804dab9c1e5ba39979d19782582ea.json @@ -1,38 +1,49 @@ { - "db_name": "PostgreSQL", - "query": "\n INSERT INTO posthog_errortrackingissuefingerprintv2 (id, team_id, issue_id, fingerprint, version, created_at)\n VALUES ($1, $2, $3, $4, 0, NOW())\n ON CONFLICT (team_id, fingerprint) DO NOTHING\n RETURNING id, team_id, issue_id, fingerprint, version\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "team_id", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "issue_id", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "fingerprint", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "version", - "type_info": "Int8" - } - ], - "parameters": { - "Left": ["Uuid", "Int4", "Uuid", "Text"] - }, - "nullable": [false, false, false, false, false] + "db_name": "PostgreSQL", + "query": "\n INSERT INTO posthog_errortrackingissuefingerprintv2 (id, team_id, issue_id, fingerprint, version, created_at)\n VALUES ($1, $2, $3, $4, 0, NOW())\n ON CONFLICT (team_id, fingerprint) DO NOTHING\n RETURNING id, team_id, issue_id, fingerprint, version\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "team_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "issue_id", + "type_info": "Uuid" + }, + { + "ordinal": 3, + "name": "fingerprint", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "version", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int4", + "Uuid", + "Text" + ] }, - "hash": "fd6745e4ed7575699286d9828c9f6c959ba804dab9c1e5ba39979d19782582ea" + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "fd6745e4ed7575699286d9828c9f6c959ba804dab9c1e5ba39979d19782582ea" } diff --git a/rust/.sqlx/query-fda1f4ef877d1a71dbb6345d71c21c0eae35356f7b92e969a12a839b41cd360a.json b/rust/.sqlx/query-fda1f4ef877d1a71dbb6345d71c21c0eae35356f7b92e969a12a839b41cd360a.json index 631e5d2d017..da2b7d92cb9 100644 --- a/rust/.sqlx/query-fda1f4ef877d1a71dbb6345d71c21c0eae35356f7b92e969a12a839b41cd360a.json +++ b/rust/.sqlx/query-fda1f4ef877d1a71dbb6345d71c21c0eae35356f7b92e969a12a839b41cd360a.json @@ -1,12 +1,19 @@ { - "db_name": "PostgreSQL", - "query": "INSERT INTO posthog_errortrackingsymbolset (id, team_id, ref, storage_ptr, failure_reason, created_at)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (team_id, ref) DO UPDATE SET storage_ptr = $4", - "describe": { - "columns": [], - "parameters": { - "Left": ["Uuid", "Int4", "Text", "Text", "Text", "Timestamptz"] - }, - "nullable": [] + "db_name": "PostgreSQL", + "query": "INSERT INTO posthog_errortrackingsymbolset (id, team_id, ref, storage_ptr, failure_reason, created_at)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (team_id, ref) DO UPDATE SET storage_ptr = $4", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Int4", + "Text", + "Text", + "Text", + "Timestamptz" + ] }, - "hash": "fda1f4ef877d1a71dbb6345d71c21c0eae35356f7b92e969a12a839b41cd360a" + "nullable": [] + }, + "hash": "fda1f4ef877d1a71dbb6345d71c21c0eae35356f7b92e969a12a839b41cd360a" } diff --git a/rust/cymbal/src/frames/resolver.rs b/rust/cymbal/src/frames/resolver.rs index b36d00fee6f..5e6cafce140 100644 --- a/rust/cymbal/src/frames/resolver.rs +++ b/rust/cymbal/src/frames/resolver.rs @@ -82,7 +82,7 @@ mod test { sourcemap::SourcemapProvider, Catalog, S3Client, }, - types::{ErrProps, Stacktrace}, + types::{RawErrProps, Stacktrace}, }; const CHUNK_PATH: &str = "/static/chunk-PGUQKT6S.js"; @@ -131,10 +131,10 @@ mod test { fn get_test_frame(server: &MockServer) -> RawFrame { let exception: ClickHouseEvent = serde_json::from_str(EXAMPLE_EXCEPTION).unwrap(); - let props: ErrProps = serde_json::from_str(&exception.properties.unwrap()).unwrap(); + let mut props: RawErrProps = serde_json::from_str(&exception.properties.unwrap()).unwrap(); let Stacktrace::Raw { frames: mut test_stack, - } = props.exception_list.unwrap().swap_remove(0).stack.unwrap() + } = props.exception_list.swap_remove(0).stack.unwrap() else { panic!("Expected a Raw stacktrace") }; diff --git a/rust/cymbal/src/issue_resolution.rs b/rust/cymbal/src/issue_resolution.rs index 3d7ab3ddd6a..6778ff10012 100644 --- a/rust/cymbal/src/issue_resolution.rs +++ b/rust/cymbal/src/issue_resolution.rs @@ -1,7 +1,10 @@ use sqlx::postgres::any::AnyConnectionBackend; use uuid::Uuid; -use crate::error::UnhandledError; +use crate::{ + error::UnhandledError, + types::{FingerprintedErrProps, OutputErrProps}, +}; pub struct IssueFingerprintOverride { pub id: Uuid, @@ -15,14 +18,18 @@ pub struct Issue { pub id: Uuid, pub team_id: i32, pub status: String, + pub name: Option, + pub description: Option, } impl Issue { - pub fn new(team_id: i32) -> Self { + pub fn new(team_id: i32, name: String, description: String) -> Self { Self { id: Uuid::new_v4(), team_id, status: "active".to_string(), // TODO - we should at some point use an enum here + name: Some(name), + description: Some(description), } } @@ -37,7 +44,7 @@ impl Issue { let res = sqlx::query_as!( Issue, r#" - SELECT id, team_id, status FROM posthog_errortrackingissue + SELECT id, team_id, status, name, description FROM posthog_errortrackingissue WHERE team_id = $1 AND id = $2 "#, team_id, @@ -55,14 +62,16 @@ impl Issue { { let did_insert = sqlx::query_scalar!( r#" - INSERT INTO posthog_errortrackingissue (id, team_id, status, created_at) - VALUES ($1, $2, $3, NOW()) + INSERT INTO posthog_errortrackingissue (id, team_id, status, name, description, created_at) + VALUES ($1, $2, $3, $4, $5, NOW()) ON CONFLICT (id) DO NOTHING RETURNING (xmax = 0) AS was_inserted "#, self.id, self.team_id, - self.status + self.status, + self.name, + self.description ) .fetch_one(executor) .await?; @@ -127,30 +136,40 @@ impl IssueFingerprintOverride { pub async fn resolve_issue<'c, A>( con: A, - fingerprint: &str, team_id: i32, -) -> Result + fingerprinted: FingerprintedErrProps, +) -> Result where A: sqlx::Acquire<'c, Database = sqlx::Postgres>, { let mut conn = con.acquire().await?; // If an override already exists, just fast-path, skipping the transaction if let Some(issue_override) = - IssueFingerprintOverride::load(&mut *conn, team_id, fingerprint).await? + IssueFingerprintOverride::load(&mut *conn, team_id, &fingerprinted.fingerprint).await? { - return Ok(issue_override); + return Ok(fingerprinted.to_output(issue_override.issue_id)); } + // UNWRAP: We never resolve an issue for an exception with no exception list + let first = fingerprinted.exception_list.first().unwrap(); + let new_name = first.exception_type.clone(); + let new_description = first.exception_message.clone(); + // Start a transaction, so we can roll it back on override insert failure conn.begin().await?; // Insert a new issue - let issue = Issue::new(team_id); + let issue = Issue::new(team_id, new_name, new_description); // We don't actually care if we insert the issue here or not - conflicts aren't possible at // this stage. issue.insert(&mut *conn).await?; // Insert the fingerprint override - let issue_override = - IssueFingerprintOverride::create_or_load(&mut *conn, team_id, fingerprint, &issue).await?; + let issue_override = IssueFingerprintOverride::create_or_load( + &mut *conn, + team_id, + &fingerprinted.fingerprint, + &issue, + ) + .await?; // If we actually inserted a new row for the issue override, commit the transaction, // saving both the issue and the override. Otherwise, rollback the transaction, and @@ -160,7 +179,8 @@ where conn.rollback().await?; } else { conn.commit().await?; + // TODO - emit new issue and override to kafka } - Ok(issue_override) + Ok(fingerprinted.to_output(issue_override.issue_id)) } diff --git a/rust/cymbal/src/lib.rs b/rust/cymbal/src/lib.rs index b88634c1828..35386be8cca 100644 --- a/rust/cymbal/src/lib.rs +++ b/rust/cymbal/src/lib.rs @@ -6,8 +6,7 @@ use error::{EventError, UnhandledError}; use fingerprinting::generate_fingerprint; use issue_resolution::resolve_issue; use tracing::warn; -use types::{ErrProps, Exception, Stacktrace}; -use uuid::Uuid; +use types::{Exception, RawErrProps, Stacktrace}; pub mod app_context; pub mod config; @@ -33,16 +32,13 @@ pub async fn handle_event( } }; - let exceptions = match take_exception_list(event.uuid, &mut props) { - Ok(r) => r, - Err(e) => { - warn!("Failed to take exception list: {}", e); - // Add an error message, and patch the event properties back up. - props.add_error_message(format!("Failed to take exception list: {}", e)); - event.properties = Some(serde_json::to_string(&props).unwrap()); - return Ok(Some(event)); - } - }; + let exceptions = std::mem::take(&mut props.exception_list); + + if exceptions.is_empty() { + props.add_error_message("No exceptions found on exception event"); + event.properties = Some(serde_json::to_string(&props).unwrap()); + return Ok(Some(event)); + } let mut results = Vec::new(); for exception in exceptions.into_iter() { @@ -53,19 +49,17 @@ pub async fn handle_event( } let fingerprint = generate_fingerprint(&results); + props.exception_list = results; + let fingerprinted = props.to_fingerprinted(fingerprint.clone()); - let issue_override = resolve_issue(&context.pool, &fingerprint, event.team_id).await?; + let output = resolve_issue(&context.pool, event.team_id, fingerprinted).await?; - props.fingerprint = Some(fingerprint); - props.resolved_issue_id = Some(issue_override.issue_id); - props.exception_list = Some(results); - - event.properties = Some(serde_json::to_string(&props).unwrap()); + event.properties = Some(serde_json::to_string(&output).unwrap()); Ok(Some(event)) } -fn get_props(event: &ClickHouseEvent) -> Result { +fn get_props(event: &ClickHouseEvent) -> Result { if event.event != "$exception" { return Err(EventError::WrongEventType(event.event.clone(), event.uuid)); } @@ -74,7 +68,7 @@ fn get_props(event: &ClickHouseEvent) -> Result { return Err(EventError::NoProperties(event.uuid)); }; - let properties: ErrProps = match serde_json::from_str(properties) { + let properties: RawErrProps = match serde_json::from_str(properties) { Ok(r) => r, Err(e) => { return Err(EventError::InvalidProperties(event.uuid, e.to_string())); @@ -84,18 +78,6 @@ fn get_props(event: &ClickHouseEvent) -> Result { Ok(properties) } -fn take_exception_list(event_id: Uuid, props: &mut ErrProps) -> Result, EventError> { - let Some(exception_list) = props.exception_list.as_mut() else { - return Err(EventError::NoExceptionList(event_id)); - }; - - if exception_list.is_empty() { - return Err(EventError::EmptyExceptionList(event_id)); - } - - Ok(std::mem::take(exception_list)) -} - async fn process_exception( context: &AppContext, team_id: i32, diff --git a/rust/cymbal/src/types/mod.rs b/rust/cymbal/src/types/mod.rs index 3084297df89..23981cc29f8 100644 --- a/rust/cymbal/src/types/mod.rs +++ b/rust/cymbal/src/types/mod.rs @@ -46,24 +46,33 @@ pub struct Exception { // of only a small subset. This struct is used to give us a strongly-typed // "view" of those event properties we care about. #[derive(Debug, Deserialize, Serialize, Clone)] -pub struct ErrProps { +pub struct RawErrProps { #[serde(rename = "$exception_list")] - pub exception_list: Option>, // Required from exception producers - we will not process events without this. Optional to support older clients, should eventually be removed - #[serde( - rename = "$exception_fingerprint", - skip_serializing_if = "Option::is_none" - )] - pub fingerprint: Option, // We expect this not to exist when the event is received, and we populate it as part of processing - #[serde( - rename = "$exception_issue_id", - skip_serializing_if = "Option::is_none" - )] - pub resolved_issue_id: Option, // We populate the exception issue id as part of processing + pub exception_list: Vec, #[serde(flatten)] // A catch-all for all the properties we don't "care" about, so when we send back to kafka we don't lose any info pub other: HashMap, } +pub struct FingerprintedErrProps { + pub exception_list: Vec, + pub fingerprint: String, + pub other: HashMap, +} + +// We emit this +#[derive(Debug, Serialize, Clone)] +pub struct OutputErrProps { + #[serde(rename = "$exception_list")] + pub exception_list: Vec, + #[serde(rename = "$exception_fingerprint")] + pub fingerprint: String, + #[serde(rename = "$exception_issue_id")] + pub issue_id: Uuid, + #[serde(flatten)] + pub other: HashMap, +} + impl Exception { pub fn include_in_fingerprint(&self, h: &mut Sha512) { h.update(self.exception_type.as_bytes()); @@ -92,7 +101,7 @@ impl Exception { } } -impl ErrProps { +impl RawErrProps { pub fn add_error_message(&mut self, msg: impl ToString) { let mut errors = match self.other.remove("$cymbal_errors") { Some(serde_json::Value::Array(errors)) => errors, @@ -106,6 +115,25 @@ impl ErrProps { serde_json::Value::Array(errors), ); } + + pub fn to_fingerprinted(self, fingerprint: String) -> FingerprintedErrProps { + FingerprintedErrProps { + exception_list: self.exception_list, + fingerprint, + other: self.other, + } + } +} + +impl FingerprintedErrProps { + pub fn to_output(self, issue_id: Uuid) -> OutputErrProps { + OutputErrProps { + exception_list: self.exception_list, + fingerprint: self.fingerprint, + issue_id, + other: self.other, + } + } } #[cfg(test)] @@ -115,7 +143,7 @@ mod test { use crate::{frames::RawFrame, types::Stacktrace}; - use super::ErrProps; + use super::RawErrProps; #[test] fn it_deserialises_error_props() { @@ -123,8 +151,8 @@ mod test { let raw: ClickHouseEvent = serde_json::from_str(raw).unwrap(); - let props: ErrProps = serde_json::from_str(&raw.properties.unwrap()).unwrap(); - let exception_list = &props.exception_list.unwrap(); + let props: RawErrProps = serde_json::from_str(&raw.properties.unwrap()).unwrap(); + let exception_list = &props.exception_list; assert_eq!(exception_list.len(), 1); assert_eq!( @@ -173,9 +201,9 @@ mod test { "$exception_list": [] }"#; - let props: Result = serde_json::from_str(raw); + let props: Result = serde_json::from_str(raw); assert!(props.is_ok()); - assert_eq!(props.unwrap().exception_list.unwrap().len(), 0); + assert_eq!(props.unwrap().exception_list.len(), 0); let raw: &'static str = r#"{ "$exception_list": [{ @@ -183,7 +211,7 @@ mod test { }] }"#; - let props: Result = serde_json::from_str(raw); + let props: Result = serde_json::from_str(raw); assert!(props.is_err()); assert_eq!( props.unwrap_err().to_string(), @@ -197,7 +225,7 @@ mod test { }] }"#; - let props: Result = serde_json::from_str(raw); + let props: Result = serde_json::from_str(raw); assert!(props.is_err()); assert_eq!( props.unwrap_err().to_string(), diff --git a/rust/cymbal/tests/resolve.rs b/rust/cymbal/tests/resolve.rs index d92eac66061..31533c3f297 100644 --- a/rust/cymbal/tests/resolve.rs +++ b/rust/cymbal/tests/resolve.rs @@ -9,7 +9,7 @@ use cymbal::{ sourcemap::SourcemapProvider, Catalog, }, - types::{ErrProps, Stacktrace}, + types::{RawErrProps, Stacktrace}, }; use httpmock::MockServer; use tokio::sync::Mutex; @@ -35,10 +35,10 @@ async fn end_to_end_resolver_test() { }); let exception: ClickHouseEvent = serde_json::from_str(EXAMPLE_EXCEPTION).unwrap(); - let props: ErrProps = serde_json::from_str(&exception.properties.unwrap()).unwrap(); + let mut props: RawErrProps = serde_json::from_str(&exception.properties.unwrap()).unwrap(); let Stacktrace::Raw { frames: mut test_stack, - } = props.exception_list.unwrap().swap_remove(0).stack.unwrap() + } = props.exception_list.swap_remove(0).stack.unwrap() else { panic!("Expected a Raw stacktrace") }; diff --git a/rust/cymbal/tests/types.rs b/rust/cymbal/tests/types.rs index 145a7606dcc..0404398a2b6 100644 --- a/rust/cymbal/tests/types.rs +++ b/rust/cymbal/tests/types.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use common_types::ClickHouseEvent; -use cymbal::types::ErrProps; +use cymbal::types::RawErrProps; use serde_json::Value; #[test] @@ -11,7 +11,7 @@ fn serde_passthrough() { let raw: ClickHouseEvent = serde_json::from_str(raw).unwrap(); let before_properties: Value = serde_json::from_str(raw.properties.as_ref().unwrap()).unwrap(); - let properties_parsed: ErrProps = + let properties_parsed: RawErrProps = serde_json::from_str(raw.properties.as_ref().unwrap()).unwrap(); let properties_raw = serde_json::to_string(&properties_parsed).unwrap(); From f6eb805277dc8584b84939ad3929e677c0221645 Mon Sep 17 00:00:00 2001 From: Richard Borcsik Date: Mon, 18 Nov 2024 13:02:14 +0100 Subject: [PATCH 12/27] fix: potential cors issue when inlining stylesheets for recordings (#25932) --- ...app-insights--trends-line-multi--light.png | Bin 57014 -> 56759 bytes frontend/utils.mjs | 1 + 2 files changed, 1 insertion(+) diff --git a/frontend/__snapshots__/scenes-app-insights--trends-line-multi--light.png b/frontend/__snapshots__/scenes-app-insights--trends-line-multi--light.png index c22f4a19b188fb9788b830063b08e8b8afbdcf47..fbc4e4428608692e8d0ab4867e1f7f9f045f8c31 100644 GIT binary patch literal 56759 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 diff --git a/frontend/utils.mjs b/frontend/utils.mjs index 3ebfbc196c9..86f9c3a02ea 100644 --- a/frontend/utils.mjs +++ b/frontend/utils.mjs @@ -87,6 +87,7 @@ export function copyIndexHtml( const cssLoader = ` const link = document.createElement("link"); link.rel = "stylesheet"; + link.crossOrigin = "anonymous"; link.href = (window.JS_URL || '') + "/static/" + ${JSON.stringify(cssFile)}; document.head.appendChild(link) ` From ead289eaeb2e8c4cd4a44c4675636597abfb5507 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Mon, 18 Nov 2024 12:11:38 +0000 Subject: [PATCH 13/27] chore(data-warehouse): Added a test for delta table deletes (#26218) --- .../tests/data_imports/test_end_to_end.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/posthog/temporal/tests/data_imports/test_end_to_end.py b/posthog/temporal/tests/data_imports/test_end_to_end.py index 16824e69b9b..1c213ec6684 100644 --- a/posthog/temporal/tests/data_imports/test_end_to_end.py +++ b/posthog/temporal/tests/data_imports/test_end_to_end.py @@ -5,6 +5,7 @@ from typing import Any, Optional from unittest import mock import aioboto3 +from deltalake import DeltaTable import posthoganalytics import psycopg import pytest @@ -938,3 +939,22 @@ async def test_non_retryable_error(team, stripe_customer): with pytest.raises(Exception): await sync_to_async(execute_hogql_query)("SELECT * FROM stripe_customer", team) + + +@pytest.mark.django_db(transaction=True) +@pytest.mark.asyncio +async def test_delta_table_deleted(team, stripe_balance_transaction): + workflow_id, inputs = await _run( + team=team, + schema_name="BalanceTransaction", + table_name="stripe_balancetransaction", + source_type="Stripe", + job_inputs={"stripe_secret_key": "test-key", "stripe_account_id": "acct_id"}, + mock_data_response=stripe_balance_transaction["data"], + sync_type=ExternalDataSchema.SyncType.FULL_REFRESH, + ) + + with mock.patch.object(DeltaTable, "delete") as mock_delta_table_delete: + await _execute_run(str(uuid.uuid4()), inputs, stripe_balance_transaction["data"]) + + mock_delta_table_delete.assert_called_once() From afeb5529ceb67cbe78af7c0d05999353e205bed5 Mon Sep 17 00:00:00 2001 From: Oliver Browne Date: Mon, 18 Nov 2024 14:12:48 +0200 Subject: [PATCH 14/27] fix(err): assorted perf/concurrency things (#26235) --- rust/cymbal/src/app_context.rs | 8 ++- rust/cymbal/src/lib.rs | 55 +++++++------- rust/cymbal/src/main.rs | 2 +- rust/cymbal/src/symbol_store/caching.rs | 24 +++++-- rust/cymbal/src/symbol_store/concurrency.rs | 79 +++++++++++++++++++++ rust/cymbal/src/symbol_store/mod.rs | 1 + rust/cymbal/src/symbol_store/saving.rs | 4 ++ 7 files changed, 140 insertions(+), 33 deletions(-) create mode 100644 rust/cymbal/src/symbol_store/concurrency.rs diff --git a/rust/cymbal/src/app_context.rs b/rust/cymbal/src/app_context.rs index dc0c513f332..ef96c84fa7a 100644 --- a/rust/cymbal/src/app_context.rs +++ b/rust/cymbal/src/app_context.rs @@ -16,6 +16,7 @@ use crate::{ frames::resolver::Resolver, symbol_store::{ caching::{Caching, SymbolSetCache}, + concurrency, saving::Saving, sourcemap::SourcemapProvider, Catalog, S3Client, @@ -80,13 +81,18 @@ impl AppContext { config.ss_prefix.clone(), ); let caching_smp = Caching::new(saving_smp, ss_cache); + // We want to fetch each sourcemap from the outside world + // exactly once, and if it isn't in the cache, load/parse + // it from s3 exactly once too. Limiting the per symbol set + // reference concurreny to 1 ensures this. + let limited_smp = concurrency::AtMostOne::new(caching_smp); info!( "AppContext initialized, subscribed to topic {}", config.consumer.kafka_consumer_topic ); - let catalog = Catalog::new(caching_smp); + let catalog = Catalog::new(limited_smp); let resolver = Resolver::new(config); Ok(Self { diff --git a/rust/cymbal/src/lib.rs b/rust/cymbal/src/lib.rs index 35386be8cca..09ea0a73f49 100644 --- a/rust/cymbal/src/lib.rs +++ b/rust/cymbal/src/lib.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::sync::Arc; use app_context::AppContext; use common_types::ClickHouseEvent; @@ -20,7 +20,7 @@ pub mod symbol_store; pub mod types; pub async fn handle_event( - context: &AppContext, + context: Arc, mut event: ClickHouseEvent, ) -> Result, UnhandledError> { let mut props = match get_props(&event) { @@ -45,7 +45,7 @@ pub async fn handle_event( // If we get an unhandled error during exception processing, we return an error, which should // cause the caller to drop the offset without storing it - unhandled exceptions indicate // a dependency is down, or some bug, adn we want to take lag in those situations. - results.push(process_exception(context, event.team_id, exception).await?); + results.push(process_exception(context.clone(), event.team_id, exception).await?); } let fingerprint = generate_fingerprint(&results); @@ -79,7 +79,7 @@ fn get_props(event: &ClickHouseEvent) -> Result { } async fn process_exception( - context: &AppContext, + context: Arc, team_id: i32, mut e: Exception, ) -> Result { @@ -96,40 +96,43 @@ async fn process_exception( return Ok(e); } - let mut results = Vec::with_capacity(frames.len()); + let mut handles = Vec::with_capacity(frames.len()); + let mut resolved_frames = Vec::with_capacity(frames.len()); - // Cluster the frames by symbol set - // TODO - we really want to cluster across exceptions (and even across events), - // rather than just within a single exception - let mut groups = HashMap::new(); - for (i, frame) in frames.into_iter().enumerate() { - let group = groups - .entry(frame.symbol_set_ref()) - .or_insert_with(Vec::new); - group.push((i, frame)); - } - - for (_, frames) in groups.into_iter() { - for (i, frame) in frames { - let resolved_frame = context + for frame in frames.into_iter() { + let context = context.clone(); + // Spawn a concurrent task for resolving every frame - we're careful elsewhere to + // ensure this kind of concurrency is fine, although this "throw it at the wall" + // data flow structure is pretty questionable. Once we switch to handling more than + // 1 event at a time, we should re-group frames into associated groups and then + // process those groups in-order (but the individual frames in them can still be + // thrown at the wall), with some cross-group concurrency. + handles.push(tokio::spawn(async move { + context .resolver .resolve(&frame, team_id, &context.pool, &context.catalog) - .await?; - results.push((i, resolved_frame)); - } + .await + })); } - results.sort_unstable_by_key(|(i, _)| *i); + // Collect the results + for handle in handles { + // Joinhandles wrap the returned type in a Result, because if the task panics, + // tokio catches it and returns an error. If any of our tasks panicked, we want + // to propogate that panic, so we unwrap the outer Result here. + let res = handle.await.unwrap()?; + resolved_frames.push(res) + } e.stack = Some(Stacktrace::Resolved { - frames: results.into_iter().map(|(_, frame)| frame).collect(), + frames: resolved_frames, }); Ok(e) } -// This is stupidly expensive, since it round-trips the event through JSON, lol. We should change ClickhouseEvent to only do serde at the -// edges +// This is expensive, since it round-trips the event through JSON. +// We could maybe change ClickhouseEvent to only do serde at the edges pub fn add_error_to_event( event: &mut ClickHouseEvent, e: impl ToString, diff --git a/rust/cymbal/src/main.rs b/rust/cymbal/src/main.rs index 8955a976761..ef96e8e490a 100644 --- a/rust/cymbal/src/main.rs +++ b/rust/cymbal/src/main.rs @@ -78,7 +78,7 @@ async fn main() { }; metrics::counter!(EVENT_RECEIVED).increment(1); - let _processed_event = match handle_event(&context, event).await { + let _processed_event = match handle_event(context.clone(), event).await { Ok(r) => { offset.store().unwrap(); r diff --git a/rust/cymbal/src/symbol_store/caching.rs b/rust/cymbal/src/symbol_store/caching.rs index 2fd24a2e9f3..5cab851fdac 100644 --- a/rust/cymbal/src/symbol_store/caching.rs +++ b/rust/cymbal/src/symbol_store/caching.rs @@ -12,6 +12,8 @@ use crate::{ use super::{saving::Saveable, Fetcher, Parser, Provider}; +// This is a type-specific symbol provider layer, designed to +// wrap some inner provider and provide a type-safe caching layer pub struct Caching

{ inner: P, cache: Arc>, @@ -42,16 +44,30 @@ where return Ok(set); } metrics::counter!(STORE_CACHE_MISSES).increment(1); + drop(cache); + + // Do the fetch, not holding the lock across it to allow + // concurrent fetches to occur (de-duping fetches is + // up to the caller of `lookup`, since relying on the + // cache to do it means assuming the caching layer is + // the outer layer, which is not something the interface + // guarentees) let found = self.inner.fetch(team_id, r).await?; let bytes = found.byte_count(); let parsed = self.inner.parse(found).await?; + let mut cache = self.cache.lock().await; // Re-acquire the cache-wide lock to insert, dropping the ref_lock + let parsed = Arc::new(parsed); cache.insert(cache_key, parsed.clone(), bytes); Ok(parsed) } } +// This is a cache shared across multiple symbol set providers, through the `Caching` above, +// such that two totally different "layers" can share an underlying "pool" of cache space. This +// is injected into the `Caching` layer at construct time, to allow this sharing across multiple +// provider layer "stacks" within the catalog. pub struct SymbolSetCache { // We expect this cache to consist of few, but large, items. // TODO - handle cases where two CachedSymbolSets have identical keys but different types @@ -113,16 +129,14 @@ impl SymbolSetCache { // remove them in a separate pass. let mut to_remove = vec![]; while self.held_bytes > self.max_bytes && !vals.is_empty() { - // We can unwrap here because we know we're not empty from the line above + // We can unwrap here because we know we're not empty from the line above (and + // really, even the !empty check could be skipped - if held_bytes is non-zero, we + // must have at least one element in vals) let (to_remove_key, to_remove_val) = vals.pop().unwrap(); self.held_bytes -= to_remove_val.bytes; to_remove.push(to_remove_key.clone()); } - for key in to_remove { - self.cached.remove(&key); - } - metrics::gauge!(STORE_CACHED_BYTES).set(self.held_bytes as f64); } } diff --git a/rust/cymbal/src/symbol_store/concurrency.rs b/rust/cymbal/src/symbol_store/concurrency.rs new file mode 100644 index 00000000000..466bfa8fce2 --- /dev/null +++ b/rust/cymbal/src/symbol_store/concurrency.rs @@ -0,0 +1,79 @@ +use std::{ + collections::HashMap, + sync::{Arc, Weak}, +}; + +use axum::async_trait; +use tokio::sync::{Mutex, OwnedMutexGuard}; + +use crate::error::Error; + +use super::Provider; + +// Limits the number of concurrent lookups +// for a given symbol set to 1. Note this places +// no concurrency limit /across/ different symbol +// sets, and places no limit on the number of users +// using the returned symbol set concurrently. Designed +// to wrap the caching/saving layers, allowing us to +// ensure we only fetch any given symbol set from the +// outside world exactly once +pub struct AtMostOne

{ + pub inner: P, + limiters: Mutex>>>, +} + +impl

AtMostOne

{ + pub fn new(inner: P) -> Self { + Self { + inner, + limiters: Default::default(), + } + } + + // This needs to be async even though all it does is take a lock because + // the returned owned guard can be (and is) held across an await point, so + // if this was a sync mutex it'd block the executor. It so happens that the + // std library Mutex doesn't provide lock_owned anyway, so we'd have to pull + // in a new dependency if we wanted to write a sync version of this, but + // that's secondary to it actually needing to be async + pub async fn acquire(&self, key: impl ToString) -> OwnedMutexGuard<()> { + let key = key.to_string(); + let mut state = self.limiters.lock().await; + let limiter = state.entry(key).or_default(); + + if let Some(lock) = limiter.upgrade() { + // If there's already a mutex in our shared state for this particular + // source ref, drop the global lock, and wait for the underlying source + // ref to be freed up + drop(state); + lock.lock_owned().await + } else { + // If there's no mutex in our shared state for this particular source ref, + // create one, acquire it, put a Weak to it in the shared state, and return + // the owning mutex guard (and therefore the underling Arc to the new mutex) + let new = Arc::new(Mutex::new(())); + *limiter = Arc::downgrade(&new); + let acquired = new.lock_owned().await; + drop(state); + acquired + } + } +} + +#[async_trait] +impl

Provider for AtMostOne

+where + P: Provider, + P::Ref: ToString + Send, +{ + type Ref = P::Ref; + type Set = P::Set; + + async fn lookup(&self, team_id: i32, r: Self::Ref) -> Result, Error> { + let lock = self.acquire(r.to_string()).await; + let result = self.inner.lookup(team_id, r).await; + drop(lock); + result + } +} diff --git a/rust/cymbal/src/symbol_store/mod.rs b/rust/cymbal/src/symbol_store/mod.rs index 458a0c116da..618db75d232 100644 --- a/rust/cymbal/src/symbol_store/mod.rs +++ b/rust/cymbal/src/symbol_store/mod.rs @@ -8,6 +8,7 @@ use reqwest::Url; use crate::error::Error; pub mod caching; +pub mod concurrency; pub mod saving; pub mod sourcemap; diff --git a/rust/cymbal/src/symbol_store/saving.rs b/rust/cymbal/src/symbol_store/saving.rs index d231d2400ec..a9b3f0ed19b 100644 --- a/rust/cymbal/src/symbol_store/saving.rs +++ b/rust/cymbal/src/symbol_store/saving.rs @@ -147,6 +147,10 @@ where error!("Found a record with no data and no error: {:?}", record); panic!("Found a record with no data and no error"); } + // TODO - this can fail due to changes in how we serialise, or changes in + // the error type - and we should handle that by deleting the symbol record + // and re-fetching, I think (we don't need to cleanup s3 since it's a failure + // case, there is no saved data). let error = serde_json::from_str(&record.failure_reason.unwrap()) .map_err(UnhandledError::from)?; return Err(Error::ResolutionError(error)); From fc6038118fd4c84c45e332c9c77d7e35c7e78a53 Mon Sep 17 00:00:00 2001 From: PostHog Bot <69588470+posthog-bot@users.noreply.github.com> Date: Mon, 18 Nov 2024 08:20:05 -0500 Subject: [PATCH 15/27] chore(deps): Update posthog-js to 1.186.2 (#26240) --- package.json | 2 +- pnpm-lock.yaml | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 9be82875a40..b9aec3e2639 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "pmtiles": "^2.11.0", "postcss": "^8.4.31", "postcss-preset-env": "^9.3.0", - "posthog-js": "1.186.0", + "posthog-js": "1.186.2", "posthog-js-lite": "3.0.0", "prettier": "^2.8.8", "prop-types": "^15.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0579185ebe5..7e30575948b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -284,8 +284,8 @@ dependencies: specifier: ^9.3.0 version: 9.3.0(postcss@8.4.31) posthog-js: - specifier: 1.186.0 - version: 1.186.0 + specifier: 1.186.2 + version: 1.186.2 posthog-js-lite: specifier: 3.0.0 version: 3.0.0 @@ -6579,7 +6579,7 @@ packages: '@storybook/client-logger': 7.6.20 '@storybook/core-events': 7.6.20 '@storybook/global': 5.0.0 - qs: 6.13.0 + qs: 6.13.1 telejson: 7.2.0 tiny-invariant: 1.3.3 dev: true @@ -7093,7 +7093,7 @@ packages: dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 - qs: 6.13.0 + qs: 6.13.1 synchronous-promise: 2.0.17 ts-dedent: 2.2.0 util-deprecate: 1.0.2 @@ -7253,7 +7253,7 @@ packages: dependencies: '@storybook/client-logger': 7.6.20 memoizerific: 1.11.3 - qs: 6.13.0 + qs: 6.13.1 dev: true /@storybook/router@7.6.4: @@ -17789,8 +17789,8 @@ packages: resolution: {integrity: sha512-dyajjnfzZD1tht4N7p7iwf7nBnR1MjVaVu+MKr+7gBgA39bn28wizCIJZztZPtHy4PY0YwtSGgwfBCuG/hnHgA==} dev: false - /posthog-js@1.186.0: - resolution: {integrity: sha512-WagGNrDtvyOhmX1Gtf1hJQMBy1mB1vx9gtC6BKEfJi2pvEFtQuAzQ9c/tMUTmY0o2ZF5ZBFiZ2IRs4kbFLMvPQ==} + /posthog-js@1.186.2: + resolution: {integrity: sha512-e2cYHnq+1UEN0N3okJMlKXkprC8JkZkoLPFqp/CjKOlBvAoz05WOW1ROJiRGPzPxc8CWZQIzGLoRbAP+C5Hsbw==} dependencies: core-js: 3.39.0 fflate: 0.4.8 @@ -18168,8 +18168,8 @@ packages: side-channel: 1.0.6 dev: true - /qs@6.13.0: - resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + /qs@6.13.1: + resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} engines: {node: '>=0.6'} dependencies: side-channel: 1.0.6 From 0fd91f47432f05e65c631881dd4f5befd8535822 Mon Sep 17 00:00:00 2001 From: Marius Andra Date: Mon, 18 Nov 2024 14:38:25 +0100 Subject: [PATCH 16/27] feat(cdp): hog to JS transpiler (#26143) --- .vscode/launch.json | 2 +- bin/hoge | 3 + ee/clickhouse/models/test/test_action.py | 2 +- hogvm/__tests__/__snapshots__/arrays.hoge | 4 +- hogvm/__tests__/__snapshots__/arrays.js | 144 +++ hogvm/__tests__/__snapshots__/arrays.stdout | 4 + hogvm/__tests__/__snapshots__/bytecodeStl.js | 66 ++ hogvm/__tests__/__snapshots__/catch.js | 134 +++ hogvm/__tests__/__snapshots__/catch2.hoge | 4 +- hogvm/__tests__/__snapshots__/catch2.js | 142 +++ hogvm/__tests__/__snapshots__/catch2.stdout | 4 +- hogvm/__tests__/__snapshots__/crypto.js | 49 + hogvm/__tests__/__snapshots__/date.js | 171 ++++ hogvm/__tests__/__snapshots__/dateFormat.js | 287 ++++++ hogvm/__tests__/__snapshots__/dicts.hoge | 2 +- hogvm/__tests__/__snapshots__/dicts.js | 57 ++ hogvm/__tests__/__snapshots__/dicts.stdout | 2 +- hogvm/__tests__/__snapshots__/exceptions.js | 152 +++ hogvm/__tests__/__snapshots__/functionVars.js | 72 ++ hogvm/__tests__/__snapshots__/functions.js | 124 +++ hogvm/__tests__/__snapshots__/ifElse.js | 69 ++ hogvm/__tests__/__snapshots__/ifJump.js | 61 ++ hogvm/__tests__/__snapshots__/json.js | 197 ++++ hogvm/__tests__/__snapshots__/keysValues.js | 54 + hogvm/__tests__/__snapshots__/lambdas.js | 129 +++ hogvm/__tests__/__snapshots__/loops.js | 108 ++ hogvm/__tests__/__snapshots__/mandelbrot.js | 125 +++ hogvm/__tests__/__snapshots__/operations.hoge | 36 +- hogvm/__tests__/__snapshots__/operations.js | 224 +++++ .../__tests__/__snapshots__/operations.stdout | 3 + hogvm/__tests__/__snapshots__/printLoops.js | 158 +++ hogvm/__tests__/__snapshots__/printLoops2.js | 156 +++ hogvm/__tests__/__snapshots__/properties.js | 122 +++ hogvm/__tests__/__snapshots__/recursion.js | 56 ++ hogvm/__tests__/__snapshots__/scope.js | 122 +++ hogvm/__tests__/__snapshots__/stl.js | 121 +++ hogvm/__tests__/__snapshots__/strings.js | 129 +++ hogvm/__tests__/__snapshots__/tuples.js | 67 ++ hogvm/__tests__/__snapshots__/typeof.js | 88 ++ hogvm/__tests__/__snapshots__/upvalues.js | 57 ++ hogvm/__tests__/__snapshots__/variables.js | 53 + hogvm/__tests__/arrays.hog | 5 + hogvm/__tests__/catch2.hog | 4 +- hogvm/__tests__/dicts.hog | 5 +- hogvm/__tests__/operations.hog | 3 + hogvm/python/test/test_execute.py | 2 +- hogvm/python/utils.py | 2 +- hogvm/stl/compile.py | 2 +- hogvm/test.sh | 121 ++- hogvm/typescript/package.json | 2 +- hogvm/typescript/src/stl/stl.ts | 10 +- hogvm/typescript/src/utils.ts | 1 + package.json | 2 +- plugin-server/package.json | 4 +- plugin-server/pnpm-lock.yaml | 8 +- pnpm-lock.yaml | 11 +- posthog/api/hog.py | 2 +- posthog/api/services/query.py | 2 +- posthog/cdp/filters.py | 2 +- posthog/cdp/test/test_filters.py | 2 +- posthog/cdp/validation.py | 2 +- posthog/hogql/cli.py | 84 +- posthog/hogql/{ => compiler}/bytecode.py | 0 posthog/hogql/compiler/javascript.py | 572 +++++++++++ posthog/hogql/compiler/javascript_stl.py | 923 ++++++++++++++++++ .../{ => compiler}/test/test_bytecode.py | 2 +- .../hogql/compiler/test/test_javascript.py | 227 +++++ posthog/hogql/metadata.py | 2 +- posthog/models/action/action.py | 2 +- 69 files changed, 5450 insertions(+), 114 deletions(-) create mode 100644 hogvm/__tests__/__snapshots__/arrays.js create mode 100644 hogvm/__tests__/__snapshots__/bytecodeStl.js create mode 100644 hogvm/__tests__/__snapshots__/catch.js create mode 100644 hogvm/__tests__/__snapshots__/catch2.js create mode 100644 hogvm/__tests__/__snapshots__/crypto.js create mode 100644 hogvm/__tests__/__snapshots__/date.js create mode 100644 hogvm/__tests__/__snapshots__/dateFormat.js create mode 100644 hogvm/__tests__/__snapshots__/dicts.js create mode 100644 hogvm/__tests__/__snapshots__/exceptions.js create mode 100644 hogvm/__tests__/__snapshots__/functionVars.js create mode 100644 hogvm/__tests__/__snapshots__/functions.js create mode 100644 hogvm/__tests__/__snapshots__/ifElse.js create mode 100644 hogvm/__tests__/__snapshots__/ifJump.js create mode 100644 hogvm/__tests__/__snapshots__/json.js create mode 100644 hogvm/__tests__/__snapshots__/keysValues.js create mode 100644 hogvm/__tests__/__snapshots__/lambdas.js create mode 100644 hogvm/__tests__/__snapshots__/loops.js create mode 100644 hogvm/__tests__/__snapshots__/mandelbrot.js create mode 100644 hogvm/__tests__/__snapshots__/operations.js create mode 100644 hogvm/__tests__/__snapshots__/printLoops.js create mode 100644 hogvm/__tests__/__snapshots__/printLoops2.js create mode 100644 hogvm/__tests__/__snapshots__/properties.js create mode 100644 hogvm/__tests__/__snapshots__/recursion.js create mode 100644 hogvm/__tests__/__snapshots__/scope.js create mode 100644 hogvm/__tests__/__snapshots__/stl.js create mode 100644 hogvm/__tests__/__snapshots__/strings.js create mode 100644 hogvm/__tests__/__snapshots__/tuples.js create mode 100644 hogvm/__tests__/__snapshots__/typeof.js create mode 100644 hogvm/__tests__/__snapshots__/upvalues.js create mode 100644 hogvm/__tests__/__snapshots__/variables.js rename posthog/hogql/{ => compiler}/bytecode.py (100%) create mode 100644 posthog/hogql/compiler/javascript.py create mode 100644 posthog/hogql/compiler/javascript_stl.py rename posthog/hogql/{ => compiler}/test/test_bytecode.py (99%) create mode 100644 posthog/hogql/compiler/test/test_javascript.py diff --git a/.vscode/launch.json b/.vscode/launch.json index 98d4f1cdae0..93a654422db 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -97,7 +97,7 @@ "console": "integratedTerminal", "cwd": "${workspaceFolder}", "env": { - "SKIP_ASYNC_MIGRATIONS_SETUP": "0", + "SKIP_ASYNC_MIGRATIONS_SETUP": "1", "DEBUG": "1", "BILLING_SERVICE_URL": "https://billing.dev.posthog.dev", "SKIP_SERVICE_VERSION_REQUIREMENTS": "1" diff --git a/bin/hoge b/bin/hoge index 897de9b9856..26e1043b6f9 100755 --- a/bin/hoge +++ b/bin/hoge @@ -3,10 +3,13 @@ set -e if [[ "$@" == *".hog"* ]]; then exec python3 -m posthog.hogql.cli --compile "$@" +elif [[ "$@" == *".js"* ]]; then + exec python3 -m posthog.hogql.cli --compile "$@" else echo "$0 - the Hog compilër! 🦔+🕶️= Hoge" echo "" echo "Usage: bin/hoge [output.hoge] compile .hog into .hoge" + echo " bin/hoge compile .hog into .js" echo " bin/hog run .hog source code" echo " bin/hog run compiled .hoge bytecode" exit 1 diff --git a/ee/clickhouse/models/test/test_action.py b/ee/clickhouse/models/test/test_action.py index d4b3a32311a..b9aaf44a4c6 100644 --- a/ee/clickhouse/models/test/test_action.py +++ b/ee/clickhouse/models/test/test_action.py @@ -1,7 +1,7 @@ import dataclasses from posthog.client import sync_execute -from posthog.hogql.bytecode import create_bytecode +from posthog.hogql.compiler.bytecode import create_bytecode from posthog.hogql.hogql import HogQLContext from posthog.hogql.property import action_to_expr from posthog.models.action import Action diff --git a/hogvm/__tests__/__snapshots__/arrays.hoge b/hogvm/__tests__/__snapshots__/arrays.hoge index c62202ce612..2e86bd37870 100644 --- a/hogvm/__tests__/__snapshots__/arrays.hoge +++ b/hogvm/__tests__/__snapshots__/arrays.hoge @@ -29,4 +29,6 @@ 33, 2, 33, 3, 43, 3, 33, 4, 2, "indexOf", 2, 2, "print", 1, 35, 52, "lambda", 1, 0, 6, 33, 2, 36, 0, 13, 38, 53, 0, 33, 1, 33, 2, 33, 3, 33, 4, 33, 5, 43, 5, 2, "arrayCount", 2, 2, "print", 1, 35, 32, "------", 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 43, 3, 36, 3, 33, 1, 45, 36, 3, 33, 2, 45, 36, 3, 33, 3, 45, 36, 3, 33, 4, 45, 2, "print", 4, 35, 36, 3, 33, --1, 45, 36, 3, 33, -2, 45, 36, 3, 33, -3, 45, 36, 3, 33, -4, 45, 2, "print", 4, 35, 35, 35, 35, 35] +-1, 45, 36, 3, 33, -2, 45, 36, 3, 33, -3, 45, 36, 3, 33, -4, 45, 2, "print", 4, 35, 32, "------", 2, "print", 1, 35, 32, +"a", 32, "b", 32, "c", 43, 3, 32, "a", 21, 2, "print", 1, 35, 32, "a", 32, "b", 32, "c", 43, 3, 32, "d", 21, 2, "print", +1, 35, 43, 0, 32, "a", 21, 2, "print", 1, 35, 35, 35, 35, 35] diff --git a/hogvm/__tests__/__snapshots__/arrays.js b/hogvm/__tests__/__snapshots__/arrays.js new file mode 100644 index 00000000000..a6954571659 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/arrays.js @@ -0,0 +1,144 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function indexOf (arrOrString, elem) { if (Array.isArray(arrOrString)) { return arrOrString.indexOf(elem) + 1 } else { return 0 } } +function has (arr, elem) { if (!Array.isArray(arr) || arr.length === 0) { return false } return arr.includes(elem) } +function arrayStringConcat (arr, separator = '') { if (!Array.isArray(arr)) { return '' } return arr.join(separator) } +function arraySort (arr) { if (!Array.isArray(arr)) { return [] } return [...arr].sort() } +function arrayReverseSort (arr) { if (!Array.isArray(arr)) { return [] } return [...arr].sort().reverse() } +function arrayReverse (arr) { if (!Array.isArray(arr)) { return [] } return [...arr].reverse() } +function arrayPushFront (arr, item) { if (!Array.isArray(arr)) { return [item] } return [item, ...arr] } +function arrayPushBack (arr, item) { if (!Array.isArray(arr)) { return [item] } return [...arr, item] } +function arrayPopFront (arr) { if (!Array.isArray(arr)) { return [] } return arr.slice(1) } +function arrayPopBack (arr) { if (!Array.isArray(arr)) { return [] } return arr.slice(0, arr.length - 1) } +function arrayCount (func, arr) { let count = 0; for (let i = 0; i < arr.length; i++) { if (func(arr[i])) { count = count + 1 } } return count } +function __setProperty(objectOrArray, key, value) { + if (Array.isArray(objectOrArray)) { + if (key > 0) { + objectOrArray[key - 1] = value + } else { + objectOrArray[objectOrArray.length + key] = value + } + } else { + objectOrArray[key] = value + } + return objectOrArray +} +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print([]); +print([1, 2, 3]); +print([1, "2", 3]); +print([1, [2, 3], 4]); +print([1, [2, [3, 4]], 5]); +let a = [1, 2, 3]; +print(__getProperty(a, 2, false)); +print(__getProperty(a, 2, true)); +print(__getProperty(a, 2, true)); +print(__getProperty(a, 7, true)); +print(__getProperty(a, 7, true)); +print(__getProperty([1, 2, 3], 2, false)); +print(__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 2, false), 2, false), 2, false)); +print(__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 2, true), 2, true), 2, true)); +print(__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 2, true), 2, true), 2, true)); +print(__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 7, true), 4, true), 2, true)); +print(__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 7, true), 4, true), 2, true)); +print((__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 2, false), 2, false), 2, false) + 1)); +print(__getProperty(__getProperty(__getProperty([1, [2, [3, 4]], 5], 2, false), 2, false), 2, false)); +print("------"); +let b = [1, 2, [1, 2, 3]]; +__setProperty(b, 2, 4); +print(__getProperty(b, 1, false)); +print(__getProperty(b, 2, false)); +print(__getProperty(b, 3, false)); +__setProperty(__getProperty(b, 3, false), 3, 8); +print(b); +print("------"); +print(arrayPushBack([1, 2, 3], 4)); +print(arrayPushFront([1, 2, 3], 0)); +print(arrayPopBack([1, 2, 3])); +print(arrayPopFront([1, 2, 3])); +print(arraySort([3, 2, 1])); +print(arrayReverse([1, 2, 3])); +print(arrayReverseSort([3, 2, 1])); +print(arrayStringConcat([1, 2, 3], ",")); +print("-----"); +let arr = [1, 2, 3, 4]; +print(arr); +arrayPushBack(arr, 5); +print(arr); +arrayPushFront(arr, 0); +print(arr); +arrayPopBack(arr); +print(arr); +arrayPopFront(arr); +print(arr); +arraySort(arr); +print(arr); +arrayReverse(arr); +print(arr); +arrayReverseSort(arr); +print(arr); +print("------"); +print(has(arr, 0)); +print(has(arr, 2)); +print(has(arr, "banana")); +print(has("banananas", "banana")); +print(has("banananas", "foo")); +print(has(["1", "2"], "1")); +print(indexOf([1, 2, 3], 1)); +print(indexOf([1, 2, 3], 2)); +print(indexOf([1, 2, 3], 3)); +print(indexOf([1, 2, 3], 4)); +print(arrayCount(__lambda((x) => (x > 2)), [1, 2, 3, 4, 5])); +print("------"); +let c = [1, 2, 3]; +print(__getProperty(c, 1, false), __getProperty(c, 2, false), __getProperty(c, 3, false), __getProperty(c, 4, false)); +print(__getProperty(c, -1, false), __getProperty(c, -2, false), __getProperty(c, -3, false), __getProperty(c, -4, false)); +print("------"); +print((["a", "b", "c"].includes("a"))); +print((["a", "b", "c"].includes("d"))); +print(([].includes("a"))); diff --git a/hogvm/__tests__/__snapshots__/arrays.stdout b/hogvm/__tests__/__snapshots__/arrays.stdout index 2790d891956..a06cfa41046 100644 --- a/hogvm/__tests__/__snapshots__/arrays.stdout +++ b/hogvm/__tests__/__snapshots__/arrays.stdout @@ -54,3 +54,7 @@ true ------ 1 2 3 null 3 2 1 null +------ +true +false +false diff --git a/hogvm/__tests__/__snapshots__/bytecodeStl.js b/hogvm/__tests__/__snapshots__/bytecodeStl.js new file mode 100644 index 00000000000..2e997fe17d9 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/bytecodeStl.js @@ -0,0 +1,66 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function like (str, pattern) { return __like(str, pattern, false) } +function arrayMap (func, arr) { let result = []; for (let i = 0; i < arr.length; i++) { result = arrayPushBack(result, func(arr[i])) } return result } +function arrayFilter (func, arr) { let result = []; for (let i = 0; i < arr.length; i++) { if (func(arr[i])) { result = arrayPushBack(result, arr[i]) } } return result} +function arrayPushBack (arr, item) { if (!Array.isArray(arr)) { return [item] } return [...arr, item] } +function arrayExists (func, arr) { for (let i = 0; i < arr.length; i++) { if (func(arr[i])) { return true } } return false } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __like(str, pattern, caseInsensitive = false) { + if (caseInsensitive) { + str = str.toLowerCase() + pattern = pattern.toLowerCase() + } + pattern = String(pattern) + .replaceAll(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + .replaceAll('%', '.*') + .replaceAll('_', '.') + return new RegExp(pattern).test(str) +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print("--- arrayMap ----"); +print(arrayMap(__lambda((x) => (x * 2)), [1, 2, 3])); +print("--- arrayExists ----"); +print(arrayExists(__lambda((x) => like(x, "%nana%")), ["apple", "banana", "cherry"])); +print(arrayExists(__lambda((x) => like(x, "%boom%")), ["apple", "banana", "cherry"])); +print(arrayExists(__lambda((x) => like(x, "%boom%")), [])); +print("--- arrayFilter ----"); +print(arrayFilter(__lambda((x) => like(x, "%nana%")), ["apple", "banana", "cherry"])); +print(arrayFilter(__lambda((x) => like(x, "%e%")), ["apple", "banana", "cherry"])); +print(arrayFilter(__lambda((x) => like(x, "%boom%")), [])); diff --git a/hogvm/__tests__/__snapshots__/catch.js b/hogvm/__tests__/__snapshots__/catch.js new file mode 100644 index 00000000000..87734f68fd9 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/catch.js @@ -0,0 +1,134 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} +function NotImplementedError (message, payload) { return __newHogError('NotImplementedError', message, payload) } +function HogError (type, message, payload) { return __newHogError(type, message, payload) } +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} + +function FishError(message) { + return HogError("FishError", message); +} +function FoodError(message) { + return HogError("FoodError", message); +} +try { + throw FishError("You forgot to feed your fish"); +} catch (__error) { if (__error.type === "FoodError") { let e = __error; +print(concat("Problem with your food: ", __getProperty(e, "message", true))); +} + else if (__error.type === "FishError") { let e = __error; +print(concat("Problem with your fish: ", __getProperty(e, "message", true))); +} + else { throw __error; }} +try { + throw FoodError("Your fish are hungry"); +} catch (__error) { if (__error.type === "FoodError") { let e = __error; +print(concat("Problem with your food: ", __getProperty(e, "message", true))); +} + else if (__error.type === "FishError") { let e = __error; +print(concat("Problem with your fish: ", __getProperty(e, "message", true))); +} + else { throw __error; }} +try { + throw NotImplementedError("Your fish are hungry"); +} catch (__error) { if (__error.type === "FoodError") { let e = __error; +print(concat("Problem with your food: ", __getProperty(e, "message", true))); +} + else if (true) { let e = __error; +print(concat("Unknown problem: ", e)); +} +} diff --git a/hogvm/__tests__/__snapshots__/catch2.hoge b/hogvm/__tests__/__snapshots__/catch2.hoge index ce7f940a43a..614e1dfb0b7 100644 --- a/hogvm/__tests__/__snapshots__/catch2.hoge +++ b/hogvm/__tests__/__snapshots__/catch2.hoge @@ -6,10 +6,10 @@ "You forgot to feed your fish", 2, "HogError", 2, 49, 51, 39, 32, 36, 0, 32, "type", 45, 32, "FoodError", 36, 1, 11, 40, 16, 32, "Problem with your food: ", 36, 0, 32, "message", 45, 2, "concat", 2, 2, "print", 1, 35, 39, 2, 35, 49, 35, 35, 51, 39, 55, 36, 0, 32, "type", 45, 32, "FishError", 36, 1, 11, 40, 16, 32, "FishError: ", 36, 0, 32, "message", 45, 2, -"concat", 2, 2, "print", 1, 35, 39, 25, 32, "Error of type ", 36, 0, 32, "name", 45, 32, ": ", 36, 0, 32, "message", 45, +"concat", 2, 2, "print", 1, 35, 39, 25, 32, "Error of type ", 36, 0, 32, "type", 45, 32, ": ", 36, 0, 32, "message", 45, 2, "concat", 4, 2, "print", 1, 35, 39, 2, 35, 49, 35, 35, 50, 49, 50, 12, 32, "FishError", 32, "You forgot to feed your fish", 2, "HogError", 2, 49, 51, 39, 32, 36, 0, 32, "type", 45, 32, "FoodError", 36, 1, 11, 40, 16, 32, "Problem with your food: ", 36, 0, 32, "message", 45, 2, "concat", 2, 2, "print", 1, 35, 39, 2, 35, 49, 35, 35, -51, 39, 55, 36, 0, 32, "type", 45, 32, "Error of type ", 36, 0, 32, "name", 45, 32, ": ", 36, 0, 32, "message", 45, 2, +51, 39, 55, 36, 0, 32, "type", 45, 32, "Error of type ", 36, 0, 32, "type", 45, 32, ": ", 36, 0, 32, "message", 45, 2, "concat", 4, 2, "print", 1, 35, 39, 25, 32, "FishError", 36, 1, 11, 40, 16, 32, "FishError: ", 36, 0, 32, "message", 45, 2, "concat", 2, 2, "print", 1, 35, 39, 2, 35, 49, 35, 35] diff --git a/hogvm/__tests__/__snapshots__/catch2.js b/hogvm/__tests__/__snapshots__/catch2.js new file mode 100644 index 00000000000..ffc20ac2811 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/catch2.js @@ -0,0 +1,142 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} +function HogError (type, message, payload) { return __newHogError(type, message, payload) } +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} + +try { + try { + throw HogError("FishError", "You forgot to feed your fish"); + } catch (__error) { if (__error.type === "FoodError") { let e = __error; + print(concat("Problem with your food: ", __getProperty(e, "message", true))); + } + else { throw __error; }} +} catch (__error) { if (__error.type === "FishError") { let e = __error; +print(concat("FishError: ", __getProperty(e, "message", true))); +} + else if (true) { let e = __error; +print(concat("Error: ", __getProperty(e, "message", true))); +} +} +try { + try { + throw HogError("FunkyError", "You forgot to feed your fish"); + } catch (__error) { if (__error.type === "FoodError") { let e = __error; + print(concat("Problem with your food: ", __getProperty(e, "message", true))); + } + else { throw __error; }} +} catch (__error) { if (__error.type === "FishError") { let e = __error; +print(concat("FishError: ", __getProperty(e, "message", true))); +} + else if (true) { let e = __error; +print(concat("Error of type ", __getProperty(e, "type", true), ": ", __getProperty(e, "message", true))); +} +} +try { + try { + throw HogError("FishError", "You forgot to feed your fish"); + } catch (__error) { if (__error.type === "FoodError") { let e = __error; + print(concat("Problem with your food: ", __getProperty(e, "message", true))); + } + else { throw __error; }} +} catch (__error) { if (true) { let e = __error; +print(concat("Error of type ", __getProperty(e, "type", true), ": ", __getProperty(e, "message", true))); +} + else if (__error.type === "FishError") { let e = __error; +print(concat("FishError: ", __getProperty(e, "message", true))); +} +} diff --git a/hogvm/__tests__/__snapshots__/catch2.stdout b/hogvm/__tests__/__snapshots__/catch2.stdout index f30ba83b8cf..7ee82d979af 100644 --- a/hogvm/__tests__/__snapshots__/catch2.stdout +++ b/hogvm/__tests__/__snapshots__/catch2.stdout @@ -1,3 +1,3 @@ FishError: You forgot to feed your fish -Error of type : You forgot to feed your fish -Error of type : You forgot to feed your fish +Error of type FunkyError: You forgot to feed your fish +Error of type FishError: You forgot to feed your fish diff --git a/hogvm/__tests__/__snapshots__/crypto.js b/hogvm/__tests__/__snapshots__/crypto.js new file mode 100644 index 00000000000..b842d251c8b --- /dev/null +++ b/hogvm/__tests__/__snapshots__/crypto.js @@ -0,0 +1,49 @@ +function sha256HmacChainHex (data, options) { return 'sha256HmacChainHex not implemented' } +function sha256Hex (str, options) { return 'SHA256 is not implemented' } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function md5Hex(string) { return 'MD5 is not implemented' } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +let string = "this is a secure string"; +print("string:", string); +print("md5Hex(string):", md5Hex(string)); +print("sha256Hex(string):", sha256Hex(string)); +let data = ["1", "string", "more", "keys"]; +print("data:", data); +print("sha256HmacChainHex(data):", sha256HmacChainHex(data)); diff --git a/hogvm/__tests__/__snapshots__/date.js b/hogvm/__tests__/__snapshots__/date.js new file mode 100644 index 00000000000..71af223af0e --- /dev/null +++ b/hogvm/__tests__/__snapshots__/date.js @@ -0,0 +1,171 @@ +function toUnixTimestampMilli (input, zone) { return __toUnixTimestampMilli(input, zone) } +function toUnixTimestamp (input, zone) { return __toUnixTimestamp(input, zone) } +function toTimeZone (input, zone) { return __toTimeZone(input, zone) } +function toString (value) { return __STLToString(value) } +function toInt(value) { + if (__isHogDateTime(value)) { return Math.floor(value.dt); } + else if (__isHogDate(value)) { const date = new Date(Date.UTC(value.year, value.month - 1, value.day)); const epoch = new Date(Date.UTC(1970, 0, 1)); const diffInDays = Math.floor((date - epoch) / (1000 * 60 * 60 * 24)); return diffInDays; } + return !isNaN(parseInt(value)) ? parseInt(value) : null; } +function toFloat(value) { + if (__isHogDateTime(value)) { return value.dt; } + else if (__isHogDate(value)) { const date = new Date(Date.UTC(value.year, value.month - 1, value.day)); const epoch = new Date(Date.UTC(1970, 0, 1)); const diffInDays = (date - epoch) / (1000 * 60 * 60 * 24); return diffInDays; } + return !isNaN(parseFloat(value)) ? parseFloat(value) : null; } +function toDateTime (input, zone) { return __toDateTime(input, zone) } +function toDate (input) { return __toDate(input) } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function fromUnixTimestampMilli (input) { return __fromUnixTimestampMilli(input) } +function fromUnixTimestamp (input) { return __fromUnixTimestamp(input) } +function __toUnixTimestampMilli(input, zone) { return __toUnixTimestamp(input, zone) * 1000 } +function __toUnixTimestamp(input, zone) { + if (__isHogDateTime(input)) { return input.dt; } + if (__isHogDate(input)) { return __toHogDateTime(input).dt; } + const date = new Date(input); + if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } + return Math.floor(date.getTime() / 1000);} +function __toTimeZone(input, zone) { if (!__isHogDateTime(input)) { throw new Error('Expected a DateTime') }; return { ...input, zone }} +function __toDateTime(input, zone) { let dt; + if (typeof input === 'number') { dt = input; } + else { const date = new Date(input); if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } dt = date.getTime() / 1000; } + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; } +function __toDate(input) { let date; + if (typeof input === 'number') { date = new Date(input * 1000); } else { date = new Date(input); } + if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } + return { __hogDate__: true, year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate() }; } +function __fromUnixTimestampMilli(input) { return __toHogDateTime(input / 1000) } +function __fromUnixTimestamp(input) { return __toHogDateTime(input) } +function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; } +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + +let dt = fromUnixTimestamp(1234334543); +print(dt); +print(toString(dt)); +print(toInt(toUnixTimestamp(dt))); +print("-"); +let dt2 = toDate("2024-05-03"); +print(dt2); +print(toString(dt2)); +print(toInt(toUnixTimestamp(dt2))); +print("-"); +let dt3 = toDateTime("2024-05-03T12:34:56Z"); +print(dt3); +print(toString(dt3)); +print(toInt(toUnixTimestamp(dt3))); +print("------"); +print(toTimeZone(dt3, "Europe/Brussels")); +print(toString(toTimeZone(dt3, "Europe/Brussels"))); +print("-"); +print(toTimeZone(dt3, "Europe/Tallinn")); +print(toString(toTimeZone(dt3, "Europe/Tallinn"))); +print("-"); +print(toTimeZone(dt3, "America/New_York")); +print(toString(toTimeZone(dt3, "America/New_York"))); +print("------"); +let timestamp = fromUnixTimestamp(1234334543.123); +print("timestamp: ", timestamp); +print("toString(timestamp): ", toString(timestamp)); +print("toInt(timestamp): ", toInt(timestamp)); +print("toDateTime(toInt(timestamp)): ", toDateTime(toInt(timestamp))); +print("toInt(toDateTime(toInt(timestamp))): ", toInt(toDateTime(toInt(timestamp)))); +print("toString(toDateTime(toInt(timestamp))): ", toString(toDateTime(toInt(timestamp)))); +print("toFloat(timestamp): ", toFloat(timestamp)); +print("toDateTime(toFloat(timestamp)): ", toDateTime(toFloat(timestamp))); +print("toFloat(toDateTime(toFloat(timestamp))): ", toFloat(toDateTime(toFloat(timestamp)))); +print("toString(toDateTime(toFloat(timestamp))): ", toString(toDateTime(toFloat(timestamp)))); +print("------"); +let millisTs = fromUnixTimestampMilli(1234334543123); +print("millisTs: ", toString(millisTs)); +print("toString(millisTs): ", toString(millisTs)); +print("toInt(millisTs): ", toInt(millisTs)); +print("toFloat(millisTs): ", toFloat(millisTs)); +print("toUnixTimestampMilli(millisTs): ", toUnixTimestampMilli(millisTs)); +print("------"); +let date = toDate("2024-05-03"); +print(date); +print(toString(date)); +print(toInt(date)); diff --git a/hogvm/__tests__/__snapshots__/dateFormat.js b/hogvm/__tests__/__snapshots__/dateFormat.js new file mode 100644 index 00000000000..a8b96d923e0 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/dateFormat.js @@ -0,0 +1,287 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function fromUnixTimestamp (input) { return __fromUnixTimestamp(input) } +function formatDateTime (input, format, zone) { return __formatDateTime(input, format, zone) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __fromUnixTimestamp(input) { return __toHogDateTime(input) } +function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; } +function __formatDateTime(input, format, zone) { + if (!__isHogDateTime(input)) { throw new Error('Expected a DateTime'); } + if (!format) { throw new Error('formatDateTime requires at least 2 arguments'); } + const timestamp = input.dt * 1000; + let date = new Date(timestamp); + if (!zone) { zone = 'UTC'; } + const padZero = (num, len = 2) => String(num).padStart(len, '0'); + const padSpace = (num, len = 2) => String(num).padStart(len, ' '); + const getDateComponent = (type, options = {}) => { + const formatter = new Intl.DateTimeFormat('en-US', { ...options, timeZone: zone }); + const parts = formatter.formatToParts(date); + const part = parts.find(p => p.type === type); + return part ? part.value : ''; + }; + const getNumericComponent = (type, options = {}) => { + const value = getDateComponent(type, options); + return parseInt(value, 10); + }; + const getWeekNumber = (d) => { + const dateInZone = new Date(d.toLocaleString('en-US', { timeZone: zone })); + const target = new Date(Date.UTC(dateInZone.getFullYear(), dateInZone.getMonth(), dateInZone.getDate())); + const dayNr = (target.getUTCDay() + 6) % 7; + target.setUTCDate(target.getUTCDate() - dayNr + 3); + const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4)); + const weekNumber = 1 + Math.round(((target - firstThursday) / 86400000 - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7); + return weekNumber; + }; + const getDayOfYear = (d) => { + const startOfYear = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); + const dateInZone = new Date(d.toLocaleString('en-US', { timeZone: zone })); + const diff = dateInZone - startOfYear; + return Math.floor(diff / 86400000) + 1; + }; + // Token mapping with corrections + const tokens = { + '%a': () => getDateComponent('weekday', { weekday: 'short' }), + '%b': () => getDateComponent('month', { month: 'short' }), + '%c': () => padZero(getNumericComponent('month', { month: '2-digit' })), + '%C': () => getDateComponent('year', { year: '2-digit' }), + '%d': () => padZero(getNumericComponent('day', { day: '2-digit' })), + '%D': () => { + const month = padZero(getNumericComponent('month', { month: '2-digit' })); + const day = padZero(getNumericComponent('day', { day: '2-digit' })); + const year = getDateComponent('year', { year: '2-digit' }); + return `${month}/${day}/${year}`; + }, + '%e': () => padSpace(getNumericComponent('day', { day: 'numeric' })), + '%F': () => { + const year = getNumericComponent('year', { year: 'numeric' }); + const month = padZero(getNumericComponent('month', { month: '2-digit' })); + const day = padZero(getNumericComponent('day', { day: '2-digit' })); + return `${year}-${month}-${day}`; + }, + '%g': () => getDateComponent('year', { year: '2-digit' }), + '%G': () => getNumericComponent('year', { year: 'numeric' }), + '%h': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })), + '%H': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: false })), + '%i': () => padZero(getNumericComponent('minute', { minute: '2-digit' })), + '%I': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })), + '%j': () => padZero(getDayOfYear(date), 3), + '%k': () => padSpace(getNumericComponent('hour', { hour: 'numeric', hour12: false })), + '%l': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })), + '%m': () => padZero(getNumericComponent('month', { month: '2-digit' })), + '%M': () => getDateComponent('month', { month: 'long' }), + '%n': () => '\n', + '%p': () => getDateComponent('dayPeriod', { hour: 'numeric', hour12: true }), + '%r': () => { + const hour = padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })); + const minute = padZero(getNumericComponent('minute', { minute: '2-digit' })); + const second = padZero(getNumericComponent('second', { second: '2-digit' })); + const period = getDateComponent('dayPeriod', { hour: 'numeric', hour12: true }); + return `${hour}:${minute} ${period}`; + }, + '%R': () => { + const hour = padZero(getNumericComponent('hour', { hour: '2-digit', hour12: false })); + const minute = padZero(getNumericComponent('minute', { minute: '2-digit' })); + return `${hour}:${minute}`; + }, + '%s': () => padZero(getNumericComponent('second', { second: '2-digit' })), + '%S': () => padZero(getNumericComponent('second', { second: '2-digit' })), + '%t': () => '\t', + '%T': () => { + const hour = padZero(getNumericComponent('hour', { hour: '2-digit', hour12: false })); + const minute = padZero(getNumericComponent('minute', { minute: '2-digit' })); + const second = padZero(getNumericComponent('second', { second: '2-digit' })); + return `${hour}:${minute}:${second}`; + }, + '%u': () => { + let day = getDateComponent('weekday', { weekday: 'short' }); + const dayMap = { 'Mon': '1', 'Tue': '2', 'Wed': '3', 'Thu': '4', 'Fri': '5', 'Sat': '6', 'Sun': '7' }; + return dayMap[day]; + }, + '%V': () => padZero(getWeekNumber(date)), + '%w': () => { + let day = getDateComponent('weekday', { weekday: 'short' }); + const dayMap = { 'Sun': '0', 'Mon': '1', 'Tue': '2', 'Wed': '3', 'Thu': '4', 'Fri': '5', 'Sat': '6' }; + return dayMap[day]; + }, + '%W': () => getDateComponent('weekday', { weekday: 'long' }), + '%y': () => getDateComponent('year', { year: '2-digit' }), + '%Y': () => getNumericComponent('year', { year: 'numeric' }), + '%z': () => { + if (zone === 'UTC') { + return '+0000'; + } else { + const formatter = new Intl.DateTimeFormat('en-US', { + timeZone: zone, + timeZoneName: 'shortOffset', + }); + const parts = formatter.formatToParts(date); + const offsetPart = parts.find(part => part.type === 'timeZoneName'); + if (offsetPart && offsetPart.value) { + const offsetValue = offsetPart.value; + const match = offsetValue.match(/GMT([+-]\d{1,2})(?::(\d{2}))?/); + if (match) { + const sign = match[1][0]; + const hours = padZero(Math.abs(parseInt(match[1], 10))); + const minutes = padZero(match[2] ? parseInt(match[2], 10) : 0); + return `${sign}${hours}${minutes}`; + } + } + return ''; + } + }, + '%%': () => '%', + }; + + // Replace tokens in the format string + let result = ''; + let i = 0; + while (i < format.length) { + if (format[i] === '%') { + const token = format.substring(i, i + 2); + if (tokens[token]) { + result += tokens[token](); + i += 2; + } else { + // If token not found, include '%' and move to next character + result += format[i]; + i += 1; + } + } else { + result += format[i]; + i += 1; + } + } + + return result; +} +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + +let dt = fromUnixTimestamp(1234377543.123456); +print(formatDateTime(dt, "%Y-%m-%d %H:%i:%S")); +print(formatDateTime(dt, "%Y-%m-%d %H:%i:%S", "Europe/Brussels")); +print(formatDateTime(dt, "%Y-%m-%d %H:%i:%S", "America/New_York")); +print(formatDateTime(dt, "%Y%m%dT%H%i%sZ")); +print("-----"); +print(concat("%a: ", formatDateTime(dt, "%a"))); +print(concat("%b: ", formatDateTime(dt, "%b"))); +print(concat("%c: ", formatDateTime(dt, "%c"))); +print(concat("%C: ", formatDateTime(dt, "%C"))); +print(concat("%d: ", formatDateTime(dt, "%d"))); +print(concat("%D: ", formatDateTime(dt, "%D"))); +print(concat("%e: ", formatDateTime(dt, "%e"))); +print(concat("%F: ", formatDateTime(dt, "%F"))); +print(concat("%g: ", formatDateTime(dt, "%g"))); +print(concat("%G: ", formatDateTime(dt, "%G"))); +print(concat("%h: ", formatDateTime(dt, "%h"))); +print(concat("%H: ", formatDateTime(dt, "%H"))); +print(concat("%i: ", formatDateTime(dt, "%i"))); +print(concat("%I: ", formatDateTime(dt, "%I"))); +print(concat("%j: ", formatDateTime(dt, "%j"))); +print(concat("%k: ", formatDateTime(dt, "%k"))); +print(concat("%l: ", formatDateTime(dt, "%l"))); +print(concat("%m: ", formatDateTime(dt, "%m"))); +print(concat("%M: ", formatDateTime(dt, "%M"))); +print(concat("%n: ", formatDateTime(dt, "%n"))); +print(concat("%p: ", formatDateTime(dt, "%p"))); +print(concat("%r: ", formatDateTime(dt, "%r"))); +print(concat("%R: ", formatDateTime(dt, "%R"))); +print(concat("%s: ", formatDateTime(dt, "%s"))); +print(concat("%S: ", formatDateTime(dt, "%S"))); +print(concat("%t: ", formatDateTime(dt, "%t"))); +print(concat("%T: ", formatDateTime(dt, "%T"))); +print(concat("%u: ", formatDateTime(dt, "%u"))); +print(concat("%V: ", formatDateTime(dt, "%V"))); +print(concat("%w: ", formatDateTime(dt, "%w"))); +print(concat("%W: ", formatDateTime(dt, "%W"))); +print(concat("%y: ", formatDateTime(dt, "%y"))); +print(concat("%Y: ", formatDateTime(dt, "%Y"))); +print(concat("%z: ", formatDateTime(dt, "%z"))); +print(concat("%%: ", formatDateTime(dt, "%%"))); +print("-----"); +print(formatDateTime(dt, "one banana")); +print(formatDateTime(dt, "%Y no way %m is this %d a %H real %i time %S")); diff --git a/hogvm/__tests__/__snapshots__/dicts.hoge b/hogvm/__tests__/__snapshots__/dicts.hoge index f0c4895e60b..20c457f34e6 100644 --- a/hogvm/__tests__/__snapshots__/dicts.hoge +++ b/hogvm/__tests__/__snapshots__/dicts.hoge @@ -1,6 +1,6 @@ ["_H", 1, 42, 0, 2, "print", 1, 35, 32, "key", 32, "value", 42, 1, 2, "print", 1, 35, 32, "key", 32, "value", 32, "other", 32, "thing", 42, 2, 2, "print", 1, 35, 32, "key", 32, "otherKey", 32, "value", 42, 1, 42, 1, 2, "print", 1, 35, -33, 3, 36, 0, 32, "value", 42, 1, 2, "print", 1, 35, 32, "key", 32, "value", 42, 1, 32, "key", 45, 2, "print", 1, 35, +32, "kk", 36, 0, 32, "value", 42, 1, 2, "print", 1, 35, 32, "key", 32, "value", 42, 1, 32, "key", 45, 2, "print", 1, 35, 32, "key", 32, "value", 42, 1, 32, "key", 45, 2, "print", 1, 35, 32, "key", 32, "otherKey", 32, "value", 42, 1, 42, 1, 32, "key", 45, 32, "otherKey", 45, 2, "print", 1, 35, 32, "key", 32, "otherKey", 32, "value", 42, 1, 42, 1, 32, "key", 45, 32, "otherKey", 45, 2, "print", 1, 35, 35] diff --git a/hogvm/__tests__/__snapshots__/dicts.js b/hogvm/__tests__/__snapshots__/dicts.js new file mode 100644 index 00000000000..a85b45440d5 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/dicts.js @@ -0,0 +1,57 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print({}); +print({"key": "value"}); +print({"key": "value", "other": "thing"}); +print({"key": {"otherKey": "value"}}); +let key = "kk"; +print({[key]: "value"}); +print(__getProperty({"key": "value"}, "key", false)); +print(__getProperty({"key": "value"}, "key", false)); +print(__getProperty(__getProperty({"key": {"otherKey": "value"}}, "key", false), "otherKey", false)); +print(__getProperty(__getProperty({"key": {"otherKey": "value"}}, "key", false), "otherKey", false)); diff --git a/hogvm/__tests__/__snapshots__/dicts.stdout b/hogvm/__tests__/__snapshots__/dicts.stdout index 33e60af57d4..337454355fa 100644 --- a/hogvm/__tests__/__snapshots__/dicts.stdout +++ b/hogvm/__tests__/__snapshots__/dicts.stdout @@ -2,7 +2,7 @@ {'key': 'value'} {'key': 'value', 'other': 'thing'} {'key': {'otherKey': 'value'}} -{3: 'value'} +{'kk': 'value'} value value value diff --git a/hogvm/__tests__/__snapshots__/exceptions.js b/hogvm/__tests__/__snapshots__/exceptions.js new file mode 100644 index 00000000000..46cb9b053a3 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/exceptions.js @@ -0,0 +1,152 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} +function __x_Error (message, payload) { return __newHogError('Error', message, payload) } +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} + +print("start"); +try { + print("try"); +} catch (__error) { if (true) { let e = __error; +print(concat(e, " was the exception")); +} +} +print("------------------"); +print("start"); +try { + print("try"); +} catch (__error) { if (true) { let e = __error; +print("No var for error, but no error"); +} +} +print("------------------"); +try { + print("try again"); + throw __x_Error(); +} catch (__error) { if (true) { let e = __error; +print(concat(e, " was the exception")); +} +} +print("------------------"); +try { + print("try again"); + throw __x_Error(); +} catch (__error) { if (true) { let e = __error; +print("No var for error"); +} +} +print("------------------"); +function third() { + print("Throwing in third"); + throw __x_Error("Threw in third"); +} +function second() { + print("second"); + third(); +} +function first() { + print("first"); + second(); +} +function base() { + print("base"); + try { + first(); + } catch (__error) { if (true) { let e = __error; + print(concat("Caught in base: ", e)); throw e; + } + } +} +try { + base(); +} catch (__error) { if (true) { let e = __error; +print(concat("Caught in root: ", e)); +} +} +print("The end"); diff --git a/hogvm/__tests__/__snapshots__/functionVars.js b/hogvm/__tests__/__snapshots__/functionVars.js new file mode 100644 index 00000000000..9f7ca6b8b4e --- /dev/null +++ b/hogvm/__tests__/__snapshots__/functionVars.js @@ -0,0 +1,72 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function base64Encode (str) { return Buffer.from(str).toString('base64') } +function base64Decode (str) { return Buffer.from(str, 'base64').toString() } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +function execFunction() { + print("execFunction"); +} +function execFunctionNested() { + function execFunction() { + print("execFunctionNew"); + } + print("execFunctionNested"); + execFunction(); +} +execFunction(); +execFunctionNested(); +execFunction(); +print("--------"); +function secondExecFunction() { + print("secondExecFunction"); +} +function secondExecFunctionNested() { + print("secondExecFunctionNested"); + secondExecFunction(); +} +secondExecFunction(); +secondExecFunctionNested(); +secondExecFunction(); +print("--------"); +let decode = __lambda(() => base64Decode); +let sixtyFour = base64Encode; +print(sixtyFour("http://www.google.com")); +print(decode()(sixtyFour("http://www.google.com"))); +print(decode()(sixtyFour("http://www.google.com"))); diff --git a/hogvm/__tests__/__snapshots__/functions.js b/hogvm/__tests__/__snapshots__/functions.js new file mode 100644 index 00000000000..2241faa08aa --- /dev/null +++ b/hogvm/__tests__/__snapshots__/functions.js @@ -0,0 +1,124 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function empty (value) { + if (typeof value === 'object') { + if (Array.isArray(value)) { return value.length === 0 } else if (value === null) { return true } else if (value instanceof Map) { return value.size === 0 } + return Object.keys(value).length === 0 + } else if (typeof value === 'number' || typeof value === 'boolean') { return false } + return !value } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print("-- test functions --"); +function add(a, b) { + return (a + b); +} +print(add); +function add2(a, b) { + let c = (a + b); + return c; +} +print(add2); +function mult(a, b) { + return (a * b); +} +print(mult); +function noArgs() { + let url = "basdfasdf"; + let second = (2 + 3); + return second; +} +print(noArgs); +function empty() { + +} +function empty2() { + +} +function empty3() { + +} +function noReturn() { + let a = 1; + let b = 2; + let c = (a + b); +} +function emptyReturn() { + return null; +} +function emptyReturnBeforeOtherStuff() { + return null; + (2 + 2); +} +function emptyReturnBeforeOtherStuffNoSemicolon() { + return (2 + 2); +} +function ifThenReturn() { + if (false) { + return null; + } + return 4; +} +print(add(3, 4)); +print(((add(3, 4) + 100) + add(1, 1))); +print((noArgs() ?? -1)); +print((empty() ?? -1)); +print((empty2() ?? -1)); +print((empty3() ?? -1)); +print((noReturn() ?? -1)); +print((emptyReturn() ?? -1)); +print((emptyReturnBeforeOtherStuff() ?? -1)); +print((emptyReturnBeforeOtherStuffNoSemicolon() ?? -1)); +print((ifThenReturn() ?? -1)); +print(mult(((add(3, 4) + 100) + add(2, 1)), 2)); +print(mult(((add2(3, 4) + 100) + add2(2, 1)), 10)); +function printArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + print(arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} +let printArgs2 = __lambda((arg1, arg2, arg3, arg4, arg5, arg6, arg7) => { + print(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return null; +}); +printArgs(1, 2, 3, 4, 5, 6, 7); +printArgs2(1, 2, 3, 4, 5, 6, 7); +printArgs(1, 2, 3, 4, 5, 6); +printArgs2(1, 2, 3, 4, 5, 6); +printArgs(1, 2, 3, 4, 5); +printArgs2(1, 2, 3, 4, 5); +printArgs(); +printArgs2(); diff --git a/hogvm/__tests__/__snapshots__/ifElse.js b/hogvm/__tests__/__snapshots__/ifElse.js new file mode 100644 index 00000000000..995143425a2 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/ifElse.js @@ -0,0 +1,69 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print("-- test if else --"); +{ + if (true) { + print(1); + } else { + print(2); + } + if (true) { + print(1); + } else { + print(2); + } + if (false) { + print(1); + } else { + print(2); + } + if (true) { + print(1); + } else { + print(2); + } + let a = true; + if (a) { + let a = 3; + print((a + 2)); + } else { + print(2); + } +} diff --git a/hogvm/__tests__/__snapshots__/ifJump.js b/hogvm/__tests__/__snapshots__/ifJump.js new file mode 100644 index 00000000000..1a6e010aa53 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/ifJump.js @@ -0,0 +1,61 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +let props = {}; +let email = __getProperty(props, "email", true); +if ((email == "")) { + print("ERROR - Email not found!"); + print("3"); +} +print("1"); +if ((email == "")) { + print("ERROR - Email not found!"); + print("3"); +} else { + print("else"); +} +print("1"); diff --git a/hogvm/__tests__/__snapshots__/json.js b/hogvm/__tests__/__snapshots__/json.js new file mode 100644 index 00000000000..d8bfeae1e32 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/json.js @@ -0,0 +1,197 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function jsonStringify (value, spacing) { + function convert(x, marked) { + if (!marked) { marked = new Set() } + if (typeof x === 'object' && x !== null) { + if (marked.has(x)) { return null } + marked.add(x) + try { + if (x instanceof Map) { + const obj = {} + x.forEach((value, key) => { obj[convert(key, marked)] = convert(value, marked) }) + return obj + } + if (Array.isArray(x)) { return x.map((v) => convert(v, marked)) } + if (__isHogDateTime(x) || __isHogDate(x) || __isHogError(x)) { return x } + if (typeof x === 'function') { return `fn<${x.name || 'lambda'}(${x.length})>` } + const obj = {}; for (const key in x) { obj[key] = convert(x[key], marked) } + return obj + } finally { + marked.delete(x) + } + } + return x + } + if (spacing && typeof spacing === 'number' && spacing > 0) { + return JSON.stringify(convert(value), null, spacing) + } + return JSON.stringify(convert(value), (key, val) => typeof val === 'function' ? `fn<${val.name || 'lambda'}(${val.length})>` : val) +} +function jsonParse (str) { + function convert(x) { + if (Array.isArray(x)) { return x.map(convert) } + else if (typeof x === 'object' && x !== null) { + if (x.__hogDateTime__) { return __toHogDateTime(x.dt, x.zone) + } else if (x.__hogDate__) { return __toHogDate(x.year, x.month, x.day) + } else if (x.__hogError__) { return __newHogError(x.type, x.message, x.payload) } + const obj = {}; for (const key in x) { obj[key] = convert(x[key]) }; return obj } + return x } + return convert(JSON.parse(str)) } +function isValidJSON (str) { try { JSON.parse(str); return true } catch (e) { return false } } +function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; } +function __toHogDate(year, month, day) { return { __hogDate__: true, year: year, month: month, day: day, } } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function JSONLength (obj, ...path) { + try { if (typeof obj === 'string') { obj = JSON.parse(obj) } } catch (e) { return 0 } + if (typeof obj === 'object' && obj !== null) { + const value = __getNestedValue(obj, path, true) + if (Array.isArray(value)) { + return value.length + } else if (value instanceof Map) { + return value.size + } else if (typeof value === 'object' && value !== null) { + return Object.keys(value).length + } + } + return 0 } +function JSONHas (obj, ...path) { + let current = obj + for (const key of path) { + let currentParsed = current + if (typeof current === 'string') { try { currentParsed = JSON.parse(current) } catch (e) { return false } } + if (currentParsed instanceof Map) { if (!currentParsed.has(key)) { return false }; current = currentParsed.get(key) } + else if (typeof currentParsed === 'object' && currentParsed !== null) { + if (typeof key === 'number') { + if (Array.isArray(currentParsed)) { + if (key < 0) { if (key < -currentParsed.length) { return false }; current = currentParsed[currentParsed.length + key] } + else if (key === 0) { return false } + else { if (key > currentParsed.length) { return false }; current = currentParsed[key - 1] } + } else { return false } + } else { + if (!(key in currentParsed)) { return false } + current = currentParsed[key] + } + } else { return false } + } + return true } +function JSONExtractBool (obj, ...path) { + try { + if (typeof obj === 'string') { + obj = JSON.parse(obj) + } + } catch (e) { + return false + } + if (path.length > 0) { + obj = __getNestedValue(obj, path, true) + } + if (typeof obj === 'boolean') { + return obj + } + return false +} +function __getNestedValue(obj, path, allowNull = false) { + let current = obj + for (const key of path) { + if (current == null) { + return null + } + if (current instanceof Map) { + current = current.get(key) + } else if (typeof current === 'object' && current !== null) { + current = current[key] + } else { + return null + } + } + if (current === null && !allowNull) { + return null + } + return current +} + +print(jsonParse("[1,2,3]")); +let event = {"event": "$pageview", "properties": {"$browser": "Chrome", "$os": "Windows"}}; +let json = jsonStringify(event); +print(jsonParse(json)); +print("-- JSONHas --"); +print(JSONHas("{\"a\": \"hello\", \"b\": [-100, 200.0, 300]}", "b")); +print(JSONHas("{\"a\": \"hello\", \"b\": [-100, 200.0, 300]}", "b", 4)); +print(JSONHas({"a": "hello", "b": [-100, 200.0, 300]}, "b")); +print(JSONHas({"a": "hello", "b": [-100, 200.0, 300]}, "b", 4)); +print(JSONHas({"a": "hello", "b": [-100, 200.0, 300]}, "b", -2)); +print(JSONHas({"a": "hello", "b": [-100, 200.0, 300]}, "b", -4)); +print(JSONHas("[1,2,3]", 0)); +print(JSONHas("[1,2,[1,2]]", -1, 1)); +print(JSONHas("[1,2,[1,2]]", -1, -3)); +print(JSONHas("[1,2,[1,2]]", 1, 1)); +print("-- isValidJSON --"); +print(isValidJSON("{\"a\": \"hello\", \"b\": [-100, 200.0, 300]}")); +print(isValidJSON("not a json")); +print("-- JSONLength --"); +print(JSONLength("{\"a\": \"hello\", \"b\": [-100, 200.0, 300]}", "b")); +print(JSONLength("{\"a\": \"hello\", \"b\": [-100, 200.0, 300]}")); +print(JSONLength({"a": "hello", "b": [-100, 200.0, 300]}, "b")); +print(JSONLength({"a": "hello", "b": [-100, 200.0, 300]})); +print("-- JSONExtractBool --"); +print(JSONExtractBool("{\"a\": \"hello\", \"b\": true}", "b")); +print(JSONExtractBool("{\"a\": \"hello\", \"b\": false}", "b")); +print(JSONExtractBool("{\"a\": \"hello\", \"b\": 1}", "b")); +print(JSONExtractBool("{\"a\": \"hello\", \"b\": 0}", "b")); +print(JSONExtractBool("{\"a\": \"hello\", \"b\": \"true\"}", "b")); +print(JSONExtractBool("{\"a\": \"hello\", \"b\": \"false\"}", "b")); +print(JSONExtractBool(true)); +print(JSONExtractBool(false)); +print(JSONExtractBool(1)); +print(JSONExtractBool(0)); +print(JSONExtractBool("true")); +print(JSONExtractBool("false")); diff --git a/hogvm/__tests__/__snapshots__/keysValues.js b/hogvm/__tests__/__snapshots__/keysValues.js new file mode 100644 index 00000000000..0adcf886f2e --- /dev/null +++ b/hogvm/__tests__/__snapshots__/keysValues.js @@ -0,0 +1,54 @@ +function values (obj) { if (typeof obj === 'object' && obj !== null) { if (Array.isArray(obj)) { return [...obj] } else if (obj instanceof Map) { return Array.from(obj.values()) } return Object.values(obj) } return [] } +function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function keys (obj) { if (typeof obj === 'object' && obj !== null) { if (Array.isArray(obj)) { return Array.from(obj.keys()) } else if (obj instanceof Map) { return Array.from(obj.keys()) } return Object.keys(obj) } return [] } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +let a = [3, 4, 5]; +let b = tuple(3, 4, 5); +let c = {"key": "value", "other": "val"}; +print(">> A"); +print(keys(a)); +print(values(a)); +print(">> B"); +print(keys(b)); +print(values(b)); +print(">> C"); +print(keys(c)); +print(values(c)); diff --git a/hogvm/__tests__/__snapshots__/lambdas.js b/hogvm/__tests__/__snapshots__/lambdas.js new file mode 100644 index 00000000000..1e2719b7cbb --- /dev/null +++ b/hogvm/__tests__/__snapshots__/lambdas.js @@ -0,0 +1,129 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function jsonStringify (value, spacing) { + function convert(x, marked) { + if (!marked) { marked = new Set() } + if (typeof x === 'object' && x !== null) { + if (marked.has(x)) { return null } + marked.add(x) + try { + if (x instanceof Map) { + const obj = {} + x.forEach((value, key) => { obj[convert(key, marked)] = convert(value, marked) }) + return obj + } + if (Array.isArray(x)) { return x.map((v) => convert(v, marked)) } + if (__isHogDateTime(x) || __isHogDate(x) || __isHogError(x)) { return x } + if (typeof x === 'function') { return `fn<${x.name || 'lambda'}(${x.length})>` } + const obj = {}; for (const key in x) { obj[key] = convert(x[key], marked) } + return obj + } finally { + marked.delete(x) + } + } + return x + } + if (spacing && typeof spacing === 'number' && spacing > 0) { + return JSON.stringify(convert(value), null, spacing) + } + return JSON.stringify(convert(value), (key, val) => typeof val === 'function' ? `fn<${val.name || 'lambda'}(${val.length})>` : val) +} +function jsonParse (str) { + function convert(x) { + if (Array.isArray(x)) { return x.map(convert) } + else if (typeof x === 'object' && x !== null) { + if (x.__hogDateTime__) { return __toHogDateTime(x.dt, x.zone) + } else if (x.__hogDate__) { return __toHogDate(x.year, x.month, x.day) + } else if (x.__hogError__) { return __newHogError(x.type, x.message, x.payload) } + const obj = {}; for (const key in x) { obj[key] = convert(x[key]) }; return obj } + return x } + return convert(JSON.parse(str)) } +function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; } +function __toHogDate(year, month, day) { return { __hogDate__: true, year: year, month: month, day: day, } } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +let b = __lambda((x) => (x * 2)); +print(b); +print(b(2)); +print(b(8)); +print("--------"); +let func = __lambda((x) => (x * 2)); +let arr = [func]; +print(func(2)); +print(__getProperty(arr, 1, false)(2)); +print(__lambda((x) => (x * 2))(2)); +print("--------"); +let withArg = __lambda((x) => { + print(x); + print("moo"); + print("cow"); +}); +withArg(2); +print("--------"); +let noArg = __lambda(() => { + print("moo"); + print("cow"); +}); +noArg(); +print("-------- lambdas do not survive json --------"); +print(b); +print(jsonStringify(b)); +let c = jsonParse(jsonStringify(b)); +print(c); diff --git a/hogvm/__tests__/__snapshots__/loops.js b/hogvm/__tests__/__snapshots__/loops.js new file mode 100644 index 00000000000..00fd42ebbf2 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/loops.js @@ -0,0 +1,108 @@ +function values (obj) { if (typeof obj === 'object' && obj !== null) { if (Array.isArray(obj)) { return [...obj] } else if (obj instanceof Map) { return Array.from(obj.values()) } return Object.values(obj) } return [] } +function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function keys (obj) { if (typeof obj === 'object' && obj !== null) { if (Array.isArray(obj)) { return Array.from(obj.keys()) } else if (obj instanceof Map) { return Array.from(obj.keys()) } return Object.keys(obj) } return [] } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print("-- test while loop --"); +{ + let i = 0; + while ((i < 3)) { + i = (i + 1) + print(i); + } + print(i); +} +print("-- test for loop --"); +{ + for (let i = 0; (i < 3); i = (i + 1)) { + print(i); + } +} +print("-- test emptier for loop --"); +{ + let i = 0; + for (; (i < 3); ) { + print("woo"); + i = (i + 1) + } + print("hoo"); +} +print("-- for in loop with arrays --"); +{ + let arr = [1, 2, 3]; + for (let i of values(arr)) { + print(i); + } +} +print("-- for in loop with arrays and keys --"); +{ + let arr = [1, 2, 3]; + for (let k of keys(arr)) { let v = arr[k]; { + print(k, v); + } } +} +print("-- for in loop with tuples --"); +{ + let tup = tuple(1, 2, 3); + for (let i of values(tup)) { + print(i); + } +} +print("-- for in loop with tuples and keys --"); +{ + let tup = tuple(1, 2, 3); + for (let k of keys(tup)) { let v = tup[k]; { + print(k, v); + } } +} +print("-- for in loop with dicts --"); +{ + let obj = {"first": "v1", "second": "v2", "third": "v3"}; + for (let i of values(obj)) { + print(i); + } +} +print("-- for in loop with dicts and keys --"); +{ + let obj = {"first": "v1", "second": "v2", "third": "v3"}; + for (let k of keys(obj)) { let v = obj[k]; { + print(k, v); + } } +} diff --git a/hogvm/__tests__/__snapshots__/mandelbrot.js b/hogvm/__tests__/__snapshots__/mandelbrot.js new file mode 100644 index 00000000000..041a6f3bd82 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/mandelbrot.js @@ -0,0 +1,125 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + +function mandelbrot(re, im, max_iter) { + let z_re = 0.0; + let z_im = 0.0; + let n = 0; + while (!!((((z_re * z_re) + (z_im * z_im)) <= 4) && (n < max_iter))) { + let temp_re = (((z_re * z_re) - (z_im * z_im)) + re); + let temp_im = (((2 * z_re) * z_im) + im); + z_re = temp_re + z_im = temp_im + n = (n + 1) + } + if ((n == max_iter)) { + return " "; + } else { + return "#"; + } +} +function main() { + let width = 80; + let height = 24; + let xmin = -2.0; + let xmax = 1.0; + let ymin = -1.0; + let ymax = 1.0; + let max_iter = 30; + let y = 0; + while ((y < height)) { + let row = ""; + let x = 0; + while ((x < width)) { + let re = (((x / width) * (xmax - xmin)) + xmin); + let im = (((y / height) * (ymax - ymin)) + ymin); + let letter = mandelbrot(re, im, max_iter); + row = concat(row, letter) + x = (x + 1) + } + print(row); + y = (y + 1) + } +} +main(); diff --git a/hogvm/__tests__/__snapshots__/operations.hoge b/hogvm/__tests__/__snapshots__/operations.hoge index 3a08b489025..4d8a16ec1d6 100644 --- a/hogvm/__tests__/__snapshots__/operations.hoge +++ b/hogvm/__tests__/__snapshots__/operations.hoge @@ -10,20 +10,22 @@ 54, 1, 35, 32, "%x%", 32, "baa", 17, 36, 0, 54, 1, 35, 32, "%A%", 32, "baa", 18, 36, 0, 54, 1, 35, 32, "%C%", 32, "baa", 18, 36, 0, 54, 1, 35, 32, "b", 32, "a", 18, 36, 0, 54, 1, 35, 32, "b", 32, "a", 19, 36, 0, 54, 1, 35, 32, "b", 32, "a", 20, 36, 0, 54, 1, 35, 32, "car", 32, "a", 21, 36, 0, 54, 1, 35, 32, "foo", 32, "a", 21, 36, 0, 54, 1, 35, 32, "car", 32, -"a", 22, 36, 0, 54, 1, 35, 32, "arg", 32, "another", 2, "concat", 2, 36, 0, 54, 1, 35, 33, 1, 31, 2, "concat", 2, 36, 0, -54, 1, 35, 29, 30, 2, "concat", 2, 36, 0, 54, 1, 35, 32, "test", 32, "e.*", 2, "match", 2, 36, 0, 54, 1, 35, 32, "test", -32, "^e.*", 2, "match", 2, 36, 0, 54, 1, 35, 32, "test", 32, "x.*", 2, "match", 2, 36, 0, 54, 1, 35, 32, "e.*", 32, -"test", 23, 36, 0, 54, 1, 35, 32, "e.*", 32, "test", 24, 36, 0, 54, 1, 35, 32, "^e.*", 32, "test", 23, 36, 0, 54, 1, 35, -32, "^e.*", 32, "test", 24, 36, 0, 54, 1, 35, 32, "x.*", 32, "test", 23, 36, 0, 54, 1, 35, 32, "x.*", 32, "test", 24, -36, 0, 54, 1, 35, 32, "EST", 32, "test", 25, 36, 0, 54, 1, 35, 32, "EST", 32, "test", 25, 36, 0, 54, 1, 35, 32, "EST", -32, "test", 26, 36, 0, 54, 1, 35, 33, 1, 2, "toString", 1, 36, 0, 54, 1, 35, 34, 1.5, 2, "toString", 1, 36, 0, 54, 1, -35, 29, 2, "toString", 1, 36, 0, 54, 1, 35, 31, 2, "toString", 1, 36, 0, 54, 1, 35, 32, "string", 2, "toString", 1, 36, -0, 54, 1, 35, 32, "1", 2, "toInt", 1, 36, 0, 54, 1, 35, 32, "bla", 2, "toInt", 1, 36, 0, 54, 1, 35, 32, "1.2", 2, -"toFloat", 1, 36, 0, 54, 1, 35, 32, "bla", 2, "toFloat", 1, 36, 0, 54, 1, 35, 32, "asd", 2, "toUUID", 1, 36, 0, 54, 1, -35, 31, 33, 1, 11, 36, 0, 54, 1, 35, 31, 33, 1, 12, 36, 0, 54, 1, 35, 33, 1, 32, "1", 11, 36, 0, 54, 1, 35, 32, "1", 33, -1, 11, 36, 0, 54, 1, 35, 29, 33, 1, 11, 36, 0, 54, 1, 35, 29, 33, 0, 11, 36, 0, 54, 1, 35, 29, 33, 2, 11, 36, 0, 54, 1, -35, 30, 33, 1, 12, 36, 0, 54, 1, 35, 32, "2", 33, 1, 11, 36, 0, 54, 1, 35, 32, "2", 33, 1, 11, 36, 0, 54, 1, 35, 32, -"2", 33, 1, 12, 36, 0, 54, 1, 35, 32, "2", 33, 1, 15, 36, 0, 54, 1, 35, 32, "2", 33, 1, 16, 36, 0, 54, 1, 35, 32, "2", -33, 1, 13, 36, 0, 54, 1, 35, 32, "2", 33, 1, 14, 36, 0, 54, 1, 35, 33, 2, 32, "1", 11, 36, 0, 54, 1, 35, 33, 2, 32, "1", -11, 36, 0, 54, 1, 35, 33, 2, 32, "1", 12, 36, 0, 54, 1, 35, 33, 2, 32, "1", 15, 36, 0, 54, 1, 35, 33, 2, 32, "1", 16, -36, 0, 54, 1, 35, 33, 2, 32, "1", 13, 36, 0, 54, 1, 35, 33, 2, 32, "1", 14, 36, 0, 54, 1, 35, 35] +"a", 22, 36, 0, 54, 1, 35, 32, "b_x", 32, "bax", 17, 36, 0, 54, 1, 35, 32, "b_x", 32, "baax", 19, 36, 0, 54, 1, 35, 32, +"b%x", 32, "baax", 17, 36, 0, 54, 1, 35, 32, "arg", 32, "another", 2, "concat", 2, 36, 0, 54, 1, 35, 33, 1, 31, 2, +"concat", 2, 36, 0, 54, 1, 35, 29, 30, 2, "concat", 2, 36, 0, 54, 1, 35, 32, "test", 32, "e.*", 2, "match", 2, 36, 0, +54, 1, 35, 32, "test", 32, "^e.*", 2, "match", 2, 36, 0, 54, 1, 35, 32, "test", 32, "x.*", 2, "match", 2, 36, 0, 54, 1, +35, 32, "e.*", 32, "test", 23, 36, 0, 54, 1, 35, 32, "e.*", 32, "test", 24, 36, 0, 54, 1, 35, 32, "^e.*", 32, "test", +23, 36, 0, 54, 1, 35, 32, "^e.*", 32, "test", 24, 36, 0, 54, 1, 35, 32, "x.*", 32, "test", 23, 36, 0, 54, 1, 35, 32, +"x.*", 32, "test", 24, 36, 0, 54, 1, 35, 32, "EST", 32, "test", 25, 36, 0, 54, 1, 35, 32, "EST", 32, "test", 25, 36, 0, +54, 1, 35, 32, "EST", 32, "test", 26, 36, 0, 54, 1, 35, 33, 1, 2, "toString", 1, 36, 0, 54, 1, 35, 34, 1.5, 2, +"toString", 1, 36, 0, 54, 1, 35, 29, 2, "toString", 1, 36, 0, 54, 1, 35, 31, 2, "toString", 1, 36, 0, 54, 1, 35, 32, +"string", 2, "toString", 1, 36, 0, 54, 1, 35, 32, "1", 2, "toInt", 1, 36, 0, 54, 1, 35, 32, "bla", 2, "toInt", 1, 36, 0, +54, 1, 35, 32, "1.2", 2, "toFloat", 1, 36, 0, 54, 1, 35, 32, "bla", 2, "toFloat", 1, 36, 0, 54, 1, 35, 32, "asd", 2, +"toUUID", 1, 36, 0, 54, 1, 35, 31, 33, 1, 11, 36, 0, 54, 1, 35, 31, 33, 1, 12, 36, 0, 54, 1, 35, 33, 1, 32, "1", 11, 36, +0, 54, 1, 35, 32, "1", 33, 1, 11, 36, 0, 54, 1, 35, 29, 33, 1, 11, 36, 0, 54, 1, 35, 29, 33, 0, 11, 36, 0, 54, 1, 35, +29, 33, 2, 11, 36, 0, 54, 1, 35, 30, 33, 1, 12, 36, 0, 54, 1, 35, 32, "2", 33, 1, 11, 36, 0, 54, 1, 35, 32, "2", 33, 1, +11, 36, 0, 54, 1, 35, 32, "2", 33, 1, 12, 36, 0, 54, 1, 35, 32, "2", 33, 1, 15, 36, 0, 54, 1, 35, 32, "2", 33, 1, 16, +36, 0, 54, 1, 35, 32, "2", 33, 1, 13, 36, 0, 54, 1, 35, 32, "2", 33, 1, 14, 36, 0, 54, 1, 35, 33, 2, 32, "1", 11, 36, 0, +54, 1, 35, 33, 2, 32, "1", 11, 36, 0, 54, 1, 35, 33, 2, 32, "1", 12, 36, 0, 54, 1, 35, 33, 2, 32, "1", 15, 36, 0, 54, 1, +35, 33, 2, 32, "1", 16, 36, 0, 54, 1, 35, 33, 2, 32, "1", 13, 36, 0, 54, 1, 35, 33, 2, 32, "1", 14, 36, 0, 54, 1, 35, +35] diff --git a/hogvm/__tests__/__snapshots__/operations.js b/hogvm/__tests__/__snapshots__/operations.js new file mode 100644 index 00000000000..20d4a40f2cc --- /dev/null +++ b/hogvm/__tests__/__snapshots__/operations.js @@ -0,0 +1,224 @@ +function toUUID (value) { return __STLToString(value) } +function toString (value) { return __STLToString(value) } +function toInt(value) { + if (__isHogDateTime(value)) { return Math.floor(value.dt); } + else if (__isHogDate(value)) { const date = new Date(Date.UTC(value.year, value.month - 1, value.day)); const epoch = new Date(Date.UTC(1970, 0, 1)); const diffInDays = Math.floor((date - epoch) / (1000 * 60 * 60 * 24)); return diffInDays; } + return !isNaN(parseInt(value)) ? parseInt(value) : null; } +function toFloat(value) { + if (__isHogDateTime(value)) { return value.dt; } + else if (__isHogDate(value)) { const date = new Date(Date.UTC(value.year, value.month - 1, value.day)); const epoch = new Date(Date.UTC(1970, 0, 1)); const diffInDays = (date - epoch) / (1000 * 60 * 60 * 24); return diffInDays; } + return !isNaN(parseFloat(value)) ? parseFloat(value) : null; } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function match (str, pattern) { return new RegExp(pattern).test(str) } +function like (str, pattern) { return __like(str, pattern, false) } +function jsonStringify (value, spacing) { + function convert(x, marked) { + if (!marked) { marked = new Set() } + if (typeof x === 'object' && x !== null) { + if (marked.has(x)) { return null } + marked.add(x) + try { + if (x instanceof Map) { + const obj = {} + x.forEach((value, key) => { obj[convert(key, marked)] = convert(value, marked) }) + return obj + } + if (Array.isArray(x)) { return x.map((v) => convert(v, marked)) } + if (__isHogDateTime(x) || __isHogDate(x) || __isHogError(x)) { return x } + if (typeof x === 'function') { return `fn<${x.name || 'lambda'}(${x.length})>` } + const obj = {}; for (const key in x) { obj[key] = convert(x[key], marked) } + return obj + } finally { + marked.delete(x) + } + } + return x + } + if (spacing && typeof spacing === 'number' && spacing > 0) { + return JSON.stringify(convert(value), null, spacing) + } + return JSON.stringify(convert(value), (key, val) => typeof val === 'function' ? `fn<${val.name || 'lambda'}(${val.length})>` : val) +} +function ilike (str, pattern) { return __like(str, pattern, true) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __like(str, pattern, caseInsensitive = false) { + if (caseInsensitive) { + str = str.toLowerCase() + pattern = pattern.toLowerCase() + } + pattern = String(pattern) + .replaceAll(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + .replaceAll('%', '.*') + .replaceAll('_', '.') + return new RegExp(pattern).test(str) +} +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + +function test(val) { + print(jsonStringify(val)); +} +print("-- test the most common expressions --"); +test((1 + 2)); +test((1 - 2)); +test((3 * 2)); +test((3 / 2)); +test((3 % 2)); +test(!!(1 && 2)); +test(!!(1 || 0)); +test(!!(1 && 0)); +test(!!(1 || !!(0 && 1) || 2)); +test(!!(1 && 0 && 1)); +test(!!(!!(1 || 2) && !!(1 || 2))); +test(true); +test((!true)); +test(false); +test(null); +test(3.14); +test((1 == 2)); +test((1 == 2)); +test((1 != 2)); +test((1 < 2)); +test((1 <= 2)); +test((1 > 2)); +test((1 >= 2)); +test(like("a", "b")); +test(like("baa", "%a%")); +test(like("baa", "%x%")); +test(ilike("baa", "%A%")); +test(ilike("baa", "%C%")); +test(ilike("a", "b")); +test(!like("a", "b")); +test(!ilike("a", "b")); +test(("car".includes("a"))); +test(("foo".includes("a"))); +test((!"car".includes("a"))); +test(like("bax", "b_x")); +test(!like("baax", "b_x")); +test(like("baax", "b%x")); +test(concat("arg", "another")); +test(concat(1, null)); +test(concat(true, false)); +test(match("test", "e.*")); +test(match("test", "^e.*")); +test(match("test", "x.*")); +test(new RegExp("e.*").test("test")); +test(!(new RegExp("e.*").test("test"))); +test(new RegExp("^e.*").test("test")); +test(!(new RegExp("^e.*").test("test"))); +test(new RegExp("x.*").test("test")); +test(!(new RegExp("x.*").test("test"))); +test(new RegExp("EST", "i").test("test")); +test(new RegExp("EST", "i").test("test")); +test(!(new RegExp("EST", "i").test("test"))); +test(toString(1)); +test(toString(1.5)); +test(toString(true)); +test(toString(null)); +test(toString("string")); +test(toInt("1")); +test(toInt("bla")); +test(toFloat("1.2")); +test(toFloat("bla")); +test(toUUID("asd")); +test((1 == null)); +test((1 != null)); +test(("1" == 1)); +test((1 == "1")); +test((1 == true)); +test((0 == true)); +test((2 == true)); +test((1 != false)); +test((1 == "2")); +test((1 == "2")); +test((1 != "2")); +test((1 < "2")); +test((1 <= "2")); +test((1 > "2")); +test((1 >= "2")); +test(("1" == 2)); +test(("1" == 2)); +test(("1" != 2)); +test(("1" < 2)); +test(("1" <= 2)); +test(("1" > 2)); +test(("1" >= 2)); diff --git a/hogvm/__tests__/__snapshots__/operations.stdout b/hogvm/__tests__/__snapshots__/operations.stdout index 849bb269926..c08036afe55 100644 --- a/hogvm/__tests__/__snapshots__/operations.stdout +++ b/hogvm/__tests__/__snapshots__/operations.stdout @@ -33,6 +33,9 @@ true true false false +true +true +true "arganother" "1" "truefalse" diff --git a/hogvm/__tests__/__snapshots__/printLoops.js b/hogvm/__tests__/__snapshots__/printLoops.js new file mode 100644 index 00000000000..a447308a88c --- /dev/null +++ b/hogvm/__tests__/__snapshots__/printLoops.js @@ -0,0 +1,158 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function jsonStringify (value, spacing) { + function convert(x, marked) { + if (!marked) { marked = new Set() } + if (typeof x === 'object' && x !== null) { + if (marked.has(x)) { return null } + marked.add(x) + try { + if (x instanceof Map) { + const obj = {} + x.forEach((value, key) => { obj[convert(key, marked)] = convert(value, marked) }) + return obj + } + if (Array.isArray(x)) { return x.map((v) => convert(v, marked)) } + if (__isHogDateTime(x) || __isHogDate(x) || __isHogError(x)) { return x } + if (typeof x === 'function') { return `fn<${x.name || 'lambda'}(${x.length})>` } + const obj = {}; for (const key in x) { obj[key] = convert(x[key], marked) } + return obj + } finally { + marked.delete(x) + } + } + return x + } + if (spacing && typeof spacing === 'number' && spacing > 0) { + return JSON.stringify(convert(value), null, spacing) + } + return JSON.stringify(convert(value), (key, val) => typeof val === 'function' ? `fn<${val.name || 'lambda'}(${val.length})>` : val) +} +function jsonParse (str) { + function convert(x) { + if (Array.isArray(x)) { return x.map(convert) } + else if (typeof x === 'object' && x !== null) { + if (x.__hogDateTime__) { return __toHogDateTime(x.dt, x.zone) + } else if (x.__hogDate__) { return __toHogDate(x.year, x.month, x.day) + } else if (x.__hogError__) { return __newHogError(x.type, x.message, x.payload) } + const obj = {}; for (const key in x) { obj[key] = convert(x[key]) }; return obj } + return x } + return convert(JSON.parse(str)) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; } +function __toHogDate(year, month, day) { return { __hogDate__: true, year: year, month: month, day: day, } } +function __setProperty(objectOrArray, key, value) { + if (Array.isArray(objectOrArray)) { + if (key > 0) { + objectOrArray[key - 1] = value + } else { + objectOrArray[objectOrArray.length + key] = value + } + } else { + objectOrArray[key] = value + } + return objectOrArray +} +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + +let obj = {"key": "value", "key2": "value2"}; +let str = "na"; +for (let i = 0; (i < 100); i = (i + 1)) { + str = concat(str, "na") + __setProperty(obj, concat("key_", i), {"wasted": concat("memory: ", str, " batman!"), "something": obj}); +} +print(obj); +let json = jsonStringify(obj); +print(jsonParse(json)); diff --git a/hogvm/__tests__/__snapshots__/printLoops2.js b/hogvm/__tests__/__snapshots__/printLoops2.js new file mode 100644 index 00000000000..3bf13ec5510 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/printLoops2.js @@ -0,0 +1,156 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function jsonStringify (value, spacing) { + function convert(x, marked) { + if (!marked) { marked = new Set() } + if (typeof x === 'object' && x !== null) { + if (marked.has(x)) { return null } + marked.add(x) + try { + if (x instanceof Map) { + const obj = {} + x.forEach((value, key) => { obj[convert(key, marked)] = convert(value, marked) }) + return obj + } + if (Array.isArray(x)) { return x.map((v) => convert(v, marked)) } + if (__isHogDateTime(x) || __isHogDate(x) || __isHogError(x)) { return x } + if (typeof x === 'function') { return `fn<${x.name || 'lambda'}(${x.length})>` } + const obj = {}; for (const key in x) { obj[key] = convert(x[key], marked) } + return obj + } finally { + marked.delete(x) + } + } + return x + } + if (spacing && typeof spacing === 'number' && spacing > 0) { + return JSON.stringify(convert(value), null, spacing) + } + return JSON.stringify(convert(value), (key, val) => typeof val === 'function' ? `fn<${val.name || 'lambda'}(${val.length})>` : val) +} +function jsonParse (str) { + function convert(x) { + if (Array.isArray(x)) { return x.map(convert) } + else if (typeof x === 'object' && x !== null) { + if (x.__hogDateTime__) { return __toHogDateTime(x.dt, x.zone) + } else if (x.__hogDate__) { return __toHogDate(x.year, x.month, x.day) + } else if (x.__hogError__) { return __newHogError(x.type, x.message, x.payload) } + const obj = {}; for (const key in x) { obj[key] = convert(x[key]) }; return obj } + return x } + return convert(JSON.parse(str)) } +function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') } +function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; } +function __toHogDate(year, month, day) { return { __hogDate__: true, year: year, month: month, day: day, } } +function __setProperty(objectOrArray, key, value) { + if (Array.isArray(objectOrArray)) { + if (key > 0) { + objectOrArray[key - 1] = value + } else { + objectOrArray[objectOrArray.length + key] = value + } + } else { + objectOrArray[key] = value + } + return objectOrArray +} +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} +function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + +let root = {"key": "value", "key2": "value2"}; +let leaf = {"key": "value", "key2": "value2"}; +for (let i = 0; (i < 30); i = (i + 1)) { + __setProperty(root, concat("key_", i), {"something": leaf}); +} +print(root); +print(jsonParse(jsonStringify(root))); diff --git a/hogvm/__tests__/__snapshots__/properties.js b/hogvm/__tests__/__snapshots__/properties.js new file mode 100644 index 00000000000..a09f437d4d7 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/properties.js @@ -0,0 +1,122 @@ +function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __setProperty(objectOrArray, key, value) { + if (Array.isArray(objectOrArray)) { + if (key > 0) { + objectOrArray[key - 1] = value + } else { + objectOrArray[objectOrArray.length + key] = value + } + } else { + objectOrArray[key] = value + } + return objectOrArray +} +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +{ + let r = [1, 2, {"d": tuple(1, 3, 42, 6)}]; + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 2, false)); +} +{ + let r = [1, 2, {"d": tuple(1, 3, 42, 6)}]; + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, false)); +} +{ + let r = [1, 2, {"d": tuple(1, 3, 42, 6)}]; + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 4, false)); +} +{ + let r = {"d": tuple(1, 3, 42, 6)}; + print(__getProperty(__getProperty(r, "d", true), 2, false)); +} +{ + let r = [1, 2, {"d": [1, 3, 42, 3]}]; + __setProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, 3); + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, false)); +} +{ + let r = [1, 2, {"d": [1, 3, 42, 3]}]; + __setProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, 3); + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, false)); +} +{ + let r = [1, 2, {"d": [1, 3, 42, 3]}]; + __setProperty(__getProperty(r, 3, false), "c", [666]); + print(__getProperty(r, 3, false)); +} +{ + let r = [1, 2, {"d": [1, 3, 42, 3]}]; + __setProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, 3); + print(__getProperty(__getProperty(r, 3, false), "d", false)); +} +{ + let r = [1, 2, {"d": [1, 3, 42, 3]}]; + __setProperty(__getProperty(r, 3, false), "d", ["a", "b", "c", "d"]); + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, false)); +} +{ + let r = [1, 2, {"d": [1, 3, 42, 3]}]; + let g = "d"; + __setProperty(__getProperty(r, 3, false), g, ["a", "b", "c", "d"]); + print(__getProperty(__getProperty(__getProperty(r, 3, false), "d", false), 3, false)); +} +{ + let event = {"event": "$pageview", "properties": {"$browser": "Chrome", "$os": "Windows"}}; + __setProperty(__getProperty(event, "properties", false), "$browser", "Firefox"); + print(event); +} +{ + let event = {"event": "$pageview", "properties": {"$browser": "Chrome", "$os": "Windows"}}; + __setProperty(__getProperty(event, "properties", true), "$browser", "Firefox") + print(event); +} +{ + let event = {"event": "$pageview", "properties": {"$browser": "Chrome", "$os": "Windows"}}; + let config = {}; + print(event); +} diff --git a/hogvm/__tests__/__snapshots__/recursion.js b/hogvm/__tests__/__snapshots__/recursion.js new file mode 100644 index 00000000000..1eb354a7e50 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/recursion.js @@ -0,0 +1,56 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +let fibonacci = __lambda((number) => { + if ((number < 2)) { + return number; + } else { + return (fibonacci((number - 1)) + fibonacci((number - 2))); + } +}); +print(fibonacci(6)); +function hogonacci(number) { + if ((number < 2)) { + return number; + } else { + return (hogonacci((number - 1)) + hogonacci((number - 2))); + } +} +print(hogonacci(6)); diff --git a/hogvm/__tests__/__snapshots__/scope.js b/hogvm/__tests__/__snapshots__/scope.js new file mode 100644 index 00000000000..6bb0aa44031 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/scope.js @@ -0,0 +1,122 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __setProperty(objectOrArray, key, value) { + if (Array.isArray(objectOrArray)) { + if (key > 0) { + objectOrArray[key - 1] = value + } else { + objectOrArray[objectOrArray.length + key] = value + } + } else { + objectOrArray[key] = value + } + return objectOrArray +} +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +let dbl = __lambda((x) => (x * 2)); +print(dbl); +print(dbl(2)); +print(dbl(8)); +print("--------"); +let __x_var = 5; +let varify = __lambda((x) => (x * __x_var)); +print(varify(2)); +__x_var = 10 +print(varify(2)); +print(varify(8)); +print("--------"); +function bigVar() { + let __x_var = 5; + let varify = __lambda((x) => (x * __x_var)); + return varify; +} +let bigVarify = bigVar(); +print(bigVarify(2)); +print(bigVarify(8)); +print("--------"); +let a = 3; +function outerA() { + print(a); + a = 4 + print(a); +} +function innerA() { + print(a); + outerA(); + print(a); +} +print(a); +innerA(); +print(a); +print("--------"); +let b = {"key": 3}; +function outerB() { + print(b); + __setProperty(b, "key", 4) + print(b); +} +function innerB() { + print(b); + outerB(); + print(b); +} +print(b); +innerB(); +print(b); +print("--------"); +function outerC() { + let x = "outside"; + function innerC() { + print(x); + } + innerC(); +} +outerC(); +print("--------"); +function myFunctionOuter() { + let b = 3; + function myFunction(a) { + return (a + b); + } + print(myFunction(2)); + print(myFunction(3)); +} +myFunctionOuter(); +print("--------"); diff --git a/hogvm/__tests__/__snapshots__/stl.js b/hogvm/__tests__/__snapshots__/stl.js new file mode 100644 index 00000000000..9af5082cd86 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/stl.js @@ -0,0 +1,121 @@ +function upper (value) { return value.toUpperCase() } +function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; } +function reverse (value) { return value.split('').reverse().join('') } +function replaceOne (str, searchValue, replaceValue) { return str.replace(searchValue, replaceValue) } +function replaceAll (str, searchValue, replaceValue) { return str.replaceAll(searchValue, replaceValue) } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function notEmpty (value) { return !empty(value) } +function lower (value) { return value.toLowerCase() } +function length (value) { return value.length } +function generateUUIDv4 () { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0; const v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16) })} +function encodeURLComponent (str) { return encodeURIComponent(str) } +function empty (value) { + if (typeof value === 'object') { + if (Array.isArray(value)) { return value.length === 0 } else if (value === null) { return true } else if (value instanceof Map) { return value.size === 0 } + return Object.keys(value).length === 0 + } else if (typeof value === 'number' || typeof value === 'boolean') { return false } + return !value } +function decodeURLComponent (str) { return decodeURIComponent(str) } +function base64Encode (str) { return Buffer.from(str).toString('base64') } +function base64Decode (str) { return Buffer.from(str, 'base64').toString() } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print("-- empty, notEmpty, length, lower, upper, reverse --"); +if (!!(empty("") && notEmpty("234"))) { + print(length("123")); +} +if ((lower("Tdd4gh") == "tdd4gh")) { + print(upper("test")); +} +print(reverse("spinner")); +print(""); +print("-- encodeURLComponent, decodeURLComponent --"); +print(encodeURLComponent("http://www.google.com")); +print(encodeURLComponent("tom & jerry")); +print(decodeURLComponent(encodeURLComponent("http://www.google.com"))); +print(decodeURLComponent(encodeURLComponent("tom & jerry"))); +print(""); +print("-- base64Encode, base64Decode --"); +print(base64Encode("http://www.google.com")); +print(base64Encode("tom & jerry")); +print(base64Decode(base64Encode("http://www.google.com"))); +print(base64Decode(base64Encode("tom & jerry"))); +print(""); +print("-- empty --"); +print(empty(null)); +print(empty(0)); +print(empty(1)); +print(empty(-1)); +print(empty(0.0)); +print(empty(0.01)); +print(empty("")); +print(empty("string")); +print(empty("0")); +print(empty([])); +print(empty({})); +print(empty(tuple())); +print(empty(tuple(0))); +print(empty(tuple(1, 2))); +print(empty(true)); +print(empty(false)); +print(""); +print("-- notEmpty --"); +print(notEmpty(null)); +print(notEmpty(0)); +print(notEmpty(1)); +print(notEmpty(-1)); +print(notEmpty(0.0)); +print(notEmpty(0.01)); +print(notEmpty("")); +print(notEmpty("string")); +print(notEmpty("0")); +print(notEmpty([])); +print(notEmpty({})); +print(notEmpty(tuple())); +print(notEmpty(tuple(0))); +print(notEmpty(tuple(1, 2))); +print(notEmpty(true)); +print(notEmpty(false)); +print(""); +print("-- replaceAll, replaceOne --"); +print(replaceAll("hello world", "l", "L")); +print(replaceOne("hello world", "l", "L")); +print(""); +print("-- generateUUIDv4 --"); +print(length(generateUUIDv4())); diff --git a/hogvm/__tests__/__snapshots__/strings.js b/hogvm/__tests__/__snapshots__/strings.js new file mode 100644 index 00000000000..9ce51632b4b --- /dev/null +++ b/hogvm/__tests__/__snapshots__/strings.js @@ -0,0 +1,129 @@ +function trimRight (str, char) { + if (char === null || char === undefined) { + char = ' ' + } + if (char.length !== 1) { + return '' + } + let end = str.length + while (str[end - 1] === char) { + end-- + } + return str.slice(0, end) +} +function trimLeft (str, char) { + if (char === null || char === undefined) { + char = ' ' + } + if (char.length !== 1) { + return '' + } + let start = 0 + while (str[start] === char) { + start++ + } + return str.slice(start) +} +function trim (str, char) { + if (char === null || char === undefined) { + char = ' ' + } + if (char.length !== 1) { + return '' + } + let start = 0 + while (str[start] === char) { + start++ + } + let end = str.length + while (str[end - 1] === char) { + end-- + } + if (start >= end) { + return '' + } + return str.slice(start, end) +} +function splitByString (separator, str, maxSplits) { if (maxSplits === undefined || maxSplits === null) { return str.split(separator) } return str.split(separator, maxSplits) } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function positionCaseInsensitive (str, elem) { if (typeof str === 'string') { return str.toLowerCase().indexOf(String(elem).toLowerCase()) + 1 } else { return 0 } } +function position (str, elem) { if (typeof str === 'string') { return str.indexOf(String(elem)) + 1 } else { return 0 } } +function notLike (str, pattern) { return !__like(str, pattern, false) } +function notILike (str, pattern) { return !__like(str, pattern, true) } +function like (str, pattern) { return __like(str, pattern, false) } +function ilike (str, pattern) { return __like(str, pattern, true) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __like(str, pattern, caseInsensitive = false) { + if (caseInsensitive) { + str = str.toLowerCase() + pattern = pattern.toLowerCase() + } + pattern = String(pattern) + .replaceAll(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + .replaceAll('%', '.*') + .replaceAll('_', '.') + return new RegExp(pattern).test(str) +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print(trim(" hello world ")); +print(trimLeft(" hello world ")); +print(trimRight(" hello world ")); +print(trim("xxxx hello world xx", "x")); +print(trimLeft("xxxx hello world xx", "x")); +print(trimRight("xxxx hello world xx", "x")); +print(splitByString(" ", "hello world and more")); +print(splitByString(" ", "hello world and more", 1)); +print(splitByString(" ", "hello world and more", 2)); +print(splitByString(" ", "hello world and more", 10)); +print(like("banana", "N")); +print(like("banana", "n")); +print(like("banana", "naan")); +print(ilike("banana", "N")); +print(ilike("banana", "n")); +print(ilike("banana", "naan")); +print(notLike("banana", "N")); +print(notILike("banana", "NO")); +print(position("abc", "a")); +print(position("abc", "b")); +print(position("abc", "c")); +print(position("abc", "d")); +print(positionCaseInsensitive("AbC", "a")); +print(positionCaseInsensitive("AbC", "b")); +print(positionCaseInsensitive("AbC", "c")); +print(positionCaseInsensitive("AbC", "d")); diff --git a/hogvm/__tests__/__snapshots__/tuples.js b/hogvm/__tests__/__snapshots__/tuples.js new file mode 100644 index 00000000000..7ac28573165 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/tuples.js @@ -0,0 +1,67 @@ +function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print(tuple()); +print(tuple(1)); +print(tuple(1, 2)); +print(tuple(1, 2)); +print(tuple(1, 2, 3)); +print(tuple(1, "2", 3)); +print(tuple(1, tuple(2, 3), 4)); +print(tuple(1, tuple(2, tuple(3, 4)), 5)); +let a = tuple(1, 2, 3); +print(__getProperty(a, 2, false)); +print(__getProperty(a, 2, true)); +print(__getProperty(a, 8, true)); +print(__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 2, false), 2, false), 2, false)); +print(__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 2, true), 2, true), 2, true)); +print(__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 2, true), 2, true), 2, true)); +print(__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 4, true), 7, true), 2, true)); +print(__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 4, true), 7, true), 2, true)); +print(__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 2, false), 2, false), 2, false)); +print((__getProperty(__getProperty(__getProperty(tuple(1, tuple(2, tuple(3, 4)), 5), 2, false), 2, false), 2, false) + 1)); diff --git a/hogvm/__tests__/__snapshots__/typeof.js b/hogvm/__tests__/__snapshots__/typeof.js new file mode 100644 index 00000000000..e4287e026eb --- /dev/null +++ b/hogvm/__tests__/__snapshots__/typeof.js @@ -0,0 +1,88 @@ +function __x_typeof (value) { + if (value === null || value === undefined) { return 'null' + } else if (__isHogDateTime(value)) { return 'datetime' + } else if (__isHogDate(value)) { return 'date' + } else if (__isHogError(value)) { return 'error' + } else if (typeof value === 'function') { return 'function' + } else if (Array.isArray(value)) { if (value.__isHogTuple) { return 'tuple' } return 'array' + } else if (typeof value === 'object') { return 'object' + } else if (typeof value === 'number') { return Number.isInteger(value) ? 'integer' : 'float' + } else if (typeof value === 'string') { return 'string' + } else if (typeof value === 'boolean') { return 'boolean' } + return 'unknown' +} +function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; } +function toDateTime (input, zone) { return __toDateTime(input, zone) } +function toDate (input) { return __toDate(input) } +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __toDateTime(input, zone) { let dt; + if (typeof input === 'number') { dt = input; } + else { const date = new Date(input); if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } dt = date.getTime() / 1000; } + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; } +function __toDate(input) { let date; + if (typeof input === 'number') { date = new Date(input * 1000); } else { date = new Date(input); } + if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } + return { __hogDate__: true, year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate() }; } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} +function __x_Error (message, payload) { return __newHogError('Error', message, payload) } +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} + +function test(obj) { + print(__x_typeof(obj)); +} +test("hello world"); +test(123); +test(1.23); +test(true); +test(false); +test(null); +test({}); +test([]); +test(tuple(1, 2, 3)); +test(__lambda(() => (1 + 2))); +test(toDateTime("2021-01-01T00:00:00Z")); +test(toDate("2021-01-01")); +test(__x_Error("BigError", "message")); diff --git a/hogvm/__tests__/__snapshots__/upvalues.js b/hogvm/__tests__/__snapshots__/upvalues.js new file mode 100644 index 00000000000..39182158f6b --- /dev/null +++ b/hogvm/__tests__/__snapshots__/upvalues.js @@ -0,0 +1,57 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __lambda (fn) { return fn } +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +function returnCallable(a) { + return __lambda((x) => (x * a)); +} +let double = returnCallable(2); +let triple = returnCallable(3); +print(double(2)); +print(triple(2)); +print("----------"); +function outer() { + let x = "outside"; + function inner() { + print(x); + } + return inner; +} +let closure = outer(); +closure(); diff --git a/hogvm/__tests__/__snapshots__/variables.js b/hogvm/__tests__/__snapshots__/variables.js new file mode 100644 index 00000000000..c6cb97d354c --- /dev/null +++ b/hogvm/__tests__/__snapshots__/variables.js @@ -0,0 +1,53 @@ +function print (...args) { console.log(...args.map(__printHogStringOutput)) } +function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +function __isHogError(obj) {return obj && obj.__hogError__ === true} +function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true } +function __isHogDate(obj) { return obj && obj.__hogDate__ === true } +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', "'": "\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\b': '\\b', '\f': '\\f', '\r': '\\r', '\n': '\\n', '\t': '\\t', '\0': '\\0', '\v': '\\v', '\\': '\\\\', '`': '\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\``; +} + +print("-- test variables --"); +{ + let a = (1 + 2); + print(a); + let b = (a + 4); + print(b); +} +print("-- test variable reassignment --"); +{ + let a = 1; + a = (a + 3) + a = (a * 2) + print(a); +} diff --git a/hogvm/__tests__/arrays.hog b/hogvm/__tests__/arrays.hog index cbf74d696f8..7cb87188f7f 100644 --- a/hogvm/__tests__/arrays.hog +++ b/hogvm/__tests__/arrays.hog @@ -76,3 +76,8 @@ print('------') let c := [1,2,3] print(c[1], c[2], c[3], c[4]) print(c[-1], c[-2], c[-3], c[-4]) + +print('------') +print('a' in ['a', 'b', 'c']) +print('d' in ['a', 'b', 'c']) +print('a' in []) diff --git a/hogvm/__tests__/catch2.hog b/hogvm/__tests__/catch2.hog index cd48ab951cf..ea3c19550eb 100644 --- a/hogvm/__tests__/catch2.hog +++ b/hogvm/__tests__/catch2.hog @@ -19,7 +19,7 @@ try { } catch (e: FishError) { print(f'FishError: {e.message}') } catch (e: Error) { - print(f'Error of type {e.name}: {e.message}') + print(f'Error of type {e.type}: {e.message}') } try { @@ -29,7 +29,7 @@ try { print(f'Problem with your food: {e.message}') } } catch (e: Error) { - print(f'Error of type {e.name}: {e.message}') + print(f'Error of type {e.type}: {e.message}') } catch (e: FishError) { print(f'FishError: {e.message}') } diff --git a/hogvm/__tests__/dicts.hog b/hogvm/__tests__/dicts.hog index 8523c26cb5f..0c060bc2649 100644 --- a/hogvm/__tests__/dicts.hog +++ b/hogvm/__tests__/dicts.hog @@ -3,7 +3,10 @@ print({'key': 'value'}) print({'key': 'value', 'other': 'thing'}) print({'key': {'otherKey': 'value'}}) -let key := 3 +// We support non-string keys... in the HogVM. +// Keys are always converted to a string in the transpiled JS version. +// TODO: this might be worth revisiting +let key := 'kk' print({key: 'value'}) print({'key': 'value', }.key) diff --git a/hogvm/__tests__/operations.hog b/hogvm/__tests__/operations.hog index 259353afcf7..6a5f299d22f 100644 --- a/hogvm/__tests__/operations.hog +++ b/hogvm/__tests__/operations.hog @@ -37,6 +37,9 @@ test('a' not ilike 'b') // true test('a' in 'car') // true test('a' in 'foo') // false test('a' not in 'car') // false +test('bax' like 'b_x') +test('baax' not like 'b_x') +test('baax' like 'b%x') test(concat('arg', 'another')) // 'arganother' test(concat(1, NULL)) // '1' test(concat(true, false)) // 'truefalse' diff --git a/hogvm/python/test/test_execute.py b/hogvm/python/test/test_execute.py index 6cdd701e826..c4ac04bcff3 100644 --- a/hogvm/python/test/test_execute.py +++ b/hogvm/python/test/test_execute.py @@ -10,7 +10,7 @@ from hogvm.python.operation import ( HOGQL_BYTECODE_VERSION as VERSION, ) from hogvm.python.utils import UncaughtHogVMException -from posthog.hogql.bytecode import create_bytecode +from posthog.hogql.compiler.bytecode import create_bytecode from posthog.hogql.parser import parse_expr, parse_program diff --git a/hogvm/python/utils.py b/hogvm/python/utils.py index 4b5ae2ee05d..b7c0ec66919 100644 --- a/hogvm/python/utils.py +++ b/hogvm/python/utils.py @@ -26,7 +26,7 @@ class UncaughtHogVMException(HogVMException): def like(string, pattern, flags=0): - pattern = re.escape(pattern).replace("%", ".*") + pattern = re.escape(pattern).replace("%", ".*").replace("_", ".") re_pattern = re.compile(pattern, flags) return re_pattern.search(string) is not None diff --git a/hogvm/stl/compile.py b/hogvm/stl/compile.py index 11cb44dfde8..0ef0cf731dd 100755 --- a/hogvm/stl/compile.py +++ b/hogvm/stl/compile.py @@ -5,7 +5,7 @@ import glob import json from posthog.hogql import ast -from posthog.hogql.bytecode import create_bytecode, parse_program +from posthog.hogql.compiler.bytecode import create_bytecode, parse_program source = "hogvm/stl/src/*.hog" target_ts = "hogvm/typescript/src/stl/bytecode.ts" diff --git a/hogvm/test.sh b/hogvm/test.sh index 99b3f0dda37..c30222e12a6 100755 --- a/hogvm/test.sh +++ b/hogvm/test.sh @@ -1,32 +1,119 @@ #!/bin/bash set -e + +# List of test files to skip the compiledjs tests +SKIP_COMPILEDJS_FILES=("crypto.hog") + +# Navigate to the script's directory +cd "$(dirname "$0")" + +# Build the project cd typescript pnpm run build cd .. +# Navigate to the project root (parent directory of 'hogvm') cd .. -rm -f hogvm/__tests__/__snapshots__/*.stdout.nodejs -rm -f hogvm/__tests__/__snapshots__/*.stdout.python +# Function to compute the basename for a given file +get_basename() { + local file="$1" + local base="${file%.hog}" + base="${base##*/}" + echo "hogvm/__tests__/__snapshots__/$base" +} -for file in hogvm/__tests__/*.hog; do +# Function to check if a value is in an array +is_in_array() { + local val="$1" + shift + local arr=("$@") + for item in "${arr[@]}"; do + if [ "$item" == "$val" ]; then + return 0 + fi + done + return 1 +} + +# Check if an argument is provided +if [ "$#" -eq 1 ]; then + test_file="$1" + # Adjust the test file path if it doesn't start with 'hogvm/' + if [[ ! "$test_file" == hogvm/* ]]; then + test_file="hogvm/__tests__/$test_file" + fi + # Check if the test file exists + if [ ! -f "$test_file" ]; then + echo "Test file $test_file does not exist." + exit 1 + fi + test_files=("$test_file") + # Remove previous outputs for this test file only + basename=$(get_basename "$test_file") + rm -f "$basename.stdout.nodejs" "$basename.stdout.python" "$basename.stdout.compiledjs" +else + shopt -s nullglob + test_files=(hogvm/__tests__/*.hog) + shopt -u nullglob + + if [ ${#test_files[@]} -eq 0 ]; then + echo "No test files found in hogvm/__tests__/" + exit 1 + fi + + # Remove all previous outputs + rm -f hogvm/__tests__/__snapshots__/*.stdout.nodejs + rm -f hogvm/__tests__/__snapshots__/*.stdout.python + rm -f hogvm/__tests__/__snapshots__/*.stdout.compiledjs +fi + +for file in "${test_files[@]}"; do echo "Testing $file" - # from hogvm/__tests__/*.hog get hogvm/__tests__/__snapshots__/* - basename="${file%.hog}" - basename="${basename##*/}" - basename="hogvm/__tests__/__snapshots__/$basename" + basename=$(get_basename "$file") + filename=$(basename "$file") - ./bin/hoge $file $basename.hoge - ./bin/hog --nodejs $basename.hoge > $basename.stdout.nodejs - ./bin/hog --python $basename.hoge > $basename.stdout.python - set +e - diff $basename.stdout.nodejs $basename.stdout.python - if [ $? -eq 0 ]; then - mv $basename.stdout.nodejs $basename.stdout - rm $basename.stdout.python + ./bin/hoge "$file" "$basename.hoge" + ./bin/hog --nodejs "$basename.hoge" > "$basename.stdout.nodejs" + ./bin/hog --python "$basename.hoge" > "$basename.stdout.python" + + # Check if the current file should skip the compiledjs tests + if is_in_array "$filename" "${SKIP_COMPILEDJS_FILES[@]}"; then + # Skip compiledjs steps for this file + echo "Skipping compiledjs tests for $filename" + set +e + diff "$basename.stdout.nodejs" "$basename.stdout.python" + if [ $? -eq 0 ]; then + mv "$basename.stdout.nodejs" "$basename.stdout" + rm "$basename.stdout.python" + echo "Test passed" + else + echo "Test failed: Output differs between Node.js and Python interpreters." + fi + set -e else - echo "Test failed" + # Proceed with compiledjs tests + set +e + ./bin/hoge "$file" "$basename.js" + node "$basename.js" > "$basename.stdout.compiledjs" 2>&1 + set -e + + set +e + diff "$basename.stdout.nodejs" "$basename.stdout.compiledjs" + if [ $? -eq 0 ]; then + diff "$basename.stdout.nodejs" "$basename.stdout.python" + if [ $? -eq 0 ]; then + mv "$basename.stdout.nodejs" "$basename.stdout" + rm "$basename.stdout.python" + rm "$basename.stdout.compiledjs" + echo "Test passed" + else + echo "Test failed: Output differs between Node.js and Python interpreters." + fi + else + echo "Test failed: Output differs between Node.js interpreter and compiled JavaScript." + fi + set -e fi - set -e done diff --git a/hogvm/typescript/package.json b/hogvm/typescript/package.json index ff4bd95f532..f48fc844452 100644 --- a/hogvm/typescript/package.json +++ b/hogvm/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@posthog/hogvm", - "version": "1.0.58", + "version": "1.0.59", "description": "PostHog Hog Virtual Machine", "types": "dist/index.d.ts", "source": "src/index.ts", diff --git a/hogvm/typescript/src/stl/stl.ts b/hogvm/typescript/src/stl/stl.ts index f398d6dd0b5..924c355cef9 100644 --- a/hogvm/typescript/src/stl/stl.ts +++ b/hogvm/typescript/src/stl/stl.ts @@ -19,6 +19,8 @@ import { } from './date' import { printHogStringOutput } from './print' +// TODO: this file should be generated from or mergred with posthog/hogql/compiler/javascript_stl.py + function STLToString(args: any[]): string { if (isHogDate(args[0])) { const month = args[0].month @@ -71,9 +73,7 @@ export const STL: Record = { }, toString: { fn: STLToString, minArgs: 1, maxArgs: 1 }, toUUID: { - fn: (args) => { - return String(args[0]) - }, + fn: STLToString, minArgs: 1, maxArgs: 1, }, @@ -148,8 +148,8 @@ export const STL: Record = { }, tuple: { fn: (args) => { - const tuple = args.slice() - ;(tuple as any).__isHogTuple = true + const tuple = args.slice(); + (tuple as any).__isHogTuple = true return tuple }, minArgs: 0, diff --git a/hogvm/typescript/src/utils.ts b/hogvm/typescript/src/utils.ts index 66c934f1e48..86aeaa1c071 100644 --- a/hogvm/typescript/src/utils.ts +++ b/hogvm/typescript/src/utils.ts @@ -36,6 +36,7 @@ export function like( pattern = String(pattern) .replaceAll(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') .replaceAll('%', '.*') + .replaceAll('_', '.') if (match) { return match((caseInsensitive ? '(?i)' : '') + pattern, string) } diff --git a/package.json b/package.json index b9aec3e2639..afc517f96bc 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "@medv/finder": "^3.1.0", "@microlink/react-json-view": "^1.21.3", "@monaco-editor/react": "4.6.0", - "@posthog/hogvm": "^1.0.58", + "@posthog/hogvm": "^1.0.59", "@posthog/icons": "0.9.1", "@posthog/plugin-scaffold": "^1.4.4", "@react-hook/size": "^2.1.2", diff --git a/plugin-server/package.json b/plugin-server/package.json index f116ce360ad..a24ecdbf06d 100644 --- a/plugin-server/package.json +++ b/plugin-server/package.json @@ -13,7 +13,7 @@ "start:dev": "NODE_ENV=dev BASE_DIR=.. nodemon --watch src/ --exec node -r @swc-node/register src/index.ts", "start:devNoWatch": "NODE_ENV=dev BASE_DIR=.. node -r @swc-node/register src/index.ts", "build": "pnpm clean && pnpm compile", - "clean": "rm -rf dist/*", + "clean": "rm -rf dist/* && rm -rf ../rust/cyclotron-node/index.node", "typescript:compile": "tsc -b", "typescript:check": "tsc --noEmit -p .", "compile": "pnpm typescript:compile", @@ -54,7 +54,7 @@ "@maxmind/geoip2-node": "^3.4.0", "@posthog/clickhouse": "^1.7.0", "@posthog/cyclotron": "file:../rust/cyclotron-node", - "@posthog/hogvm": "^1.0.58", + "@posthog/hogvm": "^1.0.59", "@posthog/plugin-scaffold": "1.4.4", "@sentry/node": "^7.49.0", "@sentry/profiling-node": "^0.3.0", diff --git a/plugin-server/pnpm-lock.yaml b/plugin-server/pnpm-lock.yaml index 4d99a3ab775..088161d2bac 100644 --- a/plugin-server/pnpm-lock.yaml +++ b/plugin-server/pnpm-lock.yaml @@ -47,8 +47,8 @@ dependencies: specifier: file:../rust/cyclotron-node version: file:../rust/cyclotron-node '@posthog/hogvm': - specifier: ^1.0.58 - version: 1.0.58(luxon@3.4.4) + specifier: ^1.0.59 + version: 1.0.59(luxon@3.4.4) '@posthog/plugin-scaffold': specifier: 1.4.4 version: 1.4.4 @@ -3119,8 +3119,8 @@ packages: engines: {node: '>=12'} dev: false - /@posthog/hogvm@1.0.58(luxon@3.4.4): - resolution: {integrity: sha512-n7NlJWth9WymJWd3w2YOKfq+soxAcycdfjNIVxxniL1bmEL+aI+Nff+MCPKrsv7YLj9qAnyLWBVAw9SZMksB1Q==} + /@posthog/hogvm@1.0.59(luxon@3.4.4): + resolution: {integrity: sha512-4KJfCXUhK7x5Wm3pheKWDmrbQ0y1lWlLWdVEjocdjSy3wOS8hQQqaFAVEKZs7hfk9pZqvNFh2UPgD4ccpwUQjA==} peerDependencies: luxon: ^3.4.4 dependencies: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e30575948b..ff63e019038 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,8 +50,8 @@ dependencies: specifier: 4.6.0 version: 4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0) '@posthog/hogvm': - specifier: ^1.0.58 - version: 1.0.58(luxon@3.5.0) + specifier: ^1.0.59 + version: 1.0.59(luxon@3.5.0) '@posthog/icons': specifier: 0.9.1 version: 0.9.1(react-dom@18.2.0)(react@18.2.0) @@ -392,7 +392,7 @@ dependencies: optionalDependencies: fsevents: specifier: ^2.3.2 - version: 2.3.3 + version: 2.3.2 devDependencies: '@babel/core': @@ -5418,8 +5418,8 @@ packages: resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} dev: false - /@posthog/hogvm@1.0.58(luxon@3.5.0): - resolution: {integrity: sha512-n7NlJWth9WymJWd3w2YOKfq+soxAcycdfjNIVxxniL1bmEL+aI+Nff+MCPKrsv7YLj9qAnyLWBVAw9SZMksB1Q==} + /@posthog/hogvm@1.0.59(luxon@3.5.0): + resolution: {integrity: sha512-4KJfCXUhK7x5Wm3pheKWDmrbQ0y1lWlLWdVEjocdjSy3wOS8hQQqaFAVEKZs7hfk9pZqvNFh2UPgD4ccpwUQjA==} peerDependencies: luxon: ^3.4.4 dependencies: @@ -13142,7 +13142,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /fsevents@2.3.3: diff --git a/posthog/api/hog.py b/posthog/api/hog.py index 6ee0f94506a..d9d4c351669 100644 --- a/posthog/api/hog.py +++ b/posthog/api/hog.py @@ -6,7 +6,7 @@ from rest_framework.response import Response from hogql_parser import parse_program from posthog.api.mixins import PydanticModelMixin from posthog.api.routing import TeamAndOrgViewSetMixin -from posthog.hogql.bytecode import create_bytecode, Local +from posthog.hogql.compiler.bytecode import create_bytecode, Local from posthog.hogql.errors import ExposedHogQLError from posthog.schema import HogCompileResponse diff --git a/posthog/api/services/query.py b/posthog/api/services/query.py index b98bb979bfc..2d61a92d34d 100644 --- a/posthog/api/services/query.py +++ b/posthog/api/services/query.py @@ -7,7 +7,7 @@ from rest_framework.exceptions import ValidationError from hogvm.python.debugger import color_bytecode from posthog.clickhouse.query_tagging import tag_queries from posthog.cloud_utils import is_cloud -from posthog.hogql.bytecode import execute_hog +from posthog.hogql.compiler.bytecode import execute_hog from posthog.hogql.constants import LimitContext from posthog.hogql.context import HogQLContext from posthog.hogql.database.database import create_hogql_database, serialize_database diff --git a/posthog/cdp/filters.py b/posthog/cdp/filters.py index 6e655e3338c..04fde83e5c5 100644 --- a/posthog/cdp/filters.py +++ b/posthog/cdp/filters.py @@ -1,6 +1,6 @@ from typing import Optional from posthog.models.action.action import Action -from posthog.hogql.bytecode import create_bytecode +from posthog.hogql.compiler.bytecode import create_bytecode from posthog.hogql.parser import parse_expr from posthog.hogql.property import action_to_expr, property_to_expr, ast from posthog.models.team.team import Team diff --git a/posthog/cdp/test/test_filters.py b/posthog/cdp/test/test_filters.py index 978b9ee2a6f..fecb983aa5b 100644 --- a/posthog/cdp/test/test_filters.py +++ b/posthog/cdp/test/test_filters.py @@ -3,7 +3,7 @@ from inline_snapshot import snapshot from hogvm.python.operation import HOGQL_BYTECODE_VERSION from posthog.cdp.filters import hog_function_filters_to_expr -from posthog.hogql.bytecode import create_bytecode +from posthog.hogql.compiler.bytecode import create_bytecode from posthog.models.action.action import Action from posthog.test.base import APIBaseTest, ClickhouseTestMixin, QueryMatchingTest diff --git a/posthog/cdp/validation.py b/posthog/cdp/validation.py index 321f135614e..0b2bbe2237d 100644 --- a/posthog/cdp/validation.py +++ b/posthog/cdp/validation.py @@ -2,7 +2,7 @@ import logging from typing import Any, Optional from rest_framework import serializers -from posthog.hogql.bytecode import create_bytecode +from posthog.hogql.compiler.bytecode import create_bytecode from posthog.hogql.parser import parse_program, parse_string_template logger = logging.getLogger(__name__) diff --git a/posthog/hogql/cli.py b/posthog/hogql/cli.py index 17b443db06f..36be3d1f086 100644 --- a/posthog/hogql/cli.py +++ b/posthog/hogql/cli.py @@ -2,7 +2,8 @@ import sys import json from hogvm.python.execute import execute_bytecode -from .bytecode import create_bytecode, parse_program +from posthog.hogql.compiler.bytecode import create_bytecode, parse_program +from posthog.hogql.compiler.javascript import to_js_program modifiers = [arg for arg in sys.argv if arg.startswith("-")] args = [arg for arg in sys.argv if arg != "" and not arg.startswith("-")] @@ -14,46 +15,53 @@ if not filename.endswith(".hog") and not filename.endswith(".hoge"): with open(filename) as file: code = file.read() -if filename.endswith(".hog"): - bytecode = create_bytecode(parse_program(code)).bytecode +if "--compile" in modifiers and len(args) == 3 and args[2].endswith(".js"): + target = args[2] + js_program = to_js_program(code) + with open(target, "w") as file: + file.write(js_program + "\n") + else: - bytecode = json.loads(code) - -if "--run" in modifiers: - if len(args) != 2: - raise ValueError("Must specify exactly one filename") - - response = execute_bytecode(bytecode, globals=None, timeout=5, team=None, debug="--debug" in modifiers) - for line in response.stdout: - print(line) # noqa: T201 - -elif "--out" in modifiers: - if len(args) != 2: - raise ValueError("Must specify exactly one filename") - print(json.dumps(bytecode)) # noqa: T201 - -elif "--compile" in modifiers: - if len(args) == 3: - target = args[2] + if filename.endswith(".hog"): + bytecode = create_bytecode(parse_program(code)).bytecode else: - target = filename[:-4] + ".hoge" + bytecode = json.loads(code) + + if "--run" in modifiers: if len(args) != 2: raise ValueError("Must specify exactly one filename") - # write bytecode to file - with open(target, "w") as file: - max_length = 120 - line = "[" - for index, op in enumerate(bytecode): - encoded = json.dumps(op) - if len(line) + len(encoded) > max_length - 2: - file.write(line + "\n") - line = "" - line += (" " if len(line) > 1 else "") + encoded + ("]" if index == len(bytecode) - 1 else ",") - if line == "[": - file.write(line + "]\n") - elif line != "": - file.write(line + "\n") + response = execute_bytecode(bytecode, globals=None, timeout=5, team=None, debug="--debug" in modifiers) + for line in response.stdout: + print(line) # noqa: T201 -else: - raise ValueError("Must specify either --run or --compile") + elif "--out" in modifiers: + if len(args) != 2: + raise ValueError("Must specify exactly one filename") + print(json.dumps(bytecode)) # noqa: T201 + + elif "--compile" in modifiers: + if len(args) == 3: + target = args[2] + else: + target = filename[:-4] + ".hoge" + if len(args) != 2: + raise ValueError("Must specify exactly one filename") + + # write bytecode to file + with open(target, "w") as file: + max_length = 120 + line = "[" + for index, op in enumerate(bytecode): + encoded = json.dumps(op) + if len(line) + len(encoded) > max_length - 2: + file.write(line + "\n") + line = "" + line += (" " if len(line) > 1 else "") + encoded + ("]" if index == len(bytecode) - 1 else ",") + if line == "[": + file.write(line + "]\n") + elif line != "": + file.write(line + "\n") + + else: + raise ValueError("Must specify either --run or --compile") diff --git a/posthog/hogql/bytecode.py b/posthog/hogql/compiler/bytecode.py similarity index 100% rename from posthog/hogql/bytecode.py rename to posthog/hogql/compiler/bytecode.py diff --git a/posthog/hogql/compiler/javascript.py b/posthog/hogql/compiler/javascript.py new file mode 100644 index 00000000000..16989c6117e --- /dev/null +++ b/posthog/hogql/compiler/javascript.py @@ -0,0 +1,572 @@ +import dataclasses +import json +import re +from enum import StrEnum +from typing import Any, Optional + +from posthog.hogql import ast +from posthog.hogql.base import AST +from posthog.hogql.compiler.javascript_stl import STL_FUNCTIONS, import_stl_functions +from posthog.hogql.errors import QueryError, NotImplementedError +from posthog.hogql.parser import parse_expr, parse_program +from posthog.hogql.visitor import Visitor + +_JS_GET_GLOBAL = "__getGlobal" +_JS_KEYWORDS = { + "await", + "break", + "case", + "catch", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "enum", + "export", + "extends", + "false", + "finally", + "for", + "function", + "if", + "import", + "in", + "instanceof", + "new", + "null", + "return", + "super", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "var", + "void", + "while", + "with", + "yield", + "implements", + "interface", + "let", + "package", + "private", + "protected", + "public", + "static", + "arguments", + "eval", + "Error", + _JS_GET_GLOBAL, # don't let this get overridden +} + + +@dataclasses.dataclass +class Local: + name: str + depth: int + + +def to_js_program(code: str) -> str: + compiler = JavaScriptCompiler() + code = compiler.visit(parse_program(code)) + imports = compiler.get_inlined_stl() + return imports + ("\n\n" if imports else "") + code + + +def to_js_expr(expr: str) -> str: + return JavaScriptCompiler().visit(parse_expr(expr)) + + +def _as_block(node: ast.Statement) -> ast.Block: + if isinstance(node, ast.Block): + return node + return ast.Block(declarations=[node]) + + +def _sanitize_identifier(name: str | int) -> str: + name = str(name) + if re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", name): + if name in _JS_KEYWORDS: + return f"__x_{name}" + if name.startswith("__x_"): + # add a second __x_ to avoid conflicts with our internal variables + return f"__x_{name}" + return name + else: + return f"[{json.dumps(name)}]" + + +class JavaScriptCompiler(Visitor): + def __init__( + self, + args: Optional[list[str]] = None, + locals: Optional[list[Local]] = None, + ): + super().__init__() + self.locals: list[Local] = locals or [] + self.scope_depth = 0 + self.args = args or [] + self.indent_level = 0 + self.inlined_stl: set[str] = set() + + # Initialize locals with function arguments + for arg in self.args: + self._declare_local(arg) + + def get_inlined_stl(self) -> str: + return import_stl_functions(self.inlined_stl) + + def _start_scope(self): + self.scope_depth += 1 + + def _end_scope(self): + self.locals = [local for local in self.locals if local.depth < self.scope_depth] + self.scope_depth -= 1 + + def _declare_local(self, name: str): + for local in reversed(self.locals): + if local.depth == self.scope_depth and local.name == name: + raise QueryError(f"Variable `{name}` already declared in this scope") + self.locals.append(Local(name=name, depth=self.scope_depth)) + + def _indent(self, code: str) -> str: + indentation = " " * self.indent_level + return "\n".join(indentation + line if line else "" for line in code.split("\n")) + + def visit_and(self, node: ast.And): + code = " && ".join([self.visit(expr) for expr in node.exprs]) + return f"!!({code})" + + def visit_or(self, node: ast.Or): + code = " || ".join([self.visit(expr) for expr in node.exprs]) + return f"!!({code})" + + def visit_not(self, node: ast.Not): + expr_code = self.visit(node.expr) + return f"(!{expr_code})" + + def visit_compare_operation(self, node: ast.CompareOperation): + left_code = self.visit(node.left) + right_code = self.visit(node.right) + op = node.op + + op_map = { + ast.CompareOperationOp.Eq: "==", + ast.CompareOperationOp.NotEq: "!=", + ast.CompareOperationOp.Gt: ">", + ast.CompareOperationOp.GtEq: ">=", + ast.CompareOperationOp.Lt: "<", + ast.CompareOperationOp.LtEq: "<=", + } + + if op in op_map: + return f"({left_code} {op_map[op]} {right_code})" + elif op == ast.CompareOperationOp.In: + return f"({right_code}.includes({left_code}))" + elif op == ast.CompareOperationOp.NotIn: + return f"(!{right_code}.includes({left_code}))" + elif op == ast.CompareOperationOp.Like: + self.inlined_stl.add("like") + return f"like({left_code}, {right_code})" + elif op == ast.CompareOperationOp.ILike: + self.inlined_stl.add("ilike") + return f"ilike({left_code}, {right_code})" + elif op == ast.CompareOperationOp.NotLike: + self.inlined_stl.add("like") + return f"!like({left_code}, {right_code})" + elif op == ast.CompareOperationOp.NotILike: + self.inlined_stl.add("ilike") + return f"!ilike({left_code}, {right_code})" + elif op == ast.CompareOperationOp.Regex: + # TODO: re2? + return f"new RegExp({right_code}).test({left_code})" + elif op == ast.CompareOperationOp.IRegex: + return f'new RegExp({right_code}, "i").test({left_code})' + elif op == ast.CompareOperationOp.NotRegex: + return f"!(new RegExp({right_code}).test({left_code}))" + elif op == ast.CompareOperationOp.NotIRegex: + return f'!(new RegExp({right_code}, "i").test({left_code}))' + elif op == ast.CompareOperationOp.InCohort or op == ast.CompareOperationOp.NotInCohort: + cohort_name = "" + if isinstance(node.right, ast.Constant): + if isinstance(node.right.value, int): + cohort_name = f" (cohort id={node.right.value})" + else: + cohort_name = f" (cohort: {str(node.right.value)})" + raise QueryError( + f"Can't use cohorts in real-time filters. Please inline the relevant expressions{cohort_name}." + ) + else: + raise QueryError(f"Unsupported comparison operator: {op}") + + def visit_arithmetic_operation(self, node: ast.ArithmeticOperation): + left_code = self.visit(node.left) + right_code = self.visit(node.right) + op_map = { + ast.ArithmeticOperationOp.Add: "+", + ast.ArithmeticOperationOp.Sub: "-", + ast.ArithmeticOperationOp.Mult: "*", + ast.ArithmeticOperationOp.Div: "/", + ast.ArithmeticOperationOp.Mod: "%", + } + op_str = op_map[node.op] + return f"({left_code} {op_str} {right_code})" + + def visit_field(self, node: ast.Field): + found_local = any(local.name == str(node.chain[0]) for local in self.locals) + array_code = "" + for index, element in enumerate(node.chain): + if index == 0: + if found_local: + array_code = _sanitize_identifier(element) + elif element in STL_FUNCTIONS: + self.inlined_stl.add(str(element)) + array_code = f"{_sanitize_identifier(element)}" + else: + array_code = f"{_JS_GET_GLOBAL}({json.dumps(element)})" + continue + + if (isinstance(element, int) and not isinstance(element, bool)) or isinstance(element, str): + self.inlined_stl.add("__getProperty") + array_code = f"__getProperty({array_code}, {json.dumps(element)}, true)" + else: + raise QueryError(f"Unsupported element: {element} ({type(element)})") + return array_code + + def visit_tuple_access(self, node: ast.TupleAccess): + tuple_code = self.visit(node.tuple) + index_code = str(node.index) + self.inlined_stl.add("__getProperty") + return f"__getProperty({tuple_code}, {index_code}, {json.dumps(node.nullish)})" + + def visit_array_access(self, node: ast.ArrayAccess): + array_code = self.visit(node.array) + property_code = self.visit(node.property) + self.inlined_stl.add("__getProperty") + return f"__getProperty({array_code}, {property_code}, {json.dumps(node.nullish)})" + + def visit_constant(self, node: ast.Constant): + value = node.value + if value is True: + return "true" + elif value is False: + return "false" + elif value is None: + return "null" + elif isinstance(value, int | float | str): + return json.dumps(value) + else: + raise QueryError(f"Unsupported constant type: {type(value)}") + + def visit_call(self, node: ast.Call): + if node.params is not None: + return self.visit(ast.ExprCall(expr=ast.Call(name=node.name, args=node.params), args=node.args or [])) + + # Handle special functions + if node.name == "not" and len(node.args) == 1: + expr_code = self.visit(node.args[0]) + return f"(!{expr_code})" + if node.name == "and" and len(node.args) > 1: + exprs_code = " && ".join([self.visit(arg) for arg in node.args]) + return f"({exprs_code})" + if node.name == "or" and len(node.args) > 1: + exprs_code = " || ".join([self.visit(arg) for arg in node.args]) + return f"({exprs_code})" + if node.name == "if" and len(node.args) >= 2: + condition_code = self.visit(node.args[0]) + then_code = self.visit(node.args[1]) + else_code = self.visit(node.args[2]) if len(node.args) == 3 else "null" + return f"({condition_code} ? {then_code} : {else_code})" + if node.name == "multiIf" and len(node.args) >= 2: + + def build_nested_if(args): + condition_code = self.visit(args[0]) + then_code = self.visit(args[1]) + if len(args) == 2: + return f"({condition_code} ? {then_code} : null)" + elif len(args) == 3: + else_code = self.visit(args[2]) + return f"({condition_code} ? {then_code} : {else_code})" + else: + else_code = build_nested_if(args[2:]) + return f"({condition_code} ? {then_code} : {else_code})" + + return build_nested_if(node.args) + if node.name == "ifNull" and len(node.args) == 2: + expr_code = self.visit(node.args[0]) + if_null_code = self.visit(node.args[1]) + return f"({expr_code} ?? {if_null_code})" + + if node.name in STL_FUNCTIONS: + self.inlined_stl.add(node.name) + name = _sanitize_identifier(node.name) + args_code = ", ".join(self.visit(arg) for arg in node.args) + return f"{name}({args_code})" + else: + # Regular function calls + name = _sanitize_identifier(node.name) + args_code = ", ".join([self.visit(arg) for arg in node.args or []]) + return f"{name}({args_code})" + + def visit_expr_call(self, node: ast.ExprCall): + func_code = self.visit(node.expr) + args_code = ", ".join([self.visit(arg) for arg in node.args]) + return f"{func_code}({args_code})" + + def visit_program(self, node: ast.Program): + code_lines = [] + self._start_scope() + for declaration in node.declarations: + code = self.visit(declaration) + code_lines.append(self._indent(code)) + self._end_scope() + return "\n".join(code_lines) + + def visit_block(self, node: ast.Block): + code_lines = [] + self._start_scope() + self.indent_level += 1 + for declaration in node.declarations: + code = self.visit(declaration) + code_lines.append(self._indent(code)) + self.indent_level -= 1 + self._end_scope() + return "{\n" + "\n".join(code_lines) + "\n" + (" " * self.indent_level) + "}" + + def visit_expr_statement(self, node: ast.ExprStatement): + if node.expr is None: + return "" + expr_code = self.visit(node.expr) + return expr_code + ";" + + def visit_return_statement(self, node: ast.ReturnStatement): + if node.expr: + return f"return {self.visit(node.expr)};" + else: + return "return null;" + + def visit_throw_statement(self, node: ast.ThrowStatement): + return f"throw {self.visit(node.expr)};" + + def visit_try_catch_statement(self, node: ast.TryCatchStatement): + try_code = self.visit(_as_block(node.try_stmt)) + code = "try " + try_code + " catch (__error) { " + has_catch_all = False + for index, catch in enumerate(node.catches): + catch_var = catch[0] or "e" + self._start_scope() + self._declare_local(catch_var) + catch_type = str(catch[1]) if catch[1] is not None else None + catch_declarations = _as_block(catch[2]) + catch_code = "".join(self._indent(self.visit(d)) for d in catch_declarations.declarations) + if index > 0: + code += " else " + if catch_type is not None and catch_type != "Error": + code += ( + f"if (__error.type === {json.dumps(catch_type)}) {{ let {_sanitize_identifier(catch_var)} = __error;\n" + f"{catch_code}\n" + f"}}\n" + ) + else: + has_catch_all = True + code += f"if (true) {{ let {_sanitize_identifier(catch_var)} = __error;\n" f"{catch_code}\n" f"}}\n" + self._end_scope() + if not has_catch_all: + code += " else { throw __error; }" + code += "}" + + if node.finally_stmt: + finally_code = self.visit(_as_block(node.finally_stmt)) + code += " finally " + finally_code + return code + + def visit_if_statement(self, node: ast.IfStatement): + expr_code = self.visit(node.expr) + then_code = self.visit(_as_block(node.then)) + code = f"if ({expr_code}) {then_code}" + if node.else_: + else_code = self.visit(_as_block(node.else_)) + code += f" else {else_code}" + return code + + def visit_while_statement(self, node: ast.WhileStatement): + expr_code = self.visit(node.expr) + body_code = self.visit(_as_block(node.body)) + return f"while ({expr_code}) {body_code}" + + def visit_for_statement(self, node: ast.ForStatement): + self._start_scope() + init_code = self.visit(node.initializer) if node.initializer else "" + init_code = init_code[:-1] if init_code.endswith(";") else init_code + condition_code = self.visit(node.condition) if node.condition else "" + condition_code = condition_code[:-1] if condition_code.endswith(";") else condition_code + increment_code = self.visit(node.increment) if node.increment else "" + increment_code = increment_code[:-1] if increment_code.endswith(";") else increment_code + body_code = self.visit(_as_block(node.body)) + self._end_scope() + return f"for ({init_code}; {condition_code}; {increment_code}) {body_code}" + + def visit_for_in_statement(self, node: ast.ForInStatement): + expr_code = self.visit(node.expr) + if node.keyVar and node.valueVar: + self._start_scope() + self._declare_local(node.keyVar) + self._declare_local(node.valueVar) + body_code = self.visit(_as_block(node.body)) + self.inlined_stl.add("keys") + resp = f"for (let {_sanitize_identifier(node.keyVar)} of keys({expr_code})) {{ let {_sanitize_identifier(node.valueVar)} = {expr_code}[{_sanitize_identifier(node.keyVar)}]; {body_code} }}" + self._end_scope() + return resp + elif node.valueVar: + self._start_scope() + self._declare_local(node.valueVar) + body_code = self.visit(_as_block(node.body)) + self.inlined_stl.add("values") + resp = f"for (let {_sanitize_identifier(node.valueVar)} of values({expr_code})) {body_code}" + self._end_scope() + return resp + else: + raise QueryError("ForInStatement requires at least a valueVar") + + def visit_variable_declaration(self, node: ast.VariableDeclaration): + self._declare_local(node.name) + if node.expr: + expr_code = self.visit(node.expr) + return f"let {_sanitize_identifier(node.name)} = {expr_code};" + else: + return f"let {_sanitize_identifier(node.name)};" + + def visit_variable_assignment(self, node: ast.VariableAssignment): + if isinstance(node.left, ast.TupleAccess): + tuple_code = self.visit(node.left.tuple) + index = node.left.index + right_code = self.visit(node.right) + self.inlined_stl.add("__setProperty") + return f"__setProperty({tuple_code}, {index}, {right_code});" + + elif isinstance(node.left, ast.ArrayAccess): + array_code = self.visit(node.left.array) + property_code = self.visit(node.left.property) + right_code = self.visit(node.right) + self.inlined_stl.add("__setProperty") + return f"__setProperty({array_code}, {property_code}, {right_code});" + + elif isinstance(node.left, ast.Field): + chain = node.left.chain + name = chain[0] + is_local = any(local.name == name for local in self.locals) + + if is_local: + array_code = "" + for index, element in enumerate(chain): + if index == 0: + array_code = _sanitize_identifier(element) + if len(chain) == 1: + array_code = f"{array_code} = {self.visit(node.right)}" + elif (isinstance(element, int) and not isinstance(element, bool)) or isinstance(element, str): + if index == len(chain) - 1: + right_code = self.visit(node.right) + self.inlined_stl.add("__setProperty") + array_code = f"__setProperty({array_code}, {json.dumps(element)}, {right_code})" + else: + self.inlined_stl.add("__getProperty") + array_code = f"__getProperty({array_code}, {json.dumps(element)}, true)" + else: + raise QueryError(f"Unsupported element: {element} ({type(element)})") + return array_code + + else: + # Cannot assign to undeclared variables or globals + raise QueryError(f'Variable "{name}" not declared in this scope. Cannot assign to globals.') + + else: + left_code = self.visit(node.left) + right_code = self.visit(node.right) + return f"{left_code} = {right_code};" + + def visit_function(self, node: ast.Function): + self._declare_local(_sanitize_identifier(node.name)) + params_code = ", ".join(_sanitize_identifier(p) for p in node.params) + self._start_scope() + for arg in node.params: + self._declare_local(arg) + if isinstance(node.body, ast.Placeholder): + body_code = ast.Block(declarations=[ast.ExprStatement(expr=node.body.expr), ast.ReturnStatement(expr=None)]) + else: + body_code = self.visit(_as_block(node.body)) + self._end_scope() + return f"function {_sanitize_identifier(node.name)}({params_code}) {body_code}" + + def visit_lambda(self, node: ast.Lambda): + params_code = ", ".join(_sanitize_identifier(p) for p in node.args) + self._start_scope() + for arg in node.args: + self._declare_local(arg) + if isinstance(node.expr, ast.Placeholder): + expr_code = self.visit( + ast.Block(declarations=[ast.ExprStatement(expr=node.expr.expr), ast.ReturnStatement(expr=None)]) + ) + else: + expr_code = self.visit(node.expr) + self._end_scope() + self.inlined_stl.add("__lambda") + # we wrap it in __lambda() to make the function anonymous (a true lambda without a name) + return f"__lambda(({params_code}) => {expr_code})" + + def visit_dict(self, node: ast.Dict): + items = [] + for key, value in node.items: + key_code = self.visit(key) + if not isinstance(key, ast.Constant) or not isinstance(key.value, str): + key_code = f"[{key_code}]" + value_code = self.visit(value) + items.append(f"{key_code}: {value_code}") + items_code = ", ".join(items) + return f"{{{items_code}}}" + + def visit_array(self, node: ast.Array): + items_code = ", ".join([self.visit(expr) for expr in node.exprs]) + return f"[{items_code}]" + + def visit_tuple(self, node: ast.Tuple): + items_code = ", ".join([self.visit(expr) for expr in node.exprs]) + self.inlined_stl.add("tuple") + return f"tuple({items_code})" + + def visit_hogqlx_tag(self, node: ast.HogQLXTag): + attrs = [f'"__hx_tag": {json.dumps(node.kind)}'] + for attr in node.attributes: + attrs.append(f'"{attr.name}": {self._visit_hogqlx_value(attr.value)}') + return f'{{{", ".join(attrs)}}}' + + def _visit_hogqlx_value(self, value: Any) -> str: + if isinstance(value, AST): + return self.visit(value) + if isinstance(value, list): + elems = ", ".join([self._visit_hogqlx_value(v) for v in value]) + return f"[{elems}]" + if isinstance(value, dict): + items = ", ".join( + [f"{self._visit_hogqlx_value(k)}: {self._visit_hogqlx_value(v)}" for k, v in value.items()] + ) + return f"{{{items}}}" + if isinstance(value, StrEnum): + return '"' + str(value.value) + '"' + if value is True: + return "true" + if value is False: + return "false" + if isinstance(value, int | float): + return str(value) + if isinstance(value, str): + return json.dumps(value) + return "null" + + def visit_select_query(self, node: ast.SelectQuery): + raise NotImplementedError("JavaScriptCompiler does not support SelectQuery") diff --git a/posthog/hogql/compiler/javascript_stl.py b/posthog/hogql/compiler/javascript_stl.py new file mode 100644 index 00000000000..b1e53d24110 --- /dev/null +++ b/posthog/hogql/compiler/javascript_stl.py @@ -0,0 +1,923 @@ +# TODO: this should be autogenerated from hogvm/typescript/src/stl/* + +STL_FUNCTIONS: dict[str, list[str | list[str]]] = { + "concat": [ + "function concat (...args) { return args.map((arg) => (arg === null ? '' : __STLToString(arg))).join('') }", + ["__STLToString"], + ], + "match": [ + "function match (str, pattern) { return new RegExp(pattern).test(str) }", + [], + ], + "like": [ + "function like (str, pattern) { return __like(str, pattern, false) }", + ["__like"], + ], + "ilike": [ + "function ilike (str, pattern) { return __like(str, pattern, true) }", + ["__like"], + ], + "notLike": [ + "function notLike (str, pattern) { return !__like(str, pattern, false) }", + ["__like"], + ], + "notILike": [ + "function notILike (str, pattern) { return !__like(str, pattern, true) }", + ["__like"], + ], + "toString": [ + "function toString (value) { return __STLToString(value) }", + ["__STLToString"], + ], + "toUUID": [ + "function toUUID (value) { return __STLToString(value) }", + ["__STLToString"], + ], + "toInt": [ + """function toInt(value) { + if (__isHogDateTime(value)) { return Math.floor(value.dt); } + else if (__isHogDate(value)) { const date = new Date(Date.UTC(value.year, value.month - 1, value.day)); const epoch = new Date(Date.UTC(1970, 0, 1)); const diffInDays = Math.floor((date - epoch) / (1000 * 60 * 60 * 24)); return diffInDays; } + return !isNaN(parseInt(value)) ? parseInt(value) : null; }""", + ["__isHogDateTime", "__isHogDate"], + ], + "toFloat": [ + """function toFloat(value) { + if (__isHogDateTime(value)) { return value.dt; } + else if (__isHogDate(value)) { const date = new Date(Date.UTC(value.year, value.month - 1, value.day)); const epoch = new Date(Date.UTC(1970, 0, 1)); const diffInDays = (date - epoch) / (1000 * 60 * 60 * 24); return diffInDays; } + return !isNaN(parseFloat(value)) ? parseFloat(value) : null; }""", + ["__isHogDateTime", "__isHogDate"], + ], + "ifNull": [ + "function ifNull (value, defaultValue) { return value !== null ? value : defaultValue } ", + [], + ], + "length": [ + "function length (value) { return value.length }", + [], + ], + "empty": [ + """function empty (value) { + if (typeof value === 'object') { + if (Array.isArray(value)) { return value.length === 0 } else if (value === null) { return true } else if (value instanceof Map) { return value.size === 0 } + return Object.keys(value).length === 0 + } else if (typeof value === 'number' || typeof value === 'boolean') { return false } + return !value }""", + [], + ], + "notEmpty": [ + "function notEmpty (value) { return !empty(value) }", + ["empty"], + ], + "tuple": [ + "function tuple (...args) { const tuple = args.slice(); tuple.__isHogTuple = true; return tuple; }", + [], + ], + "lower": [ + "function lower (value) { return value.toLowerCase() }", + [], + ], + "upper": [ + "function upper (value) { return value.toUpperCase() }", + [], + ], + "reverse": [ + "function reverse (value) { return value.split('').reverse().join('') }", + [], + ], + "print": [ + "function print (...args) { console.log(...args.map(__printHogStringOutput)) }", + ["__printHogStringOutput"], + ], + "jsonParse": [ + """function jsonParse (str) { + function convert(x) { + if (Array.isArray(x)) { return x.map(convert) } + else if (typeof x === 'object' && x !== null) { + if (x.__hogDateTime__) { return __toHogDateTime(x.dt, x.zone) + } else if (x.__hogDate__) { return __toHogDate(x.year, x.month, x.day) + } else if (x.__hogError__) { return __newHogError(x.type, x.message, x.payload) } + const obj = {}; for (const key in x) { obj[key] = convert(x[key]) }; return obj } + return x } + return convert(JSON.parse(str)) }""", + ["__toHogDateTime", "__toHogDate", "__newHogError"], + ], + "jsonStringify": [ + """function jsonStringify (value, spacing) { + function convert(x, marked) { + if (!marked) { marked = new Set() } + if (typeof x === 'object' && x !== null) { + if (marked.has(x)) { return null } + marked.add(x) + try { + if (x instanceof Map) { + const obj = {} + x.forEach((value, key) => { obj[convert(key, marked)] = convert(value, marked) }) + return obj + } + if (Array.isArray(x)) { return x.map((v) => convert(v, marked)) } + if (__isHogDateTime(x) || __isHogDate(x) || __isHogError(x)) { return x } + if (typeof x === 'function') { return `fn<${x.name || 'lambda'}(${x.length})>` } + const obj = {}; for (const key in x) { obj[key] = convert(x[key], marked) } + return obj + } finally { + marked.delete(x) + } + } + return x + } + if (spacing && typeof spacing === 'number' && spacing > 0) { + return JSON.stringify(convert(value), null, spacing) + } + return JSON.stringify(convert(value), (key, val) => typeof val === 'function' ? `fn<${val.name || 'lambda'}(${val.length})>` : val) +}""", + ["__isHogDateTime", "__isHogDate", "__isHogError"], + ], + "JSONHas": [ + """function JSONHas (obj, ...path) { + let current = obj + for (const key of path) { + let currentParsed = current + if (typeof current === 'string') { try { currentParsed = JSON.parse(current) } catch (e) { return false } } + if (currentParsed instanceof Map) { if (!currentParsed.has(key)) { return false }; current = currentParsed.get(key) } + else if (typeof currentParsed === 'object' && currentParsed !== null) { + if (typeof key === 'number') { + if (Array.isArray(currentParsed)) { + if (key < 0) { if (key < -currentParsed.length) { return false }; current = currentParsed[currentParsed.length + key] } + else if (key === 0) { return false } + else { if (key > currentParsed.length) { return false }; current = currentParsed[key - 1] } + } else { return false } + } else { + if (!(key in currentParsed)) { return false } + current = currentParsed[key] + } + } else { return false } + } + return true }""", + [], + ], + "isValidJSON": [ + "function isValidJSON (str) { try { JSON.parse(str); return true } catch (e) { return false } }", + [], + ], + "JSONLength": [ + """function JSONLength (obj, ...path) { + try { if (typeof obj === 'string') { obj = JSON.parse(obj) } } catch (e) { return 0 } + if (typeof obj === 'object' && obj !== null) { + const value = __getNestedValue(obj, path, true) + if (Array.isArray(value)) { + return value.length + } else if (value instanceof Map) { + return value.size + } else if (typeof value === 'object' && value !== null) { + return Object.keys(value).length + } + } + return 0 }""", + ["__getNestedValue"], + ], + "JSONExtractBool": [ + """function JSONExtractBool (obj, ...path) { + try { + if (typeof obj === 'string') { + obj = JSON.parse(obj) + } + } catch (e) { + return false + } + if (path.length > 0) { + obj = __getNestedValue(obj, path, true) + } + if (typeof obj === 'boolean') { + return obj + } + return false +}""", + ["__getNestedValue"], + ], + "base64Encode": [ + "function base64Encode (str) { return Buffer.from(str).toString('base64') }", + [], + ], + "base64Decode": [ + "function base64Decode (str) { return Buffer.from(str, 'base64').toString() } ", + [], + ], + "tryBase64Decode": [ + "function tryBase64Decode (str) { try { return Buffer.from(str, 'base64').toString() } catch (e) { return '' } }", + [], + ], + "encodeURLComponent": [ + "function encodeURLComponent (str) { return encodeURIComponent(str) }", + [], + ], + "decodeURLComponent": [ + "function decodeURLComponent (str) { return decodeURIComponent(str) }", + [], + ], + "replaceOne": [ + "function replaceOne (str, searchValue, replaceValue) { return str.replace(searchValue, replaceValue) }", + [], + ], + "replaceAll": [ + "function replaceAll (str, searchValue, replaceValue) { return str.replaceAll(searchValue, replaceValue) }", + [], + ], + "position": [ + "function position (str, elem) { if (typeof str === 'string') { return str.indexOf(String(elem)) + 1 } else { return 0 } }", + [], + ], + "positionCaseInsensitive": [ + "function positionCaseInsensitive (str, elem) { if (typeof str === 'string') { return str.toLowerCase().indexOf(String(elem).toLowerCase()) + 1 } else { return 0 } }", + [], + ], + "trim": [ + """function trim (str, char) { + if (char === null || char === undefined) { + char = ' ' + } + if (char.length !== 1) { + return '' + } + let start = 0 + while (str[start] === char) { + start++ + } + let end = str.length + while (str[end - 1] === char) { + end-- + } + if (start >= end) { + return '' + } + return str.slice(start, end) +}""", + [], + ], + "trimLeft": [ + """function trimLeft (str, char) { + if (char === null || char === undefined) { + char = ' ' + } + if (char.length !== 1) { + return '' + } + let start = 0 + while (str[start] === char) { + start++ + } + return str.slice(start) +}""", + [], + ], + "trimRight": [ + """function trimRight (str, char) { + if (char === null || char === undefined) { + char = ' ' + } + if (char.length !== 1) { + return '' + } + let end = str.length + while (str[end - 1] === char) { + end-- + } + return str.slice(0, end) +}""", + [], + ], + "splitByString": [ + "function splitByString (separator, str, maxSplits) { if (maxSplits === undefined || maxSplits === null) { return str.split(separator) } return str.split(separator, maxSplits) }", + [], + ], + "generateUUIDv4": [ + "function generateUUIDv4 () { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0; const v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16) })}", + [], + ], + "sha256Hex": [ + "function sha256Hex (str, options) { return 'SHA256 is not implemented' }", + [], + ], + "md5Hex": [ + """function md5Hex(string) { return 'MD5 is not implemented' }""", + [], + ], + "sha256HmacChainHex": [ + "function sha256HmacChainHex (data, options) { return 'sha256HmacChainHex not implemented' }", + [], + ], + "keys": [ + """function keys (obj) { if (typeof obj === 'object' && obj !== null) { if (Array.isArray(obj)) { return Array.from(obj.keys()) } else if (obj instanceof Map) { return Array.from(obj.keys()) } return Object.keys(obj) } return [] }""", + [], + ], + "values": [ + """function values (obj) { if (typeof obj === 'object' && obj !== null) { if (Array.isArray(obj)) { return [...obj] } else if (obj instanceof Map) { return Array.from(obj.values()) } return Object.values(obj) } return [] }""", + [], + ], + "indexOf": [ + "function indexOf (arrOrString, elem) { if (Array.isArray(arrOrString)) { return arrOrString.indexOf(elem) + 1 } else { return 0 } }", + [], + ], + "arrayPushBack": [ + "function arrayPushBack (arr, item) { if (!Array.isArray(arr)) { return [item] } return [...arr, item] }", + [], + ], + "arrayPushFront": [ + "function arrayPushFront (arr, item) { if (!Array.isArray(arr)) { return [item] } return [item, ...arr] }", + [], + ], + "arrayPopBack": [ + "function arrayPopBack (arr) { if (!Array.isArray(arr)) { return [] } return arr.slice(0, arr.length - 1) }", + [], + ], + "arrayPopFront": [ + "function arrayPopFront (arr) { if (!Array.isArray(arr)) { return [] } return arr.slice(1) }", + [], + ], + "arraySort": [ + "function arraySort (arr) { if (!Array.isArray(arr)) { return [] } return [...arr].sort() }", + [], + ], + "arrayReverse": [ + "function arrayReverse (arr) { if (!Array.isArray(arr)) { return [] } return [...arr].reverse() }", + [], + ], + "arrayReverseSort": [ + "function arrayReverseSort (arr) { if (!Array.isArray(arr)) { return [] } return [...arr].sort().reverse() }", + [], + ], + "arrayStringConcat": [ + "function arrayStringConcat (arr, separator = '') { if (!Array.isArray(arr)) { return '' } return arr.join(separator) }", + [], + ], + "arrayCount": [ + "function arrayCount (func, arr) { let count = 0; for (let i = 0; i < arr.length; i++) { if (func(arr[i])) { count = count + 1 } } return count }", + [], + ], + "arrayExists": [ + """function arrayExists (func, arr) { for (let i = 0; i < arr.length; i++) { if (func(arr[i])) { return true } } return false }""", + [], + ], + "arrayFilter": [ + """function arrayFilter (func, arr) { let result = []; for (let i = 0; i < arr.length; i++) { if (func(arr[i])) { result = arrayPushBack(result, arr[i]) } } return result}""", + ["arrayPushBack"], + ], + "arrayMap": [ + """function arrayMap (func, arr) { let result = []; for (let i = 0; i < arr.length; i++) { result = arrayPushBack(result, func(arr[i])) } return result }""", + ["arrayPushBack"], + ], + "has": [ + """function has (arr, elem) { if (!Array.isArray(arr) || arr.length === 0) { return false } return arr.includes(elem) }""", + [], + ], + "now": [ + """function now () { return __now() }""", + ["__now"], + ], + "toUnixTimestamp": [ + """function toUnixTimestamp (input, zone) { return __toUnixTimestamp(input, zone) }""", + ["__toUnixTimestamp"], + ], + "fromUnixTimestamp": [ + """function fromUnixTimestamp (input) { return __fromUnixTimestamp(input) }""", + ["__fromUnixTimestamp"], + ], + "toUnixTimestampMilli": [ + """function toUnixTimestampMilli (input, zone) { return __toUnixTimestampMilli(input, zone) }""", + ["__toUnixTimestampMilli"], + ], + "fromUnixTimestampMilli": [ + """function fromUnixTimestampMilli (input) { return __fromUnixTimestampMilli(input) }""", + ["__fromUnixTimestampMilli"], + ], + "toTimeZone": [ + """function toTimeZone (input, zone) { return __toTimeZone(input, zone) }""", + ["__toTimeZone"], + ], + "toDate": [ + """function toDate (input) { return __toDate(input) }""", + ["__toDate"], + ], + "toDateTime": [ + """function toDateTime (input, zone) { return __toDateTime(input, zone) }""", + ["__toDateTime"], + ], + "formatDateTime": [ + """function formatDateTime (input, format, zone) { return __formatDateTime(input, format, zone) }""", + ["__formatDateTime"], + ], + "HogError": [ + """function HogError (type, message, payload) { return __newHogError(type, message, payload) }""", + ["__newHogError"], + ], + "Error": [ + """function __x_Error (message, payload) { return __newHogError('Error', message, payload) }""", + ["__newHogError"], + ], + "RetryError": [ + """function RetryError (message, payload) { return __newHogError('RetryError', message, payload) }""", + ["__newHogError"], + ], + "NotImplementedError": [ + """function NotImplementedError (message, payload) { return __newHogError('NotImplementedError', message, payload) }""", + ["__newHogError"], + ], + "typeof": [ + """function __x_typeof (value) { + if (value === null || value === undefined) { return 'null' + } else if (__isHogDateTime(value)) { return 'datetime' + } else if (__isHogDate(value)) { return 'date' + } else if (__isHogError(value)) { return 'error' + } else if (typeof value === 'function') { return 'function' + } else if (Array.isArray(value)) { if (value.__isHogTuple) { return 'tuple' } return 'array' + } else if (typeof value === 'object') { return 'object' + } else if (typeof value === 'number') { return Number.isInteger(value) ? 'integer' : 'float' + } else if (typeof value === 'string') { return 'string' + } else if (typeof value === 'boolean') { return 'boolean' } + return 'unknown' +} +""", + ["__isHogDateTime", "__isHogDate", "__isHogError"], + ], + "__DateTimeToString": [ + r"""function __DateTimeToString(dt) { + if (__isHogDateTime(dt)) { + const date = new Date(dt.dt * 1000); + const timeZone = dt.zone || 'UTC'; + const milliseconds = Math.floor(dt.dt * 1000 % 1000); + const options = { timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + const formatter = new Intl.DateTimeFormat('en-US', options); + const parts = formatter.formatToParts(date); + let year, month, day, hour, minute, second; + for (const part of parts) { + switch (part.type) { + case 'year': year = part.value; break; + case 'month': month = part.value; break; + case 'day': day = part.value; break; + case 'hour': hour = part.value; break; + case 'minute': minute = part.value; break; + case 'second': second = part.value; break; + default: break; + } + } + const getOffset = (date, timeZone) => { + const tzDate = new Date(date.toLocaleString('en-US', { timeZone })); + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const offset = (tzDate - utcDate) / 60000; // in minutes + const sign = offset >= 0 ? '+' : '-'; + const absOffset = Math.abs(offset); + const hours = Math.floor(absOffset / 60); + const minutes = absOffset % 60; + return `${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + }; + let offset = 'Z'; + if (timeZone !== 'UTC') { + offset = getOffset(date, timeZone); + } + let isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + isoString += `.${milliseconds.toString().padStart(3, '0')}`; + isoString += offset; + return isoString; + } +} + """, + [], + ], + "__STLToString": [ + r"""function __STLToString(arg) { + if (arg && __isHogDate(arg)) { return `${arg.year}-${arg.month.toString().padStart(2, '0')}-${arg.day.toString().padStart(2, '0')}`; } + else if (arg && __isHogDateTime(arg)) { return __DateTimeToString(arg); } + return __printHogStringOutput(arg); }""", + ["__isHogDate", "__isHogDateTime", "__printHogStringOutput", "__DateTimeToString"], + ], + "__isHogDate": [ + """function __isHogDate(obj) { return obj && obj.__hogDate__ === true }""", + [], + ], + "__isHogDateTime": [ + """function __isHogDateTime(obj) { return obj && obj.__hogDateTime__ === true }""", + [], + ], + "__toHogDate": [ + """function __toHogDate(year, month, day) { return { __hogDate__: true, year: year, month: month, day: day, } }""", + [], + ], + "__toHogDateTime": [ + """function __toHogDateTime(timestamp, zone) { + if (__isHogDate(timestamp)) { + const date = new Date(Date.UTC(timestamp.year, timestamp.month - 1, timestamp.day)); + const dt = date.getTime() / 1000; + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; + } + return { __hogDateTime__: true, dt: timestamp, zone: zone || 'UTC' }; }""", + ["__isHogDate"], + ], + "__now": [ + """function __now(zone) { return __toHogDateTime(Date.now() / 1000, zone) }""", + ["__toHogDateTime"], + ], + "__toUnixTimestamp": [ + """function __toUnixTimestamp(input, zone) { + if (__isHogDateTime(input)) { return input.dt; } + if (__isHogDate(input)) { return __toHogDateTime(input).dt; } + const date = new Date(input); + if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } + return Math.floor(date.getTime() / 1000);}""", + ["__isHogDateTime", "__isHogDate", "__toHogDateTime"], + ], + "__fromUnixTimestamp": [ + """function __fromUnixTimestamp(input) { return __toHogDateTime(input) }""", + ["__toHogDateTime"], + ], + "__toUnixTimestampMilli": [ + """function __toUnixTimestampMilli(input, zone) { return __toUnixTimestamp(input, zone) * 1000 }""", + ["__toUnixTimestamp"], + ], + "__fromUnixTimestampMilli": [ + """function __fromUnixTimestampMilli(input) { return __toHogDateTime(input / 1000) }""", + ["__toHogDateTime"], + ], + "__toTimeZone": [ + """function __toTimeZone(input, zone) { if (!__isHogDateTime(input)) { throw new Error('Expected a DateTime') }; return { ...input, zone }}""", + ["__isHogDateTime"], + ], + "__toDate": [ + """function __toDate(input) { let date; + if (typeof input === 'number') { date = new Date(input * 1000); } else { date = new Date(input); } + if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } + return { __hogDate__: true, year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate() }; }""", + [], + ], + "__toDateTime": [ + """function __toDateTime(input, zone) { let dt; + if (typeof input === 'number') { dt = input; } + else { const date = new Date(input); if (isNaN(date.getTime())) { throw new Error('Invalid date input'); } dt = date.getTime() / 1000; } + return { __hogDateTime__: true, dt: dt, zone: zone || 'UTC' }; }""", + [], + ], + "__formatDateTime": [ + """function __formatDateTime(input, format, zone) { + if (!__isHogDateTime(input)) { throw new Error('Expected a DateTime'); } + if (!format) { throw new Error('formatDateTime requires at least 2 arguments'); } + const timestamp = input.dt * 1000; + let date = new Date(timestamp); + if (!zone) { zone = 'UTC'; } + const padZero = (num, len = 2) => String(num).padStart(len, '0'); + const padSpace = (num, len = 2) => String(num).padStart(len, ' '); + const getDateComponent = (type, options = {}) => { + const formatter = new Intl.DateTimeFormat('en-US', { ...options, timeZone: zone }); + const parts = formatter.formatToParts(date); + const part = parts.find(p => p.type === type); + return part ? part.value : ''; + }; + const getNumericComponent = (type, options = {}) => { + const value = getDateComponent(type, options); + return parseInt(value, 10); + }; + const getWeekNumber = (d) => { + const dateInZone = new Date(d.toLocaleString('en-US', { timeZone: zone })); + const target = new Date(Date.UTC(dateInZone.getFullYear(), dateInZone.getMonth(), dateInZone.getDate())); + const dayNr = (target.getUTCDay() + 6) % 7; + target.setUTCDate(target.getUTCDate() - dayNr + 3); + const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4)); + const weekNumber = 1 + Math.round(((target - firstThursday) / 86400000 - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7); + return weekNumber; + }; + const getDayOfYear = (d) => { + const startOfYear = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); + const dateInZone = new Date(d.toLocaleString('en-US', { timeZone: zone })); + const diff = dateInZone - startOfYear; + return Math.floor(diff / 86400000) + 1; + }; + // Token mapping with corrections + const tokens = { + '%a': () => getDateComponent('weekday', { weekday: 'short' }), + '%b': () => getDateComponent('month', { month: 'short' }), + '%c': () => padZero(getNumericComponent('month', { month: '2-digit' })), + '%C': () => getDateComponent('year', { year: '2-digit' }), + '%d': () => padZero(getNumericComponent('day', { day: '2-digit' })), + '%D': () => { + const month = padZero(getNumericComponent('month', { month: '2-digit' })); + const day = padZero(getNumericComponent('day', { day: '2-digit' })); + const year = getDateComponent('year', { year: '2-digit' }); + return `${month}/${day}/${year}`; + }, + '%e': () => padSpace(getNumericComponent('day', { day: 'numeric' })), + '%F': () => { + const year = getNumericComponent('year', { year: 'numeric' }); + const month = padZero(getNumericComponent('month', { month: '2-digit' })); + const day = padZero(getNumericComponent('day', { day: '2-digit' })); + return `${year}-${month}-${day}`; + }, + '%g': () => getDateComponent('year', { year: '2-digit' }), + '%G': () => getNumericComponent('year', { year: 'numeric' }), + '%h': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })), + '%H': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: false })), + '%i': () => padZero(getNumericComponent('minute', { minute: '2-digit' })), + '%I': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })), + '%j': () => padZero(getDayOfYear(date), 3), + '%k': () => padSpace(getNumericComponent('hour', { hour: 'numeric', hour12: false })), + '%l': () => padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })), + '%m': () => padZero(getNumericComponent('month', { month: '2-digit' })), + '%M': () => getDateComponent('month', { month: 'long' }), + '%n': () => '\\n', + '%p': () => getDateComponent('dayPeriod', { hour: 'numeric', hour12: true }), + '%r': () => { + const hour = padZero(getNumericComponent('hour', { hour: '2-digit', hour12: true })); + const minute = padZero(getNumericComponent('minute', { minute: '2-digit' })); + const second = padZero(getNumericComponent('second', { second: '2-digit' })); + const period = getDateComponent('dayPeriod', { hour: 'numeric', hour12: true }); + return `${hour}:${minute} ${period}`; + }, + '%R': () => { + const hour = padZero(getNumericComponent('hour', { hour: '2-digit', hour12: false })); + const minute = padZero(getNumericComponent('minute', { minute: '2-digit' })); + return `${hour}:${minute}`; + }, + '%s': () => padZero(getNumericComponent('second', { second: '2-digit' })), + '%S': () => padZero(getNumericComponent('second', { second: '2-digit' })), + '%t': () => '\\t', + '%T': () => { + const hour = padZero(getNumericComponent('hour', { hour: '2-digit', hour12: false })); + const minute = padZero(getNumericComponent('minute', { minute: '2-digit' })); + const second = padZero(getNumericComponent('second', { second: '2-digit' })); + return `${hour}:${minute}:${second}`; + }, + '%u': () => { + let day = getDateComponent('weekday', { weekday: 'short' }); + const dayMap = { 'Mon': '1', 'Tue': '2', 'Wed': '3', 'Thu': '4', 'Fri': '5', 'Sat': '6', 'Sun': '7' }; + return dayMap[day]; + }, + '%V': () => padZero(getWeekNumber(date)), + '%w': () => { + let day = getDateComponent('weekday', { weekday: 'short' }); + const dayMap = { 'Sun': '0', 'Mon': '1', 'Tue': '2', 'Wed': '3', 'Thu': '4', 'Fri': '5', 'Sat': '6' }; + return dayMap[day]; + }, + '%W': () => getDateComponent('weekday', { weekday: 'long' }), + '%y': () => getDateComponent('year', { year: '2-digit' }), + '%Y': () => getNumericComponent('year', { year: 'numeric' }), + '%z': () => { + if (zone === 'UTC') { + return '+0000'; + } else { + const formatter = new Intl.DateTimeFormat('en-US', { + timeZone: zone, + timeZoneName: 'shortOffset', + }); + const parts = formatter.formatToParts(date); + const offsetPart = parts.find(part => part.type === 'timeZoneName'); + if (offsetPart && offsetPart.value) { + const offsetValue = offsetPart.value; + const match = offsetValue.match(/GMT([+-]\\d{1,2})(?::(\\d{2}))?/); + if (match) { + const sign = match[1][0]; + const hours = padZero(Math.abs(parseInt(match[1], 10))); + const minutes = padZero(match[2] ? parseInt(match[2], 10) : 0); + return `${sign}${hours}${minutes}`; + } + } + return ''; + } + }, + '%%': () => '%', + }; + + // Replace tokens in the format string + let result = ''; + let i = 0; + while (i < format.length) { + if (format[i] === '%') { + const token = format.substring(i, i + 2); + if (tokens[token]) { + result += tokens[token](); + i += 2; + } else { + // If token not found, include '%' and move to next character + result += format[i]; + i += 1; + } + } else { + result += format[i]; + i += 1; + } + } + + return result; +} +""", + ["__isHogDateTime"], + ], + "__printHogStringOutput": [ + """function __printHogStringOutput(obj) { if (typeof obj === 'string') { return obj } return __printHogValue(obj) } """, + ["__printHogValue"], + ], + "__printHogValue": [ + """ +function __printHogValue(obj, marked = new Set()) { + if (typeof obj === 'object' && obj !== null && obj !== undefined) { + if (marked.has(obj) && !__isHogDateTime(obj) && !__isHogDate(obj) && !__isHogError(obj)) { return 'null'; } + marked.add(obj); + try { + if (Array.isArray(obj)) { + if (obj.__isHogTuple) { return obj.length < 2 ? `tuple(${obj.map((o) => __printHogValue(o, marked)).join(', ')})` : `(${obj.map((o) => __printHogValue(o, marked)).join(', ')})`; } + return `[${obj.map((o) => __printHogValue(o, marked)).join(', ')}]`; + } + if (__isHogDateTime(obj)) { const millis = String(obj.dt); return `DateTime(${millis}${millis.includes('.') ? '' : '.0'}, ${__escapeString(obj.zone)})`; } + if (__isHogDate(obj)) return `Date(${obj.year}, ${obj.month}, ${obj.day})`; + if (__isHogError(obj)) { return `${String(obj.type)}(${__escapeString(obj.message)}${obj.payload ? `, ${__printHogValue(obj.payload, marked)}` : ''})`; } + if (obj instanceof Map) { return `{${Array.from(obj.entries()).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; } + return `{${Object.entries(obj).map(([key, value]) => `${__printHogValue(key, marked)}: ${__printHogValue(value, marked)}`).join(', ')}}`; + } finally { + marked.delete(obj); + } + } else if (typeof obj === 'boolean') return obj ? 'true' : 'false'; + else if (obj === null || obj === undefined) return 'null'; + else if (typeof obj === 'string') return __escapeString(obj); + if (typeof obj === 'function') return `fn<${__escapeIdentifier(obj.name || 'lambda')}(${obj.length})>`; + return obj.toString(); +} +""", + [ + "__isHogDateTime", + "__isHogDate", + "__isHogError", + "__escapeString", + "__escapeIdentifier", + ], + ], + "__escapeString": [ + """ +function __escapeString(value) { + const singlequoteEscapeCharsMap = { '\\b': '\\\\b', '\\f': '\\\\f', '\\r': '\\\\r', '\\n': '\\\\n', '\\t': '\\\\t', '\\0': '\\\\0', '\\v': '\\\\v', '\\\\': '\\\\\\\\', "'": "\\\\'" } + return `'${value.split('').map((c) => singlequoteEscapeCharsMap[c] || c).join('')}'`; +} +""", + [], + ], + "__escapeIdentifier": [ + """ +function __escapeIdentifier(identifier) { + const backquoteEscapeCharsMap = { '\\b': '\\\\b', '\\f': '\\\\f', '\\r': '\\\\r', '\\n': '\\\\n', '\\t': '\\\\t', '\\0': '\\\\0', '\\v': '\\\\v', '\\\\': '\\\\\\\\', '`': '\\\\`' } + if (typeof identifier === 'number') return identifier.toString(); + if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier)) return identifier; + return `\\`${identifier.split('').map((c) => backquoteEscapeCharsMap[c] || c).join('')}\\``; +} +""", + [], + ], + "__newHogError": [ + """ +function __newHogError(type, message, payload) { + let error = new Error(message || 'An error occurred'); + error.__hogError__ = true + error.type = type + error.payload = payload + return error +} +""", + [], + ], + "__isHogError": [ + """function __isHogError(obj) {return obj && obj.__hogError__ === true}""", + [], + ], + "__getNestedValue": [ + """ +function __getNestedValue(obj, path, allowNull = false) { + let current = obj + for (const key of path) { + if (current == null) { + return null + } + if (current instanceof Map) { + current = current.get(key) + } else if (typeof current === 'object' && current !== null) { + current = current[key] + } else { + return null + } + } + if (current === null && !allowNull) { + return null + } + return current +} +""", + [], + ], + "__like": [ + """ +function __like(str, pattern, caseInsensitive = false) { + if (caseInsensitive) { + str = str.toLowerCase() + pattern = pattern.toLowerCase() + } + pattern = String(pattern) + .replaceAll(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&') + .replaceAll('%', '.*') + .replaceAll('_', '.') + return new RegExp(pattern).test(str) +} +""", + [], + ], + "__getProperty": [ + """ +function __getProperty(objectOrArray, key, nullish) { + if ((nullish && !objectOrArray) || key === 0) { return null } + if (Array.isArray(objectOrArray)) { + return key > 0 ? objectOrArray[key - 1] : objectOrArray[objectOrArray.length + key] + } else { + return objectOrArray[key] + } +} +""", + [], + ], + "__setProperty": [ + """ +function __setProperty(objectOrArray, key, value) { + if (Array.isArray(objectOrArray)) { + if (key > 0) { + objectOrArray[key - 1] = value + } else { + objectOrArray[objectOrArray.length + key] = value + } + } else { + objectOrArray[key] = value + } + return objectOrArray +} +""", + [], + ], + "__lambda": [ + """function __lambda (fn) { return fn }""", + [], + ], +} + + +def import_stl_functions(requested_functions): + """ + Given a list of requested function names, returns a string containing the code + for these functions and all their dependencies, in an order suitable for evaluation. + """ + + # Set to keep track of all required functions + required_functions = set() + visited = set() + + # Recursive function to find all dependencies + def dfs(func_name): + if func_name in visited: + return + visited.add(func_name) + if func_name not in STL_FUNCTIONS: + raise ValueError(f"Function '{func_name}' is not defined.") + _, dependencies = STL_FUNCTIONS[func_name] + for dep in sorted(dependencies): + dfs(dep) + required_functions.add(func_name) + + # Start DFS from each requested function + for func in requested_functions: + dfs(func) + + # Build the dependency graph + dependency_graph = {} + for func in sorted(required_functions): + _, dependencies = STL_FUNCTIONS[func] + dependency_graph[func] = dependencies + + # Perform topological sort + def topological_sort(graph): + visited = set() + temp_mark = set() + result = [] + + def visit(node): + if node in visited: + return + if node in temp_mark: + raise ValueError(f"Circular dependency detected involving {node}") + temp_mark.add(node) + for neighbor in sorted(graph.get(node, [])): + visit(neighbor) + temp_mark.remove(node) + visited.add(node) + result.append(node) + + for node in sorted(graph): + visit(node) + return result[::-1] # reverse the list to get correct order + + sorted_functions = topological_sort(dependency_graph) + + # Build the final code + code_pieces = [] + for func in sorted_functions: + code, _ = STL_FUNCTIONS[func] + code_pieces.append(str(code).strip()) + + return "\n".join(code_pieces) diff --git a/posthog/hogql/test/test_bytecode.py b/posthog/hogql/compiler/test/test_bytecode.py similarity index 99% rename from posthog/hogql/test/test_bytecode.py rename to posthog/hogql/compiler/test/test_bytecode.py index 860acb7cdec..be2c65008cc 100644 --- a/posthog/hogql/test/test_bytecode.py +++ b/posthog/hogql/compiler/test/test_bytecode.py @@ -1,6 +1,6 @@ import pytest -from posthog.hogql.bytecode import to_bytecode, execute_hog, create_bytecode +from posthog.hogql.compiler.bytecode import to_bytecode, execute_hog, create_bytecode from hogvm.python.operation import Operation as op, HOGQL_BYTECODE_IDENTIFIER as _H, HOGQL_BYTECODE_VERSION from posthog.hogql.errors import NotImplementedError, QueryError from posthog.hogql.parser import parse_program diff --git a/posthog/hogql/compiler/test/test_javascript.py b/posthog/hogql/compiler/test/test_javascript.py new file mode 100644 index 00000000000..b6848a664fd --- /dev/null +++ b/posthog/hogql/compiler/test/test_javascript.py @@ -0,0 +1,227 @@ +from posthog.hogql.compiler.javascript import JavaScriptCompiler, Local, _sanitize_identifier, to_js_program, to_js_expr +from posthog.hogql.errors import NotImplementedError, QueryError +from posthog.hogql import ast +from posthog.test.base import BaseTest + + +class TestSanitizeIdentifier(BaseTest): + def test_valid_identifiers(self): + self.assertEqual(_sanitize_identifier("validName"), "validName") + self.assertEqual(_sanitize_identifier("_validName123"), "_validName123") + + def test_keywords(self): + self.assertEqual(_sanitize_identifier("await"), "__x_await") + self.assertEqual(_sanitize_identifier("class"), "__x_class") + + def test_internal_conflicts(self): + self.assertEqual(_sanitize_identifier("__x_internal"), "__x___x_internal") + + def test_invalid_identifiers(self): + self.assertEqual(_sanitize_identifier("123invalid"), '["123invalid"]') + self.assertEqual(_sanitize_identifier("invalid-name"), '["invalid-name"]') + + def test_integer_identifiers(self): + self.assertEqual(_sanitize_identifier(123), '["123"]') + + +class TestJavaScript(BaseTest): + def test_javascript_create_basic_expressions(self): + self.assertEqual(to_js_expr("1 + 2"), "(1 + 2)") + self.assertEqual(to_js_expr("1 and 2"), "!!(1 && 2)") + self.assertEqual(to_js_expr("1 or 2"), "!!(1 || 2)") + self.assertEqual(to_js_expr("not true"), "(!true)") + self.assertEqual(to_js_expr("1 < 2"), "(1 < 2)") + self.assertEqual(to_js_expr("properties.bla"), '__getProperty(__getGlobal("properties"), "bla", true)') + + def test_javascript_string_functions(self): + self.assertEqual(to_js_expr("concat('a', 'b')"), 'concat("a", "b")') + self.assertEqual(to_js_expr("lower('HELLO')"), 'lower("HELLO")') + self.assertEqual(to_js_expr("upper('hello')"), 'upper("hello")') + self.assertEqual(to_js_expr("reverse('abc')"), 'reverse("abc")') + + def test_arithmetic_operations(self): + self.assertEqual(to_js_expr("3 - 1"), "(3 - 1)") + self.assertEqual(to_js_expr("2 * 3"), "(2 * 3)") + self.assertEqual(to_js_expr("5 / 2"), "(5 / 2)") + self.assertEqual(to_js_expr("10 % 3"), "(10 % 3)") + + def test_comparison_operations(self): + self.assertEqual(to_js_expr("3 = 4"), "(3 == 4)") + self.assertEqual(to_js_expr("3 != 4"), "(3 != 4)") + self.assertEqual(to_js_expr("3 < 4"), "(3 < 4)") + self.assertEqual(to_js_expr("3 <= 4"), "(3 <= 4)") + self.assertEqual(to_js_expr("3 > 4"), "(3 > 4)") + self.assertEqual(to_js_expr("3 >= 4"), "(3 >= 4)") + + def test_javascript_create_query_error(self): + with self.assertRaises(QueryError) as e: + to_js_expr("1 in cohort 2") + self.assertIn( + "Can't use cohorts in real-time filters. Please inline the relevant expressions", str(e.exception) + ) + + def test_scope_errors(self): + compiler = JavaScriptCompiler(locals=[Local(name="existing_var", depth=0)]) + compiler._start_scope() + compiler._declare_local("new_var") + with self.assertRaises(QueryError): + compiler._declare_local("new_var") + compiler._end_scope() + + def test_arithmetic_operation(self): + code = to_js_expr("3 + 5 * (10 / 2) - 7") + self.assertEqual(code, "((3 + (5 * (10 / 2))) - 7)") + + def test_comparison(self): + code = to_js_expr("1 in 2") + self.assertEqual(code, "(2.includes(1))") + + def test_if_else(self): + code = to_js_program("if (1 < 2) { return true } else { return false }") + expected_code = "if ((1 < 2)) {\n return true;\n} else {\n return false;\n}" + self.assertEqual(code.strip(), expected_code.strip()) + + def test_declare_local(self): + compiler = JavaScriptCompiler() + compiler._declare_local("a_var") + self.assertIn("a_var", [local.name for local in compiler.locals]) + + def test_visit_return_statement(self): + compiler = JavaScriptCompiler() + code = compiler.visit_return_statement(ast.ReturnStatement(expr=ast.Constant(value="test"))) + self.assertEqual(code, 'return "test";') + + def test_not_implemented_visit_select_query(self): + with self.assertRaises(NotImplementedError) as e: + to_js_expr("(select 1)") + self.assertEqual(str(e.exception), "JavaScriptCompiler does not support SelectQuery") + + def test_throw_statement(self): + compiler = JavaScriptCompiler() + code = compiler.visit_throw_statement(ast.ThrowStatement(expr=ast.Constant(value="Error!"))) + self.assertEqual(code, 'throw "Error!";') + + def test_visit_dict(self): + code = to_js_expr("{'key1': 'value1', 'key2': 'value2'}") + self.assertEqual(code, '{"key1": "value1", "key2": "value2"}') + + def test_visit_array(self): + code = to_js_expr("[1, 2, 3, 4]") + self.assertEqual(code, "[1, 2, 3, 4]") + + def test_visit_lambda(self): + code = to_js_expr("x -> x + 1") + self.assertTrue(code.startswith("__lambda((x) => (x + 1))")) + + def test_inlined_stl(self): + compiler = JavaScriptCompiler() + compiler.inlined_stl.add("concat") + stl_code = compiler.get_inlined_stl() + self.assertIn("function concat", stl_code) + + def test_sanitize_keywords(self): + self.assertEqual(_sanitize_identifier("for"), "__x_for") + self.assertEqual(_sanitize_identifier("await"), "__x_await") + + def test_json_parse(self): + code = to_js_expr('jsonParse(\'{"key": "value"}\')') + self.assertEqual(code, 'jsonParse("{\\"key\\": \\"value\\"}")') + + def test_javascript_create_2(self): + self.assertEqual(to_js_expr("1 + 2"), "(1 + 2)") + self.assertEqual(to_js_expr("1 and 2"), "!!(1 && 2)") + self.assertEqual(to_js_expr("1 or 2"), "!!(1 || 2)") + self.assertEqual(to_js_expr("1 or (2 and 1) or 2"), "!!(1 || !!(2 && 1) || 2)") + self.assertEqual(to_js_expr("(1 or 2) and (1 or 2)"), "!!(!!(1 || 2) && !!(1 || 2))") + self.assertEqual(to_js_expr("not true"), "(!true)") + self.assertEqual(to_js_expr("true"), "true") + self.assertEqual(to_js_expr("false"), "false") + self.assertEqual(to_js_expr("null"), "null") + self.assertEqual(to_js_expr("3.14"), "3.14") + self.assertEqual(to_js_expr("properties.bla"), '__getProperty(__getGlobal("properties"), "bla", true)') + self.assertEqual(to_js_expr("concat('arg', 'another')"), 'concat("arg", "another")') + self.assertEqual( + to_js_expr("ifNull(properties.email, false)"), + '(__getProperty(__getGlobal("properties"), "email", true) ?? false)', + ) + self.assertEqual(to_js_expr("1 in 2"), "(2.includes(1))") + self.assertEqual(to_js_expr("1 not in 2"), "(!2.includes(1))") + self.assertEqual(to_js_expr("match('test', 'e.*')"), 'match("test", "e.*")') + self.assertEqual(to_js_expr("not('test')"), '(!"test")') + self.assertEqual(to_js_expr("or('test', 'test2')"), '("test" || "test2")') + self.assertEqual(to_js_expr("and('test', 'test2')"), '("test" && "test2")') + + def test_javascript_code_generation(self): + js_code = to_js_program(""" + fun fibonacci(number) { + if (number < 2) { + return number; + } else { + return fibonacci(number - 1) + fibonacci(number - 2); + } + } + return fibonacci(6); + """) + expected_js = """function fibonacci(number) { + if ((number < 2)) { + return number; + } else { + return (fibonacci((number - 1)) + fibonacci((number - 2))); + } +} +return fibonacci(6);""" + self.assertEqual(js_code.strip(), expected_js.strip()) + + def test_javascript_hogqlx(self): + code = to_js_expr("") + self.assertEqual(code.strip(), '{"__hx_tag": "Sparkline", "data": [1, 2, 3]}') + + def test_sanitized_function_names(self): + code = to_js_expr("typeof('test')") + self.assertEqual(code, '__x_typeof("test")') + + def test_function_name_sanitization(self): + code = to_js_expr("Error('An error occurred')") + self.assertEqual(code, '__x_Error("An error occurred")') + + def test_ilike(self): + code = to_js_expr("'hello' ilike '%ELLO%'") + self.assertEqual(code, 'ilike("hello", "%ELLO%")') + + def test_not_ilike(self): + code = to_js_expr("'hello' not ilike '%ELLO%'") + self.assertEqual(code, '!ilike("hello", "%ELLO%")') + + def test_regex(self): + code = to_js_expr("'hello' =~ 'h.*o'") + self.assertEqual(code, 'new RegExp("h.*o").test("hello")') + + def test_not_regex(self): + code = to_js_expr("'hello' !~ 'h.*o'") + self.assertEqual(code, '!(new RegExp("h.*o").test("hello"))') + + def test_i_regex(self): + code = to_js_expr("'hello' =~* 'H.*O'") + self.assertEqual(code, 'new RegExp("H.*O", "i").test("hello")') + + def test_not_i_regex(self): + code = to_js_expr("'hello' !~* 'H.*O'") + self.assertEqual(code, '!(new RegExp("H.*O", "i").test("hello"))') + + def test_array_access(self): + code = to_js_expr("array[2]") + self.assertEqual(code, '__getProperty(__getGlobal("array"), 2, false)') + + def test_tuple_access(self): + code = to_js_expr("(1, 2, 3).2") + self.assertEqual(code, "__getProperty(tuple(1, 2, 3), 2, false)") + + def test_function_assignment_error(self): + compiler = JavaScriptCompiler() + with self.assertRaises(QueryError) as context: + compiler.visit_variable_assignment( + ast.VariableAssignment(left=ast.Field(chain=["globalVar"]), right=ast.Constant(value=42)) + ) + self.assertIn( + 'Variable "globalVar" not declared in this scope. Cannot assign to globals.', str(context.exception) + ) diff --git a/posthog/hogql/metadata.py b/posthog/hogql/metadata.py index fdfaa8bcde7..9498c809d02 100644 --- a/posthog/hogql/metadata.py +++ b/posthog/hogql/metadata.py @@ -2,7 +2,7 @@ from typing import Optional, cast from django.conf import settings -from posthog.hogql.bytecode import create_bytecode +from posthog.hogql.compiler.bytecode import create_bytecode from posthog.hogql.context import HogQLContext from posthog.hogql.errors import ExposedHogQLError from posthog.hogql.filters import replace_filters diff --git a/posthog/models/action/action.py b/posthog/models/action/action.py index e049f7e7e54..d920b0913a7 100644 --- a/posthog/models/action/action.py +++ b/posthog/models/action/action.py @@ -90,7 +90,7 @@ class Action(models.Model): def refresh_bytecode(self): from posthog.hogql.property import action_to_expr - from posthog.hogql.bytecode import create_bytecode + from posthog.hogql.compiler.bytecode import create_bytecode try: new_bytecode = create_bytecode(action_to_expr(self)).bytecode From b03a40ca02022c7b93a81581403c1a4b57d39415 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 18 Nov 2024 14:12:02 +0000 Subject: [PATCH 17/27] chore(data-warehouse): Saving as view shouldn't require aliasing every field (#26219) --- .../nodes/HogQLQuery/HogQLQueryEditor.tsx | 4 +- .../data-warehouse/editor/QueryWindow.tsx | 2 +- posthog/hogql/metadata.py | 27 ++++-- posthog/hogql/test/test_metadata.py | 89 ++++++++++++++++++- .../warehouse/api/test/test_saved_query.py | 2 +- 5 files changed, 111 insertions(+), 13 deletions(-) diff --git a/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx b/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx index 2f6a7ae53e1..37a8c5fce49 100644 --- a/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx +++ b/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx @@ -290,7 +290,7 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element { hasErrors ? error ?? 'Query has errors' : !isValidView - ? 'All fields must have an alias' + ? 'Some fields may need an alias' : '' } data-attr="hogql-query-editor-update-view" @@ -307,7 +307,7 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element { hasErrors ? error ?? 'Query has errors' : !isValidView - ? 'All fields must have an alias' + ? 'Some fields may need an alias' : '' } data-attr="hogql-query-editor-save-as-view" diff --git a/frontend/src/scenes/data-warehouse/editor/QueryWindow.tsx b/frontend/src/scenes/data-warehouse/editor/QueryWindow.tsx index c0dac586cce..c2e9ed092af 100644 --- a/frontend/src/scenes/data-warehouse/editor/QueryWindow.tsx +++ b/frontend/src/scenes/data-warehouse/editor/QueryWindow.tsx @@ -60,7 +60,7 @@ export function QueryWindow(): JSX.Element { onQueryInputChange={runQuery} onSave={saveAsView} saveDisabledReason={ - hasErrors ? error ?? 'Query has errors' : !isValidView ? 'All fields must have an alias' : '' + hasErrors ? error ?? 'Query has errors' : !isValidView ? 'Some fields may need an alias' : '' } />

diff --git a/posthog/hogql/metadata.py b/posthog/hogql/metadata.py index 9498c809d02..de309adf441 100644 --- a/posthog/hogql/metadata.py +++ b/posthog/hogql/metadata.py @@ -2,20 +2,30 @@ from typing import Optional, cast from django.conf import settings +from posthog.hogql import ast from posthog.hogql.compiler.bytecode import create_bytecode from posthog.hogql.context import HogQLContext from posthog.hogql.errors import ExposedHogQLError from posthog.hogql.filters import replace_filters -from posthog.hogql.parser import parse_select, parse_program, parse_expr, parse_string_template +from posthog.hogql.parser import ( + parse_expr, + parse_program, + parse_select, + parse_string_template, +) from posthog.hogql.printer import print_ast from posthog.hogql.query import create_default_modifiers_for_team +from posthog.hogql.resolver_utils import extract_select_queries from posthog.hogql.variables import replace_variables from posthog.hogql.visitor import clone_expr from posthog.hogql_queries.query_runner import get_query_runner from posthog.models import Team -from posthog.hogql.resolver_utils import extract_select_queries -from posthog.schema import HogQLMetadataResponse, HogQLMetadata, HogQLNotice, HogLanguage -from posthog.hogql import ast +from posthog.schema import ( + HogLanguage, + HogQLMetadata, + HogQLMetadataResponse, + HogQLNotice, +) def get_hogql_metadata( @@ -116,8 +126,15 @@ def process_expr_on_table( def is_valid_view(select_query: ast.SelectQuery | ast.SelectSetQuery) -> bool: + """Is not a valid view if: + a) There are any function calls in the select clause + b) There are any wildcard fields in the select clause + """ for query in extract_select_queries(select_query): for field in query.select: - if not isinstance(field, ast.Alias): + if isinstance(field, ast.Call): return False + if isinstance(field, ast.Field): + if field.chain and field.chain[-1] == "*": + return False return True diff --git a/posthog/hogql/test/test_metadata.py b/posthog/hogql/test/test_metadata.py index e19778e6f3f..ca617283b51 100644 --- a/posthog/hogql/test/test_metadata.py +++ b/posthog/hogql/test/test_metadata.py @@ -1,11 +1,12 @@ from typing import Optional -from posthog.hogql.metadata import get_hogql_metadata -from posthog.models import PropertyDefinition, Cohort -from posthog.schema import HogQLMetadata, HogQLMetadataResponse, HogQLQuery, HogLanguage -from posthog.test.base import APIBaseTest, ClickhouseTestMixin from django.test import override_settings +from posthog.hogql.metadata import get_hogql_metadata +from posthog.models import Cohort, PropertyDefinition +from posthog.schema import HogLanguage, HogQLMetadata, HogQLMetadataResponse, HogQLQuery +from posthog.test.base import APIBaseTest, ClickhouseTestMixin + class TestMetadata(ClickhouseTestMixin, APIBaseTest): maxDiff = None @@ -383,3 +384,83 @@ class TestMetadata(ClickhouseTestMixin, APIBaseTest): "errors": [{"end": 17, "fix": None, "message": "Hog function `NONO` is not implemented", "start": 11}], }, ) + + def test_is_valid_view_when_all_fields_have_aliases(self): + metadata = self._select("SELECT event AS event FROM events") + self.assertEqual( + metadata.dict(), + metadata.dict() + | { + "isValid": True, + "isValidView": True, + "query": "SELECT event AS event FROM events", + "errors": [], + }, + ) + + def test_is_valid_view_is_true_when_not_all_fields_have_aliases(self): + metadata = self._select("SELECT event AS event, uuid FROM events") + self.assertEqual( + metadata.dict(), + metadata.dict() + | { + "isValid": True, + "isValidView": True, + "query": "SELECT event AS event, uuid FROM events", + "errors": [], + }, + ) + + def test_is_valid_view_is_false_when_fields_that_are_transformations_dont_have_aliases(self): + metadata = self._select("SELECT toDate(timestamp), count() FROM events GROUP BY toDate(timestamp)") + self.assertEqual( + metadata.dict(), + metadata.dict() + | { + "isValid": True, + "isValidView": False, + "query": "SELECT toDate(timestamp), count() FROM events GROUP BY toDate(timestamp)", + "errors": [], + }, + ) + + def test_is_valid_view_is_true_when_fields_that_are_transformations_have_aliases(self): + metadata = self._select( + "SELECT toDate(timestamp) as timestamp, count() as total_count FROM events GROUP BY timestamp" + ) + self.assertEqual( + metadata.dict(), + metadata.dict() + | { + "isValid": True, + "isValidView": True, + "query": "SELECT toDate(timestamp) as timestamp, count() as total_count FROM events GROUP BY timestamp", + "errors": [], + }, + ) + + def test_is_valid_view_is_false_when_using_asterisk(self): + metadata = self._select("SELECT * FROM events") + self.assertEqual( + metadata.dict(), + metadata.dict() + | { + "isValid": True, + "isValidView": False, + "query": "SELECT * FROM events", + "errors": [], + }, + ) + + def test_is_valid_view_is_false_when_using_scoped_asterisk(self): + metadata = self._select("SELECT e.* FROM events e") + self.assertEqual( + metadata.dict(), + metadata.dict() + | { + "isValid": True, + "isValidView": False, + "query": "SELECT e.* FROM events e", + "errors": [], + }, + ) diff --git a/posthog/warehouse/api/test/test_saved_query.py b/posthog/warehouse/api/test/test_saved_query.py index e739a1d0b5b..6bc7f0c07ac 100644 --- a/posthog/warehouse/api/test/test_saved_query.py +++ b/posthog/warehouse/api/test/test_saved_query.py @@ -124,7 +124,7 @@ class TestSavedQuery(APIBaseTest): }, }, ) - self.assertEqual(saved_view_2_response.status_code, 400, saved_view_2_response.content) + self.assertEqual(saved_view_2_response.status_code, 201, saved_view_2_response.content) def test_create_with_saved_query(self): response = self.client.post( From 938be854201572b6db0bf47fd975a8e1dee60dd4 Mon Sep 17 00:00:00 2001 From: David Newell Date: Mon, 18 Nov 2024 14:34:43 +0000 Subject: [PATCH 18/27] feat: better stacktraces (#26237) --- ...anonymous-error-with-stack-trace--dark.png | Bin 30188 -> 30439 bytes ...nonymous-error-with-stack-trace--light.png | Bin 30335 -> 30521 bytes ...-error-display--importing-module--dark.png | Bin 35916 -> 35556 bytes ...error-display--importing-module--light.png | Bin 36082 -> 35651 bytes ...ize-observer-loop-limit-exceeded--dark.png | Bin 32277 -> 31909 bytes ...ze-observer-loop-limit-exceeded--light.png | Bin 32421 -> 31981 bytes ...ror-display--safari-script-error--dark.png | Bin 29275 -> 28908 bytes ...or-display--safari-script-error--light.png | Bin 29433 -> 28991 bytes ...es-app-errortracking--group-page--dark.png | Bin 105883 -> 104580 bytes ...s-app-errortracking--group-page--light.png | Bin 106113 -> 103792 bytes frontend/src/lib/api.ts | 8 ++ .../lib/components/Errors/ErrorDisplay.scss | 6 ++ .../lib/components/Errors/ErrorDisplay.tsx | 98 +++++++++--------- .../lib/components/Errors/stackFrameLogic.tsx | 30 ++++++ .../lemon-ui/LemonCollapse/LemonCollapse.scss | 5 + .../lemon-ui/LemonCollapse/LemonCollapse.tsx | 34 +++--- 16 files changed, 118 insertions(+), 63 deletions(-) create mode 100644 frontend/src/lib/components/Errors/ErrorDisplay.scss create mode 100644 frontend/src/lib/components/Errors/stackFrameLogic.tsx diff --git a/frontend/__snapshots__/components-errors-error-display--anonymous-error-with-stack-trace--dark.png b/frontend/__snapshots__/components-errors-error-display--anonymous-error-with-stack-trace--dark.png index 202f1a5b6cbf9ccf5aae4bb39947a6d7a9e23ac3..50d668e3f3bf6aeb48cd9c9f052cdefb610fc61f 100644 GIT binary patch delta 10054 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 WmkQ5U%4`QMM6cvt!}FiN`}lwB?Hx=2 delta 9903 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 Bt;GNU diff --git a/frontend/__snapshots__/components-errors-error-display--anonymous-error-with-stack-trace--light.png b/frontend/__snapshots__/components-errors-error-display--anonymous-error-with-stack-trace--light.png index acf86648a2db95b733d1acedcce6b029c78f7173..2f226c7c05f95126729c7b52d7b751d7f63975a2 100644 GIT binary patch delta 10604 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 diff --git a/frontend/__snapshots__/components-errors-error-display--importing-module--dark.png b/frontend/__snapshots__/components-errors-error-display--importing-module--dark.png index 80e85acfb3a2f58a144928ee7f078fcdd6227b4a..67811b05acb58770ce54ed3ae34cc36f2ab4c757 100644 GIT binary patch delta 15074 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 delta 15437 zcmb`u1yogC)Gmw(qJ*R%;SmKSm6TQx5ozfL=~lY8$^itVr1JoWPU$=xrMtVOySvU^ zyzh7K{k}2o{l~c9_!$ghpS9QCYp%8CeC9KsH6L-kBl>y>IW9fUbu26_`x&o$g)nP* zhOFFCI9Q+QbvAHk!rhbq1MLSUX#1oSQLy1d{A;N{@R!Nj-2Gl z6Ikn6^Kp|Uktn12Ve^sQOA}5`r$kNTuAR}=ggD2w;k=Yu_sD#U!(6kROAW`ZOJqzj z`4f8jjoqnLJsSy}m4U4KjV+l`T(YgJBLkNpes@*Fl1#J6vsilN?` zEX{vc)z%4aa8nq4Pr6?EJ=-4_mg-_>!DsY_gynGSI702Y)O<4^gKT1@!`bHVYZtDE z%TrYjQrz67i9&*|huanQE2}?^a^~ItTpU=0qM; z1?J&Q!%!l^hdeOY{PezFQrF>g0A}mRW8LV{q#Zyd%?jFA|hgA zb@qJbj{!OP(#(v!iAnQfXWUZ;$a1jHxPNh@ue3Xndtyc$ zOhMPs?j_Yqm24vaS%*l-=_L;g)?1Iv2~&*w-jYetPmgvZ7qL6MF52RS9UR~v;NXDn z&L8OQ6^1rb3qutOguRN2ik@aist3GbXVT32h9cAFpn!+m#_L#^dN%z`O* zy*nK{J7zm{&NrB9cxY&Me;pF8v-pleZS*9238$xTjJnCohBv81*837T*xQ@-jl7qU zktxyL@BHRhcpvuU#k0z~+j+W2XB;|g-BThe;;!AcX)U(Jf!0INa=++E)q&lzYR+j-!qOX z&?3jV2`3ar(4KQB?RylWA^B=Y*#WzugehUyQ&+Z)_|>7joRpMVTEZvV0tdIYs(J6H z2nkLFr-d30>A-fNhJ|KwKG*eu_|g72u0mXVe7D_s^*4rTw=?YW^0B5kfvbi!Gf*H+M&l2R|kzY9xX$e*XMf zU-$Tu&rZ7LUc_~#ibt%7Zjr)6qtXkg&U z^JVb>vQBNS__d+DxX>NR#kddGzdmAN`8a;4%`r}2eE2?;R@X42yc=~!P;I|CKR@8u zwBITboS=c$hXOi&J{-!U|f@Pd&a~h>~uLB-b!5M z_!&BHD8T)n25Mj6i0OdC--z1|!Ql<>c@Uo}f7*$Xyk>xpjFu(}TlGcvLhos7?Y6GL zQgwvH_+VtL@$Gug^L6$d96uvo*iFgWAd;XZ_NQ%z#>T{=EErQIeJ?hxn!d5Fll}~8 zYAY+mxGVoA2Fo?ONI+XN%s0!CnXmFg)L`3^ULy$Is`WEg}+qjD%9m zxHQz9pB!W)XJzRXXN@tZzHkL0a$%TenJe1$!gz17bl|Re#D;-340m0X%D}vP z3bx-JSh@8ise^RMY1Vh>)gzeUcG9(3KGR{g&HMVVyA!8~*7E+km3seZAuH%5SkB|q1dfG%%-Su*|y3;EbLiIA6fY(t0d)=Z}{}mY6P@OkBLV#L0@BWd9o> z5fxE-dXsr?-KjdCo!rru$n5fn@${574UM)*XT0Nj%jM+-vrdIDGxPZ5WS#~25v~*y zkuD>N>(+$raZlnDN)QG4;B8K!0vK;a<*z9kr&qf*UtXNvd&pxtO=Hs=Hgj=CpsC4w zaN<^-VN#x_IV6|BQTQwA6$!k133zR3T{)YJstD!fe+^7VPJY+BZhk(Tn4!Ccwp+|M z_}Qg}8cDLenv#-MmLj9QXiL3>+}*o(&A7(0hv8;s$8e=8fQ-$g&v0)iqwlCvB6ab+#yP!YFKnqpZ^Xh0;VYk02itFuKdZElvikBTydS5~gn3RUA%@AJ9L zZp(Qn-NS;gWUwk;9WANlO?y?wcGcE`& z50u%X;9T;97B-g18C`1?KYSn}C9PlDLr8fPKEvgED{Odl|2QWGIpv5h#OfG%7zzs;SNYpxA56v6xMzsI06U zFSm;4cS$+Q2k!MK$|OuU>Q3RYE-KlUcH-JEFDu0CozXF{|uTy7L^yxX_YUqhBLM;`Vm1#uACf z$3tT@BCcOF*aDj8A|h?yNSSEY+Isw{GfE*=xhS=qg})fEDz`e@oMVv1@O>Ovl(EPf zB}z+6qokxHXVXcpRe7+=&HwUcIREFK-=5&L4LM>4CSS>rT}H?9=p~Vta)^{t#w?T2 zhq=s+d8_1E3VTW)Ecc>Q-!!d~&c-KDvqRc1WpK=TX*^(#pN-g#-LF7W!wF-~EU^E_1^ddauyHEb_W73{RgnH=@y= zljTKnYIk5%_`FCCkynp4&ji$9Fn#JtA^IP*b5pII9Ub9~AB~KS!7kFOvfs#p5a{DO zapmhXpI&-l9}M^Rb8>UT;PFCEq0MtL@y`!~MJP$3GspSmR{^YbWnBKBLv} zJBNp5u2rsCW-A0Vf`>b!n1waf7*=Lx<~VMXzbJuW78c4}-J>YyDJ@0wUkgj@TAmnT z{l3&fe0;}KS66lQ(bwI&o8u6~_@Zz&jp%Av;WE}!CW^##l!1})=e^_O8K>90MfI(9 zbRy(1m+_=mO%K~E?6~Ry%ad+C z_v&}jdPwmVO#V_N)`fd@p$(sp`RX^L!2iDup#P_51j*t^%J>mqG@=6cQJ%g1#hTo6 zQ?)KeCq>@eeQ)B(I*(4*@7=v~Oh`Mo6_y=Ve0p+A3H_Oj46n>)JbHI$ zZu`E0o!wq$LQs%ZS0Z28(iXMH838G-_h3O959m8PG~h1iFzF@5o;vWS)2M**q9T%w zLQ_3YJNTSvY+<9f-Dt@@7IxLK-Kudl8PTf) z;T0&inx*cz119?UmShyzI&w08anC(VGJp5LZYV0wHU&~EkIL^B_(lxUHV17&qz_M- zc=ne=FCrrYNd#kKiOTJo7i&FSAx~Pk6b1m6NZqJ?qp|8{xATf#5LazE>${Mg#m6KUiphz53w;Er2t0+Tt#B1|L6CVc1r88#xE)0~&EX|B{m& zM>l>*JLIx7{k)viof92WQ67qk=Nsxv7x#Wa%4cpedWNPYsqL2_kQCxaG+sn&pJJDebf#l-WlT}8DDIrm@dTat}b^Yy(;H{x7 z?9vsrUJ%mW^^HaK*r0%idj3 zO^79mLSRlbC0hq`c!|P(A_QH?s81gA^EaJp4F5GE(6< zZToLM16U}gW2v7l*VkreZT`TLum0~FG5_U5PSkm5jF81x-7PzM>G;d#o&FfkbQT>hoArukau?@W#IzH8%F4=>pLUqyIu9v% zAT@36Jc)v@VBah>heIW1{q*HFI&2G{*t9BGNN`a;c#Au2t3%wDJ-^hs|JkRA)w2mK z&Z{p)(eIHe34e9Oe*9Ra74VGZ=d#(9wzA55Eq3|C-ya5_sPYK$?a;@B+I5EN8)07*gqYFj2$D zNyet5@K-_fdzuka_`;{5sWy`4<}I@|(}U$f%-V3u+OW;-Tf#hCT+6(A4-nmG&kJL{ z-*l?vCQK%zl5*WI-RFMnd@muD*>%=GLg#a z8zCX>g8K$KH4qN46B@HTF-q)p`*3_^gH9y<9BF4PXHuwE?-QJC9pQFFd!mER)U#MX zT=^W4!K3)WzM|fMB!(1})8^E4RcGAk`cx~c2*%FZnkHg^j2sFGfY?uUgn1526SUVx zi_?W%&$-w(QQe6*Y?;OvP>l@@&a?9rF)`}?Hz5W%p*p8ZT1H_lCghb75j^DAb_*Py z>c}R$tEr|xSXeOi-6V$B-R5X@Wi-!X=`MLeg_Es8p;~Qic@9~&Aob)}Mw*fQ9b(uM z!N(k&ob8=?sK*j_U@I$#Ot`WuA<6z>XEng)I4}^Y;UOSh5=O}3oJ7aI#p&%IRDJ|C zp<8Gv*rLjfH`0ll33MvY3Bp>{imk(r{lLyps(X*)=W#HWuB<8ku}x%keuQ2~NX$Ox zjd-K`yLXo7n0~!%J2qgIb0z8C48JfFLeU_aDG8j>8W-Q?&sm`g9-`l!-%8;;V`fGQ zcSQ3+3;vCqCerE^dRWx-@D&|@$q5WaEk40Sy(z2%H=%=;e^)^?4B*%-I(^_0^p`~E1c7OO?dHr z?Y1t(#9d+3*@CC1t|{T)e?~@HTa0UjA_oHO7x2D)tI*0nPH(_GJjd7%LGLp^83KSA z86V%5sZgIY><%E%n=`z7`@~^Ca|jhL6|}Xf75d~_TU$vN5(fYElG$5)IcVrn#QPv> z-i3KTF}tO%c(mR#2S#4r0&8tCCS*ipLKvq-mnbPI>BG3idLR5)9*2)+W-IxVKW!-a zM#fonxQ+mGgZHo;^52T0oe+6sT6f%wf9QBWRAKha?P&A$)6f*5gSBB|c0DDu=WG4s zbF#Jq4a%tYYNxHgfa==cx1XF85cZr^)jF36)nVM+Te@yQY_KC_Y@B}U)-8Xkr|<_u z+$19AO6W_ILL^$;o30jG<B)% zM%rfj>Vx$0DgzB}4)FI+PABHF8dH0m9u(A7i<%Oov1!V6q3S{>&bQu?#o==}wFKsf zWL<;q-P;$>DEa&g!QtY*o-@p@w|wPEXFm(bn9;Y?SfkOKDHw|5^L-rZuy( znJiQadit{M<}eJml~}{2uYK))7#%k{R+hp;y}ltW{o~@sHxj=0c;8I_+>~hM0r6JH zAFsEYjs$mbV8D>(rw9iNnZ-dishJtY4Qv7^qt|q8=<=y&3JBC)T|ooJIVwB_2K8he z2yK1o6A3S|I$)8pvJ=mo5-S56qXXY>c@fZmEcq2}0jG_VrTyNMJ>%|ZzF@*xRC|Vn z>e1aLIgm!6e*Nk}g~b7K3lI%oz9e-c?(&y7QNM6kV~!)^tE?1qbC$P(Fz;?ope%Cy z{63qSI-4BHCQJ$_2xO@`&fjE!r>44VRXBSe1+mJ}PNN*wtQ}?ZOC1!0H??hTZB4o~ z9ueZaQ3lK^E&sCJ!5AK8AkTyaqi_9W@zJA$iu{_ZC6gY-E>>J@cYA+p4*>L?j2dN} zr~RAgBUk$^*VFmGdk}ekkLgv)!LEzmymUi6mdI*`GX&9AeA>Y+wSEQYp!1bR?x(O9 ztzBJ?t+OXbw1WPAE>At*UAA;2at}^S*zXRg`}wtk;2y{6R^=<9y1KePhAMX}?`jUF zx#}gjd5@AOy46q%wWxVzQ4jY+r>&urh8;1G6g-CD_ozAExyzb6bX|c^#QV2hl!SyN zWHh7IQA<-E*Z|rAPIY`H7({4|M zP0DeT4c|+(KX~3_vC?-73VQHXXk@&`sM<6#;~WVODYu!{Mt`;d0KBS-zp$`?*K#Z} zBt&VHN9j+Ei_}oQ_G?xh=Fs9ciWtB@u+q!LZqJIhT$}~tz}$|gDFrhzV}s1suO}9d zuJ7;v@VrqI$*TU`umww*G-7#q1iU#=9V0l$ptB`sj`_1Wy0}q`u3YW{T5PE5SCej^m-E&l-OBF{Z{G5$;dfpAsJKQp$Z{L>*Y?V>t4eRB?V1;= zmXv(S(8OV5$^dl9{UPQJkK$Zw=e9`mP@XEfM&{`eG_HtRRrI-LV`YK%Z13u4z<0x2 zB_%txo&KwM`?ilV+f|3}MIF1w(sCFO-L%}f7=+j<89C|bSb6fLxT>OJ4l?ba{b5!n zPf(XWjJ<6fj*y|a?LLvZGR%fRyREstbzM#NsGdf-aN8eeGLhc^{XK;Vm~2cJ+wt-? zLv?l6DHCK(dhWp7zkVUKJ>1RHJh~v2)TB<(E|_wqA~{@~DTG!ZQV@&sJMGnc+Mt0w zVd2p~IJF{*i&P1u#fFz!8aa&~{n^_tU&^1@9H@+A)OaYdWKoW|>0LYJbX=l8={nE_ zv7P3R*C;BbXE_A)_4Snu1oy@9SGl%dLK+ZerTuq^YV{$_3!WEgi58Kn$n&P}N@^Wz z-7k1Ih4FCR_PWKV53M(CtLR=(E(9i@|AL3yM>d^Jxg9>9-AJA@vDz5FDbd(o!;fr| ztvY!0h;hC1D-shO9orgg2`2E-lQPxmufaF!Z6-X%O4Rox6-|WP?t2^z8N{iSK?{LU z8fAeV>BVh))cV;Y#{Gk|hev04R7_*+Rm2bO`G`HtXeQY5!x!>&?#|M7Tisi^%R6K} zp`-r-7*bxe$Zm*T7ZT(si7F{EG0tZ@V)}nfMBh287&|(WWrQp0YZZtz=js%G zI&b;I5;^vh)Zz~8YjZWipfoFUEk8 zfdytbAMJ;1mYb@ys!tN0bT80VFSX9;km7WmNY$r%Yok`|KJtZTYi^oGz(Z0-Tier6 znN<0VCx}>rARy=-#trkr0WUDL{uC7ysPW6$$YoA)ejzW!wprwIU#}bccJR&Mz+Af*P!8qs8lQ*Hkbl(}8)M-v^*yp)T3WJF$B+jedWb`#5mHNj!y`jklau4T zhSqGFFXP@KJ z`@X27)pU4hVtN*&?%V!1oIHlGPLG3NV>}@&!Qt=3ijD_1%@~F^qh!BsR1rHE!D@5P zJa~+olhkV(mfodNYbtBHZ72FpWibOUC#o|MJ>Pf2IqUSz$A=!4y1YiNz&T=B=98Yj z%p;%r04!5Rn2Uw>!TKbEaCQ#0F&Q@;5h%65tn@KEKN(7%QNRBemeQRJV~^#rkbTN{ z=^5OmwV!}?HVTN$uwo*&NB&zaml+}1CbU|jLtQ>hx$tA9WA+m$fxg&xx@QtSd{@>D$xO+ke=2Csq5zA`mzD-6WQ(f*n57``^ma{AV8Ji{)3;5xeH@%Ngop@)B3JNS04r4ky?WcO!wYrRe>r#F!QySy7Ms371=JkzqDjVerO}>O9s&6!%x>P!6DO za^tp(q=fa_IuYf$=wiBGRwc@7ZryCIJ5l&ha66{z6isv5mRndSM*6m;tBr-_*wSM7 zt$oXAn#aUAFL0znlzsE?&aN&dh>fYp=@SWcQK=0xHH>+$KZ@PkDnUC_hCe~rbQ$Ny z4Kcn@QrL^j2rGAQ+oEDzVJKg9`lZkY-GKy-f`URQW7Ek{T6JjzZ03U?6TKn z1-h>@B%}ebtj}V8WE%Ko2t}6+s^}8BLj;l$kncDTgbMu>GGXc9!ZBwZjg8^}W?FDu)CGSc@@5TQd z{6bVjf{2?fbdrs?p*0CQsdC)n10(MBOX0bD^P62pFt~dRc>KNFWP4DXUdz$ab*2IXONIx!I_fnWGXDUt8MGw>`DX zG7Y3u$31pmRjrOyFDL9|ju>GvDmIa!D0e?-YVBXF35MLxTQ0dDmIcHh_|ay4CNtyhX1nsYq@HK+`U>R91-M^gtqfv2!h+S3tf@5U;pHcEK_R^ zxoq*VOfCWo?46vWhpdPCd7aPr9cLdDeBjaaG(357TPui3^)*iAr$dss&O|}0pcogg z`1RZ~C--1lzDJYQncsgYx06dJKzuf>{-rxRHYPIEaZzz%)RYT@x+F5P|3+6X?1$~< zK1mj_xKbS16b*gZJKh#YV`W9zb(LUs$i#ElO|<;s;LVXoehbW!jf048hqbZ;szIQ{ zVXDkRH|h{yr24}xY${;wFF!AorwkNhm^{7_+1fkaNBm$cRCnuuG)q!q9QIJvPV8d1)neld*v`M%kt}vs+Zrn=GP7<1iyuw2X7CU4RJyC%gu6?MjM_27CHbdC=CvB8 zrwDt9hv47B!ujJg<@drX6CC^*_sssmr|0%*T9g^m$|GRjw|`JN{dNc{K_HN{uW0ZRGoJbtjzq|J35Y*8t6EQd(>=nc)DmA(Y3cl|XpXe>h6pFq;Z0Pv zIJj@7g2gU!(Q zK{mob<-LN!=hv^38))OSHHu5$IqmVDa%*2f`D510gZNTq=7)C!ZVxQ^;6bb!r6qu3 zt9qNgL-|5QSB{--PBHLJP7hqN-(vhmqsE94xGPiW>MmV`4m_l#W%<|kJJEO3waU-{ z6O3-IKWEs+oavwRXMhRQrhdg9;Z%AoO>K-H;lMmx+q={?OG`%4Hco2qe)}G)LFh9n zvhLx&Y%%IsUMDEs)O8{4ZU!h>EOsV5yX1Bq=Q$iO>Aj)-{!0Dg30US{S@LNYmT(H558+X@LsK1t^BJEfmj&J!M)?cV_fU7%&EX zC}v2zpPa8W&pVZs<$1o2dfKv;)bjh9M;3=Z?Aji**ahM(?X1DmQ`7#GlUh{uw-pt`5WU7%7AW=X!24uxX<%vjgamhM!sF4*-Jx6^YfH=dks%lti|9EV zR8uxVT|6a46z3T$tJOf}-ybVsZb!RR&rO|mbcDf7$jfJDWJr-lCVrqGqlpRKX&o4V z8jxh@q(XQ^1PT~@b(2Wb94SOhfkJkdWME?N-OKERZP!E6o3%HMUcj~KDpOa zq`IAmY5kGWWsSPsQpY1W&duxE+S*JIdsI)Mf$yBeQNSj)ot6+&k=t+P|6+-5v8CB^oliB$kQioVm*?SLjc zGE!f^S8ue>8y*6vjj}SkbXKIqHN2^xz)MW^h1`a?L|cHU zE>H6%m)VeO*MxX~h74p}sMIKyr&jh(T>R;yN0~C?_%gAhRZc5Ai=6^=$WzXAx%^Qc z;4xoW9SWJG^{)uIxe|(Is$WYX0DtwYi0qCPA|9Hlu%M@ETlUF<+rDoB*E@yT_^e3P@JFJaa`Yr!A;H0 zH8glWI9o1URU1mzc(XDxM3c9{&|@D{pW8J&=TD$HTRn&^jRUA0@JOC>L%jwJPes+$ zqKQQz*#zOJusA6kPoT)>_6HN(b{-@6*i7H-Gs+#Q2}4S3Uj~sGG=$QdE@IV zJyX+})mav%$=1n0LfexzZl=zZn>U4>Ovh^#O~fINna(&TK-~iwl55#}oSo&V2*TZ2 zqj%QUQ%C;%4v*jy+bCAg*|3aDIH95;-Qfc9%ge7fiFqBJPJy^^s# zj*dOt?p2h&2L|wka^FLk`QTDUx+7;|LU1(=ao&wUrWjDIZ=4=%kUrS|1~D0bw0r|b zpS`(t9du^`_6N;mb)oa2_5dCTrz(BlHX|pFO1dF`~;qvnd$6opQfWBCmXI6+E!mYUPNl) zESSicoaH&S=(g8&?ozC!Jr1_~>e`xyChvl+%h8q)5hzBrD5;rgiKsI!M^Eva;mKKNI)P%0qL{1$PSbo z<@}_Oq~ep^6mL6d496}U#03{0-O_n%f1L_t_ zp0i$L#;k-~f^hr7?!@F|B)ev2UYaVeNrF>DXn#FttLt#|z2bhWfRg5WkXs^8&P&ay5#0!WquHG39?-V?2BMq3CC5Mg;=!VYk0sYtSqg5cQ0OWumAvj*!Elt-;CW@f6Ar z2iJXlc_bZ(5;j~Z)P=#&Uk&zTu_Np2=|Igem0)RM!50qqgG@XQVz-iD&{Q?%xd4MN z^cIP8TW z@;hvXDs4RN1|MRPr1q?B%irY_5SXfUSokBP+gye}kO;~SKx*?22a=SLl9N0+u6}qW zEi1*@bK=DcABf|%iMf{!P!Drdx9v-+udiOAj2izMcN5KFVci|N5)*uiV%2;a`|#=k z+jpPa+v7n_4_{GyuAE?2wFwUoUj_x1)#c|8IyyRX&yHw2W6ECwz5AB+6?`6Gi|+mp zP1T+{bX6hvHx&SX{5LWI5zlI6nZUIC{QNq@K8hdHW2qRXYlvGK7)jq73|Fn4MLq#xe*BV6J$G0K{D#<6k)9_|Mg@0+c(&;244aU!U#RX`oR}2 zahU)xlDvh!$NwS6x-#q$ZHxNB!GTG4q5@sArKQFXT3+Lcir(AM?c3a>d&7##%GAQ{ zBU{$uc*NS2lz}RA*DSWnu1MHvSxLJgMChl?oSf=vr+YZ}s@zXjp;J;uwkWrq*#%v7 z18#N+?~LJrwAYDXR=3gFWO>=h{CrttFA)*Z9oXq9X2WP4)9fiEb>0Ww1nZqabgcTX z(We~26cmHQP;YPV&=Ao@uPGP4FP#FYwdRRo59e$13kV2MP&@=m#m|*m9v&Bk25%$6 z!}r(5n}6l&fBZ-UH2ZcIa>1J$+S;)^R&`5zKrUuDWMO2)XWD}$`aLWRSr+MNY^;)_ z!pg~648TTzEh?w7Qe8uXKkCdw#`BiJ*htCpZ~;U>TC9TtviFrdjnaE}?l2cz45&Mn z(CJ$nwPRPmGe|d2R4pjj0jf|Ak+>Ub}ceaHoP<(`qM)NzY zDw%Wu8#72hct}Ypi?<7^fVc72O$-e7R{Ap{SvB`pCUacu*4E?WfuQL0^ps8_s0BI? z=Sza7@i(*|@|H0@d-jZxk+~js^n=DspbCuoupbYrFPld(lPPF+-LTM2*mbI4nqU&)%)ILq6ZaPOA%PZ zRM*g-KbJAk@AfDlVa*WpJ!Bzc2EbEU*{EXp*Y@|8-$_YTJ`Q=5nv%higSINSnzgjG zQASd6Jw2Zs91e!^G;R4N800QWN=o9X#z9$E(B)KGLLx)GpWbGwR#8>8+-fpg=fbty zOXsF9yl8Zt4N91_v$I9JpNL+Gsf){t58M`MiHMqvi>nF$?W zuW(!_sQQXCOpFX7BO)Z5!>2v5vE9%nmjiZxDk_}8$tQ-4GB_cbRA5$}I|jNGlay># zM4NCQbjhbRX~AVPuzleqK*Qwc2PF8ER8$%&DrCgOoTf8a*;rn!&Luvg zo$XV~)}QrkvZ6!(f}9O9SMX9gnU1a!9z(D=Nr_-5N8`^A)&>Kss6A%Jmu6-%zIb6)G2BBy3jrq;ChT$gguywDQFw7S)5O-u z2yoP|gi4s1=K^%SfeycS3CL}*v8%VJl~mhXj(d-TX%#ic%ZTo3TEBg|iyVw@;y>_6WtwVHbqjl@(!PiqVe>ax`+dWP9AuXnWLZO z)?bp7U#pJ>mtWOi0rRjqQOTh5Rsxb}9vGNk?j;@|FAAjO4yVYjsEF3C8_HH(n!|`x zf+Jq~&ua@x#AOO{b1D7Qb$v(k>z*i;A^Yl>hiLop?h1)ad>3x<|xul zW+4|h$i)ZZIFbirjK#zm+q(W z7IrN<)Kz>CZ#f$t?&&@9L0yx#zpsyjoBOka83SjyJmbB) z!OLT%#Ssx{K$r@gJGvI7S#JHb_&E&TX$+2H0J#(JagnO&MK6q)3NEgHeMHY+W)~$( zhDT{?X2xAsRAdI3iBb0r4?pCw|5WcoHa0e<63B{H+Ja@?6mP02($XGNS5pIROHHk< zY;4HMXkG{Eym5Y$5oC?`P~)l(8*u&TB7|$FJ$Z(deQO{0u4=Zva%Sd-a+!#&!qxq& zRh`=E*2T0V93m}9v(*$Bmrz|HAi%e{xCjmg+CytY;>NAZ%MWOx*5>CkbC8NkT2!>O zv}7uqB7ZG;#=E=G7ExVbkJZ<=C-kUiMMqdcpWc~LAf_v&81V1{0d$8jzlA+qi9~@W z$SV=OygntVtu4gKxp(R18wLa$J;Co<=@g6_v^f0%WqR!Di&c6?g1GSjW&n5GSsH-SV4>m9Px!S*bk zeU4d*nOTY^>PTVzX{yF|*^B_4+83Oh8>9Vu+kXvk6LW0jd6}6t7h!~XaI{_D?9G#`|6X>cb;<&9i<*zD#OPXG>YhLL; z;i_J#_wSXIm~>XCnZ(5-lt0w5{Z~Lng|Eu^#C&xXUHudzFfhn{?0(I+{#gN56P021 z_P;}Yz+dGTFg*#NDnuEWo|2N1o)06$0hGi7c~i94yR?7ts-LlS zZ}@4$$3iZyff#9euRq6=d8cx-dnZOlM$@$spDMNf3%YHNdqstht^5A+^4JE~8-{gzxefuBp;{ehC diff --git a/frontend/__snapshots__/components-errors-error-display--importing-module--light.png b/frontend/__snapshots__/components-errors-error-display--importing-module--light.png index bcb070820baf461a531ccfe85cdcfc8c6c2dc89a..046a20b8c39356e2afc66f64566d7f4cd78ee165 100644 GIT binary patch delta 15138 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 SN)7JEk$No;%YF61*e;B(uc9CzEvk)D1ndvae1 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 ZYDbIn<}VevdAAEDE2St|BL3l@{{v6OOw|AY diff --git a/frontend/__snapshots__/components-errors-error-display--resize-observer-loop-limit-exceeded--light.png b/frontend/__snapshots__/components-errors-error-display--resize-observer-loop-limit-exceeded--light.png index 540d3972b08950dd325e67ebe12bc766b2277499..a63f72eabf26ca24dbbbe471e751e2c3c5ef5e24 100644 GIT binary patch delta 12095 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 delta 12538 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 W7n{#iz5^@3Qjk@Jl{|m>_J09XR?C_I diff --git a/frontend/__snapshots__/components-errors-error-display--safari-script-error--dark.png b/frontend/__snapshots__/components-errors-error-display--safari-script-error--dark.png index fa4a28066135fb1040af1668e69b0f31a7b04edb..6b2259c04bc1c75913d99a436d254b543f79b62c 100644 GIT binary patch delta 9525 zcmbVy2Q=K>yRLjG@<|W`(G!9w(M$A1Msz{+8io_cZePx%>TN6jOIEJGkP|0VR?SuDM24C^( zK-D#>x%TtII4i@h^00^9eQ;MdilVC=f#JxDmKMb8(c z`SE(qx!EIM5!q84D;;#q^PN)p3?-!&wjPtOdc44(rj5$%Oxo|U`L4Uczz5jEmJTCCaesS}J0&OG)+x2^% zE;n9fU&u2p@&e))cp5lOeAg+1Z)Ax!CzG5)&S-nrz9yh8)G@ z_yKUZMyfm?2Z6ZHqR@$yRr$8AvGir1GQ!Xi+^IFv_tl% z<6SA(z2!;Io*0?HY2P0#Gi)*65USuXgUs*LEwg*q)z1ztq3nVpDFa z;Jvv%nu^@}`=(RLRJ)DSGhRDp1=d)kJ8-;9*>t?`;o;?fC zo2=4aUM<_U#l-^HxEBV+r(6%$i?^=xIhiD?WlIOjT6e^&<~~myG%K`wrjMAP1Lnw? zWT);!VZV)@xw-a{c3fX$Jmj_uH%eR$1x)_Ho0!hZJ)+6Zzj@_3!kj8QMSRJz`b( zV^unf=WJUSe&3D9)7sk3^Rm<7J%lf&9B|^LMTZ^wGchq)85<+v38mpG56Tl&vZ(Xl z8>tL~JxKV&TiC68Z-hg*;>gz5y9(cTE$$@nCMf2=yk~s*V*WfKL7P3fd6z-n3_mbG-d}k03jtMMLFk@McyYNX)s02Mxp}V01LSB zn)$DaaH621q=p0KXpTdxrc$tcg`74%qF#Squ=W2^qP!c490Tks-`=!9H%@^dMMg&f=ChS z6Khhrq^umO$uz{p+1&h0S-?Wf^6V+9M%Z!BaPt;J{;!to?u}GaSMFBU6X^NRgOJs3 zzro`5-Ls)6EDf~8T>gBjwh4$FXw}$^V%>A`UmIL<1ib&=5OeKr3*XW)6imOdK5D+1 zmwYFeM_fi)+G+H=JkLF@?OEhOTePm^B6tg}$}ixu0-`jd-{2Vg7u?U&#OgA9gA5H> zQ_coE#Q6+Snwpw2KBthgV;85&!O2Wg@Xb)?5Tl$HHzoHi+3ruN0mlw4i;(!VG+|)I zntf#)c=ftj6%_+%o^fl%DIgY#j{5C7H~MRbXO(usf8z0;1gzse+ap=0<|G+k-Nl|% zB?xu++!G&)el;AT*uo+W?JikfnJ8c!pKdAidgSNRP~xFWKfe7APV>%a2`sN6WX~~K z%th8`B5Tx>u1*H99+{95C2uJjx178uqIZwVdF)S=UjP zX=?jp}$e2`Rqoh1&QjVrejNe@XdNpx7TZF#pK!uN%+P~M#{Px?} zQtSUD>gJ2hs9gacXShb!NTthoY;yAcH10%JcEZ`o$wmb3;=)Qbzc3#Tu|~yo-kWwg z-SF|~sK{H|taM?MeMLgWlc1KMmaWI@>EW5kZ!T{;)&|*~YwvG=0TT-KTDg;|5-wzr3a6ea#q5W3svVst@_!7W+pZ z;^PPY&~V2DE8kq3e!kg4L*tj3HK(I!{V6EuW7Ev(`Y{x9Ks<)JSWHbEr6<4U0fA}Y zaSqHW`+3@}-UxcZurU05lG~Men?(^O2IN8N7v^d+uyYgq23^b@`TO$wV?WO70iT;> z1JYS9+6?h1F)Vi^aK3E`gs{no1&oD4nqiom;#U6ku_G(BgB;%?cQy6`6Q#X1!bgAI zVkr29N-JC-?nY{$5J`U-8&f95Y)R61c<$UBZ1uNc?bhbK4Y?oJ9;R|Hk%lU?X^2s^ zpHNf^TWAo?jn3w3%jIgTm+{X7Qc?=1V&Pkg8W0bp#?FLrvbeKu&!9K4v4uLk`BwwD zsmJ2Q%nl>JQbu2mWo;4KvOTK5gmtIY3cdR2w=V4!9T72I=gbkYhpnGR(4*l9#OcWn z=M8z|K92I~%1vK`k@vA@&nWmG@Uwqwjbai$nYJJJ(@SW}X?6`tiIQ7E_994C7SQ?Sp*wpCGJvmX64RELuGzIpn3q5Lvw%$*O$u0X||0wHd0$z`AI zZ9(}R=Rpw=_{;O-klQQQZ;+9dC@Be=9^2zTKfFeJTV00(aSrRm z%b{WlAPc$GOAHG2bvoC2P)Wso1bVojP1rO+=_jC_tjJp zPejYg1kZzez`fXN)7NvG6N9nBARA|d|7Klu52Dz`9&BI2fge{8)HE{QdO*XmcUgO%DSJzm;$SI4PMn=(#no|LW` z57g3P0oX!9gjbmfq$q*!HWE4t(K9fBHDS;d^O&&fan2X*bXmISFem3D30Vtc<7&9~ z_b(=V03RP==V*U_-%KE}X~sxQ1MK%ES^a|eZ7=pH>E;itsaZ_kOi;PMpxJ-1sK*tJ zC;v`5MIR!`0poY6%w5vQxlR?6UNZcuZS3<`vwng3tE7z8o=mw zbabezr@uO*iLf-Pq@8rBds32%2fzF0*{O3hN|VXbb@N)MPgBU0v&qSnT8(oo>{(3e zl3A^f#njV?0fP+Cr4E$0XEBc0UR)i))zj(eHS)XP4iDdtRJ~?rlpQ&>mv{(=Q^vV) zn-*ML*&D`rSBCM1w`XBX5TH4qhFgoO_v_nZ(Mkza0M>c(4igJpaD6B{B3Hp&%<@6G zU0t%|0d%jd;POded$(FD_@Rp_jAaZ9tsIPlM}p5O=`1acbtN@0(Aj5wgqq&($YKly zdKt|lH}=pbv07Dxc^tssY^ry~*&iOkpXF-{oFCZjt=3-kxgHjd%YZk4_aW(D z8`4Ig>Wu*C1sTO19(lG7yuEx(!6clMH5Y4i`mKCdb$v`r!)h{H4~%5N!;_PpXgb~< zt6o*!BZBce#EXLn11S*3Zt3Hb>0-;Sc@KTw1PJ@qmOb&Pti}B4JMKUs^9*gh>>k>o z&KbABF-)eTiV&4*c9}_q1GtjwYqx$cEVMQQW>%7XyFZ$N;NZPa?Kafm?^~?(eG@D6 zMxL~u!Z8coNL7ehc3*pYc)MDK*DBpMVZ(W4^#>jg-Ocl@^}WF$>t*xgNyb&^#opU3 zy3n}qoCwi-3iV%0^OokLdY@btQ}=_z{V_hAF>NP=S5?5{McBjBYd4u=j;pB;aJfZ(=mp_W>1)4BZcZr{D9{K3#@p z0={4ulnK^#sL{1^Bs_*yZe!@7O-E>4L7&wN2Uc+p$neLP;Sg!RZf?yKto;Vzd`HkP z{MFP1(qDeM*@bZ!=QmuvLnrPC%nTO=TPil99M;Q<$z)U@D3hbkv^^@Sv#Le zCgrK32XPE+n)5r(VudC(b2O|m^bGLqfY6WNJ`nHs)wSvf3kI$Wk@=sa7(meE@K=By_s#0crO`vJ78ydn?CVM`Hm>M z9oohbmX}(e9-+Jr*5L5(x6eF!zJ0jY2pbeO1$ZHGE` z?z7a!oVtHOO1;Pj^ajUl&2zl|oS`#Eoc2*!;~;URj%eXcSc%D;sRa&I3wd2#1=){} z5~n|WhzNfGDmA+?FyN7G>yWcdp{&XUQ1s!Qia^Tiz4AyD3qi_(o=Jx{K|sL!os6$u z;>J`a9~FzN*LziwJF$r+*SwbcaJl({KQ*=L;?mN9b{GZ;7iTA1?T-j6R#Kv;PyFtb z=XafoMb1ZYr(uU)fGRdL)DH}xT2pS3tve3;^c~wFx_Z(Q%xk=k8e7ymvEa16tBj}T z$-!Jc{Z&axk5F=h!xwuh^~}A?F1>&7IyzMOm41SkOmNsjCz5L9-kWON$z7Sn9t^!3 zpne1Zuvt;ubgaN4^aARZZ zPuS58EO>8uZ+w$DEV|bCu0-qJmB|wvPR(O=<2f-$?XCo8b=q9u_g&~T)uo6 zq_x(Lj)ekWEj$gBM5-sgH{8r$8+Yde)?R}29}ECv^WmV!tTd3r%Uf>kq@{vj%PL)k zEh;))=z5P?6kwHM-I{Bs=?}Va5QHj7GhwT-5g|;;JJs_mkW|@ddP@DXKw`Viio&9P zk4ZF3Op=1D0kJwkn}p=nJ5|UNJvX;p@aap*$Q&JtC92tiB9uP8wj`iqQm{y=5Q7)3 zwFe*0qpzF3DZ`$RzRb>k0w;yRredOSTho?+P_2&oRTxi>*GK$3b*yfF-$cHig91rx zG6HK?a_KVZ{`w$Bxz;Dpyw+!VtO5_ll-!zW-9bKP>D5y^Axt^^H8k6(uk}|%xk6-?1;BSei z_#7|0{m0Gq_k4bJe^XPCmn=Z^KPNVw9I(N1HVjHksDL{o#MP3zJCBwo9X7!5{ITW_ zu5UkrNU3!+)}pSFo4z`Ox|HWn4|wxzi%{WYtdkbROiO;TN?Mnkde6lB3_3wyxOYM` ztgLV+A$tZ2(O-S$)#5ke3P7VgSRKz*jr08nkzm`O{``s4kZ9_ZXDrahq;&2YMbLE( z`qcnee9Ke|dLgmF)nIoVrB9rc3R#fUHmy+BfC9qUH6ozNz!{a6;-_FphN zQdwDvQ>>-Yfi&AsmOTF=s|msR9oT%9KHJ@~2#55Q*+!607rXluYeLq?j!;H*MK0!v zRZNnD%EB?RKC6t@Su=zgD&7R%qUXS?$8YM5_~rff-z{Jj&dUsW6ZV#R_b{9{SeV~; zMkrMVVy)WtyA;+(jT6Spat6L6CMrXqZIL!)<@?Ti>otQl`pZ5$FhzDM&2))skSxI5 z>WC{hZd|*tl|Kz{n>tgXKsTNapI1(o&%ns16&pVjF!bM>U&Po2l-q0pf59ZsZxa^> zc-Vw|)gRsw0xav=OhNH680p_w6*Ur`33bXf@Tfc^oJJf zF4xT|_4CsRL0U4P1$6sdoUK_o&6YU-I?u(sXru37T-U{|&xems_T3n3y8i%6{q4nz zSq?4cAw*PZhD+f2nZUxOahf*DNlnd12%Gc;!fk!ZPF;=Vmvi%l=aaQDVX*F`$o&u>=)4GsJ3v9DST5gumX!xo}UsV1kV zr?)iH%R2E^ZO>d~^4*NOJO8>l!rV+NE_#GV?| zxDOp2oqM$`hk{X79ZkVW_jUH;faxE;(@ehG1ITZ))~qpx+S;#|{`7(oo9LFFQn2{u znKN+S_*`CH6UUdx*O9I;T@D|&Q%_tS${g<+sXA1R%bnKJidDJa(h@Tih_M=6@us^8 z?sM%o*h$d5l3jeS*h~P}o?C9!G#y4wH~WKv3o^>Qc3e z{^zNk7R!ybTMcXWBfm~kD)_=5$Z$*Yt^P=%xCJ`fYct8(*Brjh&D|CVT_yCN{`!HV z4u|CHiS*E^-0$O5uhX8U1+xNghTjmD=C(l%+wp#a8YPQ7FLn5rFU+aTEPxcVOJLxS z<$k-xPSg0Lq}`lMaD92krP2QiDy&%kuR^K+M&RBUEYTYs+rIkOr5L=e=Ob6KENp^q z#>e(~_E;nK*reCjTLI?IS`Tm|IdCLe>d|#$P|Y*iH7nN5pYqak<)n*fnelLTKJu^Y z!r0l;er`*;Oc+c6W5A-KSw0Z09PUPE#zla7kX{G9Amk9f$*aqo;DLzP?9?Hf~SOg-M@ATK+TSOu+v+6)^QKvTJk{4(zWX>GC^TpGz@by}&? zp9^;OFlaP`C~P1ly0LK}H>AbdI7{({#YOPo`XvG8G`O{BaQD{kQZHy^2|=Wk^@BIg zvvrq=XQY;P5&E($w5%@qFM{~NDE7qJ_-xM0xJ+uQr&NglDy8tnxXjSUS++`nIC_^KzGC1_%$c7BmwC0p0d zZZVvO$VnX@a+7sVcbJodBQDIOVt1KoC|BKWaiJ@P=k|x$S!&$6gni%Z<}fP=7;-M% z_4?T(_^Ln08??2LKZ0t!{@&l-?rd*Q0Msn&-VQZO2LzasGl+!c_YV$=b8}-gQ-*qb z(IK;T(c1@(<5*WCH#crU!5%QbqnRWmz{M3ECMzcwLcu~kQ5~0?tE{CJt-;mrtn<>a z@cU`?)XTN?^+J(_?(Xh5?&p!=;m~VGM>~s6p_E&DdjW@ktX79m*T|WFm1RG-0(5lX zN1ouG+zG7<3Y}~cUT!LhzjHKG!XV%J`gFbZ!Jw+C@!0F{jftu)nfdwo=V`LGE5owB zV9I32%LXCqYy@gejk!vJR$CJ|hUOR*krzjO)`c@UMJTM}O58npJ8b zl%4(D3o4pP|L<0F69za>Qoq6HD%Ma!Ll~#^xph+%zG}-tvKF$tfpg-F^ps zNNHrGrt2wWpnF>I?$=4nME1;Y-#DpNRaEHZ)7fZf?4V6dq6oc-s6)JA@ql;!c$PiQ zq_D6cRMfrm>R(S*hw6ld-T!*~)p>kKH+=UrI6^T)=t1dId;8_18-SFwbmglleyREB z$9MlYj<;5%0jq<2!^O&NVJ)-2(&Rowd`OoMP`mKj*qwvg!{KZY|ItPhwT7<(pZowJ zz+`cwH&Zz|7tD;^ktR5gSJGX-5*wQs_vsUpWMJE5)7ccx3x&zoeh`_?7_4Yz{c^j$ zKDbI+fQcix;@!;FYZEkb_{K%b>1*PT+Har`130Wql2Wqf9bCCmUK=1|jGfDWksGeU zn?R*w-H6I~N-BB+W`$cK5QRjr}rz5M}{ zYasWjacYjm7P$RGcOEJw^O%k4dRN=kc>H{gH)D(fc%Ciw0>Yk(`T6!2$C7uM3fMZT zG-Ey3nDk?hU21Hp=daMM(}fnd!Z0Pu%87{z&owl5x9kJY5RqmA;Q!3R{&!xyX_|*9 zDJlHy=DJ9d`uO-@786=;~y6u1QT6>{GD@KBcb~Z(6L;1J&Ki{ka8{M}a3= zxGf>T7rFMfjbNOm#j!O$K7M2E%IN6minWxKlt!z8fx+k4SSi>p@DsGTeo+xNdH+{g z+iJoAo#Mhf!XDL%pbw*w0LvZzx%v5gtf!~v<-blXeY9VuBp&b{l2Vq9A6N9|4ZW1N znu}ab<1%l39<}@y7lLnnZ8fQ*3lw$y0j2XLkt8%aObJMrqYhUBL88-yS+gmG95e*q z{*8sXIo?me?at);I53U=_#o#F)!F_@Am$xbBNaig!;C_*^y)g&#nP=J!ye7g%uInC zoOsr#+uv7gRt@txP1a!B>Ci9K;f^qR#@Z^jC8gQlQ)L1B;(~jNtHifz&vYOP)3vXW zyphC@V7`Ij;M}&MxtVrKK0<M+@Ogy;y1|Gi((WnN27)Ha>~3{Y##(>>mrlf z3hiF`ZeAmQuV~fJrRi^aB4Q~8$PBZJZ%>Ah<5-xPlf|4*%N=N5nrJZWbdYUKw2zOQ zKDb@!u-spq3OG%W!**SoCzqyBj-VK)m{Dr0p6){wtnbT)OKZpyLMTc~-Ln4@&CF0U zmw;J9^_MS*j{wxu$)xc2g|?#{!@9{ZmI>8<>F(|hu6_#lbni2up`sG6n*HR-TdnA5 z+xdBWdwVqc+WDLCmRT@`v`4mnbXP`3p!>ICvD%>V=wXR++fUjLX&I9sQ6M8D6Ev@p zeWeYs^YZf6dF+|=uug&y7#K)g76l9nln58wr~yF?M7H;eGlagr7r8xib8{jm1Xr#H z`UNhNHDkbV!QRpq0c;Rjo%Oa)i&i+7wVP#-^m-k9DTOsDHiX}MG$|koIe7zondU_l zPt4gA`aCf?s&TC%`D<@m`%W0cx?qKgU;Ge=-OXv=#cnnY*`aE!$#?G*ahBE9gMM<* zjkPsdmx(0sS0g3`im%Bd&Hf=K3}2x54g~Nrc5ukGr1+k>*-8z>yw<|NVqx<%m# zmpj29KSc4XHT`d-iaj>0t?&?+qs=4BRHt%ZV)tPy^G)G@_*_)WXO%2o+EKDAuF{_X zink3~8QN<1sh?gITKH-hY)Ao;Y$Il6Zu)RY$Kv?dpCbtGsZqtK5kFl_8-{j-C!wIM z%!3dt3@m&#$p2?0T%QwtJz)_&i{qnzgF1d_6TDvsmvEa5jI{uw8AzKoWv@Uf7R)aW zum8Krxj?Lno6LfEQ_@9<&+|wA|4EGhUrIU4zqI_xbCQha%)K)T*0qZRQ&rM}6f3@b F_iry@ps4@= delta 9895 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 delta 9793 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 diff --git a/frontend/__snapshots__/scenes-app-errortracking--group-page--dark.png b/frontend/__snapshots__/scenes-app-errortracking--group-page--dark.png index 65789fcd50fe2b597a6681ab8d11bac9455aac47..38d5bc497d4e41625f4bf4fe90ea7116d093e4cc 100644 GIT binary patch literal 104580 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�{jPiw0Q$RDo- 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 literal 105883 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