From 254f689bbc6c1c5e1f4bac1f515fced662165a40 Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Tue, 9 Apr 2024 08:25:47 +0200 Subject: [PATCH 01/20] [web] Include flags in custom events --- packages/web/src/generic.ts | 6 ++++-- packages/web/src/server/index.ts | 27 +++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index a0bf1ea..738d6c3 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -89,7 +89,8 @@ function inject( */ function track( name: string, - properties?: Record + properties?: Record, + options?: { flags?: string[] } ): void { if (!isBrowser()) { const msg = @@ -106,7 +107,7 @@ function track( } if (!properties) { - window.va?.('event', { name }); + window.va?.('event', { name, options }); return; } @@ -118,6 +119,7 @@ function track( window.va?.('event', { name, data: props, + options, }); } catch (err) { if (err instanceof Error && isDevelopment()) { diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index dd645b1..6091f09 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -19,11 +19,19 @@ interface ContextWithHeaders { type Context = ContextWithRequest | ContextWithHeaders; +interface Options { + flags?: string[]; +} + interface RequestContext { get: () => { headers: Record; url: string; waitUntil?: (promise: Promise) => void; + flags?: { + getValues: () => Record; + reportValue: (key: string, value: unknown) => void; + }; }; } @@ -33,7 +41,8 @@ const logPrefix = '[Vercel Web Analytics]'; export async function track( eventName: string, properties?: Record, - context?: Context + context?: Context, + options?: Options ): Promise { const ENDPOINT = process.env.VERCEL_WEB_ANALYTICS_ENDPOINT || process.env.VERCEL_URL; @@ -98,12 +107,26 @@ export async function track( const url = new URL(origin); + let flagsToReport: Record = {}; + const allFlags = requestContext?.flags?.getValues(); + if (options?.flags && allFlags) { + options.flags.forEach((key) => { + flagsToReport[key] = allFlags[key]; + }); + } else if (allFlags) { + // Default to all flags. The ingest endpoint will truncate them. + flagsToReport = allFlags; + } + const body = { o: origin, ts: new Date().getTime(), r: '', en: eventName, ed: props, + flags: { + plain: flagsToReport, + }, }; const hasHeaders = Boolean(headers); @@ -135,7 +158,7 @@ export async function track( body: JSON.stringify(body), method: 'POST', }) - // We want to always consume to body; some cloud providers track fetch concurrency + // We want to always consume the body; some cloud providers track fetch concurrency // and may not release the connection until the body is consumed. .then((response) => response.text()) .catch((err: unknown) => { From acd5e737d6b43b0b9355b1d6efd3892aa9a5a4df Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Tue, 9 Apr 2024 09:23:11 +0200 Subject: [PATCH 02/20] Rename property to plainValues --- packages/web/src/server/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 6091f09..200bb34 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -125,7 +125,7 @@ export async function track( en: eventName, ed: props, flags: { - plain: flagsToReport, + plainValues: flagsToReport, }, }; From 5e04c5ccdbdc3203459f9c9b1a633f66f692e7bf Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Thu, 11 Apr 2024 22:40:33 +0200 Subject: [PATCH 03/20] Rename properties --- packages/web/src/server/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 200bb34..253fbf9 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -124,8 +124,8 @@ export async function track( r: '', en: eventName, ed: props, - flags: { - plainValues: flagsToReport, + f: { + p: flagsToReport, }, }; From eaba47a9bc6c046b8f7edc67560bb8043068a2ee Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Fri, 19 Apr 2024 13:29:32 +0200 Subject: [PATCH 04/20] Unify options and require flags list --- packages/web/src/server/index.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 253fbf9..ef63979 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -17,12 +17,12 @@ interface ContextWithHeaders { headers: AllowedHeaders; } -type Context = ContextWithRequest | ContextWithHeaders; - interface Options { flags?: string[]; } +type OptionsAndContext = Options & (ContextWithRequest | ContextWithHeaders); + interface RequestContext { get: () => { headers: Record; @@ -41,8 +41,7 @@ const logPrefix = '[Vercel Web Analytics]'; export async function track( eventName: string, properties?: Record, - context?: Context, - options?: Options + options?: OptionsAndContext ): Promise { const ENDPOINT = process.env.VERCEL_WEB_ANALYTICS_ENDPOINT || process.env.VERCEL_URL; @@ -84,10 +83,10 @@ export async function track( let headers: AllowedHeaders | undefined; - if (context && 'headers' in context) { - headers = context.headers; - } else if (context?.request) { - headers = context.request.headers; + if (options && 'headers' in options) { + headers = options.headers; + } else if (options?.request) { + headers = options.request.headers; } else if (requestContext?.headers) { // not explicitly passed in context, so take it from async storage headers = requestContext.headers; @@ -107,15 +106,13 @@ export async function track( const url = new URL(origin); - let flagsToReport: Record = {}; + const flagsToReport: Record = {}; const allFlags = requestContext?.flags?.getValues(); + if (options?.flags && allFlags) { options.flags.forEach((key) => { flagsToReport[key] = allFlags[key]; }); - } else if (allFlags) { - // Default to all flags. The ingest endpoint will truncate them. - flagsToReport = allFlags; } const body = { From 5716656f59b0df63e7c8ccde4b7094cd59b612bf Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Fri, 19 Apr 2024 13:35:48 +0200 Subject: [PATCH 05/20] Rename flags variables --- packages/web/src/server/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index ef63979..ff049d9 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -106,12 +106,12 @@ export async function track( const url = new URL(origin); - const flagsToReport: Record = {}; - const allFlags = requestContext?.flags?.getValues(); + const flagValuesToReport: Record = {}; + const allFlagValues = requestContext?.flags?.getValues(); - if (options?.flags && allFlags) { + if (options?.flags && allFlagValues) { options.flags.forEach((key) => { - flagsToReport[key] = allFlags[key]; + flagValuesToReport[key] = allFlagValues[key]; }); } @@ -122,7 +122,7 @@ export async function track( en: eventName, ed: props, f: { - p: flagsToReport, + p: flagValuesToReport, }, }; From 09ae24adf9289762e799ea4420d6c0fb9b356cf5 Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Mon, 22 Apr 2024 20:56:30 +0200 Subject: [PATCH 06/20] Rename option --- packages/web/src/generic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index 738d6c3..d2373dc 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -90,7 +90,7 @@ function inject( function track( name: string, properties?: Record, - options?: { flags?: string[] } + options?: { flagKeys?: string[] } ): void { if (!isBrowser()) { const msg = From 7dc0abf3ab26a3ceac9cbd16f403e6e0329a5dea Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Mon, 22 Apr 2024 20:58:05 +0200 Subject: [PATCH 07/20] Update options --- packages/web/src/server/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index ff049d9..7e47275 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -18,7 +18,7 @@ interface ContextWithHeaders { } interface Options { - flags?: string[]; + flagKeys?: string[]; } type OptionsAndContext = Options & (ContextWithRequest | ContextWithHeaders); @@ -109,8 +109,8 @@ export async function track( const flagValuesToReport: Record = {}; const allFlagValues = requestContext?.flags?.getValues(); - if (options?.flags && allFlagValues) { - options.flags.forEach((key) => { + if (options?.flagKeys && allFlagValues) { + options.flagKeys.forEach((key) => { flagValuesToReport[key] = allFlagValues[key]; }); } From 68a2d25ed779f373c0b9f6cf6e0f975dc6f239eb Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Mon, 22 Apr 2024 21:06:23 +0200 Subject: [PATCH 08/20] Update options type --- packages/web/src/server/index.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 7e47275..3cba8de 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -10,19 +10,12 @@ function isHeaders(headers?: AllowedHeaders): headers is Headers { return typeof (headers as HeadersObject).entries === 'function'; } -interface ContextWithRequest { - request: { headers: AllowedHeaders }; -} -interface ContextWithHeaders { - headers: AllowedHeaders; -} - interface Options { flagKeys?: string[]; + headers?: AllowedHeaders; + request?: { headers: AllowedHeaders }; } -type OptionsAndContext = Options & (ContextWithRequest | ContextWithHeaders); - interface RequestContext { get: () => { headers: Record; @@ -41,7 +34,7 @@ const logPrefix = '[Vercel Web Analytics]'; export async function track( eventName: string, properties?: Record, - options?: OptionsAndContext + options?: Options ): Promise { const ENDPOINT = process.env.VERCEL_WEB_ANALYTICS_ENDPOINT || process.env.VERCEL_URL; From 1e5f6345c2382dbf064dfc05df8dd2040bcfe2d7 Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Thu, 25 Apr 2024 11:17:12 +0200 Subject: [PATCH 09/20] Add `setDefaultProps` --- packages/web/src/generic.ts | 4 ++++ packages/web/src/types.ts | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index d2373dc..a263898 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -41,6 +41,10 @@ function inject( window.va?.('beforeSend', props.beforeSend); } + if (props.setDefaultProps) { + window.va?.('setProps', props.setDefaultProps()); + } + const src = props.scriptSrc || (isDevelopment() ? DEV_SCRIPT_URL : PROD_SCRIPT_URL); diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts index aab7ee0..c76878c 100644 --- a/packages/web/src/types.ts +++ b/packages/web/src/types.ts @@ -6,6 +6,21 @@ interface CustomEvent { type: 'event'; url: string; } +interface FlagsData { + /** Relevant keys that should get tracked. */ + k?: string[]; + /** All plain text flags. */ + p?: Record; + /** All encrypted flags that were found, which will get decrypted later. */ + e?: string[]; +} +interface DefaultProps { + $flags?: (input: { + type: string; + data?: unknown; + options?: { flagKeys?: string[] }; + }) => FlagsData | undefined; +} export type BeforeSendEvent = PageViewEvent | CustomEvent; @@ -25,12 +40,14 @@ export interface AnalyticsProps { endpoint?: string; dsn?: string; + + setDefaultProps?: () => DefaultProps; } declare global { interface Window { // Base interface va?: ( - event: 'beforeSend' | 'event' | 'pageview', + event: 'beforeSend' | 'setProps' | 'event' | 'pageview', properties?: unknown ) => void; // Queue for actions, before the library is loaded From 019cbb4e47944d636d214955187f5c233f5e48e4 Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Thu, 25 Apr 2024 13:25:56 +0200 Subject: [PATCH 10/20] Rename property --- packages/web/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts index c76878c..4d87b41 100644 --- a/packages/web/src/types.ts +++ b/packages/web/src/types.ts @@ -15,7 +15,7 @@ interface FlagsData { e?: string[]; } interface DefaultProps { - $flags?: (input: { + $getFlags?: (input: { type: string; data?: unknown; options?: { flagKeys?: string[] }; From 8c89c518ca1eb635a9d2ffe2d112d73780ac926a Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Tue, 30 Apr 2024 14:31:41 +0200 Subject: [PATCH 11/20] Rename function --- packages/web/src/generic.ts | 4 ++-- packages/web/src/types.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index a263898..c034fb5 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -41,8 +41,8 @@ function inject( window.va?.('beforeSend', props.beforeSend); } - if (props.setDefaultProps) { - window.va?.('setProps', props.setDefaultProps()); + if (props.setInitialProps) { + window.va?.('setProps', props.setInitialProps()); } const src = diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts index 4d87b41..db4b1e2 100644 --- a/packages/web/src/types.ts +++ b/packages/web/src/types.ts @@ -14,7 +14,7 @@ interface FlagsData { /** All encrypted flags that were found, which will get decrypted later. */ e?: string[]; } -interface DefaultProps { +interface InitialProps { $getFlags?: (input: { type: string; data?: unknown; @@ -41,7 +41,11 @@ export interface AnalyticsProps { dsn?: string; - setDefaultProps?: () => DefaultProps; + /** + * A function that will be called before the Analytics script starts + * processing events to set initial values for specific properties for them. + */ + setInitialProps?: () => InitialProps; } declare global { interface Window { From 2160c27c64d012e5e185467ff71bec0b4b96aa6f Mon Sep 17 00:00:00 2001 From: Tobias Lins Date: Wed, 22 May 2024 11:53:26 +0200 Subject: [PATCH 12/20] Remove initialProps again and allow raw passing of `flags` --- packages/web/src/generic.ts | 9 ++++----- packages/web/src/types.ts | 21 --------------------- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index c034fb5..361f5fd 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -41,10 +41,6 @@ function inject( window.va?.('beforeSend', props.beforeSend); } - if (props.setInitialProps) { - window.va?.('setProps', props.setInitialProps()); - } - const src = props.scriptSrc || (isDevelopment() ? DEV_SCRIPT_URL : PROD_SCRIPT_URL); @@ -94,7 +90,10 @@ function inject( function track( name: string, properties?: Record, - options?: { flagKeys?: string[] } + options?: { + flagKeys?: string[]; + flags?: Record; + } ): void { if (!isBrowser()) { const msg = diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts index db4b1e2..a63114c 100644 --- a/packages/web/src/types.ts +++ b/packages/web/src/types.ts @@ -6,21 +6,6 @@ interface CustomEvent { type: 'event'; url: string; } -interface FlagsData { - /** Relevant keys that should get tracked. */ - k?: string[]; - /** All plain text flags. */ - p?: Record; - /** All encrypted flags that were found, which will get decrypted later. */ - e?: string[]; -} -interface InitialProps { - $getFlags?: (input: { - type: string; - data?: unknown; - options?: { flagKeys?: string[] }; - }) => FlagsData | undefined; -} export type BeforeSendEvent = PageViewEvent | CustomEvent; @@ -40,12 +25,6 @@ export interface AnalyticsProps { endpoint?: string; dsn?: string; - - /** - * A function that will be called before the Analytics script starts - * processing events to set initial values for specific properties for them. - */ - setInitialProps?: () => InitialProps; } declare global { interface Window { From 74609d960b6e7a399120e42af2c5964c9e9608c9 Mon Sep 17 00:00:00 2001 From: Tobias Lins Date: Wed, 22 May 2024 15:52:14 +0200 Subject: [PATCH 13/20] Cleanup --- packages/web/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts index a63114c..aab7ee0 100644 --- a/packages/web/src/types.ts +++ b/packages/web/src/types.ts @@ -30,7 +30,7 @@ declare global { interface Window { // Base interface va?: ( - event: 'beforeSend' | 'setProps' | 'event' | 'pageview', + event: 'beforeSend' | 'event' | 'pageview', properties?: unknown ) => void; // Queue for actions, before the library is loaded From 598a1de444709887812fd80ee317639e36f6d401 Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Wed, 22 May 2024 09:59:37 -0400 Subject: [PATCH 14/20] Remove unused type --- packages/web/src/generic.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index 361f5fd..a05c6d6 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -92,7 +92,6 @@ function track( properties?: Record, options?: { flagKeys?: string[]; - flags?: Record; } ): void { if (!isBrowser()) { From 469a2823df4067bea773a0209f5f3ecbd58d18da Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Wed, 22 May 2024 17:44:58 -0400 Subject: [PATCH 15/20] Update type and consider max. amount of flags --- packages/web/src/generic.ts | 2 +- packages/web/src/server/index.ts | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index a05c6d6..75ab74c 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -91,7 +91,7 @@ function track( name: string, properties?: Record, options?: { - flagKeys?: string[]; + flags?: (string | Record)[] | Record; } ): void { if (!isBrowser()) { diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 3cba8de..bca8787 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -11,7 +11,7 @@ function isHeaders(headers?: AllowedHeaders): headers is Headers { } interface Options { - flagKeys?: string[]; + flags?: (string | Record)[] | Record; headers?: AllowedHeaders; request?: { headers: AllowedHeaders }; } @@ -28,6 +28,8 @@ interface RequestContext { }; } +const MAX_FLAG_KEYS = 5; + const symbol = Symbol.for('@vercel/request-context'); const logPrefix = '[Vercel Web Analytics]'; @@ -99,11 +101,21 @@ export async function track( const url = new URL(origin); + const flags = options?.flags; const flagValuesToReport: Record = {}; - const allFlagValues = requestContext?.flags?.getValues(); + const allFlagValues = requestContext?.flags?.getValues() ?? {}; + + if (flags) { + const list = Array.isArray(flags) ? flags : [flags]; + + const keys = list.flatMap((keyOrObject) => { + if (typeof keyOrObject === 'string') return keyOrObject; + Object.assign(allFlagValues, keyOrObject); // Add values to global list + return Object.keys(keyOrObject); // Retrieve the keys + }); - if (options?.flagKeys && allFlagValues) { - options.flagKeys.forEach((key) => { + // Only report the first MAX_FLAG_KEYS flags + keys.slice(0, MAX_FLAG_KEYS).forEach((key) => { flagValuesToReport[key] = allFlagValues[key]; }); } From ee152767645bb47a9b012258dbf1a3c3728eae0d Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Wed, 22 May 2024 18:58:28 -0400 Subject: [PATCH 16/20] Always report the first 5 flags --- packages/web/src/server/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index bca8787..99c05b8 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -28,8 +28,6 @@ interface RequestContext { }; } -const MAX_FLAG_KEYS = 5; - const symbol = Symbol.for('@vercel/request-context'); const logPrefix = '[Vercel Web Analytics]'; @@ -115,6 +113,14 @@ export async function track( }); // Only report the first MAX_FLAG_KEYS flags + keys.forEach((key) => { + flagValuesToReport[key] = allFlagValues[key]; + }); + } else { + // If no `options.flags` was provided, we'll take the first 5 flags + // from the `allFlagValues` list and report them. + const MAX_FLAG_KEYS = 5; + const keys = Object.keys(allFlagValues); keys.slice(0, MAX_FLAG_KEYS).forEach((key) => { flagValuesToReport[key] = allFlagValues[key]; }); From 339e5773c6e9278bf419869aa18a47f18f2f2b53 Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Wed, 22 May 2024 19:13:03 -0400 Subject: [PATCH 17/20] Do not use default flags --- packages/web/src/server/index.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 99c05b8..2e600bf 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -116,14 +116,6 @@ export async function track( keys.forEach((key) => { flagValuesToReport[key] = allFlagValues[key]; }); - } else { - // If no `options.flags` was provided, we'll take the first 5 flags - // from the `allFlagValues` list and report them. - const MAX_FLAG_KEYS = 5; - const keys = Object.keys(allFlagValues); - keys.slice(0, MAX_FLAG_KEYS).forEach((key) => { - flagValuesToReport[key] = allFlagValues[key]; - }); } const body = { From f071b839ba396fb4fdcc53cc8c2174adc0b262ad Mon Sep 17 00:00:00 2001 From: Andy Bitz Date: Wed, 22 May 2024 20:08:15 -0400 Subject: [PATCH 18/20] Remove comment --- packages/web/src/server/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 2e600bf..74a3688 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -112,7 +112,6 @@ export async function track( return Object.keys(keyOrObject); // Retrieve the keys }); - // Only report the first MAX_FLAG_KEYS flags keys.forEach((key) => { flagValuesToReport[key] = allFlagValues[key]; }); From ae1b174d7bed0d9fc1dd3920ce4fa629397ddfb4 Mon Sep 17 00:00:00 2001 From: Tobias Lins Date: Thu, 23 May 2024 11:27:14 +0200 Subject: [PATCH 19/20] Refactor flags server integration Co-Authored-By: Damien Simonin Feugas --- packages/web/src/generic.ts | 8 +++- packages/web/src/server/index.ts | 67 ++++++++++++++++++++------------ packages/web/src/types.ts | 3 ++ 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/packages/web/src/generic.ts b/packages/web/src/generic.ts index 75ab74c..6009ed5 100644 --- a/packages/web/src/generic.ts +++ b/packages/web/src/generic.ts @@ -1,6 +1,10 @@ import { name as packageName, version } from '../package.json'; import { initQueue } from './queue'; -import type { AllowedPropertyValues, AnalyticsProps } from './types'; +import type { + AllowedPropertyValues, + AnalyticsProps, + FlagsDataInput, +} from './types'; import { isBrowser, parseProperties, @@ -91,7 +95,7 @@ function track( name: string, properties?: Record, options?: { - flags?: (string | Record)[] | Record; + flags?: FlagsDataInput; } ): void { if (!isBrowser()) { diff --git a/packages/web/src/server/index.ts b/packages/web/src/server/index.ts index 74a3688..eeb0b6f 100644 --- a/packages/web/src/server/index.ts +++ b/packages/web/src/server/index.ts @@ -1,5 +1,9 @@ /* eslint-disable no-console -- Allow logging on the server */ -import type { AllowedPropertyValues } from '../types'; +import type { + AllowedPropertyValues, + FlagsDataInput, + PlainFlags, +} from '../types'; import { isProduction, parseProperties } from '../utils'; type HeadersObject = Record; @@ -11,7 +15,7 @@ function isHeaders(headers?: AllowedHeaders): headers is Headers { } interface Options { - flags?: (string | Record)[] | Record; + flags?: FlagsDataInput; headers?: AllowedHeaders; request?: { headers: AllowedHeaders }; } @@ -22,7 +26,7 @@ interface RequestContext { url: string; waitUntil?: (promise: Promise) => void; flags?: { - getValues: () => Record; + getValues: () => PlainFlags; reportValue: (key: string, value: unknown) => void; }; }; @@ -99,33 +103,13 @@ export async function track( const url = new URL(origin); - const flags = options?.flags; - const flagValuesToReport: Record = {}; - const allFlagValues = requestContext?.flags?.getValues() ?? {}; - - if (flags) { - const list = Array.isArray(flags) ? flags : [flags]; - - const keys = list.flatMap((keyOrObject) => { - if (typeof keyOrObject === 'string') return keyOrObject; - Object.assign(allFlagValues, keyOrObject); // Add values to global list - return Object.keys(keyOrObject); // Retrieve the keys - }); - - keys.forEach((key) => { - flagValuesToReport[key] = allFlagValues[key]; - }); - } - const body = { o: origin, ts: new Date().getTime(), r: '', en: eventName, ed: props, - f: { - p: flagValuesToReport, - }, + f: safeGetFlags(options?.flags, requestContext), }; const hasHeaders = Boolean(headers); @@ -179,3 +163,38 @@ export async function track( console.error(err); } } + +function safeGetFlags( + flags: Options['flags'], + requestContext?: ReturnType +): + | { + p: PlainFlags; + } + | undefined { + try { + if (!requestContext || !flags) return; + // In the case plain flags are passed, just return them + if (!Array.isArray(flags)) { + return { p: flags }; + } + + const plainFlags: Record = {}; + // returns all available plain flags + const resolvedPlainFlags = requestContext.flags?.getValues() ?? {}; + + for (const flag of flags) { + if (typeof flag === 'string') { + // only picks the desired flags + plainFlags[flag] = resolvedPlainFlags[flag]; + } else { + // merge user-provided values with resolved values + Object.assign(plainFlags, flag); + } + } + + return { p: plainFlags }; + } catch { + /* empty */ + } +} diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts index aab7ee0..6301022 100644 --- a/packages/web/src/types.ts +++ b/packages/web/src/types.ts @@ -39,3 +39,6 @@ declare global { vam?: Mode; } } + +export type PlainFlags = Record; +export type FlagsDataInput = (string | PlainFlags)[] | PlainFlags; From f1ccbc32ab617a7c659aedb21d793b07750f290a Mon Sep 17 00:00:00 2001 From: Tobias Lins Date: Thu, 23 May 2024 11:32:54 +0200 Subject: [PATCH 20/20] Update package.json Co-Authored-By: Damien Simonin Feugas --- packages/web/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/package.json b/packages/web/package.json index 906a561..510d49e 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,6 +1,6 @@ { "name": "@vercel/analytics", - "version": "1.2.2", + "version": "1.3.0", "description": "Gain real-time traffic insights with Vercel Web Analytics", "keywords": [ "analytics",