From 2bfea919fefc5eff4caecaadabc4870744ffc041 Mon Sep 17 00:00:00 2001 From: Anshuman Pandey <54475686+pandeymangg@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:10:58 +0530 Subject: [PATCH] fix: merges the app and website js sdk into `@formbricks/js` (#3314) Co-authored-by: Matthias Nannt --- apps/demo/components/SurveySwitch.tsx | 22 - apps/demo/next.config.mjs | 10 - apps/demo/pages/{app => }/index.tsx | 6 +- apps/demo/pages/website/index.tsx | 143 ------- apps/docs/app/app-surveys/actions/page.mdx | 2 - .../app-surveys/advanced-targeting/page.mdx | 2 - .../app/app-surveys/framework-guides/page.mdx | 35 +- .../app/app-surveys/quickstart/images/I1.webp | Bin 25134 -> 71809 bytes .../app/app-surveys/quickstart/images/I2.webp | Bin 22308 -> 90508 bytes .../app/app-surveys/quickstart/images/I3.webp | Bin 24990 -> 104708 bytes .../app-surveys/quickstart/images/I3_1.webp | Bin 0 -> 112476 bytes .../app/app-surveys/quickstart/images/I5.webp | Bin 41564 -> 152993 bytes apps/docs/app/app-surveys/quickstart/page.mdx | 44 +- apps/docs/app/app-surveys/recontact/page.mdx | 2 - .../app-surveys/user-identification/page.mdx | 7 - .../1-set-up-in-app-micro-survey-popup.webp | Bin 57494 -> 0 bytes .../1-set-up-in-app-micro-survey-popup.webp | Bin 0 -> 84136 bytes .../images/2-micro-survey-pop-up-in-app.webp | Bin .../3-survey-logs-in-app-survey-popup.webp | Bin .../{app-survey-sdk => js-sdk}/page.mdx | 16 +- .../docs/app/developer-docs/overview/page.mdx | 8 +- apps/docs/app/global/hidden-fields/page.mdx | 2 - .../actions/images/StepOne.webp | Bin 15456 -> 0 bytes .../actions/images/StepTwo.webp | Bin 54620 -> 0 bytes .../docs/app/website-surveys/actions/page.mdx | 132 ------ .../framework-guides/components/Libraries.tsx | 60 --- .../framework-guides/images/env-id.webp | Bin 20914 -> 0 bytes .../react-in-app-survey-app-popup-form.webp | Bin 68884 -> 0 bytes .../images/widget-connected.webp | Bin 5988 -> 0 bytes .../images/widget-not-connected.webp | Bin 8198 -> 0 bytes .../website-surveys/framework-guides/page.mdx | 404 ------------------ .../website-surveys/quickstart/images/I1.webp | Bin 25134 -> 0 bytes .../website-surveys/quickstart/images/I2.webp | Bin 22308 -> 0 bytes .../website-surveys/quickstart/images/I3.webp | Bin 24990 -> 0 bytes .../website-surveys/quickstart/images/I4.webp | Bin 42626 -> 0 bytes .../website-surveys/quickstart/images/I5.webp | Bin 40094 -> 0 bytes .../website-surveys/quickstart/images/I6.webp | Bin 34714 -> 0 bytes .../website-surveys/quickstart/images/I7.webp | Bin 26292 -> 0 bytes .../website-surveys/quickstart/images/I8.webp | Bin 23318 -> 0 bytes .../app/website-surveys/quickstart/page.mdx | 115 ----- apps/docs/lib/navigation.ts | 82 ++-- apps/docs/next.config.mjs | 16 + .../OnboardingSetupInstructions.tsx | 8 +- .../[environmentId]/connect/page.tsx | 4 +- .../products/new/channel/page.tsx | 2 +- .../edit/components/CardStylingSettings.tsx | 4 +- .../edit/components/HowToSendCard.tsx | 80 +--- .../edit/components/SettingsView.tsx | 63 ++- .../edit/components/SurveyEditor.tsx | 6 +- .../edit/components/TargetingCard.tsx | 20 +- .../edit/components/WhenToSendCard.tsx | 4 +- .../surveys/[surveyId]/edit/page.tsx | 1 - .../app/(app)/components/FormbricksClient.tsx | 2 +- .../(people)/attributes/page.tsx | 7 - .../components/PersonSecondaryNavigation.tsx | 10 +- .../[environmentId]/actions/page.tsx | 10 +- .../components/EnvironmentLayout.tsx | 4 - .../components/MainNavigation.tsx | 3 +- .../components/TopControlBar.tsx | 20 +- .../components/TopControlButtons.tsx | 8 +- .../components/WidgetStatusIndicator.tsx | 82 ++-- .../[environmentId]/integrations/page.tsx | 43 +- .../product/(setup)/app-connection/page.tsx | 17 +- .../(setup)/components/SetupInstructions.tsx | 32 +- .../(setup)/website-connection/loading.tsx | 139 ------ .../(setup)/website-connection/page.tsx | 71 --- .../[environmentId]/product/api-keys/page.tsx | 6 +- .../components/ProductConfigNavigation.tsx | 14 +- .../[environmentId]/product/general/page.tsx | 14 +- .../product/languages/page.tsx | 2 - .../product/look/components/EditBranding.tsx | 4 +- .../components/ThemeStylingPreviewSurvey.tsx | 16 +- .../[environmentId]/product/look/page.tsx | 28 +- .../[environmentId]/product/tags/page.tsx | 6 +- .../components/EmptyInAppSurveys.tsx | 7 +- .../summary/components/SuccessMessage.tsx | 5 +- .../summary/components/SummaryList.tsx | 9 +- .../summary/components/SurveyAnalysisCTA.tsx | 4 +- .../components/SurveyStatusDropdown.tsx | 4 +- apps/web/app/api/packages/[package]/route.ts | 7 +- .../environment/lib/environmentState.ts | 9 +- .../{app => }/environment/route.ts | 2 +- .../people/[userId]/lib/personState.ts | 2 +- .../people/[userId]/lib/segments.ts | 0 .../people/[userId]/route.ts | 0 .../environment/lib/environmentState.ts | 126 ------ .../website/environment/route.ts | 59 --- apps/web/app/api/v1/management/me/route.ts | 1 - apps/web/app/lib/formbricks.ts | 2 +- apps/web/next.config.mjs | 24 ++ apps/web/playwright/js.spec.ts | 2 +- .../data-migration.ts | 75 ++++ .../migration.sql | 8 + packages/database/package.json | 3 +- packages/database/schema.prisma | 35 +- .../components/advanced-targeting-card.tsx | 20 +- packages/js-core/package.json | 25 +- packages/js-core/src/app/lib/person.ts | 43 -- packages/js-core/src/{app => }/index.ts | 22 +- packages/js-core/src/{app => }/lib/actions.ts | 12 +- packages/js-core/src/{app => }/lib/api.ts | 6 +- .../js-core/src/{app => }/lib/attributes.ts | 48 +-- .../src/{shared => lib}/commandQueue.ts | 13 +- packages/js-core/src/{app => }/lib/config.ts | 22 +- packages/js-core/src/lib/constants.ts | 5 + .../src/{shared => lib}/environmentState.ts | 13 +- .../js-core/src/{shared => lib}/errors.ts | 0 .../src/{app => }/lib/eventListeners.ts | 16 +- .../js-core/src/{app => }/lib/initialize.ts | 211 +++++---- .../js-core/src/{shared => lib}/logger.ts | 0 .../src/{app => }/lib/noCodeActions.ts | 10 +- packages/js-core/src/lib/person.ts | 34 ++ .../src/{shared => lib}/personState.ts | 22 +- packages/js-core/src/{shared => lib}/utils.ts | 7 +- packages/js-core/src/{app => }/lib/widget.ts | 82 ++-- packages/js-core/src/shared/constants.ts | 3 - packages/js-core/src/website/index.ts | 46 -- packages/js-core/src/website/lib/actions.ts | 57 --- packages/js-core/src/website/lib/common.ts | 31 -- packages/js-core/src/website/lib/config.ts | 86 ---- .../js-core/src/website/lib/eventListeners.ts | 59 --- .../js-core/src/website/lib/initialize.ts | 343 --------------- .../js-core/src/website/lib/noCodeActions.ts | 189 -------- packages/js-core/src/website/lib/widget.ts | 290 ------------- .../{app.vite.config.ts => vite.config.ts} | 4 +- packages/js-core/website.vite.config.ts | 34 -- packages/js/index.html | 4 +- packages/js/package.json | 25 +- packages/js/src/app.ts | 23 - packages/js/src/index.ts | 20 + .../js/src/{shared => lib}/load-formbricks.ts | 19 +- packages/js/src/website.ts | 23 - packages/js/vite.config.ts | 6 +- packages/lib/environment/service.ts | 1 - packages/lib/response/tests/constants.ts | 1 - .../lib/survey/tests/__mock__/survey.mock.ts | 6 +- packages/react-native/src/formbricks.tsx | 6 +- packages/react-native/src/lib/actions.ts | 6 +- packages/react-native/src/lib/attributes.ts | 2 +- .../react-native/src/lib/command-queue.ts | 7 +- packages/react-native/src/lib/config.ts | 6 +- packages/react-native/src/lib/index.ts | 12 +- packages/react-native/src/lib/initialize.ts | 8 +- packages/react-native/src/lib/person.ts | 4 +- packages/react-native/src/lib/sync.ts | 2 +- packages/react-native/src/survey-web-view.tsx | 4 +- .../components/wrappers/AutoCloseWrapper.tsx | 2 +- packages/types/environment.ts | 3 - packages/types/js.ts | 13 +- packages/types/surveys/types.ts | 2 +- .../ui/components/EmptySpaceFiller/index.tsx | 19 +- .../ui/components/PreviewSurvey/index.tsx | 6 +- .../components/SingleResponseCardHeader.tsx | 6 +- .../SurveysList/components/CopySurveyForm.tsx | 13 +- .../SurveysList/components/SurveyCard.tsx | 13 +- .../SurveysList/components/SurveyFilters.tsx | 2 +- .../components/TemplateFilters.tsx | 2 + .../TemplateList/components/TemplateTags.tsx | 10 +- packages/ui/components/TemplateList/index.tsx | 20 +- .../ui/components/TemplateList/lib/utils.ts | 6 +- packages/ui/components/Tooltip/index.tsx | 4 +- 161 files changed, 835 insertions(+), 3446 deletions(-) delete mode 100644 apps/demo/components/SurveySwitch.tsx rename apps/demo/pages/{app => }/index.tsx (97%) delete mode 100644 apps/demo/pages/website/index.tsx create mode 100644 apps/docs/app/app-surveys/quickstart/images/I3_1.webp delete mode 100644 apps/docs/app/developer-docs/app-survey-sdk/images/1-set-up-in-app-micro-survey-popup.webp create mode 100644 apps/docs/app/developer-docs/js-sdk/images/1-set-up-in-app-micro-survey-popup.webp rename apps/docs/app/developer-docs/{app-survey-sdk => js-sdk}/images/2-micro-survey-pop-up-in-app.webp (100%) rename apps/docs/app/developer-docs/{app-survey-sdk => js-sdk}/images/3-survey-logs-in-app-survey-popup.webp (100%) rename apps/docs/app/developer-docs/{app-survey-sdk => js-sdk}/page.mdx (83%) delete mode 100644 apps/docs/app/website-surveys/actions/images/StepOne.webp delete mode 100644 apps/docs/app/website-surveys/actions/images/StepTwo.webp delete mode 100644 apps/docs/app/website-surveys/actions/page.mdx delete mode 100644 apps/docs/app/website-surveys/framework-guides/components/Libraries.tsx delete mode 100644 apps/docs/app/website-surveys/framework-guides/images/env-id.webp delete mode 100644 apps/docs/app/website-surveys/framework-guides/images/react-in-app-survey-app-popup-form.webp delete mode 100644 apps/docs/app/website-surveys/framework-guides/images/widget-connected.webp delete mode 100644 apps/docs/app/website-surveys/framework-guides/images/widget-not-connected.webp delete mode 100644 apps/docs/app/website-surveys/framework-guides/page.mdx delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I1.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I2.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I3.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I4.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I5.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I6.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I7.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/images/I8.webp delete mode 100644 apps/docs/app/website-surveys/quickstart/page.mdx delete mode 100644 apps/web/app/(app)/environments/[environmentId]/product/(setup)/website-connection/loading.tsx delete mode 100644 apps/web/app/(app)/environments/[environmentId]/product/(setup)/website-connection/page.tsx rename apps/web/app/api/v1/client/[environmentId]/{app => }/environment/lib/environmentState.ts (92%) rename apps/web/app/api/v1/client/[environmentId]/{app => }/environment/route.ts (97%) rename apps/web/app/api/v1/client/[environmentId]/{app => identify}/people/[userId]/lib/personState.ts (97%) rename apps/web/app/api/v1/client/[environmentId]/{app => identify}/people/[userId]/lib/segments.ts (100%) rename apps/web/app/api/v1/client/[environmentId]/{app => identify}/people/[userId]/route.ts (100%) delete mode 100644 apps/web/app/api/v1/client/[environmentId]/website/environment/lib/environmentState.ts delete mode 100644 apps/web/app/api/v1/client/[environmentId]/website/environment/route.ts create mode 100644 packages/database/data-migrations/20241002123456_migrate_survey_types/data-migration.ts create mode 100644 packages/database/migrations/20241004070040_removed_website_setup_completed/migration.sql delete mode 100644 packages/js-core/src/app/lib/person.ts rename packages/js-core/src/{app => }/index.ts (68%) rename packages/js-core/src/{app => }/lib/actions.ts (84%) rename packages/js-core/src/{app => }/lib/api.ts (66%) rename packages/js-core/src/{app => }/lib/attributes.ts (81%) rename packages/js-core/src/{shared => lib}/commandQueue.ts (80%) rename packages/js-core/src/{app => }/lib/config.ts (75%) create mode 100644 packages/js-core/src/lib/constants.ts rename packages/js-core/src/{shared => lib}/environmentState.ts (88%) rename packages/js-core/src/{shared => lib}/errors.ts (100%) rename packages/js-core/src/{app => }/lib/eventListeners.ts (80%) rename packages/js-core/src/{app => }/lib/initialize.ts (63%) rename packages/js-core/src/{shared => lib}/logger.ts (100%) rename packages/js-core/src/{app => }/lib/noCodeActions.ts (96%) create mode 100644 packages/js-core/src/lib/person.ts rename packages/js-core/src/{shared => lib}/personState.ts (83%) rename packages/js-core/src/{shared => lib}/utils.ts (97%) rename packages/js-core/src/{app => }/lib/widget.ts (79%) delete mode 100644 packages/js-core/src/shared/constants.ts delete mode 100644 packages/js-core/src/website/index.ts delete mode 100644 packages/js-core/src/website/lib/actions.ts delete mode 100644 packages/js-core/src/website/lib/common.ts delete mode 100644 packages/js-core/src/website/lib/config.ts delete mode 100644 packages/js-core/src/website/lib/eventListeners.ts delete mode 100644 packages/js-core/src/website/lib/initialize.ts delete mode 100644 packages/js-core/src/website/lib/noCodeActions.ts delete mode 100644 packages/js-core/src/website/lib/widget.ts rename packages/js-core/{app.vite.config.ts => vite.config.ts} (91%) delete mode 100644 packages/js-core/website.vite.config.ts delete mode 100644 packages/js/src/app.ts create mode 100644 packages/js/src/index.ts rename packages/js/src/{shared => lib}/load-formbricks.ts (85%) delete mode 100644 packages/js/src/website.ts diff --git a/apps/demo/components/SurveySwitch.tsx b/apps/demo/components/SurveySwitch.tsx deleted file mode 100644 index 752c3ec037..0000000000 --- a/apps/demo/components/SurveySwitch.tsx +++ /dev/null @@ -1,22 +0,0 @@ -interface SurveySwitchProps { - value: "website" | "app"; - formbricks: any; -} - -export const SurveySwitch = ({ value, formbricks }: SurveySwitchProps) => { - return ( - - ); -}; diff --git a/apps/demo/next.config.mjs b/apps/demo/next.config.mjs index c8a450c888..151cc3ec71 100644 --- a/apps/demo/next.config.mjs +++ b/apps/demo/next.config.mjs @@ -1,15 +1,5 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: true, - async redirects() { - return [ - { - source: "/", - destination: "/app", - permanent: false, - }, - ]; - }, images: { remotePatterns: [ { diff --git a/apps/demo/pages/app/index.tsx b/apps/demo/pages/index.tsx similarity index 97% rename from apps/demo/pages/app/index.tsx rename to apps/demo/pages/index.tsx index 3a4fd17a47..421ed20bad 100644 --- a/apps/demo/pages/app/index.tsx +++ b/apps/demo/pages/index.tsx @@ -1,9 +1,8 @@ import Image from "next/image"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; -import formbricks from "@formbricks/js/app"; -import { SurveySwitch } from "../../components/SurveySwitch"; -import fbsetup from "../../public/fb-setup.png"; +import formbricks from "@formbricks/js"; +import fbsetup from "../public/fb-setup.png"; declare const window: any; @@ -63,7 +62,6 @@ const AppPage = ({}) => {
-

Formbricks In-product Survey Demo App diff --git a/apps/demo/pages/website/index.tsx b/apps/demo/pages/website/index.tsx deleted file mode 100644 index b75abd8afb..0000000000 --- a/apps/demo/pages/website/index.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import Image from "next/image"; -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import formbricks from "@formbricks/js/website"; -import { SurveySwitch } from "../../components/SurveySwitch"; -import fbsetup from "../../public/fb-setup.png"; - -declare const window: any; - -const AppPage = ({}) => { - const [darkMode, setDarkMode] = useState(false); - const router = useRouter(); - - useEffect(() => { - if (darkMode) { - document.body.classList.add("dark"); - } else { - document.body.classList.remove("dark"); - } - }, [darkMode]); - - useEffect(() => { - // enable Formbricks debug mode by adding formbricksDebug=true GET parameter - const addFormbricksDebugParam = () => { - const urlParams = new URLSearchParams(window.location.search); - if (!urlParams.has("formbricksDebug")) { - urlParams.set("formbricksDebug", "true"); - const newUrl = `${window.location.pathname}?${urlParams.toString()}`; - window.history.replaceState({}, "", newUrl); - } - }; - - addFormbricksDebugParam(); - - if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) { - const defaultAttributes = { - language: "en", - }; - - formbricks.init({ - environmentId: process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID, - apiHost: process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST, - attributes: defaultAttributes, - }); - } - - // Connect next.js router to Formbricks - if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) { - const handleRouteChange = formbricks?.registerRouteChange; - router.events.on("routeChangeComplete", handleRouteChange); - - return () => { - router.events.off("routeChangeComplete", handleRouteChange); - }; - } - }); - - return ( -
-
-
- -
-

- Formbricks Website Survey Demo App -

-

- This app helps you test your app surveys. You can create and test user actions, create and - update user attributes, etc. -

-
-
- - -
- -
-
-
-

1. Setup .env

-

- Copy the environment ID of your Formbricks app to the env variable in /apps/demo/.env -

- fb setup - -
-

You're connected with env:

-
- - {process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID} - - - - - -
-
-
-
-

2. Widget Logs

-

- Look at the logs to understand how the widget works.{" "} - Open your browser console to see the logs. -

- {/*
- -
*/} -
-
- -
-
-

- Reset person / pull data from Formbricks app -

-

- On formbricks.reset() the local state will be deleted and formbricks gets{" "} - reinitialized. -

- - -

- If you made a change in Formbricks app and it does not seem to work, hit 'Reset' and - try again. -

-
-
-
-
- ); -}; - -export default AppPage; diff --git a/apps/docs/app/app-surveys/actions/page.mdx b/apps/docs/app/app-surveys/actions/page.mdx index 64cba73f6c..8d3bf1b33c 100644 --- a/apps/docs/app/app-surveys/actions/page.mdx +++ b/apps/docs/app/app-surveys/actions/page.mdx @@ -9,8 +9,6 @@ export const metadata = { "Dive deep into how actions in Formbricks help products and organizations to engage users at precise moments in their journey. Discover the power of actions, from coding to no-code setups, to refine user targeting and generate richer, more detailed user insights.", }; -#### App Surveys - # Actions Actions are predefined events within your app that prompt Formbricks to display a survey when triggered. These are detected by the Formbricks widget, which then presents the appropriate survey based on your predefined settings. diff --git a/apps/docs/app/app-surveys/advanced-targeting/page.mdx b/apps/docs/app/app-surveys/advanced-targeting/page.mdx index 70e998b048..d93bd5cb7f 100644 --- a/apps/docs/app/app-surveys/advanced-targeting/page.mdx +++ b/apps/docs/app/app-surveys/advanced-targeting/page.mdx @@ -4,8 +4,6 @@ export const metadata = { "Advanced Targeting allows you to show surveys to just the right group of people. You can target surveys based on user attributes, metadata, and other segments. This helps you get more relevant feedback and make data-driven decisions.", }; -#### App Surveys - # Advanced Targeting Advanced Targeting allows you to show surveys to the right group of people. You can target surveys based on user attributes, device type, and more instead of spraying and praying. This helps you get more relevant feedback and make data-driven decisions. All of this without writing a single line of code. diff --git a/apps/docs/app/app-surveys/framework-guides/page.mdx b/apps/docs/app/app-surveys/framework-guides/page.mdx index 915f3ad58f..205e0adc72 100644 --- a/apps/docs/app/app-surveys/framework-guides/page.mdx +++ b/apps/docs/app/app-surveys/framework-guides/page.mdx @@ -42,8 +42,8 @@ All you need to do is copy a ` ``` @@ -58,9 +58,6 @@ All you need to do is copy a ` - -``` - - -### Required customizations to be made - - - - Formbricks Environment ID. - - - - - URL of the hosted Formbricks instance. - - - -Refer to our [Example HTML project](https://github.com/formbricks/examples/tree/main/html) for more help! Now visit the [Validate your Setup](#validate-your-setup) section to verify your setup! - ---- - -## ReactJS - -Install the Formbricks SDK using one of the package managers ie `npm`,`pnpm`,`yarn`. Note that zod is required as a peer dependency and must also be installed in your project. - - - -```shell {{ title: 'npm' }} -npm install @formbricks/js zod -``` -```shell {{ title: 'pnpm' }} -pnpm add @formbricks/js zod -``` -```shell {{ title: 'yarn' }} -yarn add @formbricks/js zod -``` - - - -Now, update your App.js/ts file to initialise Formbricks. - - - -```js -// other imports -import formbricks from "@formbricks/js/website"; - -if (typeof window !== "undefined") { - formbricks.init({ - environmentId: "", - apiHost: "", - }); -} - -function App() { - // your own app -} - -export default App; -``` - - - -### Required customizations to be made - - - - Formbricks Environment ID. - - - - - URL of the hosted Formbricks instance. - - - -Refer to our [Example ReactJs project](https://github.com/formbricks/examples/tree/main/reactjs) for more help! Now visit the [Validate your Setup](#validate-your-setup) section to verify your setup! - ---- - -## NextJS - -NextJs projects typically follow two main conventions: the App Directory and the Pages Directory. -To ensure smooth integration with the Formbricks SDK, which operates solely on the client side, follow the -guidelines for each convention below: - -- App directory: You will have to define a new component in `app/formbricks.tsx` file and call it in your `app/layout.tsx` file. -- Pages directory: You will have to visit your `_app.tsx` and just initialise Formbricks there. - -Code snippets for the integration for both conventions are provided to further assist you. - - - -```shell {{ title: 'npm' }} -npm install @formbricks/js zod -``` -```shell {{ title: 'pnpm' }} -pnpm add @formbricks/js zod -``` -```shell {{ title: 'yarn' }} -yarn add @formbricks/js zod -``` - - - - -### App Directory - - - - -```tsx {{title: 'Typescript'}} -"use client"; - -import { usePathname, useSearchParams } from "next/navigation"; -import { useEffect } from "react"; -import formbricks from "@formbricks/js/website"; - -export default function FormbricksProvider() { - const pathname = usePathname(); - const searchParams = useSearchParams(); - - useEffect(() => { - formbricks.init({ - environmentId: "", - apiHost: "", - }); - }, []); - - useEffect(() => { - formbricks?.registerRouteChange(); - }, [pathname, searchParams]); - - return null; -} -``` - - - - -```tsx {{title: 'Typescript'}} -// other imports -import FormbricksProvider from "./formbricks"; - -export default function RootLayout({ children }: { children: React.ReactNode }) { - return ( - - - {children} - - ); -} -``` - - - - -Refer to our [Example NextJS App Directory project](https://github.com/formbricks/examples/tree/main/nextjs-app) for more help! - -### Pages Directory - - - - -```tsx {{ title: 'Typescript' }} -// other import -import { useRouter } from "next/router"; -import { useEffect } from "react"; -import formbricks from "@formbricks/js/website"; - -if (typeof window !== "undefined") { - formbricks.init({ - environmentId: "", - apiHost: "", - }); -} - -export default function App({ Component, pageProps }: AppProps) { - const router = useRouter(); - - useEffect(() => { - // Connect next.js router to Formbricks - const handleRouteChange = formbricks?.registerRouteChange; - router.events.on("routeChangeComplete", handleRouteChange); - - return () => { - router.events.off("routeChangeComplete", handleRouteChange); - }; - }, []); - return ; -} -``` - - - -Refer to our [Example NextJS Pages Directory project](https://github.com/formbricks/examples/tree/main/nextjs-pages) for more help! - -### Required customizations to be made - - - - Formbricks Environment ID. - - - - - URL of the hosted Formbricks instance. - - - -First initialize the Formbricks SDK, ensure that it only runs on the client side. -To connect the Next.js router to Formbricks and ensure the SDK can keep track of every page change, we are registering the route change event. - -Now visit the [Validate your Setup](#validate-your-setup) section to verify your setup! - ---- - -## VueJs - -Integrating the Formbricks SDK with Vue.js is a straightforward process. -We will make sure the SDK is only loaded and used on the client side, as it's not intended for server-side usage. - - - -```shell {{ title: 'npm' }} -npm install @formbricks/js -``` - -```shell {{ title: 'pnpm' }} -pnpm add @formbricks/js -``` - -```shell {{ title: 'yarn' }} -yarn add @formbricks/js -``` - - - - - -```js -import formbricks from "@formbricks/js/website"; - -if (typeof window !== "undefined") { - formbricks.init({ - environmentId: "", - apiHost: "", - }); -} - -export default formbricks; -``` - - - - - -```js -// other imports -import formbricks from "@/formbricks"; - -const app = createApp(App); - -app.use(router); - -app.mount("#app"); - -router.afterEach((to, from) => { - if (typeof formbricks !== "undefined") { - formbricks.registerRouteChange(); - } -}); -``` - - - -### Required customizations to be made - - - - Formbricks Environment ID. - - - - - URL of the hosted Formbricks instance. - - - -Refer to our [Example VueJs project](https://github.com/formbricks/examples/tree/main/vuejs) for more help! Now visit the [Validate your Setup](#validate-your-setup) section to verify your setup! - -## Validate your setup - -Once you have completed the steps above, you can validate your setup by checking the **Setup Checklist** in the Settings. Your widget status indicator should go from this: - - - -To this: - - - -## Debugging Formbricks Integration - -Enabling Formbricks debug mode in your browser is a useful troubleshooting step for identifying and resolving complex issues. This section outlines how to activate debug mode, covers common use cases, and provides insights into specific debug log messages. - -### Activate Debug Mode - -To activate Formbricks debug mode: - -1. **Via URL Parameter:** - - - Enable debug mode mode by adding `?formbricksDebug=true` to your application's URL (e.g. `https://example.com?formbricksDebug=true` or `https://example.com?page=123&formbricksDebug=true`). This parameter will enable debugging for the current page. - -2. **View Debug Logs:** - - - Open your browser's developer tools by pressing `F12` or right-clicking and selecting "Inspect." - - Navigate to the "Console" tab to view Formbricks debugging information. - - **How to Open Browser Console:** - - - **Google Chrome:** Press `F12` or right-click, select "Inspect," and go to the "Console" tab. - - **Firefox:** Press `F12` or right-click, select "Inspect Element," and go to the "Console" tab. - - **Safari:** Press `Option + Command + C` to open the developer tools and navigate to the "Console" tab. - - **Edge:** Press `F12` or right-click, select "Inspect Element," and go to the "Console" tab. - -### Common Use Cases - -Debug mode is beneficial for scenarios such as: - -- Verifying Formbricks initialization. -- Identifying survey trigger issues. -- Troubleshooting unexpected behavior. - -### Debug Log Messages - -Debug log messages provide insights into: - -- API calls and responses. -- Event tracking, survey triggers and form interactions. -- Initialization errors. - -**Can’t figure it out? [Join our Discord!](https://formbricks.com/discord)** - ---- diff --git a/apps/docs/app/website-surveys/quickstart/images/I1.webp b/apps/docs/app/website-surveys/quickstart/images/I1.webp deleted file mode 100644 index b607cc0ec8fc3bec42de10be6231a6fa0ea347d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25134 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 diff --git a/apps/docs/app/website-surveys/quickstart/images/I2.webp b/apps/docs/app/website-surveys/quickstart/images/I2.webp deleted file mode 100644 index 410211005847c69e28a4663b91204b1829cfc4ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22308 zcmd42W0Wq<)+Ji@F6^>xSM9QG+qP}nwzTwI zGBQ@K6?4rsBXXpogs3Qv8W510h@iZxJUap6U+vjT;2dBoesFS7-URV{>5^iy!UD$h z^x2=#X11Sl9DAhDlNx*>6&-gm5P*Bvj=NlLM5j}|Z?Q79&p0`}xX=Et;*T!C+>^yO z{&)98-pLnT&#kAw-`DfvH!xtO2EPoj z;rIJ{^cC`}=VRmw|5;Aj592NE2C(U8-_z@*tow@4(Q2+;^_6xmN@1f_i=b3K=Q1Y@509<>$WB~vjFV|@Rz*m7VZd%6k zu}@o`t=YzZXe5=!+E8ht#f^!$72$Q%!>ja~mM+{Y=$ww!TneSwW0p64CaZZeUUVQH zX+v1r@R6c!M|)lma;O1kpw>!Wv?%NOQuIkg~KSTIG`WTz8Bnf(~-F+25h zu#Ng_7?)D*K2RUFxzIgR^GH{MYgfJilK$w4XGsHLndb{0w(Kk-1Bu49s!@m!m~5Wa zM4fe`@9TVv#ZW=4Cv+jVSLDBZ`A5i7-XoOhi@T*kF6zoPj{nYk5li8|&) z@oOA^ja(R|exZpMB3xsTTJAIC8=Y_+>uXR8s@w5#ZKHThIPai~`KV%0JY_qbR)ccY zd;DucPDu2≪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 I00000019G)>;M1& diff --git a/apps/docs/app/website-surveys/quickstart/images/I4.webp b/apps/docs/app/website-surveys/quickstart/images/I4.webp deleted file mode 100644 index f7bae96938f37bac8514a4796733d3e78ed14b1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42626 zcmb6AV|XTA*EI^qwrwXJJ006b$F`kxY}>YzGq!DX$F^-}=eq9ae!g$Nd;i(>qqL5- zs%q67bBr;MDkVuVG0zepAazk81vLduBHQo%>qL-jV45f}Qc%8li5wa7B9a190;Gm8V|Dyl?%G`3$e!dA_$FT%NRF;a|V! zAuoKZ5I^-cbKQD&y#@GteN`XyzH-05zSR5VANgOmzP`@iQGD6HD$jnu#9wcHHrzgK zPJAAfL4JMN~q*Ny}6z}--s{DuaU{Z*R5;aVxQuVfsdo-+&jJ6Eq%fX{`#-c z&yN?5JH5Bq6<>NB2XoX|!FPtQaV6f%YK96G_Gd}XTVoNBsY%<0) zTdH77Ypze0;(M+B{Xv!;MW_BU3~n6m7f)XB0OQ3kAN!tl+tf<9hCkQUi#Bw$Pn6ZY z%3Dl`W&#UTq_ed><@ePIpz@ghVkol;b37Np%NF+QYsyk3?DK!hqnntCJ#F)RG*mq# zaNf8CIBX#S%cG7uPuGWV&YDbFb9g*&e3a|SwM9wPv8AL*vGq!CBOO!GcrR93_p56)P@#8SAS*N2lrh%D9x2G)Yp^NCDjf z)5UnudOG%GI0fAMJI5p<))PM3RbTC;x0dkz)<>{eR7zjSJiSsB+ERGHZtMGj`P|oX zC@h8o6hKDiEGkNniTqi4kI5Qx(dVOvok244tfqmq?Vha7q5w=L$agtn0wmJIArT@o|}sziH7>oKDs1qdX|k=wV_r zfmK1Bgln#0Hc<1kKdrT zFLG&ti%AzVBdI(a+QPu^?zH{Che?g5d#mmL89kyTR%2c=uf|rre=I{+<3*Y#>eM^n6V3kl+xEcF8y+rjAZ2SoWX*KwciIN1kp~#UC0-!}e^8ys|z)bzi z3HPE)c=c9X1ls$R;ulcODukUIhQ*V^2%5|~vAJD?ozfJdyVKM|+$sS*7r9xe2{UJw zkmTI$u$^qI>G)D8jxijqOVsK%9S{2xR;A5HQJ|}A;DEuJY`|9~s~-Hc{lG!lEY@MA zOT`_CeX<~ucxsBH;@^Nu{7;VadL*3eCT#_p%|6Avw{_(jXlXrZl7fx$D*nz2 zemS5Y8P&60023vw!uhrLIcskL_2E7MlfTkLV|Rw4fft{RS%cVJYQ#Z&)q5CI6T zp^y}^DF^DSj#*NO^0^hL#an8i!`+Evk>nwikK)U;<;4LH(X%G@Vqzfjdvtt-= z>#h3ip%D^R)1aB*Rm&S-A|W!vDuIml8FdzSgnQ3r zU5$%k?GHvlfsW@W8iXN8%~;IsSg>ibL$+~-_&HWyVc{n9WAx4d%xMZd_V{>|z@<|A z@Saeh@$;Q&Wvn4%r*Aa|dxXo$R2k|luYT4D@~6PHT>NDaz5AbeIC#dG_%^aMX+a7y zz2NNc2|H5pvQKI9V~5W3b3><$R7=sgU6@*6HIhP}328}PqE{ra0)HQ#1-*iP$^=)t zJg+dw`|#S(42exK?;Hu0MGId zKjothc2YJKD02u;%;i=@*YN&a+9#RfG(+55Yo8xiJMnx3XCTy!~VkUG0n{MTGzF1wc5pf|OSK1LC`}h;EEjOp?{c zwOa~30Bva?&lPGC&Ut|Z`paXG7WxbT z82i@Sm*E@<+GGvj+y8@qAmMYZ7My|YPfvo8wWP7Xqoz$QOVe?%+ThiG7uuJU%Y)-{K-_Qn%85a=jevZ4=*_u966)B#=$L~^0dK%hH$oEBrR&-p?DNy?Y8Q1EHM=f2Plw8v zCq;5{TtUujUn(~C3)|AP-r6AqbVH(diJ{%RGm*imIRL#gB64=}Ej=-{YiV&NekZ~q zgiKi=XC$%vFj#Z~sTKveYxJsxf0&fc6T^V5E%uXSH_%r&2dAHH zpW&=@A4_>*ec3-tVxst?Mow9!p5|9Iq;~%k0P2EUkXU9gU>^O?tdK)x=t1WFt$L&1uADk|&|P z#>id?U`wyWmq(`&6!BwYBnncfE4ZE@6sRAnOL;-^pB1F?`-XtvO4;`YF&{ODanE%G zchJTkLL|RR;mODfq)+WZw6ECD*;kk~mQ7NcXWZegF{*rh!KzMBxFEF z(7j#emZh{!%FtT9+7tc5jV{Ib7|*32qiy~_bfbhY_02kd-cZacXPL z++iW4Oy_@DaeeNej7`6V>WFPmEy;w;5?KslVycix)J|!C7-M#AnUp)Upgwk)DL?!NxneXK+BzQT`B5fZKupwpJv@(znjKgYRL7w}0vhgmg z3K>J`a?83WfPq5R&{^_Pr9qSw*j@a#Pj`ty2`t-eZ=AIr`-lPG11Sa$l9oH3vi?do z5fN=@s?6)<>10LV$Wcg%s+AuLfDxGciYgS63+f`>&C&ETA2aaRI+`*={!Drmy@cGX z+QbB{DG_imfGdTvedR~N40|ZcTYRQItlrdx8~JsZPYhlbm|OMnQ7sWX!Dbi3a9N-d z^__@8rR8C|5{BpWUz?0)ipg3RwMDJU*r+Jp&~2`vMHG)QuibzLfU`I&iG#!%&vWw+ zIKvo^hVzZKEm|s?!jTf@$wU3Pp~%i6ob8*ZwcIx9$;uXQ>JMKM{$WSDcwpnuK@G+C z&R(40xX)zw47UlGZ_uSqCLB=B(8I_5!_B?(V01sgA^)EcqBwZvOuPt>|y@!Od)r;~W`D%fG1mPx~T# z>LU19bfYVg$-JWLORw=2T`8_+M~#%SCfM^A|dh~zbO1`d+{+-a&2pkd&$dClu z62zzO%;%ly*P!Q}3`z6inO``9|JOYXpyT#N!hnDl@LwrKa;GwjpePTwH-4hLUN>qxkyjrf-Am53Y*#EI}V9u#L$z_;@6^B!!M7OJ+{X%)pCj!Gb1?^_Ne32^QRTz@lvHVW04#StOYOL+K zt=e*@zFV>FAMENxVjCG&j18KhKE5fPK))-c#WJW8Twwok8JRZTMmPPUsx(PJ<>;bE za2Lpz;(NZS#Fv~xaD$3A=6%C?hX{Ow{^dr_h-ySVRopfb4s2--bfh4@0HZ_uKv_KxFYk4|9hr89@9OOiKVg>;l4QZPK=5C_hrG(JT0J zBiUb+WIID?f4nV%A-Z8utkL?8gpOrL?TTH#K4?8vLEb0yo|I2!pqj&!g6+L4IHi`H(xRvKd#>pH}Ax_k{!8JcuXtHu& zc>iYlf2<*Eh2)UtjX)2@e-Di;2mbz}cqD;#MKC$wUhKZH{x6jOgLSf8989E!$ecME z(pSEV_aEK1GdeQX@hd_T@7X75Vo+3i#Va1v%b8-V}L2D)8ql z5;&M|MQ;Sd4_-|1U}pOA{r~*FlgPJlE9&r4$q0879>%AwU;EvYp7hZ2-{~>tu?gXL z?*}}nFZL{|;jJzHubnYII{2;@$TngR6()jSmLzDib9zQ3hmywI!#80I?|C%i+4qcx zN{BCX!`Q6q#5MlI`!s1=$OR{qoD^{}p)UKKlo?4Rdx9GhT@5R*XElrG75!KC0B*%q zkDqurXv&kKWB=wKTYZ=B*Jco*JDyb6l=E;U0ZO9=I@z0y%DCjF7r@$A-M{%i`RzFx z`$SEH3Mj=01-WUS)6A_Ydn8emeStY zt*J;XX75TtgQv1CUYfSzEWUh&L;8N{ycV=S;zW93^}b>jz%dQ8YiKZvDwOR*h0X6N z`+`cEKaQliYcRA)W?Mdh>~0wsvFcZs`>!0ppdAdZnYisj=bFkk)STjzLES?I0 z2F1O2Qkj4y5n$y-J89C<(;5uGW51N~f?OjbD+g1xVsjxG`-cYb{wwzXtsVX1Zc=vi z7}xyYBGP;$#dnZ6&;&rs94V+{3R%MPT(=X79ZH!n6gpvYcRo}QdeNa{Vt0ydJh|w` zhvRjdk~zVAv7m7NZXPG5E&a!#$@_;)MF1vsI=&5Q`nRz4#!V;h59j`6eHEhe&6hNk zqUBFEB=cSA(s@t2hY2~^s1TZnN~4xPnxc8dpdxjlQd@E}@2?+@U9m-(PO z98f=IBq{dqa8*D1y{~WdsQ_SgjC8nEJEx67Pc%BIpc2vw9#IfBRW;z6VBsrUaYkHm zGh~=hK8`RkS!X1Jc>;;iP+8bR*b6%!GkLm!C3ZzYN1BTh0BYsRxVI8JIwS=SX45?N z%1dYe)IrEqiBg14VN~1zgXI)v#)s94pAlL#`5`zOTdz{oQMOj5mu?pqkAauC&=nnh z>wJObVuKd8gk(~2>a(KnSIco11P^N2J>HYufq)kk6|MZmczksf2QVhH#*R?8CJ}CO zZz|Xia@Dgh)W%jJVf$N6Hb=SCk<`uApz`wsD*Mq|$6tq0HM%HTPYWS;)wk_HbL}2j zrE=GK_~`a1Y48qsZ|W3S&(qjqYH6tFHe*M#!QQ;u>9O2Dtb9H-7BZ4-m~HmQ{(U{cLPP6jxLEc$-_#>z;kjevx@(wokADurwh;+JaLtq*EneU|J zCAMl2PkwI#3!_pG6Dt$1)v%mdYEYUoAuBWDJrFRLzD&H@I(HNi47>p)k*fyE_a;Y#E5jBi?msAB{#H z+6XkEN_qCo5Q2@K$0r#PaExL5FENwxA-jh@Fk_u))iC)m1hC{rPj5l*Jj;-NY{B>i zkskF|LaTt2Dt+F59f(`DO^+wsNN z-VpU1fuxew`|O#D4==+9nw~h|nqh#js=W-f^DII`UAYp6LcNrzG{aDOlimR-fZ9P4 z=fxefeB*2C5f~MU@&;UApRdmB-RmO%;Si>YcU?#q7ilg%RIhk#6uE@2;m7rhz!N(8 z{#RlTJ$Iht{Tk=Q4N=@&Hq7owQ-j%HHX3EE=?&dg(Wdxkgslk{eWK$;C-;bY@6@qT z@G2H+xQxv}XDl(L1P3Kz*I;|555eTQoWrmc+CrkIkh*`RdK^H@Pq60BGL=(*e4_JRRwz4kOu-`7G6%ERL=sPT`o+1 zn~5#F!SQh015I|$1JUMy!JNY)#gy?Ykwv%u+SakfW@~b$EivK+zsWFML*jt zhB=P!d_bgNF*@712UKY@);=9=+RPlbB(itD9jh-7NJxxT?AP}%Kqt4@IBqRrD*^-EF0FGLOe&gGzu5w{?l3cXWe5>0 z(C_~RUtu|DNlg+_zGy@tFQ7A=)mD3c1~>RKGEj}mf&>F1#q2iB&oobl ziwH*wk|qN0#Vk9=tA)}HFUUD8xIG&TYN_K3PM@)7wdDS=CTRY^rx45jps$sA3+gNu z>r-BAU6)3Hkj$Efx(9#S9Qx)p`HJe15-ffCFYeEeW8Cz^ z5xND*X*w*Y0gtAt`QeQ=Jo}SbT=Q3jw@Yn3a3O?`1q&om(UTvV8MvfN{N)C>gujtUDvngg`z!xa<^KUtKh)kl^9Baw?vdz|2H*-jQG!36MDSpdK*n((0F+j@X_kB^bSJ+VI42QKdU_Z2C*t#=sDqN8TL% zX+-1_kFsv>Gq^G{Xn2y3d1chh7vO0~htfc#7V0Kc@>giuF;d~?V#v%6wQqIkOC>0< zjM|OA!y}KSgAw5V9V3g$)7tzYFEtbYH(2yhTr51-ceDXTA#kpl6j#GT4b`6~|C!K( z*Ty@fw(*x(T^?=~AVH6YcF~C^$k!KPM&(X0uVYwU_EOnm4!gDa4H_H&Mar9L#a{xP zp5;_aD#Fic*wz5rlj`$JGQ+e<+>ZtsojTf?%e=~L4C^-|vq1k14%u#Yy4dX)iY--M zwtF>!j}QIX%*%cp^R4~P6itJfS*91MS}3>}hYIj2k5kkwHH-_b37{cF!U zNF*llfZakwAXSUKg*AK>GGO39vo9bVYWRW@Q^#P$QF3Y{U}(^`C=4k%`G@JUi(haL zd+|@1S;(FtTm{hmH$NicD-w~X)D(Y_y6j2s(}CC4W-fAl#P{$v7L&z^%-{`%=r*c7 zW4XnZh36v+VgT!iI%{gLGa@rR|82l^xm)aLvPH0fkG$tiJ^;TL{PpFX^oI_#PXM%8 zk-;8W*GF3QC+s*Z3_Mtk9=U$mQdvU#R-Vq1zFz}`lQCH*e?_z}PAep#0d{D8HEury->hFR4J77l0y zB+H6oqSMBfbO3a!VwQR1g9n85jA`&JnVRl}Grt_N3oW|urT!M)L2NT;{+~Yt>m{Iyz9k!nSSPfn*qO(5&k!Y>b6A*LAO}GN_p|G_WWqR?v zA`BqG)I`q_vO9tcSQWn?R!w9z;H=>-i^^$uE(?u*?vFD+ADHP{xQ6Pg^=kK#K<_4{ zOc8usirzbUEl(_~5V)t)r-d(sU-@gtEo8~MTW+Yhc~kUTg4K&{fgybGN>OcSk^I9A zXK$qcgeS+H3pVS4-0D+q$X#PXt#h=7NdKc&F62+rOp*uW>TVppo%yVk|Ekx*HNV(9 z6>o{0t|GfqS5+NnCjuQC6{SAP;C*2vLKiesbt7((I&dLt=1F$w+j*s;RbXTtk+rU! z1l8`G01}w;mX^U&*8M~^@UL?gbHNXq8zRe>Xbo7Z`<;L-Bfgwlz%;LbGGMR0f_3x; zF#YQo>Vm@tuUB#GU{c`aQyhzTEL8;v4**%krtlVOp{rOq)EJ*BaunGv&Y|b~0bHMG zna)QQC6v-72=-yxEl?RkIE~hoEDN>lhKM6GIgvpny~}6au5(v({EC(r2aVr%GCj*q z1?oy!QRme?;@*aY7dqdr8IN#xj3a@Kcg`3t2|xj_jo^PM_rLP0k9y*JMDV{6gm0MIrFT7^?42+p=R@?#oMvtUd z2E`m0{mQk_Q|M&`jS;Oo#CrT>{!e#Ot~YF03WFN&zT@4k2vd7O%ur8ARsVE1Sw<1l z8XXb7qEek#$qE*HI+i~8V(W-t`-HUrTo#eymg=hFlG&`Eo{ed^ceF_atI(d>?)uAU z8*f~jmQB_vDN(dig`mMurRbh94T(5Tt&gH7(9}#t{)s4}*l06ZT^75k~LEt*N#UszeEGzZC{~UCUMmr{*+Ft6Hy)&sD-s72v^R)9mn-N zooWcCFd$&|Vf4S3q*Df~v57Tl?ZlUqACst%T35cTrJobC1Km;)lfEj6#xp87HZsOp zW9W9#P74zIgE|e+B9VG`Xj4hS@O+&dDZ};Za#a~~AHx9b^yXaXKvNuqOsMQY=bfx3 zyH7!4z5V&JS-xKbfNp%8he3)@ei~b>hNSY`+q?wNQj*+RBrEO|f~6b#S-gf-r}4$0 zh_}EG^1}!~;t{VS{c^JP{D9i43Pta5#e#-dF6zCVe?{IOwASJHUy7jUa41FjRDS5sYjCsk3M)l77>XN?>vutgn19N&->je*dw#BZtfRh@8ysR7^ zO5iH}R$+PIrjN$sSRPY95izHWE?Pp6S1DM)KD87PjI$C2%@J9^S>26fwNEBF3+7Lq z)k;8pJ@V>U;1ayX*qLnCFmSZ z{LrIpjpifsokfNz$Tz5zhZ@q5@16Hd9W?t|hcER_7!d=a7TX}CUWSR|9ZeH7rQaX9 z53YOWQU*$>9Pm(Nt?|YTtri-s*mzyHxcFgNyf@q`#=}ddau^PBc z-GMgeu5R>?ej=RV_NXT{--B0$1^pU8fQo?^({0Lp0t`cBjOCr#ekD`&H6{?Mv+zEn z%5#`h)H?Z{moDk1JPvOAZb~f_P>{}OF|jR=`N*XnRyv+uA*-X}yyq?`l%u**F!D!! z&HmQaBtT$*(lmg3B=Y?w)3+pS1U67Z;DhpFde>V3z5IY?7-NMYrrGoF!g2^ z;W$@QEeLPR(EYKahiLN~fF55s)q^BTWDamyQ4J0wu8BK=gp5WSoNnPj7m#9GlbUIs zqtElIZL&#NZdD$+l-|-+e!`bz11uQWW5ZsOttuscU%Y&(Xo|XJx!PfwfRm;3*n6_< zzz84^{YhFwo`u5mAafo9{+W@XLeEw|sHZ(u#QzI+!o*yVdEP|clYG(MJE#N#v&};( z7LVgt?dOzvemQ@a!k5?*pwK9!U}KJ>cds?eFNMqMNqWUjJ}RchFgNB^=1QDU?T*ir zxU?K|n6)QQnVIFWe0qD@0VaeVcW_r+wn{;aP%c5Zjwe8%Vd_8vW-+*Y*b3=oUen8t zTO0Q1rsR+Lu$OgPT!8Gt-eBK{uPm*B!a|>&Jm|h4{A$CiKX5Cms2D0!!g7b=wwxb( zaJz}UD#qWl#ipTA&CbS|$T{MrUVGJ3xO1+bf5x5F+@+H%EZ-waqhJtsUuKkPc6vsS zyr#WGe^uOIDmZWwy?f@OS05gt3pQSdE@K$hHiA$aSW7%@p1P3{cztPqAc@S~?dDk0 zW6Yz7y1BHYlh|Wfw^j6PD4mIA_dqbB99&(PkW5dOlnKs&{Cx3LFa@4~S>Z{=VA0c~ zzgjrT!{#6?tdG19)5R~E9TITk74eISPZ0}{i~xSiRrS*lf8}zSHYyUdE4c=GJ4s73 z1ewY%x9KuPjT#6NVH6C>r(yYO?V*u2r_ydc&rLHI*I6bNjln2MiJi} z=O8UJkv}xQxQ**qg7wE;OiX}qLFXm4LfP5|x2$?dM|YW71sWk;_ZDmHN6#$r#6B8` zqJ3b{;m7B>*BK~=ehV)NMh+z4m4nd-H9XG9R81=@4oMgYo;gz6NGM&Ehvn8D{Sm^@ z(-<^Zd`Rx~oE4OBXqLy%^d{DH?J^*jGPbQ!U_ zj+6n}VzRrJ4e+NNQ(t^0ycM3(-TuU zR)Nuv@?Z+CNPp&QGyoYoj5cj32HC>D1|$H*V+&oxr2bq0$9C;Xtw^AEhS~YsKX3{p z{i8LLJkbVIW?_At`Pq~n!an;bAD@ZMAmygzYi7pJs_crs8=1i}p~>rVK8qw(_q_pm zJj4o^aJ}0iGVD*Kj{k)2fwF%k%-hnB6z}Cyc{+<)4az=3!lSg}opOgR-)3Aau(h9y zbGBLSL%8lXwzl5(OWI`jPUpeBjz2&6D}=-8|<7L z7ce35I$`uGo@b`5e8{tjBaBHv?ol?PnqgpaHqy`^8XWr(o@(TilK-qJsJ z^?DnVb@+g+1F5smRE&j~2-7@1zU1DTO~P9Wf@|bot-7#B-oxL{Ol`-__r^C3C@_@2 z*MOTb_}s04P<6U*_3t}k%|gpLZdGi-=a!8xTdu}wM z>VJvlS!#6dqb*~Z8$lDmA9Z|+B#S;K_vpmS9|2J1bVH?+H`NH(2rA1%?f^M^Ja<$JDR1)j1NyDcVdYjC7iIy%p5f(TpkP3h@9q)1H zIZWx609#FnY3)Uu+bKz|UBY2yii&1(kmVjO>DccsPc#`o4r@;~M2@_Dq= zk%hLX=kR~!36fa0Z;LDb-qh_`m|^@GbFALRMc-EdNaSyK!s0qMp~a&0!dl3 zyvyuwZY_KDcLktBO4wDb$?G?Tx3!1Xref;+J523q>b*9M9(5X3 z-O8v|_G-#iy|?Z3rVkb`+?ht_8|n_wBfQK{0U~8L>T=*>uRhVZqYg?Zj^4{Kue;t!hVpVsJ0oY=;! zcNCdwz5yA(08kceC>0+Y>6I8hf3AT!1dpYvI3%2m&Ez*^`pL`!Rn-D5g) zhjR!ACZ<2&+QGd{g^vgnNr!FT^OI3I3r^zyZCPXD5Jp_W2-~1ZIZx8~RRqzhm?#ziBW*cfe!0LZlR+}Ihyet?LXCtIkp0Kx zA=(~&HUu!v{C8c8vg2-2Jd4h&^#B?vIP}eIITxcZ$9G zO5mqTf71F^oDj>{hLBY;y6!p#T6)~ir|d>z=053I<-hforipNqTW#5J_Om-g!tI-q z5z}3sUaT1EV6AZ#%`o_Ft!?V6%eTN31{U{akiLXJ^j`LUA8QT>;!p}m&v7vKErk2% zD-O9YuKcCiuBY}ix@Z$?zv~$OxFXat0P;X(RtV$=VBet1N&Pk;B|~uaM~qipmHjrklH!{GC^n2q8Q4@JUs`w*^fm zAuQ|*3l>-2+x+>BJ*UvHQ%0463;Ot;Q0v9_G*(dpwA29FA@)jdW#*`2zBH0S=$Lej zBbyhq-s9YsE7=fDmWsv|8d;!ar29pT%$Bbl)GiI&rB z_e(hHrs505E(weYQ16c9i8_&EQhQZk*4uVx17GDx)l=;0nS0C)M`?e0)LpQ2XtA!s zJ#)rCb@aQ*b%w7_g28d?A^w$U#figiy%l6+Q%U%e8~o{wrTEUJow@RQA`K(LaZ$FS zV%LI4a6eTGssB8vQ`yqcytwh9T5MF^3GSiXrRPdT`EYYFA`>nUSSeoDQ<(%+C21-~ z^+RSh#vr>!u{M?;nH~J{9I#tpUN}&?!M}6(K}$5h1jHEw`e)<}lVmu)o>T{jZszaG zJ$6*QLu8-J*e8Zt=M)MV<0kl{mVHN}qvdH%;z)->jls|rFGl(8Stg9W`OzHNhy!aA zJL&2kHXMAaINDKfYyJQcd$9Aq)}}3ObIEN*%t50SGuG%tY|L8Z^91+m?LF+7DQ%=1 z6{zYP7Ha?_hVCMlk!};F_!66>O8$3cq!1Q~B(CkVUrwd&B(^!}tfo0=sXO3$^4N=~ z`stGBh92t8{e`mVm5G+Nwh2hXp>nYulaQVSmsN?D#|Zxc${8HI$yI35)H!=kl_NYMw2BKiIOND*OP`+B_NPRx=xh>V?;;#&$$-^LOyh=hdq?DoF5awpNXwE@=k(Juy%|^tEt?haSkMA9<=% z4|vBSdK8;lzetsvM2o{e-O2Ab9`=be4t1IKYq@F=KQ-RnWahN4`0Mgd!RYRW9ZLaZ| zo!6*4=si4zmF5`j2Ih6?S0N56BOKmjUXdogy=sT zPV(H^8s-XBe|)7VOVe;jdXEgKHse!y!}e2eaWmuI5<#R{t=D9d%`ox6k2;9BAHR6h@RYEqfw2vJc8#a}o%n{GwA10U=q?U}H&C|P z#~I>ZpgT@gp%GaX0zh@g7Fd2Il&(YPeN-lTQblH0nS8M5h})I)r>FfmFFAE0Ft4#uq{mWTNsy9y&$R7!UnpTw+yPiP zkust+`=~e3c4-~AztQoSG5a{{#UBN28|_yElA z$O?r9S}(yHw}01sv*4Lpxv(lC=cLE1IkBEv!BClGa>&884fJ~~tA6p`ADQfFxC+H8 z{6Vt1{ZYy`Xtbx=lA)X8SmBbeQ{8mxF1C3lO=G|n>tv5k?LJ-{^N>c&>F(FB%FTq2 zsi1^-i}a)Rtt;(x*i*j+Y}aK13Ez$E5tMY7d+Vc@?ZT_`+I66*8)(>fWS=}nIB*Vo z_<+Owq+fssCFzj(IUf?s6%#+!tzCJxE-|AvL`MRYO)CLYr3Et%6%|KmP9w zQD3kJi4bGLYCsA2TFipZWif5T{#vt(1Vz^oA(9u4Gh%p*U8Eb5U~5G4cMD?2lm@Y> zQ+PX)D`AOlIjf2IPXXv9AbrSG$(YldnO|H!x&)!WV6T%iS^5B~7BbZw6C`7;RrN3J zLrDhqQ@oo6?gcWt)P{5qy6P1LSOq=Ii{s#Eg&3(`dHDf}n#j(flkTczqM-LwG-sRF zGSeJondsYPmFVwvo;6LVOCjcLE%=J zr$9nTKOiIL45vml!LAZxf>hO^7rn8mQ5>5m-$gg= zN&5Rnv6PmjRvkhnb>VX8f?l7?KWeNySy**6LswpN}dU;Y5=kvoY1Y4R(^uc z=v>jNnKQmc9S`cEy`fJd{-xKS^FtDECUVuz_O`cCIG*4v!9fLnHIVHMdL?0HO@;}& z^iuOUq5M2}M-@JTCw#s69?-kUOg(-R!JuHmQ<-(OJn?x^isMwq)%hB9wm)S>$X(9+0C+hOUj%;m)LnraFwR`Z%B^`Yt>`ZCgB3#3=WWWvKfvtLVqzlDqV&z)b z!Ph5hApjIn7&Q2(Ncp_yS#*$#vW}2JIfW5+{uxg2v?Sg*MnxP?-4cNBX#KteLqSKR<&jV>Eg-7%Jf&LgOEz2`ECHAfonIp(Z%UKO^oO1E4D@<`|r*k)2;nka^E!Ib7c3|}6^6f|t44a4Z*D%GL~xc; zQCtIPBhm&7K?Q%&k1aO?&_K+2#9R2^8M;0?e=fNqGv0z=m|nP4DI(JvW!QlCz+gYn zV~RwG3NXX)ZO8cQ4l2fVe}L;p#o;sPVG$s65Dao zDp3SI+)={An_ZOw6w%M=aILZG6B-FL*C;7yJ@hANz@*AVoqb@~QS)Hr*&tNM8lyF~ zI$4Bd490_B%PN+d8>bNt(^ybsU;UdX0crHpe3Mz(t6Ow7O3i7yc(f3Q*u`at5Ce=+ zAtU|nwq`ebD>2FEJ@`uA;`ZMAe>?XknNHZ&pktimW|?Hk6q${_{~xv=FU8Lzl+=bZPBw}}+~_`TDap%kcPp&D5QSq|>)?hsRovyy2(buasU z42Y`E>EliRSgu%8b+>;j<3zU^2w2DCz?KGd;v z7ipTt;E7O=0PC*+h+%XUK~yEYr1)4gAWMYtUVsKmbW!pXU%Wv-_F>Go6?|e-QayWw zSF)uCXt;3=1p=H?AYqg*^+za z`8cIoBU*7I)`K7?B@6Wu4xPwIiuZpp*Tbh;`4-C>; zqwh|qQ#}w0nVbV=z35Ex);QPk2Aa#he%ehhNSy3tkE$WT;3Q&jI17kdw&~H{8MT7w`1Zy}b5;Eox5MqCzPdv_2uG*DJHB&vjBetFaL}PcnXaH{!x_^g z-QiQ;mA3-w94jUaDzm=`vxZ9c8mZT(ota=zvlLA`mnFA^2Fq6?oMWMeDjy)1bxMZV z6dzEMe$dQzt!!cRn+oUIaBjq1N}SoQkv@jBa@kG!a3_vc0qP`o6zT<%kL<2CC_I-jZPbNv?0o z_7JRTh2qg7riBp6Rk44Wl>>~D_w2L$?y5&3@a<~+%q18y*et1Mr6hG zb6-=7;jL?Ej*Plh1zAR9O4y@gUtUywS`VAUgp&&`L=}={L&Lzt8z*=ui(PfhZr7j74{$d6svP5RWF zO`sRGzp!bQ6ahL|AJsr?bg`|W|7SQ0&L&&&bwj;CrTe5@lRC@@+VFpXcGAP!;pqGd zIVU8J&V)~JMwmBffVI~GR@dAj<7vv8bS=Z0#nC7?t@h_@a=7rs)_ltRv>>L^bt0VM zMB8OJZ|tj9vuq`?2Q-1`72d?i$OP5=+0m;mtI>fK9VMmcR#y346SLqIEF}4vuvh8 z)tCQHDxGb2O~8>>R{imJ>r+> zKX@?l2K)+`da`2J&cTZ&{|nT6Q0#RG&Q6YM1yZ#L$9f;V6CFe!*etf(6{P)^jVUq7 zrMwy6JT>l1cq+AxoP{)Z`GR<ipN~`a~Ps);FPjDTa~=*R2%`RzmunovoxSfWanVfQx&vpwd6&Q?9u1ne5Vo zZVJquUWU=4Q;-sBn=*Yg($Y}n*5PcN3A$L9A{f6f&8K&rh2CZRmLRAe>0r?dg}{x- ze|g;9nq7XFd((3=dDS@4d`P2mlGMF9`^c;*_Fp(YGwXGRYZnx$8lbj-T=G-%C|6M=O#r(TztrHL&3$wg~H`bMmzI)p5qM1%mr z9=ogVD;ozIHonKRU+ed6#)?;(=8^FgEF#IoWA{|IoZ)BYCD6^yMp@h46Q?KCp4WV~ z>8#y+Z)0X%kT1K_~@iQ2C_U9(2qyva5Z{Z_ya=v@i5ghF$JsZo0a5u z#P5Z$d*Z5R+KR8MjM#eFN4tgdy^x!mX8uM?7!YEd6a>Hak8LSfcs)BfmIh{l zSW+nUMoRdP?(!0kw4_FI!{n~;cU|A&MQO*Q)&%;`A%&1Xo-FDfmCGFnq86tn*|&*! zs~(y`TGBc%X>>kod7K9>1-tMsn&`J!J|weOq=nQsvIp;AFUFes%f?kKX-X{BqIM(> zQ6lSqyNR|JW4_5aJ`kSjTG@a>agA}OEhZ-QwnGjiyh&eoa~_?)X1gn8UVq+KFg2{1 zGQ}lZDeCv0ukNzk{OQx4#=er3hlLA#jzkR!^$nu9fmb^wfLBzqniKLKE^fdY#+Qgm_gX! zYbRJB000001UJzlrHIJoB}9Vr)UXE{Ra03!cx>#jiOf9zGHDf)V1Pco+`FUH20@TX zeSQD{0001vT5gmV%SbdT51R5PP$KBhUizz#YCt_EO9qwL?R$k1h>>;#<>Hg=$AHLK9y zZ)YG^F9B26rlJ9GUhxqIX)0B)8GpFKslb{evdEXIlC$wxAUa_zund~~wXaeZ`z2*i z>Y}k|*Bo)~qRIlI2 z2`+u2cEzNOlZETTfS6+Y=$NBdI>S*VW#79ARdUdny%_z6u;>UL;++zJh)(NZ6w=vO z^bUd%zU@Od)&vRj1r{7lJB)xF9!_0u&$4{4{7G4PM*u1DKPO7^Vm$OGE0`#6!kfB48DAIN^GSD>($IK+vH zHIm>NH^H0gz8}LPKzY7F;d6~qW_3s{Ek51Fi_0sK5L=5N*mA`CpBV<|Y-3QpsMKqv z;l2#99qa_1Qyeu9e<3$^Rf%Hv$X6h>0igC9h|Q(H;l%4W7ehMMFF!0Oq&TgwxrDBW z^r)tE{oGTcP!)4%m`6J8b9;$3^~8$b*nGmhfCsQ@QvddbjnnuS5dK3*HXN}&=f*+0 z8ni2rT7b}d4a8vmlc+I4>6sj3x1WhGPu3no-kt}eV}U{Bz%Ul5ld&o{%DF1#6{FH{RI0000msGO?s009Q&@oBbaTmS&cZO8j^__-$5 zFhBr2{{CPsoA1E`Y=~r0+GxBQQ{d@g{l0!g9KeLOR$R_Oe&KN>?sjmxF3k>BECaIk zxH6YWyBUix$9bTmRtp8=O2&K~ZXRm#viDpbv_pB-#I5nJ8I;hmxyx+|tLhqX0 zzjrl%AGC$=oVW-KEKP>xJr$bhy+c4};|2la7J$_}?A&YA$Y|bsIG;CJqSa($9fT|crkygW`q*?#gWg$gVDwt#(xYxMM9OxNA z|6l?u?hb|KA=NLgK>2Os+hvfBFMHMtTxpfFgVA22imZ|K*zdwivdoqhIDzMrv_h5+ z@+)kUOeD-BN-HNpnHeDHwu~`=FX&6QMs$K%AydG*0`Bk+<8i)>jC1enE(AK2N3j2TEeMrt2AENL3?UR+_HWU#vtZd?&Z0HICML>Haqi&id@$V ztbYhCYoV>)zK8jJ38A>kQ8fO<B6A0g^jEnRel zj#!Bynyf+R8+Yo3$T?vwFj0MiI1JS_w*3Zx=;G^qb;sdp?~j0qqlYJYlE|3hia;^= zL?SsLcXi?8i%FVE8Kuze+7Gp7tvCZT1~84i6x$BV)%(MKW9KMD5ka|;B@EU0z))FP)p1;_AtdO- z4qWURhn`}dgNQ6c2>!oAQTtidR@Xuu2x@7PN5V=VG=JIZsl}ZhnB)E&C*Jr%C&|KI zjI>7_r@&C`Uewt5!~ueEfgevnINjcC@#ANs;g$Jz{3HTswUR8YBbgQ$RL^fa6iFyR z?0kx?PhFz`P=IBxX))q*90s%CH4$U93^*;}+@`T5G>-DRQU*2OZ%{MJi+nOY) zb~K>{qm-oiZ(vYuH^$lxn*e)MZDw_N zODie2*Hx7xeV#$u_p*8LhY^+&=&^QyitXk$#b0>;2(slHD-9#K0Mq;@uLBWT_CQa^ z5n73!!NCq@B^fm-*yTX(NS0<>0g6_V7`WG_x7S~riTctQ00iO67Sb1nfR1x36i8d4 zvLKV)eDF^@ke-IIBgAorX@V6<00+7hX=fGG%VP2CIi!1-Y+@0VCFEf~8kUqbnf2%`89Wic>Ej~U&&G8mve;PDhL z*vEzsXx6Nh0Ioj5^2^0UxAWLecu!bYM$koIeZFUqchTZL#0=(ha2Xi7)M75KC)DEsoI0ui^T%z7!+I2I=E%^PA})3yr-l!Iufu~Y1rH(+v_b- zg$r7eC;^G>dRiFx6o^YQd4P(eP|+KNfA*8GdXwew{`H2IE&Ni$dzo$bQ+r?=CoDqO zHo{-8CZk=RA>U>@mA;BW(s6(tqyyq`Bb$2q)5d}hIvarDnvvIkFS4ECUv>hU-)mnh z$it8u8Vy&_Z$k)phO{P!2+rG z?#>kwg!=7Q^9$C9$egLnc?2Vi(B_xjx;-KhGEf^DHnhn$M5ms<1aS*cH5F%69Ay(B zm|sv9KQj-67M+dT7Hrw~GMPH^3n*hut^aUt2Qy5K?e`q8nd+piw`bWYIZD$!MXZf_ z^yL9zFng6g%5lX==(5k!fZ!xkTummzu1@+_kLEBGTW&Zz)`ux5{m8e(h2OIvLWLi- zfBZ9oU*2^f834`Wj#}!)f)T6A)SOTNE{RrLR&E_Mz53}bF7P!nY|<;Vu>7tPs!(@q z{?N0X=PVh(2);wTaDFudJ^qMtaWmwqF&VxpQunQ!&k-PKvIvV1<&DDKlaf>vXUC@g zz#1@SaKc(T&g}PNO0pANCY&;{OLbgOC~YgI6(+5yCntTzf#0#N_XU6-Rp` z->GAcM0L|h(d(4_+{*OOoyRY%iD=k5smf~3(Y?G{xUs)OS%g~& z?P}6FL^H3dOg@C%{uixSTBq7#gFLGV5wDe4xh4Ipwr zT~+)t!P2lm&Wb1)tZGy?Z9*@p!`+SV1awXiEW!nRmMoBzg(E z1aqXi4v?g#)c8)Im%pEiIad)H1%?O_x~1VY9)AaJ4)j}Qr5IsR30H3ELtFCZn@9-n z=VLCyR~uI@Ty=oy7?!h6qf0-X!uetS1ugP^1R;3+IsLA|CeIB6gqg?Aj;3`$nMApq zw#_>6ni$}?csjiYz~WL{QW-wq==5;8;hco}z?-MGZ$R{%{X*_z~NF#^G!{e9^yM-8<#vlhKp0ze(w9Z zydAcdf8}r;j8eq2g!3y|K4v)9OwFs^SXf#|ptYU0>T)ymHw`@4&c7s+h{ ze1HSBR90B--(g?#mj^_Axiuf#y8=zOFX!6xnJbJQXsI-7Rb@-e<7?zf))fQB2E8wG z@QJksfNyVJ1zurw6pxv3aViH~AFi;>-7mnJ+JefR&}CQCZ@Z}7xNi}=%nqG~a`(Xs z(RX)RNDW|s=)F8G!5~_Q0(YWDVqW#}tydzxofrfbVsr-dqzoiE{lQQG0J`h)6h(~= zD$_^k$@LYNsajv$Q`&^FEO@zE`LU`NrjJtHu#{e0#4j$FxY}*R>-c=FPU`upE)xYpmGq<1hkPECv*5D@k?co=(yZzfYCHFV+YX^81cKB2AT^;c_@ zb%-$`!xlt=+%rG>@_twWt8eam9gR!>S#I1keHMl+KD(0M^R_OqLAk%Qhr zb{y^1S~>AQDx#~MU$fr6*2|R%Te*|Kv2rc@Qqa9JCA_Fuf1mP|2fWh4&-_BOfQMM+EW#tu+VfT zn!x?zXBM_YaLJ~e()7Gv)c$*wJc*-9YX1oI%(0p8BB-+tW4&j&8$@Q&u|_EA`3b7W zev#%7T2}N8AF29MN<^rO;D6$XE>`u4Ms$ubyhGaAFu)rmt~QAgV@? zZXd*f(J)o1Fc8!b<9^z|4TMaLV*9gwJj+*lDv6+MfQS{K8qU|m1>1}|%;nmh9MGB))GB3JQ*dQB@HZWFQZYUY$YFT;dO z#3PIa-WH^rImAr9>NV0!Hbei_@m)F8th;~@#Y4~_7 zWgXt`q2zoHC)2E-Ozn(NQzR$iRSM{zOA+HJkks8G&a{W&f=m=ngpGdBk^G9&=$!_f zM+Kkm9i9~lxrm`X4QFdFD+ESHm0#6^3bOa>J0_}>?ysoVUX)m1cF(_R6~t(1RJE?+ zLva2Z{}Aehxaic7a3yB=CE$-oos7r^_o8K2@KhzD6p6f6fuhz302b82Df(Db zb&bNpJB$uL?1cO=5nnS&tA}{OCXP%@JKsD?psL0s%a>tHh$QhfL+YR)ufHNX~xb|l&76VM$@+b(y~=U zHG#xW2kjC=;7~lu?soqeNoB4lzyKl*9OW_0fYPOIPkW$l;17H4D;33Ea0vE9pOFsz z1nOCOb|VR3m_)8bNPCLE zR1qs&G(zG==9InC%WUP`0GBQGWy!7c!0!lkLk)IsNzNC%{@}!GpGf%R#~ndoJT*Kv z;kxZDPG*E0D`xF-)rIKgmvHexA#QgUKkg**yS-u)=4}a2fx4fCFz&pUZAg2}&7AAY z&~gK4ofb1$ewc`bZXltHHd2I|`fA_+oOjmvxBoPSH{(~7d4IAGV!g40UCy{A&Nt5l zB7cDLfC2aSdY@z;daUG+Z_u(zI~q^ogUm@!0$nl7D-4?;?!eo5Jbl(Tyx-9?y4;ld zb&-R5I+Px-L>07)(~qn4-TcOFM!#>_#Rc(8xq}{=@<^a&AxOY%b4Z{Cc{c3OwUpra zKbX+mtH(tdRPk!JI#gXR{AgDvJVS27U|2A=Y$frk)$Vo`Zu58c;S*iGRJ$`dhP{@t zI6&avh2aCA7JIon@COw(KoKfq_nj23K9zw!kW`qizxuk5*$$?D*QDgY8$baEJL<*a z{s?oOTxY7JdY?`MQQ|XdGSCJjNw8XnVuh<6%IE4WDA#d1wzdg9yAL`f@)^Wl5&kM! zw!l>U0Vg&x8y*F!)kw{BtbjGSEcG(R6MCfjyWWZhAK@o~~4FfyHj<*F@4pwlNu@yZLh%y^vRqzZOce91>@V+49N|EBk{megv8?j5S3{n8^) zkw#l+)RorL$)kLtP&}b?#4+xH z)u8{sK8USAe#d0YyMi?!{-tZntoHeDcJE?Zad%p&&N%ex#2dfg;VB}1(Y+A80}&0_ zbgmQFB*a4oKp+@8uFd{(8C5QBAxv}<6+3SNPRfpS|48_vXhy{qMy&^x^|@hj~|!MFz~dD10Enw!)9%fPW#zyMXmM^*Y4iwzb$U#f0)!d8{RQrH#xR=N?8KdNK@hHFCBWVlh-52~s>v;LP6ornR*bmAaI@)? zt>^GcvadN|<>@T2#XMK;{Q*qD{gUcM8fC*Tdj(Z5F^xQ+OTHS`dypJU5#UD9TS1k)6x>r#LPWZY3__jjU{AyXQV##>#ZIJued24|PE3SbXlDtEQ_fK6 zj5XazZ=bd4VqykIH#>s^tr?2=iIpj2I1B^dnuK2DFi+P7vEeD*l!+SVc$rgrIjD=c-;Ee#HKtG7TAvo&NV*kXC+{07~2oXX* zZh~GNbzm1r6+ZzmZhZUZ>{NV!JsNkTkij8&04@PJqKU*SfV{p6VMJYa0?N6+y3aU=8gT2>p=*!u7DVTS(L0)u8FkxH?%C(3v1r?MO@41 z&P5@fks@lI9CjODnG?R!$2ZGSP<3^UXxcElr?79aEx0)Y|U;NgwMB&`k&8vqviE3 z)MVN4JFVmR*|LL)*_6tcLO)yae_M%VA~xC`0(ptKfu@Y_Tf#Y)(Mb1GswF?&D?(Ia zV5HjHK&S&g05BdWzH|!`$G8RknLvazPe3ZnaMBiXGiIQ@!=Jg70FbXIF=G@|o*RV_ z+5{rRq=l=O6!cW<|OV#Y!ra*Q6;Iu>lsqMjGNADFHk8(Nu$@mex z?`8ny59<>K_IQLqxN4lW&=_4O`m%R)Gmib)OjgGI1vBzTY)wHNVjCdL}5I}6$B55=_9kY zEUdu9wU2;eTC6D%lwQ+s5`I@CcoWM<>HhF6j?cP!f=QZoA~!UL(@OL)5SFJKXKMdR z!_r^_lif;MTg_dNPN&+Tf%9D?pzT`mhPO5J{(H0)$0lxTB}(Nam4XnN(%|+Koy88X z9wwZ*>PCbg4juMOF#@R^tN64+Ko_P={~&O17h~D=oLmfl>jbLu> zGo%JePE&yC!anH+B)n+)T|2mi7He)kMFrP0L39Ou|{H#Uc|zDOZVK__0+$cMUbx%K!iX z03&s{%CfH#0003bMpDA~q|nP8t1s0+01oXKhaPPt04sqYwlK zC58rJuoZ7ZcX&mgUeknhP7cA#8Dl1fD?3)DBdnD98~f`k0ZN!fT1lhFLP`H+2DKt6 z{RKR%g)YzyPeLT?OEfg?p)qG33gU0`bn(c0n;6gA1voAu)P?u*2SRhOZsp`YNJ|0f zsdnLL7Me5F<@zkretL91Eo$WSsW|%bBilTAA^^nJe2X$(J?1j(a&495eT+CWj)Rn=d z^U3(p#nc;onfM(ApZ^~K#7F2rLVKYoWvx&xnkxxbl7FXNxqG6Kj4s|_dQIs_JhNr} z@jL}Ihz#8%7V~LqP*vM-b`Q^JsTJGF^MqCj?B&zCV0xS~HrY(2t{dJ;T~us`xA1D9 zm!th+9(b2Qfw+?FCns@mF&QmFta~b!rFqg>&E)x1xf01`13P)CXK)h|KofB(dQk!(GCVqIWg?OX@-D}97xYyY1u3fxCxw(U zNhg6n8p~t&i!vKTo;+E6^R|{lUcFkC&>kW0kTFUt$I&Nbw5qD=^^HLwAGpk3;j~_Y;HPgqG?v2`G{2HJqKUQpR;^7 zg79ZcY1rC!O{4lUMzYj6PvAh{1l<$4-gdgaPOLydR-cCc z2^o|kW#I|V;dyZoJhX`lgHdAcl|U*@ARgZjUWY<1UCGqhGPH@g6qJq9u5wHK=~te! z`|Rf+Ek7IU62d@MoNh3=A82`Tou+0kC*<3OT$zYX20_7ss+!`|9{B{uVIcqA-AkN^=@13AA$sDMM)V`-nO)f_y zDR93kb4_KBbGM2A|KlU#RLp!hAEBFl6)yE0e^*f``0xM$l5tc!+f0eF%sfeWV&gX9 zjh_SocA1QD+{tC{cW0kRSYt)#@lOoZVas6b6ZIx7VPQ^@n<>LEOyEgDX*I|#fivHP zuX+C*rv%VdRM#?L^|;s!mpsIsSVLhbU_xFf=vkuL!m+H|)YQ;MHtvrH>KC=A#qHl? zE%$DZnNo%FW$`^GsWmc3@B%7^k_?CG*exD^*lP4GsNzXpnTg#o16dtn-2bXBq-=Yn z`QC|=&V$G=bKXnudaH~B3THrmZVjA`*MHE&7d-JW!c^QR=<}TQ?3bYU8NW|4HhsV9 zT=VwzW^tjqOe-zY6Ag>dfVRtIqt-bW>tD1X^b6R^nF2yhyahB!O4>x9sq|y?GQW+7N)$g}<#7I*Deg+& z_Nw+@GzQgp{tW>8U9)ymyXvNS_eJRas(z;$;9eYq*!sVmg&;Vwi>yKaT1OE_ww_4wQig|ju1G82D=%lOXnHY zqf{1zObHF}^?dV_=+zRKB|zu2ssl0K-(TSt9PZ+TT6`w1X$8uCrE_*Y#FG184q>o; zcysVlg|a3$@6i^$y38@~=BtOojmhT*2AkBBBSExgSJlLdz!XIke;9z9@rZHwT0P)H z!lSr+SmPSMio>XN#9Hr=!M%ijIF_FiEb)i!(z^-AxD2Uyx1%vD4lgRkK5*_ML73C{^3afpOdG7jTEDkrb z-Ls?9jiy2%zB3qn3*{u-UcwinJhf-U4-(EkZpU z#F>Fb%clG<^BhE$dUokkAGNFzxgAtT?qZP~cPnOhvY;BzTl9W)4#-iF^-@{vOd7>diW z3{Wc%JWPN)6B|(<^w@zidAlO^Ca zQOC$9I(I4QLV{c>c=H1r{qiv`_O}=afhP&yZ7o*U}K zI0ACOMZ0B|t|;M;h#ZCP@AxLUz$U#y9Ab?=h=847R|~A;sNywg`a|7Knpt+!OcGYN z;q8(|htwWKM-?;3oKBWWf_IsW7~qc&FmJpL{wmj;_N9|UBm_bBY3u&!mfQA<7bHls zqt=Zv=mwaT(BC_sNvkKw%aZZH7X(z2Uf3O%sjoyYjwVa&uiJ3$ql?bLxF!RMdQWDJfNS4{`r z-(KnXb>)*5Xmjm;u5R&!)T7+>XESEEo$NVY%fMI4Eh9$c`Q^YK%BR&$jgVD;u~y5( zg@Iq%+JoLfw%4;gJDf`L|9CS1A5(Kkog}ctXG-RQ!_ zAKD(}l7LBtF_bHdVWDQk*iLCsk37{1xuoZvoz37}Q7Pb_mZdU1;l2O3_da#lngGFA z=vs*wI-%eMG5+-~5VwkcypLbFyo1kMN+|GPkg!_xg^ofzFPlBtbrVzV(0+-QHb)INXH_nT>x-FgnwYl|_~ z;i7#`Zcwp+m{q0+sJy4s;exIikKRwADQj<9O3)B0dU?%!H{Y)if zDO91QMZ9~nm+-Pp>_a9jU0hDi((L}nF|aOY9!#heJfHp(jpdl5{Num*m0n~*QvN%7 z`ly6n)#tuGP60J!HhriUybm5WN&bgOv+rbY$H0!xv>fc=fJR`K=S|t8xCJct)uhSA zO+^X9=cR_Hi8!`xPU)>-2{?ZKCh9o6k8}C+%C<8=pHU4adj$&%^czJ9gLN zDD0guuy^Mji4U8Xs_`FHzE)I~Xot@sEuNxl?#wfik27XA!&3|o)6?!b;i`UnjV|Mg zo6>ecrsrZtbs3xaYdC~ou?(KFi1pMs(OuDWhd~n@!Bq6Abwd$)poZ>}m<4Z^%K^}# zXqeYxBcJqfMC#S$V49BTzuOUI02DFtdu%-U^8^nJ71b2t7b~KK%&+g z{E3(elP_LvNSr#&5Bsr zz?Lko$$&izhauePCa2m~__Hq3_mp&28$uT+2y__!Yh-L1$i5dxyLYt`F6|>fwt`5@ zQE0lbz;(+COx8Ok55v1H>;ESs<(rr`XYGp8Wil8IbB*AEh9&5VtEvut{ZqG%`@!E6 z7%d}-#rIgAoxK`e)6?o=S5;XP$YxM4tnhsLU+I3Btcx$EbRHM|P`)>j_6J6BT%QS} z*dPXf2g_+|=fbXw!J+;;EGHDLbQ_F0cUI7oA*IDeq@(R|78v{R(<19^tRYfF^u9q} zsFP)Zzt~{sxo*%>+v9N{>&uln4fpTHhNoV)R08OE#c`cfVb$+*^TzY-N}tII>|+06 z5Sq>U(7VW7e5l*L7O(Bv7L$NZq}vS7tGLaZe!HUt&(H?W#)^C_>01vpVhvz@9MAVR znyhndJ5nCp#pG{N0MLniDj$nOxe+k`zAW5$K zx_UkkH8Kf|H+IfTUa901yo_)GN?h_pz+EaRnX5N@5%l|*hmqjM2t!4uA7OBIM4uFv zcz{IT#=+SU*c`ST|Hz!hiEwHf>4^VgS_|(;FKd)+B_A^z3OV8E_;qVEP+)`y1WqZjVj6 z0(G>Ky`78FZ7=;bU10cS`Pnr~1onM{C$lR5^p9YBUS#NdB0cl)n?%V!L<;)-Sx9&j z|25@TJSj(fRuo*M#q@GcYb~K$jo8iEVO?9Kp{5WOG@lC5bo=~yTE~#%fkZe_`aPO? zCQ$XFw>hy5W}&|XQ_ve-x8f4wWoJLI94d_YzPErdYQw2Bf3HHi9F&xh_}4P&lsOl; zfN;ojNZ9S0%12}SwNyCAd1}ZudvhdCB_uXzlYN(GkY6Z^8Y0Kb?++Rh=gyx`u@^33{yNXfO|Q;2eRID z5p&Jb0w(P2zUlIL9C*Linsiwsq71;L%AD;#LBb*-@oRv`=5(;No_HWdwdo8m`9*7l zI~m(*6_?_P%peAM)1Ys(wEAABsVgaBYXH2nQvcPsj@~|&?Z4vM*@TM zr11#~&_dE|_7|`4caJcHL)|DVdK-EdLyfk1A>g4Lh|OH524-!Qe^4Vo4PA zxKhI`-aZw+*PB-mjNM`=56~?ZG%gF#j12~LPPDxwm$&b>JdNf=&|;>XbayjtW0I}V z<~Kkg6Cv`}&KY<_9f(5qHD;bRH4~?X8!d4InV}NS@wpf=<>c?XKEa~z3o;W0jxlEc zJAf&6)~b2>LXMpWC*QUYjHz$?_$F^QHxe*FGFC%hiUi>QloiOH)O7bfg7eXvpp5g9 z!DZe5GCBvKT;Kci?gi7n6v*Bl0*1?c0(t5TlgeiPwQr~h^#Hh;bV05l7>+2i%?h3< z=I^MnQxhXGJ$eCEIWi63Kj92=EjDhg*&-={XO$Mx*zQ;zAoMcWjy`diGJixTcWVSI zYq({D^SA>@P9yM+LVsHuU(@prWV8BP)TxxTI{3G}t2FjA``R?0iM&9{dtP*qgR4pz z?ePWAzv$OhBCM|9GJx+}H+-&Xm!Bp#yzpPQ4#f3?xHVt{h4|!zbh}W$#mON{*3iT9 z>U0Lu-bIH5XTvo`p%(|8#3qxcevIA$5+v>0EdtR%UClF=5N;#8@tuF^Pw=3{Z0FxT zv?|RFR2-PtdOC?gL{6NxNxtU+uHv2H70ttP!p(%${U4kJyU;6D^(ZV2U+FWF`E~NT zKp(LgHrvJQA&T*#P^N zxGHyTM>+vKN8LzQGxZ#GVx2jg!}R>>EK1Zr{nDk4)_g=lQ?NED;S(l;m)|X#i~wGU z>HXc*;QOay>Y*-UlkU8EI~b-j+y&PqjFBFI){4-dnvFU2z!`2_H;LZMg#CxUgYfBb zV)#dn0FsZRY62ooHf8eZ4iStN=tI2q*pQpAgeUrj;)e*Z*k>n8I8TFGo$X$lMS=cHXnKjNf!@`b1}T9m$o3`-`fRE zW}{}x@{nygEMObP`%56tv6gE_Z%P<|4)spvkR@$DINJxlya{cqhD-QNuka$`S~E(3 zQq!Die)LJD_%naRu??iEbpSDFesb;2Z?{1S*y#ppRKVyHzNR66nl$Zumwez`AVJ3D zvtvG)OZnMW9?mCv>i(0yy4$-HUU^&5dUm+6{!QvsWS9ioynkyXNkLA1thc2#k7NN6 zou>kVzr`?|fz=`OS6bYinO@1D!I8tN@Qc3QUrpPrvt}`yK<27Vhl-h4jgbL*YuOM- zUqk_acn|{GCq|FL*T{xQU~ch!0&XIXy5K5_-Vnk$8C)NDfo!$a+wP{xN-7UY#?V6j z7IYYFnl$#LL4DKw2FVpZ);wY|U`n7F)Z6&Gjb)cGyy+G~VSs6tnv7&9t-MGp23;Mj zdnj#Q%F-|SmHPTJJ~p4qR1)8~K-qn(&VH1rlp#KAwtth&H)DObR$x-|-v{7#&C_MZ zjJ-~v3%Kdm12^QJ2&W?_@N=B7B7XjKDqBq<*hL4X`i8rpPDwPeBRAVsPum-`lVRJwTOW+Plo2e`;D?H&`mRuzfJzlF;+fVy?Euv(_ zX1GN(rKt=su1!x_a}tWla5Y6}#sdBf@|5{xBF(%eF93(i*Q5)=zYkMR+@UfV%dLkr z@n0$SCj=(RAPoJbDzaV_RF<0s>Y#nUVB|-_>)#@xtwp`N5~qX=+%2<4$5vo^voFQ3 zYm$~XQVRAz;ULv{Ll+HbuT!f+%fbY z`*S_{{2w8wTlCu<0WaB;4xK2v4ZGUPP$?V2ab<%X##i ziG^*_IgQpA4pPahVE<}N0H}!T)qGuKEzRvZMEA!1L{*@L-$@_G)=eI4!r`~Gp;NR} zuIRVqv4{QgT!6>hHZ1|(dgVT&=jzyT7H%K;L(R_(Pl?B)CfFpIz2K+?YGrzIz@GW< z0B_Q;$fhA%M^q`;BEme!wum09>xHVT*Vgo%ezfu)t^aByg<<1`-82%=9!R{D1zsq} zRm~wDxLjt7-!hq_quAU9}M4nbkp{JRIZegP$0e-KbEwxa|JdvBD z*U4_8nYNMdwht9HMaZ!Ogta|{I1IOrqAY2ouK(4*a*w*%vAoqM=fhL|cu&_YfWXa@ z;eNrTZL_9KF1bK%U0$XLhBU8kD8(^({JDndUR)N03di5wGJ|0jM_8IKL?qfGQI%L} zop}j9bUs&aGA%{bBy-M7n7Wcl_0zMbfg4d8Qg)8NAByQ{o8k!(_w2OY45+-+At!){ zOALu}LwX-2ML?wuhO$262ZWdAqzH;^ta^+9+k{f=BNp-^6gy9lXg)AajZihyS$;yz zKZ3R~vgpo1aVJm>DYk(K)Uh7WKPYKZhf3buY1FMfL((| z+y5vm(EV! zFz6yBBEa_T3nOYrlTN1FGaRtO+;PiU`Bz=Q&c#zQt_!2!1ZX^s#xu5Wx(n~jJ!9?0{r-oJ(j zc16wSkwWy~Md!7|u}B4SEH0@7_5c6?0b---riklGwzhPt_o%&oe5MUx31Av7{?UG@ zZV!VyWL{2C|K~8)B(y@&G$I3Z)QxbE3&M}g{D|PE3dXsAo#f7d00000 z000000000000000063SW^jmvr0?NP8J9av8HP_}C-el8>-}(Zi7_bq@Ns9nB_+U0i zEjVAB)r~=j2;OAViQn3sPX5&5clM_n80vF~Ky(777Q!o`w5w;g0000M`nk`SJfAB% zfB*mhw4MT?M9Y23C6{;)a9l`-!)xN-icb;!a@=LhC9_1ERt=SseRF)QBRqc1AV#zpPNLN zKTN^|l=fWl7h}V76DA>~XsG*VlrkQJ<1QL1YL~?}EY)N@Q2U>PXT}^yq1yO14eSK$ z0e9+?L@GEUnoKHfV;mgbYqv<7F7U5Epk6WiNZEQT2)uL(=4vxu z00=i3klxN%gD>8Sb%Aa7LfNKV-#!pnXuxFVOv;lOgY;=@haO>$B5SaSO-HNH~oh%z}&7s8cO*1ag^FY z5J!I>ashy8M}w(YZ<*2K#vFGC#Y+N>K&gQ@kF@RqS42j9kFx+J1p`u2*J^KkE^47s z#cCy#B0jZ%dHif$q_i;3&QF@}6g7n*urh2XgRjJY#LxgMjq!9=^=<9YK3xfD(5g(} z9GKxHGgRONRnh=ooTrO*YG(LM$ke0Uc^59NC`==xcS%wL@ETm$f*Ajs2mo~=EH-yj z5Q$0;Pf3}cS4f_6%~RNB)n$*RfXO;n*+I3M2ZRX`yG_M9ve2WWk!-DC00_ryNxR{{ zoJyJvhDo;qSH2?PVid=pEwZNF5b~tlvc){YUEDl`7TQiU=R3tj2i`lT4PMK|=}iW~~)%?CuM27`1S2R89sN4MU|xieoj*zCa<2hig63kR#NiqBUFC>nMP% zq|j)~(#F|(uPf95ZF@{Gkji`20f+fQqKHm3hYPn52^F+;LD=l9Be-lQmd7plEoVH4 z@k%gAD)?4jo}A<|reTIr$^S4Nm=n1xDGnpIYs)S^n+p+X`3~r6yWQ?R`@-xM;|=USK=V;KQOEET z=7#aZCq=F!&aj)aAi;Um_Ku2LPsD0SE%=d`l^VdJV3q*L(`{KrwzqF{L{<@wZ_(UY zB^YXAu+%^f`??w?*9w9-wVYfpgnr9$Q=G=NvGtH%(eD-eLK`OPC+cvMQ+_#_#Xz?5 zuv2)<&V36d7pM}e&h`Ad$GC2#35oe%6&0>cw0hDyLn_t5ql-e!TfKUp^hj%wefkz; z$yh`w8w;=bZ-KzPJ&yz1D&jtF+V$Akv}B14rarlPjG$wTXPP1=6bdaa3fo-Yj7m@X zo!9gog%0tRZY7DXmd=rdNeJo@T=iZQ=B5jx<<0>_^vba&+ZG0}+MB+1x!P(K#v8e; z$&#ujJ%3Qsnm%v0!sc5iWX?`NG@oEPm!;=<>+}bLBjP_#yF}4V0Mz=?e!j@QIkv1L z6t8z@51ey;-0`EdmF3XDDU+{)UtUQ{l~t-vR51$xSG%jN3*Z*ch0c&~Id&26x5=Y##Ra)6z(7#8jYNjzCjB%r6I)i-k| z4<+o&1{-g_zSB3U)8m8G|Cy)W#-@uV4|8!^nXBy6^}_4JNmDG}nEhS8nA?+M0mCw2 zAN*14Tn+SSY|_(N;f6_dN%@}}nOXg()*6#=bB|ah6ta4-EJvNsY3<>8LVFDSio#p1wxF@tMim7nz2~5g)K53v3DxzFZbJYE`A#} zh%(%hd#3$ak_UZ^0@@%2TPQ?=6`vBP@N#(E&c|T;?U`he{fGU6VrtKJWIhx|&vPO` z8LaeFrx9XcE7DbZwMh^~>S(G8JHrm037h6fwmvdP>BHLawn7#CQv$5Oj+pLOv47|f z_zig_wZmv?69x(>f^=6FF|>E0043l~6uehXd!)E37%u;NV0%L{p~TIVDFwZctl~tI z*)n$#dQ3EnY;@V7!V8sh+K@|pDsiR-J^{m00nGL(nHpNkf?D-r?%Zl6^g?3$i0(yGhZcT z`S*@i_jg+1t)Oz9(i+Xs#eTz3)2WZk9gpHy_3L;~3103L;RAKh9F*-QPh(VzM_J%O zdlClEU^lY?Fv#)}Fzy-c^&;v*$H#R^30I?nG{K^!;WZ#m?TnLyBATrfi(~d0Ih`s< zNU0jWFpZu$A+!A(9%6-&c!j6C`7^Rq4dbo=pH~{JrFl$9>BeXpC-4VqvJzvgm@P9p zOd19a*z~Dq_a7_}2=9ti8y!Jx`MZ_irvS}R&b+6LM9)4hlDHU`TLn0hb(VRiGDw9= zl&NKF6bxg8-;T*6hU)uBD^@~MrRC%4ygGUvJ5P+acdSt+VPo=pV_YG3)q*}^ zQ=o8{5id_^%n$4>=@ym=X*ICy1R!Qx(yY>urnKS%>!Zwqe-RO5xN&7IJ zIb8++%RsdhU0arn@Zyger@kL?OVc>CA{eW*o1+S1R2x4dL;2@lR+^fRKD05-hyDaC zj9V+3Bn$)(z4~Gngttn#;J^L>y@6%EMlYcts8#Bk=C`^B2WW{eZhu}cXGntSnE?UNch zu$Dv<%2GtyQI+eL=$Xuyh+i`?fB|%au?(`Cb=l>Vz)ogQ7!ueEb79W0Px=D{YrVJ? z3m~j&;`=|iDA!#B&c`GgFd9MBL*>@6be{ zE#xFreuJxSUw*S!Bc{BV7%#U!4fRNM3SNJp3E+Isz_?vVYgcV&nC~Rrvb$gfn(=^# z^v%9BU9V8w>sajB@k5jw)gVu~8blkN;NWLVcxOyd&92MHs*O$@6%}_oPjVri5+95R zED>H}&?3{1pe-MJqm?_-Hm$Pz7UFdSx>A{Uc3b=6E>%U zG&l0;hWH#|bTe!Oh_+KN@m!<9o-16c?sv*7bo$H=x@)|hQu6d@yXX&o4^G zH8m|p)y$S@XpnI217^Cxi_ma)V=KBIv}T&NoE{XqdxFzH(}@$m&fWSSDJ+qs#tHt2 zF?SOsD73Fzo-QvcE)wB>u=b=Lgz0GYH1?aEpmz#8Ccjh5oGXglFE-hY;bVLRxVT7A z(h@O=a;EC~-=bya>p4dv2YcASg7#(xn>Uo+c@>N7w_M)j10Gttx1e#7Y{cwcoTs|V zhWdUEh4&3X=M{h%LuihLjCCg)+y_AIozX|i$YY*hT4iVl>Qct2ZN4jBr{;rH+mGZF z!idGqK;;(<0~PIjRMe<@GW#Tkh7jRC{c%u4Fw4~42nHX6zd_3S)=ixoAD7;=rcX^l znGTha%<&!}D-{Z-yi(acP^r2}H^eq2BtRs)IE=4!T%@n(8{h_9kDdU|=0ypig?la9 z#S*!@V=&}rgg&^9*kOe-)@DldSG6Z}sG}}8=-8ujCPMJUsQF`2NhqLjB|^_3fA|xB zXbV^VMzJrx`m53MBRN_GgF*$|1#400AC?y%nlj@yNC$A-5p%#C!IM3zUA}N66sfK{Uh<*Xx$YCw{Jdic{eyqi0%b|27eMUwyVPG99Bz&_6dNL zo-kKh`;n~d)eSe26AB9rWGt_Sl9_|bsr+AB2B<4#cw-!US^WXfcn*EEJS6f$ajYy+ zD1*J#tU+zOvd!HNqnC?eEGt@4kO%fS(y#5Z@iC`-y#>DIg zDEa+llv=*DKNnVv5w>3wq?p}umhpYH#rR41_pvrjDLDbk(&QdYNM5s+Z}}N9+zCqy z=F$drmeK>R7tEEQRy{zrXa~;`Dz9$J5QRoeB^M(*$xu>dfct4nm~CK>tmWbRSaoz} zAQ@`+oNM!V0pB7#`S|frq5u;sA3Hj{Yf^}4+KfC;#XYnV^I8cRB6^8^z!yn|F~zv| z8-_qiIL`XUEYsp#quh)buYn;?tI1Zpa+CntvnUIFQjr1hXsZxS;`SsGAW2{77Lw=`HHyrA zCi8$KY}Jby=uW;nkT;+5_GV}!%pCjk>HJ?4_G}#CUBid|o@;-S;PtZ1?t(7A3Y?)3 zaW-Nt{mw%kFMrH)O6a)Ux-&JfOiif?Z?qRwOJ0g$%Z4OW&6VR2Sg?$|nObsKY}R3O zephEtM|f^}kjz+s8%_Xg6bmp}PWwQ>hvU~r4qBoMoMdg|jP#HC+U^sC`#~t{}&I@XM)|R0HZi*^f#3%0DbIuXy@7 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 H00000c=nzU diff --git a/apps/docs/app/website-surveys/quickstart/images/I6.webp b/apps/docs/app/website-surveys/quickstart/images/I6.webp deleted file mode 100644 index a24c2af56d1b26601b7c43f178a634bbc8eb8abd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34714 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∨Z&nh4(3kAQDch^pUQkfq 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 R@kd}D{$cQtzW>t!{x7E!yNLh* diff --git a/apps/docs/app/website-surveys/quickstart/images/I7.webp b/apps/docs/app/website-surveys/quickstart/images/I7.webp deleted file mode 100644 index 4a3a352d2d6b3e74639553d2a35023b74e7dbbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26292 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 diff --git a/apps/docs/app/website-surveys/quickstart/images/I8.webp b/apps/docs/app/website-surveys/quickstart/images/I8.webp deleted file mode 100644 index e5c0ab744281de66ab4d9f9c5eacf82a8cbeb215..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23318 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 SKVVM+d46lN{mbD0WB3Py6zxd> diff --git a/apps/docs/app/website-surveys/quickstart/page.mdx b/apps/docs/app/website-surveys/quickstart/page.mdx deleted file mode 100644 index 7395a19d53..0000000000 --- a/apps/docs/app/website-surveys/quickstart/page.mdx +++ /dev/null @@ -1,115 +0,0 @@ -import { MdxImage } from "@/components/MdxImage"; - -import I1 from "./images/I1.webp"; -import I2 from "./images/I2.webp"; -import I3 from "./images/I3.webp"; -import I4 from "./images/I4.webp"; -import I5 from "./images/I5.webp"; -import I6 from "./images/I6.webp"; -import I7 from "./images/I7.webp"; -import I8 from "./images/I8.webp"; - -export const metadata = { - title: "Formbricks Quickstart Guide: Website Surveys Made Easier & Faster", - description: - "Formbricks is the easiest way to create and manage website surveys. This quickstart guide will show you how to create your first website survey in under 5 minutes.", -}; - -#### Website Surveys - -# Quickstart - -Website Surveys make it easy for your public website visitors to give you feedback. They are a great way to get feedback from your users, without interrupting their workflow. This quickstart guide will show you how to create your first website survey in under 5 minutes. - - - Website Surveys are ideal for **public facing websites**. If you are looking to run surveys in your app where you have user identification & want advanced user targeting, head over to the [App Surveys Quickstart Guide](/app-surveys/quickstart). - - -1. **Create a free Formbricks Cloud account**: While you can [self-host](/self-hosting/deployment) Formbricks, but the quickest and easiest way to get started is with the free Cloud plan. Just [sign up here](https://app.formbricks.com/auth/signup) and you'll be guided to our onboarding like below: - - - Website & App Surveys have the same integration process. The difference will come when we setup our survey. - - - - -2. **Connect your App/Website**: Once you get through a couple of onboarding steps, you’ll be asked to connect your app or website. This is where you’ll find the code snippet for both HTML as well as the npm package which you need to embed in your app: - - - -Paste the code snippet in your app and reload the page. You should now see the Formbricks widget in the lower right corner of your app! The integration is now complete. - - - -Onboarding is complete! Now let’s create our first survey as you should see templates to choose from after clicking on **Next**: - - - -3. **Create your first survey**: To be able to see a survey in your app, you need to create one. We’ll choose one of the templates and head over to the survey settings: - -Pick the Survey Type as **Website Survey**. - - - -1. **Set Trigger for the Survey**: Scroll down to Survey Trigger and click on **+ Add action**, choose **New Session**. This will cause this survey to appear when the Formbricks Widget tracks a new session: - - - -5. **Set Recontact Options for debugging**: In Recontact Options we choose the following settings, so that we can play around with the survey more easily. By default, each survey will be shown only once for each session to prevent survey fatigue: - - - Please change this setting later on after testing your survey to prevent survey fatigue for your users. - - - - -6. **Publish your survey**: Now hit **Publish** and you’ll be forwarded to the Summary Page. This is where you’ll find the responses to this survey. - - - ---- - -- We offer framework guides for various frontend tech, head over to the the [Website Survey Framework Guides](/website-survey/framework-guides) to get started with your public facing website surveys. -- Head over to our Website Survey SDK documentation to get started with the [Website Survey JS SDK](/developer-docs/website-survey-sdk). - -Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you! diff --git a/apps/docs/lib/navigation.ts b/apps/docs/lib/navigation.ts index e201180666..904347457c 100644 --- a/apps/docs/lib/navigation.ts +++ b/apps/docs/lib/navigation.ts @@ -22,58 +22,6 @@ export const navigation: Array = [ }, ], }, - { - title: "App Surveys", - links: [ - { title: "Quickstart", href: "/app-surveys/quickstart" }, - { title: "Framework Guides", href: "/app-surveys/framework-guides" }, - { - title: "Features", - children: [ - { title: "Identify Users", href: "/app-surveys/user-identification" }, - { title: "Actions", href: "/app-surveys/actions" }, - { title: "Advanced Targeting", href: "/app-surveys/advanced-targeting" }, - { title: "Show Survey to % of users", href: "/global/show-survey-to-percent-of-users" }, // app and website - { title: "Recontact Options", href: "/app-surveys/recontact" }, - { title: "Hidden Fields", href: "/global/hidden-fields" }, // global - { title: "Multi Language Surveys", href: "/global/multi-language-surveys" }, // global - { title: "User Metadata", href: "/global/metadata" }, // global - { title: "Custom Styling", href: "/global/overwrite-styling" }, // global - { title: "Conditional Logic", href: "/global/conditional-logic" }, // global - { title: "Start & End Dates", href: "/global/custom-start-end-conditions" }, // global - { title: "Limit submissions", href: "/global/limit-submissions" }, // global - { title: "Recall Functionality", href: "/global/recall" }, // global - { title: "Partial Submissions", href: "/global/partial-submissions" }, // global - { title: "Shareable Dashboards", href: "/global/shareable-dashboards" }, - ], - }, - ], - }, - { - title: "Website Surveys", - links: [ - { title: "Quickstart", href: "/website-surveys/quickstart" }, - { title: "Framework Guides", href: "/website-surveys/framework-guides" }, - { - title: "Features", - children: [ - { title: "Actions", href: "/website-surveys/actions" }, - { title: "Show Survey to % of users", href: "/global/show-survey-to-percent-of-users" }, // app and website - { title: "Recontact Options", href: "/app-surveys/recontact" }, - { title: "Hidden Fields", href: "/global/hidden-fields" }, // global - { title: "Multi Language Surveys", href: "/global/multi-language-surveys" }, // global - { title: "User Metadata", href: "/global/metadata" }, // global - { title: "Custom Styling", href: "/global/overwrite-styling" }, // global - { title: "Conditional Logic", href: "/global/conditional-logic" }, // global - { title: "Start & End Dates", href: "/global/custom-start-end-conditions" }, // global - { title: "Limit submissions", href: "/global/limit-submissions" }, // global - { title: "Recall Functionality", href: "/global/recall" }, // global - { title: "Partial Submissions", href: "/global/partial-submissions" }, // global - { title: "Shareable Dashboards", href: "/global/shareable-dashboards" }, - ], - }, - ], - }, { title: "Link Surveys", links: [ @@ -104,6 +52,33 @@ export const navigation: Array = [ }, ], }, + { + title: "Website & App Surveys", + links: [ + { title: "Quickstart", href: "/app-surveys/quickstart" }, + { title: "Framework Guides", href: "/app-surveys/framework-guides" }, + { + title: "Features", + children: [ + { title: "Identify Users", href: "/app-surveys/user-identification" }, + { title: "Actions", href: "/app-surveys/actions" }, + { title: "Advanced Targeting", href: "/app-surveys/advanced-targeting" }, + { title: "Show Survey to % of users", href: "/global/show-survey-to-percent-of-users" }, // app and website + { title: "Recontact Options", href: "/app-surveys/recontact" }, + { title: "Hidden Fields", href: "/global/hidden-fields" }, // global + { title: "Multi Language Surveys", href: "/global/multi-language-surveys" }, // global + { title: "User Metadata", href: "/global/metadata" }, // global + { title: "Custom Styling", href: "/global/overwrite-styling" }, // global + { title: "Conditional Logic", href: "/global/conditional-logic" }, // global + { title: "Start & End Dates", href: "/global/custom-start-end-conditions" }, // global + { title: "Limit submissions", href: "/global/limit-submissions" }, // global + { title: "Recall Functionality", href: "/global/recall" }, // global + { title: "Partial Submissions", href: "/global/partial-submissions" }, // global + { title: "Shareable Dashboards", href: "/global/shareable-dashboards" }, + ], + }, + ], + }, { title: "Core Features", links: [ @@ -142,8 +117,7 @@ export const navigation: Array = [ { title: "Zapier", href: "/developer-docs/integrations/zapier" }, ], }, - { title: "SDK: Web Apps", href: "/developer-docs/app-survey-sdk" }, - { title: "SDK: Public Websites", href: "/developer-docs/website-survey-sdk" }, + { title: "SDK: Formbricks JS", href: "/developer-docs/js-sdk" }, { title: "SDK: React Native", href: "/developer-docs/react-native-in-app-surveys" }, { title: "SDK: Formbricks API", href: "/developer-docs/api-sdk" }, { title: "REST API", href: "/developer-docs/rest-api" }, diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index 71f23d4527..e3ee4cc31c 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -121,6 +121,22 @@ const nextConfig = { destination: "/developer-docs/integrations/:path", permanent: true, }, + + { + source: "/developer-docs/website-survey-sdk", + destination: "/developer-docs/js-sdk", + permanent: true, + }, + { + source: "/website-surveys/quickstart", + destination: "/app-surveys/quickstart", + permanent: true, + }, + { + source: "/website-surveys/framework-guides", + destination: "/app-surveys/framework-guides", + permanent: true, + }, ]; }, }; diff --git a/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/components/OnboardingSetupInstructions.tsx b/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/components/OnboardingSetupInstructions.tsx index f462c3c3f2..3bf0eeba7f 100644 --- a/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/components/OnboardingSetupInstructions.tsx +++ b/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/components/OnboardingSetupInstructions.tsx @@ -34,7 +34,7 @@ export const OnboardingSetupInstructions = ({ var apiHost = "${webAppUrl}"; var environmentId = "${environmentId}"; var userId = "testUser"; - var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src=apiHost+"/api/packages/app";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e),setTimeout(function(){window.formbricks.init({environmentId: environmentId, apiHost: apiHost, userId: userId})},500)}(); + var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src=apiHost+"/api/packages/js";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e),setTimeout(function(){window.formbricks.init({environmentId: environmentId, apiHost: apiHost, userId: userId})},500)}(); `; @@ -44,13 +44,13 @@ export const OnboardingSetupInstructions = ({ !function(){ var apiHost = "${webAppUrl}"; var environmentId = "${environmentId}"; - var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src=apiHost+"/api/packages/website";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e),setTimeout(function(){window.formbricks.init({environmentId: environmentId, apiHost: apiHost})},500)}(); + var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src=apiHost+"/api/packages/js";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e),setTimeout(function(){window.formbricks.init({environmentId: environmentId, apiHost: apiHost})},500)}(); `; const npmSnippetForAppSurveys = ` - import formbricks from "@formbricks/js/app"; + import formbricks from "@formbricks/js"; if (typeof window !== "undefined") { formbricks.init({ @@ -69,7 +69,7 @@ export const OnboardingSetupInstructions = ({ const npmSnippetForWebsiteSurveys = ` // other imports - import formbricks from "@formbricks/js/website"; + import formbricks from "@formbricks/js"; if (typeof window !== "undefined") { formbricks.init({ diff --git a/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/page.tsx b/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/page.tsx index 20e4f4f053..8238a83e12 100644 --- a/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/page.tsx +++ b/apps/web/app/(app)/(onboarding)/environments/[environmentId]/connect/page.tsx @@ -36,9 +36,7 @@ const Page = async ({ params }: ConnectPageProps) => {

diff --git a/apps/web/app/(app)/environments/[environmentId]/product/tags/page.tsx b/apps/web/app/(app)/environments/[environmentId]/product/tags/page.tsx index d2955096ae..a11630f499 100644 --- a/apps/web/app/(app)/environments/[environmentId]/product/tags/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/product/tags/page.tsx @@ -7,7 +7,6 @@ import { getEnvironment } from "@formbricks/lib/environment/service"; import { getMembershipByUserIdOrganizationId } from "@formbricks/lib/membership/service"; import { getAccessFlags } from "@formbricks/lib/membership/utils"; import { getOrganizationByEnvironmentId } from "@formbricks/lib/organization/service"; -import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service"; import { getTagsOnResponsesCount } from "@formbricks/lib/tagOnResponse/service"; import { ErrorComponent } from "@formbricks/ui/components/ErrorComponent"; @@ -21,10 +20,9 @@ const Page = async ({ params }) => { throw new Error("Environment not found"); } - const [tags, environmentTagsCount, product, organization, session] = await Promise.all([ + const [tags, environmentTagsCount, organization, session] = await Promise.all([ getTagsByEnvironmentId(params.environmentId), getTagsOnResponsesCount(params.environmentId), - getProductByEnvironmentId(params.environmentId), getOrganizationByEnvironmentId(params.environmentId), getServerSession(authOptions), ]); @@ -45,7 +43,6 @@ const Page = async ({ params }) => { const isTagSettingDisabled = isViewer; const isMultiLanguageAllowed = await getMultiLanguagePermission(organization); - const currentProductChannel = product?.config.channel ?? null; return !isTagSettingDisabled ? ( @@ -54,7 +51,6 @@ const Page = async ({ params }) => { environmentId={params.environmentId} activeId="tags" isMultiLanguageAllowed={isMultiLanguageAllowed} - productChannel={currentProductChannel} /> diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/EmptyInAppSurveys.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/EmptyInAppSurveys.tsx index 3406132f65..63b120dd7f 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/EmptyInAppSurveys.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/EmptyInAppSurveys.tsx @@ -5,10 +5,9 @@ import { Button } from "@formbricks/ui/components/Button"; interface TEmptyAppSurveysProps { environment: TEnvironment; - surveyType?: "app" | "website"; } -export const EmptyAppSurveys = ({ environment, surveyType = "app" }: TEmptyAppSurveysProps) => { +export const EmptyAppSurveys = ({ environment }: TEmptyAppSurveysProps) => { return (
@@ -19,10 +18,10 @@ export const EmptyAppSurveys = ({ environment, surveyType = "app" }: TEmptyAppSu

You're not plugged in yet!

- Connect your {surveyType} with Formbricks to run {surveyType} surveys. + Connect your website or app with Formbricks to get started.

- + diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SuccessMessage.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SuccessMessage.tsx index 5c1c4f2d99..463e8a5d9a 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SuccessMessage.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SuccessMessage.tsx @@ -16,9 +16,8 @@ export const SuccessMessage = ({ environment, survey }: SummaryMetadataProps) => const searchParams = useSearchParams(); const [confetti, setConfetti] = useState(false); - const isAppSurvey = survey.type === "app" || survey.type === "website"; - const widgetSetupCompleted = - survey.type === "app" ? environment.appSetupCompleted : environment.websiteSetupCompleted; + const isAppSurvey = survey.type === "app"; + const widgetSetupCompleted = environment.appSetupCompleted; useEffect(() => { const newSurveyParam = searchParams?.get("success"); diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx index 7be3d929fb..36d67a5071 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx @@ -50,8 +50,6 @@ export const SummaryList = ({ attributeClasses, }: SummaryListProps) => { const { setSelectedFilter, selectedFilter } = useResponseFilter(); - const widgetSetupCompleted = - survey.type === "app" ? environment.appSetupCompleted : environment.websiteSetupCompleted; const setFilter = ( questionId: string, @@ -107,10 +105,8 @@ export const SummaryList = ({ return (
- {(survey.type === "app" || survey.type === "website") && - responseCount === 0 && - !widgetSetupCompleted ? ( - + {survey.type === "app" && responseCount === 0 && !environment.appSetupCompleted ? ( + ) : summary.length === 0 ? ( ) : responseCount === 0 ? ( @@ -119,7 +115,6 @@ export const SummaryList = ({ environment={environment} noWidgetRequired={survey.type === "link"} emptyMessage={totalResponseCount === 0 ? undefined : "No response matches your filter"} - widgetSetupCompleted={widgetSetupCompleted} /> ) : ( summary.map((questionSummary) => { diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SurveyAnalysisCTA.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SurveyAnalysisCTA.tsx index faf533b4b9..17588754cd 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SurveyAnalysisCTA.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SurveyAnalysisCTA.tsx @@ -30,9 +30,7 @@ export const SurveyAnalysisCTA = ({ const router = useRouter(); const [showShareSurveyModal, setShowShareSurveyModal] = useState(searchParams.get("share") === "true"); - - const widgetSetupCompleted = - survey.type === "app" ? environment.appSetupCompleted : environment.websiteSetupCompleted; + const widgetSetupCompleted = environment.appSetupCompleted; useEffect(() => { if (searchParams.get("share") === "true") { diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx index 86f6d0fc38..29778ef409 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx @@ -65,9 +65,7 @@ export const SurveyStatusDropdown = ({
- {(survey.type === "link" || - environment.appSetupCompleted || - environment.websiteSetupCompleted) && ( + {(survey.type === "link" || environment.appSetupCompleted) && ( )} diff --git a/apps/web/app/api/packages/[package]/route.ts b/apps/web/app/api/packages/[package]/route.ts index 0cd496b3c6..6c96e9d837 100644 --- a/apps/web/app/api/packages/[package]/route.ts +++ b/apps/web/app/api/packages/[package]/route.ts @@ -7,11 +7,8 @@ export const GET = async (_: NextRequest, { params }: { params: { package: strin const packageRequested = params.package; switch (packageRequested) { - case "app": - path = `../../packages/js-core/dist/app.umd.cjs`; - break; - case "website": - path = `../../packages/js-core/dist/website.umd.cjs`; + case "js": + path = `../../packages/js-core/dist/index.umd.cjs`; break; case "surveys": path = `../../packages/surveys/dist/index.umd.cjs`; diff --git a/apps/web/app/api/v1/client/[environmentId]/app/environment/lib/environmentState.ts b/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts similarity index 92% rename from apps/web/app/api/v1/client/[environmentId]/app/environment/lib/environmentState.ts rename to apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts index fb34f8a81a..ca99392067 100644 --- a/apps/web/app/api/v1/client/[environmentId]/app/environment/lib/environmentState.ts +++ b/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts @@ -18,7 +18,7 @@ import { productCache } from "@formbricks/lib/product/cache"; import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { surveyCache } from "@formbricks/lib/survey/cache"; import { getSurveys } from "@formbricks/lib/survey/service"; -import { InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors"; +import { ResourceNotFoundError } from "@formbricks/types/errors"; import { TJsEnvironmentState } from "@formbricks/types/js"; /** @@ -26,7 +26,6 @@ import { TJsEnvironmentState } from "@formbricks/types/js"; * @param environmentId * @returns The environment state * @throws ResourceNotFoundError if the environment or organization does not exist - * @throws InvalidInputError if the channel is not "app" */ export const getEnvironmentState = async ( environmentId: string @@ -52,10 +51,6 @@ export const getEnvironmentState = async ( throw new ResourceNotFoundError("product", null); } - if (product.config.channel && product.config.channel !== "app") { - throw new InvalidInputError("Invalid channel"); - } - if (!environment.appSetupCompleted) { await Promise.all([ prisma.environment.update({ @@ -117,7 +112,7 @@ export const getEnvironmentState = async ( revalidateEnvironment, }; }, - [`environmentState-app-${environmentId}`], + [`environmentState-${environmentId}`], { ...(IS_FORMBRICKS_CLOUD && { revalidate: 24 * 60 * 60 }), tags: [ diff --git a/apps/web/app/api/v1/client/[environmentId]/app/environment/route.ts b/apps/web/app/api/v1/client/[environmentId]/environment/route.ts similarity index 97% rename from apps/web/app/api/v1/client/[environmentId]/app/environment/route.ts rename to apps/web/app/api/v1/client/[environmentId]/environment/route.ts index 919fc350f9..3ec1823f38 100644 --- a/apps/web/app/api/v1/client/[environmentId]/app/environment/route.ts +++ b/apps/web/app/api/v1/client/[environmentId]/environment/route.ts @@ -1,4 +1,4 @@ -import { getEnvironmentState } from "@/app/api/v1/client/[environmentId]/app/environment/lib/environmentState"; +import { getEnvironmentState } from "@/app/api/v1/client/[environmentId]/environment/lib/environmentState"; import { responses } from "@/app/lib/api/response"; import { transformErrorToDetails } from "@/app/lib/api/validator"; import { NextRequest } from "next/server"; diff --git a/apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/lib/personState.ts b/apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/lib/personState.ts similarity index 97% rename from apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/lib/personState.ts rename to apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/lib/personState.ts index ae3531a6ac..9ced049337 100644 --- a/apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/lib/personState.ts +++ b/apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/lib/personState.ts @@ -1,4 +1,3 @@ -import { getPersonSegmentIds } from "@/app/api/v1/client/[environmentId]/app/people/[userId]/lib/segments"; import { prisma } from "@formbricks/database"; import { attributeCache } from "@formbricks/lib/attribute/cache"; import { getAttributesByUserId } from "@formbricks/lib/attribute/service"; @@ -17,6 +16,7 @@ import { getResponsesByUserId } from "@formbricks/lib/response/service"; import { segmentCache } from "@formbricks/lib/segment/cache"; import { ResourceNotFoundError } from "@formbricks/types/errors"; import { TJsPersonState } from "@formbricks/types/js"; +import { getPersonSegmentIds } from "./segments"; /** * diff --git a/apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/lib/segments.ts b/apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/lib/segments.ts similarity index 100% rename from apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/lib/segments.ts rename to apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/lib/segments.ts diff --git a/apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/route.ts b/apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/route.ts similarity index 100% rename from apps/web/app/api/v1/client/[environmentId]/app/people/[userId]/route.ts rename to apps/web/app/api/v1/client/[environmentId]/identify/people/[userId]/route.ts diff --git a/apps/web/app/api/v1/client/[environmentId]/website/environment/lib/environmentState.ts b/apps/web/app/api/v1/client/[environmentId]/website/environment/lib/environmentState.ts deleted file mode 100644 index 0e1d2d73cf..0000000000 --- a/apps/web/app/api/v1/client/[environmentId]/website/environment/lib/environmentState.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { prisma } from "@formbricks/database"; -import { actionClassCache } from "@formbricks/lib/actionClass/cache"; -import { getActionClasses } from "@formbricks/lib/actionClass/service"; -import { cache } from "@formbricks/lib/cache"; -import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants"; -import { environmentCache } from "@formbricks/lib/environment/cache"; -import { getEnvironment } from "@formbricks/lib/environment/service"; -import { organizationCache } from "@formbricks/lib/organization/cache"; -import { - getMonthlyOrganizationResponseCount, - getOrganizationByEnvironmentId, -} from "@formbricks/lib/organization/service"; -import { - capturePosthogEnvironmentEvent, - sendPlanLimitsReachedEventToPosthogWeekly, -} from "@formbricks/lib/posthogServer"; -import { productCache } from "@formbricks/lib/product/cache"; -import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; -import { surveyCache } from "@formbricks/lib/survey/cache"; -import { getSurveys } from "@formbricks/lib/survey/service"; -import { InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors"; -import { TJsEnvironmentState } from "@formbricks/types/js"; - -/** - * Get the environment state - * @param environmentId - * @returns The environment state - * @throws ResourceNotFoundError if the organization, environment or product is not found - * @throws InvalidInputError if the product channel is not website - */ -export const getEnvironmentState = async ( - environmentId: string -): Promise<{ state: TJsEnvironmentState["data"]; revalidateEnvironment?: boolean }> => - cache( - async () => { - let revalidateEnvironment = false; - const [environment, organization, product] = await Promise.all([ - getEnvironment(environmentId), - getOrganizationByEnvironmentId(environmentId), - getProductByEnvironmentId(environmentId), - ]); - - if (!environment) { - throw new ResourceNotFoundError("environment", environmentId); - } - - if (!organization) { - throw new ResourceNotFoundError("organization", null); - } - - if (!product) { - throw new ResourceNotFoundError("product", null); - } - - if (product.config.channel && product.config.channel !== "website") { - throw new InvalidInputError("Product channel is not website"); - } - - // check if response limit is reached - let isWebsiteSurveyResponseLimitReached = false; - if (IS_FORMBRICKS_CLOUD) { - const currentResponseCount = await getMonthlyOrganizationResponseCount(organization.id); - const monthlyResponseLimit = organization.billing.limits.monthly.responses; - - isWebsiteSurveyResponseLimitReached = - monthlyResponseLimit !== null && currentResponseCount >= monthlyResponseLimit; - - if (isWebsiteSurveyResponseLimitReached) { - try { - await sendPlanLimitsReachedEventToPosthogWeekly(environmentId, { - plan: organization.billing.plan, - limits: { monthly: { responses: monthlyResponseLimit, miu: null } }, - }); - } catch (error) { - console.error(`Error sending plan limits reached event to Posthog: ${error}`); - } - } - } - - if (!environment?.websiteSetupCompleted) { - await Promise.all([ - await prisma.environment.update({ - where: { - id: environmentId, - }, - data: { websiteSetupCompleted: true }, - }), - capturePosthogEnvironmentEvent(environmentId, "website setup completed"), - ]); - - revalidateEnvironment = true; - } - - const [surveys, actionClasses] = await Promise.all([ - getSurveys(environmentId), - getActionClasses(environmentId), - ]); - - // Common filter condition for selecting surveys that are in progress, are of type 'website' and have no active segment filtering. - const filteredSurveys = surveys.filter( - (survey) => survey.status === "inProgress" && survey.type === "website" - ); - - const state: TJsEnvironmentState["data"] = { - surveys: filteredSurveys, - actionClasses, - product, - }; - - return { - state, - revalidateEnvironment, - }; - }, - [`environmentState-website-${environmentId}`], - { - ...(IS_FORMBRICKS_CLOUD && { revalidate: 24 * 60 * 60 }), - tags: [ - environmentCache.tag.byId(environmentId), - organizationCache.tag.byEnvironmentId(environmentId), - productCache.tag.byEnvironmentId(environmentId), - surveyCache.tag.byEnvironmentId(environmentId), - actionClassCache.tag.byEnvironmentId(environmentId), - ], - } - )(); diff --git a/apps/web/app/api/v1/client/[environmentId]/website/environment/route.ts b/apps/web/app/api/v1/client/[environmentId]/website/environment/route.ts deleted file mode 100644 index e5b20a0bf4..0000000000 --- a/apps/web/app/api/v1/client/[environmentId]/website/environment/route.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { responses } from "@/app/lib/api/response"; -import { transformErrorToDetails } from "@/app/lib/api/validator"; -import { NextRequest } from "next/server"; -import { environmentCache } from "@formbricks/lib/environment/cache"; -import { ResourceNotFoundError } from "@formbricks/types/errors"; -import { ZJsSyncInput } from "@formbricks/types/js"; -import { getEnvironmentState } from "./lib/environmentState"; - -export const OPTIONS = async (): Promise => { - return responses.successResponse({}, true); -}; - -export const GET = async ( - _: NextRequest, - { params }: { params: { environmentId: string } } -): Promise => { - try { - const syncInputValidation = ZJsSyncInput.safeParse({ - environmentId: params.environmentId, - }); - - if (!syncInputValidation.success) { - return responses.badRequestResponse( - "Fields are missing or incorrectly formatted", - transformErrorToDetails(syncInputValidation.error), - true - ); - } - - const { environmentId } = syncInputValidation.data; - - try { - const environmentState = await getEnvironmentState(environmentId); - - if (environmentState.revalidateEnvironment) { - environmentCache.revalidate({ - id: syncInputValidation.data.environmentId, - productId: environmentState.state.product.id, - }); - } - - return responses.successResponse( - environmentState.state, - true, - "public, s-maxage=600, max-age=840, stale-while-revalidate=600, stale-if-error=600" - ); - } catch (err) { - if (err instanceof ResourceNotFoundError) { - return responses.notFoundResponse(err.resourceType, err.resourceId); - } - - console.error(err); - return responses.internalServerErrorResponse(err.message ?? "Unable to complete response", true); - } - } catch (error) { - console.error(error); - return responses.internalServerErrorResponse(`Unable to complete response: ${error.message}`, true); - } -}; diff --git a/apps/web/app/api/v1/management/me/route.ts b/apps/web/app/api/v1/management/me/route.ts index 378d452ec6..13ab9d9433 100644 --- a/apps/web/app/api/v1/management/me/route.ts +++ b/apps/web/app/api/v1/management/me/route.ts @@ -24,7 +24,6 @@ export const GET = async () => { }, }, appSetupCompleted: true, - websiteSetupCompleted: true, }, }, }, diff --git a/apps/web/app/lib/formbricks.ts b/apps/web/app/lib/formbricks.ts index 73927d2dee..c80b553cd9 100644 --- a/apps/web/app/lib/formbricks.ts +++ b/apps/web/app/lib/formbricks.ts @@ -1,4 +1,4 @@ -import formbricks from "@formbricks/js/app"; +import formbricks from "@formbricks/js"; import { env } from "@formbricks/lib/env"; export const formbricksEnabled = diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 5545d63325..d5a90c3550 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -165,6 +165,30 @@ const nextConfig = { }, ]; }, + async rewrites() { + return [ + { + source: "/api/packages/website", + destination: "/api/packages/js", + }, + { + source: "/api/packages/app", + destination: "/api/packages/js", + }, + { + source: "/api/v1/client/:environmentId/website/environment", + destination: "/api/v1/client/:environmentId/environment", + }, + { + source: "/api/v1/client/:environmentId/app/environment", + destination: "/api/v1/client/:environmentId/environment", + }, + { + source: "/api/v1/client/:environmentId/app/people/:userId", + destination: "/api/v1/client/:environmentId/identify/people/:userId", + }, + ]; + }, env: { NEXTAUTH_URL: process.env.WEBAPP_URL, }, diff --git a/apps/web/playwright/js.spec.ts b/apps/web/playwright/js.spec.ts index a23a19135c..4f83234cdd 100644 --- a/apps/web/playwright/js.spec.ts +++ b/apps/web/playwright/js.spec.ts @@ -59,7 +59,7 @@ test.describe("JS Package Test", async () => { // Formbricks In App Sync has happened const syncApi = await page.waitForResponse( (response) => { - return response.url().includes("/app/environment"); + return response.url().includes("/environment"); }, { timeout: 120000, diff --git a/packages/database/data-migrations/20241002123456_migrate_survey_types/data-migration.ts b/packages/database/data-migrations/20241002123456_migrate_survey_types/data-migration.ts new file mode 100644 index 0000000000..8d6800e790 --- /dev/null +++ b/packages/database/data-migrations/20241002123456_migrate_survey_types/data-migration.ts @@ -0,0 +1,75 @@ +/* eslint-disable no-console -- logging is allowed in migration scripts */ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); +const TRANSACTION_TIMEOUT = 30 * 60 * 1000; // 30 minutes in milliseconds + +async function runMigration(): Promise { + const startTime = Date.now(); + console.log("Starting data migration..."); + + await prisma.$transaction( + async (transactionPrisma) => { + const websiteSurveys = await transactionPrisma.survey.findMany({ + where: { type: "website" }, + }); + + const updationPromises = []; + + for (const websiteSurvey of websiteSurveys) { + updationPromises.push( + transactionPrisma.survey.update({ + where: { id: websiteSurvey.id }, + data: { + type: "app", + segment: { + connectOrCreate: { + where: { + environmentId_title: { + environmentId: websiteSurvey.environmentId, + title: websiteSurvey.id, + }, + }, + create: { + title: websiteSurvey.id, + isPrivate: true, + environmentId: websiteSurvey.environmentId, + }, + }, + }, + }, + }) + ); + } + + await Promise.all(updationPromises); + console.log(`Updated ${websiteSurveys.length.toString()} website surveys to app surveys`); + }, + { + timeout: TRANSACTION_TIMEOUT, + } + ); + + const endTime = Date.now(); + console.log(`Data migration completed. Total time: ${((endTime - startTime) / 1000).toFixed(2)}s`); +} + +function handleError(error: unknown): void { + console.error("An error occurred during migration:", error); + process.exit(1); +} + +function handleDisconnectError(): void { + console.error("Failed to disconnect Prisma client"); + process.exit(1); +} + +function main(): void { + runMigration() + .catch(handleError) + .finally(() => { + prisma.$disconnect().catch(handleDisconnectError); + }); +} + +main(); diff --git a/packages/database/migrations/20241004070040_removed_website_setup_completed/migration.sql b/packages/database/migrations/20241004070040_removed_website_setup_completed/migration.sql new file mode 100644 index 0000000000..45812adf63 --- /dev/null +++ b/packages/database/migrations/20241004070040_removed_website_setup_completed/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `websiteSetupCompleted` on the `Environment` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Environment" DROP COLUMN "websiteSetupCompleted"; diff --git a/packages/database/package.json b/packages/database/package.json index 75e628477c..59a0105688 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -51,7 +51,8 @@ "data-migration:add-display-id-to-response": "ts-node ./data-migrations/20240905120500_refactor_display_response_relationship/data-migration.ts", "data-migration:address-question": "ts-node ./data-migrations/20240924123456_migrate_address_question/data-migration.ts", "data-migration:advanced-logic": "ts-node ./data-migrations/20240828122408_advanced_logic_editor/data-migration.ts", - "data-migration:segments-actions-cleanup": "ts-node ./data-migrations/20240904091113_removed_actions_table/data-migration.ts" + "data-migration:segments-actions-cleanup": "ts-node ./data-migrations/20240904091113_removed_actions_table/data-migration.ts", + "data-migration:migrate-survey-types": "ts-node ./data-migrations/20241002123456_migrate_survey_types/data-migration.ts" }, "dependencies": { "@prisma/client": "^5.18.0", diff --git a/packages/database/schema.prisma b/packages/database/schema.prisma index d7ed320930..3342dca9ed 100644 --- a/packages/database/schema.prisma +++ b/packages/database/schema.prisma @@ -386,24 +386,23 @@ model Integration { } model Environment { - id String @id @default(cuid()) - createdAt DateTime @default(now()) @map(name: "created_at") - updatedAt DateTime @updatedAt @map(name: "updated_at") - type EnvironmentType - product Product @relation(fields: [productId], references: [id], onDelete: Cascade) - productId String - widgetSetupCompleted Boolean @default(false) - appSetupCompleted Boolean @default(false) - websiteSetupCompleted Boolean @default(false) - surveys Survey[] - people Person[] - actionClasses ActionClass[] - attributeClasses AttributeClass[] - apiKeys ApiKey[] - webhooks Webhook[] - tags Tag[] - segments Segment[] - integration Integration[] + id String @id @default(cuid()) + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @updatedAt @map(name: "updated_at") + type EnvironmentType + product Product @relation(fields: [productId], references: [id], onDelete: Cascade) + productId String + widgetSetupCompleted Boolean @default(false) + appSetupCompleted Boolean @default(false) + surveys Survey[] + people Person[] + actionClasses ActionClass[] + attributeClasses AttributeClass[] + apiKeys ApiKey[] + webhooks Webhook[] + tags Tag[] + segments Segment[] + integration Integration[] @@index([productId]) } diff --git a/packages/ee/advanced-targeting/components/advanced-targeting-card.tsx b/packages/ee/advanced-targeting/components/advanced-targeting-card.tsx index 839b8d6fff..c09cf5a1d1 100644 --- a/packages/ee/advanced-targeting/components/advanced-targeting-card.tsx +++ b/packages/ee/advanced-targeting/components/advanced-targeting-card.tsx @@ -16,6 +16,7 @@ import type { TSegmentUpdateInput, } from "@formbricks/types/segment"; import type { TSurvey } from "@formbricks/types/surveys/types"; +import { Alert, AlertDescription } from "@formbricks/ui/components/Alert"; import { AlertDialog } from "@formbricks/ui/components/AlertDialog"; import { Button } from "@formbricks/ui/components/Button"; import { LoadSegmentModal } from "@formbricks/ui/components/LoadSegmentModal"; @@ -161,7 +162,7 @@ export function AdvancedTargetingCard({ return (
+ +
+ + + + User targeting is currently only available when{" "} + + identifying users + {" "} + with the Formbricks SDK. + + + +
); diff --git a/packages/js-core/package.json b/packages/js-core/package.json index 73e8436c47..c3e2dbebfb 100644 --- a/packages/js-core/package.json +++ b/packages/js-core/package.json @@ -20,33 +20,20 @@ "dist" ], "exports": { - "./app": { - "import": "./dist/app.js", - "require": "./dist/app.umd.cjs", - "types": "./dist/app.d.ts" - }, - "./website": { - "import": "./dist/website.js", - "require": "./dist/website.umd.cjs", - "types": "./dist/website.d.ts" - }, - "./*": "./dist/*" + "import": "./dist/index.js", + "require": "./dist/index.umd.cjs", + "types": "./dist/index.d.ts" }, "typesVersions": { "*": { - "app": [ - "./dist/app.d.ts" - ], - "website": [ - "./dist/website.d.ts" + "*": [ + "./dist/index.d.ts" ] } }, "scripts": { "dev": "vite build --watch --mode dev", - "build:app": "tsc && vite build --config app.vite.config.ts", - "build:website": "tsc && vite build --config website.vite.config.ts", - "build": "pnpm build:app && pnpm build:website", + "build": "tsc && vite build", "build:dev": "tsc && vite build --mode dev", "go": "vite build --watch --mode dev", "lint": "eslint . --ext .ts,.js,.tsx,.jsx", diff --git a/packages/js-core/src/app/lib/person.ts b/packages/js-core/src/app/lib/person.ts deleted file mode 100644 index b3c9b6b9e4..0000000000 --- a/packages/js-core/src/app/lib/person.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { NetworkError, Result, err, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { AppConfig } from "./config"; -import { deinitalize, initialize } from "./initialize"; -import { closeSurvey } from "./widget"; - -const appConfig = AppConfig.getInstance(); -const logger = Logger.getInstance(); - -export const logoutPerson = async (): Promise => { - deinitalize(); - appConfig.resetConfig(); -}; - -export const resetPerson = async (): Promise> => { - logger.debug("Resetting state & getting new state from backend"); - closeSurvey(); - - const userId = appConfig.get().personState.data.userId; - if (!userId) { - return err({ - code: "network_error", - status: 500, - message: "Missing userId", - url: `${appConfig.get().apiHost}/api/v1/client/${appConfig.get().environmentId}/people/${userId}/attributes`, - responseMessage: "Missing userId", - }); - } - - const syncParams = { - environmentId: appConfig.get().environmentId, - apiHost: appConfig.get().apiHost, - userId, - attributes: appConfig.get().personState.data.attributes, - }; - await logoutPerson(); - try { - await initialize(syncParams); - return okVoid(); - } catch (e) { - return err(e as NetworkError); - } -}; diff --git a/packages/js-core/src/app/index.ts b/packages/js-core/src/index.ts similarity index 68% rename from packages/js-core/src/app/index.ts rename to packages/js-core/src/index.ts index 88b4cbabd5..9a7811d774 100644 --- a/packages/js-core/src/app/index.ts +++ b/packages/js-core/src/index.ts @@ -1,11 +1,11 @@ -import { TJsAppConfigInput, TJsTrackProperties } from "@formbricks/types/js"; -import { CommandQueue } from "../shared/commandQueue"; -import { ErrorHandler } from "../shared/errors"; -import { Logger } from "../shared/logger"; +import { TJsConfigInput, TJsTrackProperties } from "@formbricks/types/js"; import { trackCodeAction } from "./lib/actions"; import { getApi } from "./lib/api"; import { setAttributeInApp } from "./lib/attributes"; +import { CommandQueue } from "./lib/commandQueue"; +import { ErrorHandler } from "./lib/errors"; import { initialize } from "./lib/initialize"; +import { Logger } from "./lib/logger"; import { checkPageUrl } from "./lib/noCodeActions"; import { logoutPerson, resetPerson } from "./lib/person"; @@ -14,9 +14,9 @@ const logger = Logger.getInstance(); logger.debug("Create command queue"); const queue = new CommandQueue(); -const init = async (initConfig: TJsAppConfigInput) => { +const init = async (initConfig: TJsConfigInput) => { ErrorHandler.init(initConfig.errorHandler); - queue.add(false, "app", initialize, initConfig); + queue.add(false, initialize, initConfig); await queue.wait(); }; @@ -26,27 +26,27 @@ const setEmail = async (email: string): Promise => { }; const setAttribute = async (key: string, value: any): Promise => { - queue.add(true, "app", setAttributeInApp, key, value); + queue.add(true, setAttributeInApp, key, value); await queue.wait(); }; const logout = async (): Promise => { - queue.add(true, "app", logoutPerson); + queue.add(true, logoutPerson); await queue.wait(); }; const reset = async (): Promise => { - queue.add(true, "app", resetPerson); + queue.add(true, resetPerson); await queue.wait(); }; const track = async (name: string, properties?: TJsTrackProperties): Promise => { - queue.add(true, "app", trackCodeAction, name, properties); + queue.add(true, trackCodeAction, name, properties); await queue.wait(); }; const registerRouteChange = async (): Promise => { - queue.add(true, "app", checkPageUrl); + queue.add(true, checkPageUrl); await queue.wait(); }; diff --git a/packages/js-core/src/app/lib/actions.ts b/packages/js-core/src/lib/actions.ts similarity index 84% rename from packages/js-core/src/app/lib/actions.ts rename to packages/js-core/src/lib/actions.ts index 297196f9b5..1148bf3a3e 100644 --- a/packages/js-core/src/app/lib/actions.ts +++ b/packages/js-core/src/lib/actions.ts @@ -1,11 +1,11 @@ import { TJsTrackProperties } from "@formbricks/types/js"; -import { InvalidCodeError, NetworkError, Result, err, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { AppConfig } from "./config"; +import { Config } from "./config"; +import { InvalidCodeError, NetworkError, Result, err, okVoid } from "./errors"; +import { Logger } from "./logger"; import { triggerSurvey } from "./widget"; const logger = Logger.getInstance(); -const appConfig = AppConfig.getInstance(); +const config = Config.getInstance(); export const trackAction = async ( name: string, @@ -17,7 +17,7 @@ export const trackAction = async ( logger.debug(`Formbricks: Action "${aliasName}" tracked`); // get a list of surveys that are collecting insights - const activeSurveys = appConfig.get().filteredSurveys; + const activeSurveys = config.get().filteredSurveys; if (!!activeSurveys && activeSurveys.length > 0) { for (const survey of activeSurveys) { @@ -38,7 +38,7 @@ export const trackCodeAction = ( code: string, properties?: TJsTrackProperties ): Promise> | Result => { - const actionClasses = appConfig.get().environmentState.data.actionClasses; + const actionClasses = config.get().environmentState.data.actionClasses; const codeActionClasses = actionClasses.filter((action) => action.type === "code"); const action = codeActionClasses.find((action) => action.key === code); diff --git a/packages/js-core/src/app/lib/api.ts b/packages/js-core/src/lib/api.ts similarity index 66% rename from packages/js-core/src/app/lib/api.ts rename to packages/js-core/src/lib/api.ts index 508f939230..e2a325ba65 100644 --- a/packages/js-core/src/app/lib/api.ts +++ b/packages/js-core/src/lib/api.ts @@ -1,9 +1,9 @@ import { FormbricksAPI } from "@formbricks/api"; -import { AppConfig } from "./config"; +import { Config } from "./config"; export const getApi = (): FormbricksAPI => { - const inAppConfig = AppConfig.getInstance(); - const { environmentId, apiHost } = inAppConfig.get(); + const config = Config.getInstance(); + const { environmentId, apiHost } = config.get(); if (!environmentId || !apiHost) { throw new Error("formbricks.init() must be called before getApi()"); diff --git a/packages/js-core/src/app/lib/attributes.ts b/packages/js-core/src/lib/attributes.ts similarity index 81% rename from packages/js-core/src/app/lib/attributes.ts rename to packages/js-core/src/lib/attributes.ts index d7f7660902..aef097b806 100644 --- a/packages/js-core/src/app/lib/attributes.ts +++ b/packages/js-core/src/lib/attributes.ts @@ -1,12 +1,12 @@ import { FormbricksAPI } from "@formbricks/api"; import { TAttributes } from "@formbricks/types/attributes"; -import { MissingPersonError, NetworkError, Result, err, ok, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { fetchPersonState } from "../../shared/personState"; -import { filterSurveys } from "../../shared/utils"; -import { AppConfig } from "./config"; +import { Config } from "./config"; +import { MissingPersonError, NetworkError, Result, err, ok, okVoid } from "./errors"; +import { Logger } from "./logger"; +import { fetchPersonState } from "./personState"; +import { filterSurveys } from "./utils"; -const appConfig = AppConfig.getInstance(); +const config = Config.getInstance(); const logger = Logger.getInstance(); export const updateAttribute = async ( @@ -21,8 +21,8 @@ export const updateAttribute = async ( Error | NetworkError > > => { - const { apiHost, environmentId } = appConfig.get(); - const userId = appConfig.get().personState.data.userId; + const { apiHost, environmentId } = config.get(); + const userId = config.get().personState.data.userId; if (!userId) { return err({ @@ -58,7 +58,7 @@ export const updateAttribute = async ( // @ts-expect-error status: res.error.status ?? 500, message: res.error.message ?? `Error updating person with userId ${userId}`, - url: `${appConfig.get().apiHost}/api/v1/client/${environmentId}/people/${userId}/attributes`, + url: `${config.get().apiHost}/api/v1/client/${environmentId}/people/${userId}/attributes`, responseMessage: res.error.message, }); } @@ -93,7 +93,7 @@ export const updateAttributes = async ( const updatedAttributes = { ...attributes }; try { - const existingAttributes = appConfig.get().personState.data.attributes; + const existingAttributes = config.get().personState.data.attributes; if (existingAttributes) { for (const [key, value] of Object.entries(existingAttributes)) { if (updatedAttributes[key] === value) { @@ -140,7 +140,7 @@ export const updateAttributes = async ( }; export const isExistingAttribute = (key: string, value: string): boolean => { - if (appConfig.get().personState.data.attributes[key] === value) { + if (config.get().personState.data.attributes[key] === value) { return true; } @@ -156,14 +156,7 @@ export const setAttributeInApp = async ( return okVoid(); } - const userId = appConfig.get().personState.data.userId; - - if (!userId) { - return err({ - code: "missing_person", - message: "Missing userId", - }); - } + const userId = config.get().personState.data.userId; logger.debug("Setting attribute: " + key + " to value: " + value); // check if attribute already exists with this value @@ -172,23 +165,30 @@ export const setAttributeInApp = async ( return okVoid(); } + if (!userId) { + logger.error( + "UserId not provided, please provide a userId in the init method before setting attributes." + ); + return okVoid(); + } + const result = await updateAttribute(key, value.toString()); if (result.ok) { if (result.value.changed) { const personState = await fetchPersonState( { - apiHost: appConfig.get().apiHost, - environmentId: appConfig.get().environmentId, + apiHost: config.get().apiHost, + environmentId: config.get().environmentId, userId, }, true ); - const filteredSurveys = filterSurveys(appConfig.get().environmentState, personState); + const filteredSurveys = filterSurveys(config.get().environmentState, personState); - appConfig.update({ - ...appConfig.get(), + config.update({ + ...config.get(), personState, filteredSurveys, }); diff --git a/packages/js-core/src/shared/commandQueue.ts b/packages/js-core/src/lib/commandQueue.ts similarity index 80% rename from packages/js-core/src/shared/commandQueue.ts rename to packages/js-core/src/lib/commandQueue.ts index c05369acc1..c372a569e7 100644 --- a/packages/js-core/src/shared/commandQueue.ts +++ b/packages/js-core/src/lib/commandQueue.ts @@ -1,13 +1,10 @@ import { wrapThrowsAsync } from "@formbricks/types/error-handlers"; -import { TJsPackageType } from "@formbricks/types/js"; -import { checkInitialized as checkInitializedInApp } from "../app/lib/initialize"; -import { ErrorHandler, Result } from "../shared/errors"; -import { checkInitialized as checkInitializedWebsite } from "../website/lib/initialize"; +import { ErrorHandler, Result } from "./errors"; +import { checkInitialized } from "./initialize"; export class CommandQueue { private queue: { command: (args: any) => Promise> | Result | Promise; - packageType: TJsPackageType; checkInitialized: boolean; commandArgs: any[any]; }[] = []; @@ -17,11 +14,10 @@ export class CommandQueue { public add
( checkInitialized: boolean = true, - packageType: TJsPackageType, command: (...args: A[]) => Promise> | Result | Promise, ...args: A[] ) { - this.queue.push({ command, checkInitialized, commandArgs: args, packageType }); + this.queue.push({ command, checkInitialized, commandArgs: args }); if (!this.running) { this.commandPromise = new Promise((resolve) => { @@ -48,8 +44,7 @@ export class CommandQueue { // make sure formbricks is initialized if (currentItem.checkInitialized) { // call different function based on package type - const initResult = - currentItem.packageType === "website" ? checkInitializedWebsite() : checkInitializedInApp(); + const initResult = checkInitialized(); if (initResult && initResult.ok !== true) { errorHandler.handle(initResult.error); diff --git a/packages/js-core/src/app/lib/config.ts b/packages/js-core/src/lib/config.ts similarity index 75% rename from packages/js-core/src/app/lib/config.ts rename to packages/js-core/src/lib/config.ts index 63c5d4e659..ca9cfe6bfd 100644 --- a/packages/js-core/src/app/lib/config.ts +++ b/packages/js-core/src/lib/config.ts @@ -1,9 +1,9 @@ import { TJsConfig, TJsConfigUpdateInput } from "@formbricks/types/js"; -import { APP_SURVEYS_LOCAL_STORAGE_KEY } from "../../shared/constants"; -import { Result, err, ok, wrapThrows } from "../../shared/errors"; +import { JS_LOCAL_STORAGE_KEY } from "./constants"; +import { Result, err, ok, wrapThrows } from "./errors"; -export class AppConfig { - private static instance: AppConfig | undefined; +export class Config { + private static instance: Config | undefined; private config: TJsConfig | null = null; private constructor() { @@ -14,11 +14,11 @@ export class AppConfig { } } - static getInstance(): AppConfig { - if (!AppConfig.instance) { - AppConfig.instance = new AppConfig(); + static getInstance(): Config { + if (!Config.instance) { + Config.instance = new Config(); } - return AppConfig.instance; + return Config.instance; } public update(newConfig: TJsConfigUpdateInput): void { @@ -45,7 +45,7 @@ export class AppConfig { public loadFromLocalStorage(): Result { if (typeof window !== "undefined") { - const savedConfig = localStorage.getItem(APP_SURVEYS_LOCAL_STORAGE_KEY); + const savedConfig = localStorage.getItem(JS_LOCAL_STORAGE_KEY); if (savedConfig) { // TODO: validate config // This is a hack to get around the fact that we don't have a proper @@ -69,7 +69,7 @@ export class AppConfig { private async saveToStorage(): Promise, Error>> { return wrapThrows(async () => { - await localStorage.setItem(APP_SURVEYS_LOCAL_STORAGE_KEY, JSON.stringify(this.config)); + await localStorage.setItem(JS_LOCAL_STORAGE_KEY, JSON.stringify(this.config)); })(); } @@ -79,7 +79,7 @@ export class AppConfig { this.config = null; return wrapThrows(async () => { - localStorage.removeItem(APP_SURVEYS_LOCAL_STORAGE_KEY); + localStorage.removeItem(JS_LOCAL_STORAGE_KEY); })(); } } diff --git a/packages/js-core/src/lib/constants.ts b/packages/js-core/src/lib/constants.ts new file mode 100644 index 0000000000..bf19f961e6 --- /dev/null +++ b/packages/js-core/src/lib/constants.ts @@ -0,0 +1,5 @@ +export const RN_ASYNC_STORAGE_KEY = "formbricks-react-native"; +export const JS_LOCAL_STORAGE_KEY = "formbricks-js"; +export const LEGACY_JS_WEBSITE_LOCAL_STORAGE_KEY = "formbricks-js-website"; +export const LEGACY_JS_APP_LOCAL_STORAGE_KEY = "formbricks-js-app"; +export const CONTAINER_ID = "formbricks-app-container"; diff --git a/packages/js-core/src/shared/environmentState.ts b/packages/js-core/src/lib/environmentState.ts similarity index 88% rename from packages/js-core/src/shared/environmentState.ts rename to packages/js-core/src/lib/environmentState.ts index ce881a563a..72c6d85dd1 100644 --- a/packages/js-core/src/shared/environmentState.ts +++ b/packages/js-core/src/lib/environmentState.ts @@ -1,11 +1,11 @@ // shared functions for environment and person state(s) import { TJsEnvironmentState, TJsEnvironmentSyncParams } from "@formbricks/types/js"; -import { AppConfig } from "../app/lib/config"; -import { WebsiteConfig } from "../website/lib/config"; +import { Config } from "./config"; import { err } from "./errors"; import { Logger } from "./logger"; import { filterSurveys, getIsDebug } from "./utils"; +const config = Config.getInstance(); const logger = Logger.getInstance(); let environmentStateSyncIntervalId: number | null = null; @@ -19,7 +19,6 @@ let environmentStateSyncIntervalId: number | null = null; */ export const fetchEnvironmentState = async ( { apiHost, environmentId }: TJsEnvironmentSyncParams, - sdkType: "app" | "website", noCache: boolean = false ): Promise => { let fetchOptions: RequestInit = {}; @@ -29,7 +28,7 @@ export const fetchEnvironmentState = async ( logger.debug("No cache option set for sync"); } - const url = `${apiHost}/api/v1/client/${environmentId}/${sdkType}/environment`; + const url = `${apiHost}/api/v1/client/${environmentId}/environment`; const response = await fetch(url, fetchOptions); @@ -56,10 +55,7 @@ export const fetchEnvironmentState = async ( }; }; -export const addEnvironmentStateExpiryCheckListener = ( - sdkType: "app" | "website", - config: AppConfig | WebsiteConfig -): void => { +export const addEnvironmentStateExpiryCheckListener = (): void => { let updateInterval = 1000 * 60; // every minute if (typeof window !== "undefined" && environmentStateSyncIntervalId === null) { environmentStateSyncIntervalId = window.setInterval(async () => { @@ -79,7 +75,6 @@ export const addEnvironmentStateExpiryCheckListener = ( apiHost: config.get().apiHost, environmentId: config.get().environmentId, }, - sdkType, true ); diff --git a/packages/js-core/src/shared/errors.ts b/packages/js-core/src/lib/errors.ts similarity index 100% rename from packages/js-core/src/shared/errors.ts rename to packages/js-core/src/lib/errors.ts diff --git a/packages/js-core/src/app/lib/eventListeners.ts b/packages/js-core/src/lib/eventListeners.ts similarity index 80% rename from packages/js-core/src/app/lib/eventListeners.ts rename to packages/js-core/src/lib/eventListeners.ts index 0a1532b0b0..4ee436a2f9 100644 --- a/packages/js-core/src/app/lib/eventListeners.ts +++ b/packages/js-core/src/lib/eventListeners.ts @@ -1,11 +1,7 @@ import { addEnvironmentStateExpiryCheckListener, clearEnvironmentStateExpiryCheckListener, -} from "../../shared/environmentState"; -import { - addPersonStateExpiryCheckListener, - clearPersonStateExpiryCheckListener, -} from "../../shared/personState"; +} from "./environmentState"; import { addClickEventListener, addExitIntentListener, @@ -15,14 +11,14 @@ import { removeExitIntentListener, removePageUrlEventListeners, removeScrollDepthListener, -} from "../lib/noCodeActions"; -import { AppConfig } from "./config"; +} from "./noCodeActions"; +import { addPersonStateExpiryCheckListener, clearPersonStateExpiryCheckListener } from "./personState"; let areRemoveEventListenersAdded = false; -export const addEventListeners = (config: AppConfig): void => { - addEnvironmentStateExpiryCheckListener("app", config); - addPersonStateExpiryCheckListener(config); +export const addEventListeners = (): void => { + addEnvironmentStateExpiryCheckListener(); + addPersonStateExpiryCheckListener(); addPageUrlEventListeners(); addClickEventListener(); addExitIntentListener(); diff --git a/packages/js-core/src/app/lib/initialize.ts b/packages/js-core/src/lib/initialize.ts similarity index 63% rename from packages/js-core/src/app/lib/initialize.ts rename to packages/js-core/src/lib/initialize.ts index c6366c1733..61a41de96c 100644 --- a/packages/js-core/src/app/lib/initialize.ts +++ b/packages/js-core/src/lib/initialize.ts @@ -1,7 +1,14 @@ import { TAttributes } from "@formbricks/types/attributes"; -import type { TJsAppConfigInput, TJsConfig } from "@formbricks/types/js"; -import { APP_SURVEYS_LOCAL_STORAGE_KEY } from "../../shared/constants"; -import { fetchEnvironmentState } from "../../shared/environmentState"; +import { type TJsConfig, type TJsConfigInput } from "@formbricks/types/js"; +import { trackNoCodeAction } from "./actions"; +import { updateAttributes } from "./attributes"; +import { Config } from "./config"; +import { + JS_LOCAL_STORAGE_KEY, + LEGACY_JS_APP_LOCAL_STORAGE_KEY, + LEGACY_JS_WEBSITE_LOCAL_STORAGE_KEY, +} from "./constants"; +import { fetchEnvironmentState } from "./environmentState"; import { ErrorHandler, MissingFieldError, @@ -12,18 +19,14 @@ import { err, okVoid, wrapThrows, -} from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { fetchPersonState } from "../../shared/personState"; -import { filterSurveys, getIsDebug } from "../../shared/utils"; -import { trackNoCodeAction } from "./actions"; -import { updateAttributes } from "./attributes"; -import { AppConfig } from "./config"; +} from "./errors"; import { addCleanupEventListeners, addEventListeners, removeAllEventListeners } from "./eventListeners"; +import { Logger } from "./logger"; import { checkPageUrl } from "./noCodeActions"; +import { DEFAULT_PERSON_STATE_NO_USER_ID, fetchPersonState } from "./personState"; +import { filterSurveys, getIsDebug } from "./utils"; import { addWidgetContainer, removeWidgetContainer, setIsSurveyRunning } from "./widget"; -const appConfigGlobal = AppConfig.getInstance(); const logger = Logger.getInstance(); let isInitialized = false; @@ -32,38 +35,72 @@ export const setIsInitialized = (value: boolean) => { isInitialized = value; }; -const checkForOlderLocalConfig = (): boolean => { - const oldConfig = localStorage.getItem(APP_SURVEYS_LOCAL_STORAGE_KEY); +const migrateLocalStorage = (): { changed: boolean; newState?: TJsConfig } => { + const oldWebsiteConfig = localStorage.getItem(LEGACY_JS_WEBSITE_LOCAL_STORAGE_KEY); + const oldAppConfig = localStorage.getItem(LEGACY_JS_APP_LOCAL_STORAGE_KEY); - if (oldConfig) { - const parsedOldConfig = JSON.parse(oldConfig); - if (parsedOldConfig.state || parsedOldConfig.expiresAt) { - // local config follows old structure - return true; + if (oldWebsiteConfig) { + localStorage.removeItem(LEGACY_JS_WEBSITE_LOCAL_STORAGE_KEY); + const parsedOldConfig = JSON.parse(oldWebsiteConfig) as TJsConfig; + + if ( + parsedOldConfig.environmentId && + parsedOldConfig.apiHost && + parsedOldConfig.environmentState && + parsedOldConfig.personState && + parsedOldConfig.filteredSurveys + ) { + const newLocalStorageConfig = { ...parsedOldConfig }; + + return { + changed: true, + newState: newLocalStorageConfig, + }; } } - return false; + if (oldAppConfig) { + localStorage.removeItem(LEGACY_JS_APP_LOCAL_STORAGE_KEY); + const parsedOldConfig = JSON.parse(oldAppConfig) as TJsConfig; + + if ( + parsedOldConfig.environmentId && + parsedOldConfig.apiHost && + parsedOldConfig.environmentState && + parsedOldConfig.personState && + parsedOldConfig.filteredSurveys + ) { + return { + changed: true, + }; + } + } + + return { + changed: false, + }; }; export const initialize = async ( - configInput: TJsAppConfigInput + configInput: TJsConfigInput ): Promise> => { const isDebug = getIsDebug(); if (isDebug) { logger.configure({ logLevel: "debug" }); } + let config = Config.getInstance(); - const isLocalStorageOld = checkForOlderLocalConfig(); + const { changed, newState } = migrateLocalStorage(); - let appConfig = appConfigGlobal; + if (changed) { + config.resetConfig(); + config = Config.getInstance(); - if (isLocalStorageOld) { - logger.debug("Local config is of an older version"); - logger.debug("Resetting config"); - - appConfig.resetConfig(); - appConfig = AppConfig.getInstance(); + // If the js sdk is being used for non identified users, and we have a new state to update to after migrating, we update the state + // otherwise, we just sync again! + if (!configInput.userId && newState) { + config.update(newState); + } } if (isInitialized) { @@ -73,7 +110,7 @@ export const initialize = async ( let existingConfig: TJsConfig | undefined; try { - existingConfig = appConfigGlobal.get(); + existingConfig = config.get(); logger.debug("Found existing configuration."); } catch (e) { logger.debug("No existing configuration found."); @@ -85,7 +122,7 @@ export const initialize = async ( logger.debug( "Formbricks is in error state, but debug mode is active. Resetting config and continuing." ); - appConfigGlobal.resetConfig(); + config.resetConfig(); return okVoid(); } @@ -122,38 +159,32 @@ export const initialize = async ( }); } - if (!configInput.userId) { - logger.debug("No userId provided"); - - return err({ - code: "missing_field", - field: "userId", - }); - } - logger.debug("Adding widget container to DOM"); addWidgetContainer(); let updatedAttributes: TAttributes | null = null; if (configInput.attributes) { - const res = await updateAttributes( - configInput.apiHost, - configInput.environmentId, - configInput.userId, - configInput.attributes - ); - if (res.ok !== true) { - return err(res.error); + if (configInput.userId) { + const res = await updateAttributes( + configInput.apiHost, + configInput.environmentId, + configInput.userId, + configInput.attributes + ); + if (res.ok !== true) { + return err(res.error); + } + updatedAttributes = res.value; + } else { + updatedAttributes = { ...configInput.attributes }; } - updatedAttributes = res.value; } if ( existingConfig && existingConfig.environmentState && existingConfig.environmentId === configInput.environmentId && - existingConfig.apiHost === configInput.apiHost && - existingConfig.personState?.data?.userId === configInput.userId + existingConfig.apiHost === configInput.apiHost ) { logger.debug("Configuration fits init parameters."); let isEnvironmentStateExpired = false; @@ -164,7 +195,12 @@ export const initialize = async ( isEnvironmentStateExpired = true; } - if (existingConfig.personState.expiresAt && new Date(existingConfig.personState.expiresAt) < new Date()) { + // if the config has a userId and the person state has expired, we need to sync the person state + if ( + configInput.userId && + existingConfig.personState.expiresAt && + new Date(existingConfig.personState.expiresAt) < new Date() + ) { logger.debug("Person state expired. Syncing."); isPersonStateExpired = true; } @@ -172,29 +208,33 @@ export const initialize = async ( try { // fetch the environment state (if expired) const environmentState = isEnvironmentStateExpired - ? await fetchEnvironmentState( - { - apiHost: configInput.apiHost, - environmentId: configInput.environmentId, - }, - "app" - ) + ? await fetchEnvironmentState({ + apiHost: configInput.apiHost, + environmentId: configInput.environmentId, + }) : existingConfig.environmentState; // fetch the person state (if expired) - const personState = isPersonStateExpired - ? await fetchPersonState({ + + let { personState } = existingConfig; + + if (isPersonStateExpired) { + if (configInput.userId) { + personState = await fetchPersonState({ apiHost: configInput.apiHost, environmentId: configInput.environmentId, userId: configInput.userId, - }) - : existingConfig.personState; + }); + } else { + personState = DEFAULT_PERSON_STATE_NO_USER_ID; + } + } // filter the environment state wrt the person state const filteredSurveys = filterSurveys(environmentState, personState); // update the appConfig with the new filtered surveys - appConfigGlobal.update({ + config.update({ ...existingConfig, environmentState, personState, @@ -204,13 +244,13 @@ export const initialize = async ( const surveyNames = filteredSurveys.map((s) => s.name); logger.debug("Fetched " + surveyNames.length + " surveys during sync: " + surveyNames.join(", ")); } catch (e) { - putFormbricksInErrorState(appConfig); + putFormbricksInErrorState(config); } } else { logger.debug( "No valid configuration found or it has been expired. Resetting config and creating new one." ); - appConfigGlobal.resetConfig(); + config.resetConfig(); logger.debug("Syncing."); try { @@ -219,21 +259,22 @@ export const initialize = async ( apiHost: configInput.apiHost, environmentId: configInput.environmentId, }, - "app", - false - ); - const personState = await fetchPersonState( - { - apiHost: configInput.apiHost, - environmentId: configInput.environmentId, - userId: configInput.userId, - }, false ); + const personState = configInput.userId + ? await fetchPersonState( + { + apiHost: configInput.apiHost, + environmentId: configInput.environmentId, + userId: configInput.userId, + }, + false + ) + : DEFAULT_PERSON_STATE_NO_USER_ID; const filteredSurveys = filterSurveys(environmentState, personState); - appConfigGlobal.update({ + config.update({ apiHost: configInput.apiHost, environmentId: configInput.environmentId, personState, @@ -250,14 +291,14 @@ export const initialize = async ( // update attributes in config if (updatedAttributes && Object.keys(updatedAttributes).length > 0) { - appConfigGlobal.update({ - ...appConfigGlobal.get(), + config.update({ + ...config.get(), personState: { - ...appConfigGlobal.get().personState, + ...config.get().personState, data: { - ...appConfigGlobal.get().personState.data, + ...config.get().personState.data, attributes: { - ...appConfigGlobal.get().personState.data.attributes, + ...config.get().personState.data.attributes, ...updatedAttributes, }, }, @@ -266,7 +307,7 @@ export const initialize = async ( } logger.debug("Adding event listeners"); - addEventListeners(appConfigGlobal); + addEventListeners(); addCleanupEventListeners(); setIsInitialized(true); @@ -293,7 +334,7 @@ export const handleErrorOnFirstInit = () => { }; // can't use config.update here because the config is not yet initialized - wrapThrows(() => localStorage.setItem(APP_SURVEYS_LOCAL_STORAGE_KEY, JSON.stringify(initialErrorConfig)))(); + wrapThrows(() => localStorage.setItem(JS_LOCAL_STORAGE_KEY, JSON.stringify(initialErrorConfig)))(); throw new Error("Could not initialize formbricks"); }; @@ -317,7 +358,7 @@ export const deinitalize = (): void => { setIsInitialized(false); }; -export const putFormbricksInErrorState = (appConfig: AppConfig): void => { +export const putFormbricksInErrorState = (config: Config): void => { if (getIsDebug()) { logger.debug("Not putting formbricks in error state because debug mode is active (no error state)"); return; @@ -325,8 +366,8 @@ export const putFormbricksInErrorState = (appConfig: AppConfig): void => { logger.debug("Putting formbricks in error state"); // change formbricks status to error - appConfig.update({ - ...appConfigGlobal.get(), + config.update({ + ...config.get(), status: { value: "error", expiresAt: new Date(new Date().getTime() + 10 * 60000), // 10 minutes in the future diff --git a/packages/js-core/src/shared/logger.ts b/packages/js-core/src/lib/logger.ts similarity index 100% rename from packages/js-core/src/shared/logger.ts rename to packages/js-core/src/lib/logger.ts diff --git a/packages/js-core/src/app/lib/noCodeActions.ts b/packages/js-core/src/lib/noCodeActions.ts similarity index 96% rename from packages/js-core/src/app/lib/noCodeActions.ts rename to packages/js-core/src/lib/noCodeActions.ts index f057e7b739..c1bb675260 100644 --- a/packages/js-core/src/app/lib/noCodeActions.ts +++ b/packages/js-core/src/lib/noCodeActions.ts @@ -1,11 +1,11 @@ import type { TActionClass } from "@formbricks/types/action-classes"; -import { ErrorHandler, NetworkError, Result, err, match, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { evaluateNoCodeConfigClick, handleUrlFilters } from "../../shared/utils"; import { trackNoCodeAction } from "./actions"; -import { AppConfig } from "./config"; +import { Config } from "./config"; +import { ErrorHandler, NetworkError, Result, err, match, okVoid } from "./errors"; +import { Logger } from "./logger"; +import { evaluateNoCodeConfigClick, handleUrlFilters } from "./utils"; -const appConfig = AppConfig.getInstance(); +const appConfig = Config.getInstance(); const logger = Logger.getInstance(); const errorHandler = ErrorHandler.getInstance(); diff --git a/packages/js-core/src/lib/person.ts b/packages/js-core/src/lib/person.ts new file mode 100644 index 0000000000..b94905e25f --- /dev/null +++ b/packages/js-core/src/lib/person.ts @@ -0,0 +1,34 @@ +import { Config } from "./config"; +import { NetworkError, Result, err, okVoid } from "./errors"; +import { deinitalize, initialize } from "./initialize"; +import { Logger } from "./logger"; +import { closeSurvey } from "./widget"; + +const config = Config.getInstance(); +const logger = Logger.getInstance(); + +export const logoutPerson = async (): Promise => { + deinitalize(); + config.resetConfig(); +}; + +export const resetPerson = async (): Promise> => { + logger.debug("Resetting state & getting new state from backend"); + closeSurvey(); + + const userId = config.get().personState.data.userId; + + const syncParams = { + environmentId: config.get().environmentId, + apiHost: config.get().apiHost, + ...(userId && { userId }), + attributes: config.get().personState.data.attributes, + }; + await logoutPerson(); + try { + await initialize(syncParams); + return okVoid(); + } catch (e) { + return err(e as NetworkError); + } +}; diff --git a/packages/js-core/src/shared/personState.ts b/packages/js-core/src/lib/personState.ts similarity index 83% rename from packages/js-core/src/shared/personState.ts rename to packages/js-core/src/lib/personState.ts index c575dda87e..7c4231168e 100644 --- a/packages/js-core/src/shared/personState.ts +++ b/packages/js-core/src/lib/personState.ts @@ -1,13 +1,14 @@ import { TJsPersonState, TJsPersonSyncParams } from "@formbricks/types/js"; -import { AppConfig } from "../app/lib/config"; +import { Config } from "./config"; import { err } from "./errors"; import { Logger } from "./logger"; import { getIsDebug } from "./utils"; +const config = Config.getInstance(); const logger = Logger.getInstance(); let personStateSyncIntervalId: number | null = null; -export const DEFAULT_PERSON_STATE_WEBSITE: TJsPersonState = { +export const DEFAULT_PERSON_STATE_NO_USER_ID: TJsPersonState = { expiresAt: null, data: { userId: null, @@ -39,7 +40,7 @@ export const fetchPersonState = async ( logger.debug("No cache option set for sync"); } - const url = `${apiHost}/api/v1/client/${environmentId}/app/people/${userId}`; + const url = `${apiHost}/api/v1/client/${environmentId}/identify/people/${userId}`; const response = await fetch(url, fetchOptions); @@ -60,6 +61,8 @@ export const fetchPersonState = async ( const data = await response.json(); const { data: state } = data; + console.log("Person state fetched", state); + const defaultPersonState: TJsPersonState = { expiresAt: new Date(new Date().getTime() + 1000 * 60 * 30), // 30 minutes data: { @@ -84,25 +87,24 @@ export const fetchPersonState = async ( /** * Add a listener to check if the person state has expired with a certain interval - * @param appConfig - The app config + * @param config - The configuration for the SDK */ -export const addPersonStateExpiryCheckListener = (appConfig: AppConfig): void => { +export const addPersonStateExpiryCheckListener = (): void => { const updateInterval = 1000 * 60; // every 60 seconds if (typeof window !== "undefined" && personStateSyncIntervalId === null) { personStateSyncIntervalId = window.setInterval(async () => { - const userId = appConfig.get().personState.data.userId; + const userId = config.get().personState.data.userId; if (!userId) { return; } // extend the personState validity by 30 minutes: - - appConfig.update({ - ...appConfig.get(), + config.update({ + ...config.get(), personState: { - ...appConfig.get().personState, + ...config.get().personState, expiresAt: new Date(new Date().getTime() + 1000 * 60 * 30), // 30 minutes }, }); diff --git a/packages/js-core/src/shared/utils.ts b/packages/js-core/src/lib/utils.ts similarity index 97% rename from packages/js-core/src/shared/utils.ts rename to packages/js-core/src/lib/utils.ts index 4911566edc..de566febdb 100644 --- a/packages/js-core/src/shared/utils.ts +++ b/packages/js-core/src/lib/utils.ts @@ -158,11 +158,10 @@ export const getIsDebug = () => window.location.search.includes("formbricksDebug // takes the environment and person state and returns the filtered surveys export const filterSurveys = ( environmentState: TJsEnvironmentState, - personState: TJsPersonState, - sdkType: "app" | "website" = "app" + personState: TJsPersonState ): TSurvey[] => { const { product, surveys } = environmentState.data; - const { displays, responses, lastDisplayAt, segments } = personState.data; + const { displays, responses, lastDisplayAt, segments, userId } = personState.data; if (!displays) { return []; @@ -220,7 +219,7 @@ export const filterSurveys = ( } }); - if (sdkType === "website") { + if (!userId) { return filteredSurveys; } diff --git a/packages/js-core/src/app/lib/widget.ts b/packages/js-core/src/lib/widget.ts similarity index 79% rename from packages/js-core/src/app/lib/widget.ts rename to packages/js-core/src/lib/widget.ts index 29173029d3..ccc03e3b24 100644 --- a/packages/js-core/src/app/lib/widget.ts +++ b/packages/js-core/src/lib/widget.ts @@ -6,19 +6,18 @@ import { TJsFileUploadParams, TJsPersonState, TJsTrackProperties } from "@formbr import { TResponseHiddenFieldValue, TResponseUpdate } from "@formbricks/types/responses"; import { TUploadFileConfig } from "@formbricks/types/storage"; import { TSurvey } from "@formbricks/types/surveys/types"; -import { Logger } from "../../shared/logger"; +import { Config } from "./config"; +import { CONTAINER_ID } from "./constants"; +import { Logger } from "./logger"; import { filterSurveys, getDefaultLanguageCode, getLanguageCode, handleHiddenFields, shouldDisplayBasedOnPercentage, -} from "../../shared/utils"; -import { AppConfig } from "./config"; +} from "./utils"; -const containerId = "formbricks-app-container"; - -const appConfig = AppConfig.getInstance(); +const config = Config.getInstance(); const logger = Logger.getInstance(); let isSurveyRunning = false; let setIsError = (_: boolean) => {}; @@ -65,8 +64,8 @@ const renderWidget = async ( logger.debug(`Delaying survey "${survey.name}" by ${survey.delay} seconds.`); } - const { product } = appConfig.get().environmentState.data ?? {}; - const { attributes } = appConfig.get().personState.data ?? {}; + const { product } = config.get().environmentState.data ?? {}; + const { attributes } = config.get().personState.data ?? {}; const isMultiLanguageSurvey = survey.languages.length > 1; let languageCode = "default"; @@ -82,12 +81,12 @@ const renderWidget = async ( languageCode = displayLanguage; } - const surveyState = new SurveyState(survey.id, null, null, appConfig.get().personState.data.userId); + const surveyState = new SurveyState(survey.id, null, null, config.get().personState.data.userId); const responseQueue = new ResponseQueue( { - apiHost: appConfig.get().apiHost, - environmentId: appConfig.get().environmentId, + apiHost: config.get().apiHost, + environmentId: config.get().environmentId, retryAttempts: 2, onResponseSendingFailed: () => { setIsError(true); @@ -121,21 +120,16 @@ const renderWidget = async ( setIsResponseSendingFinished = f; }, onDisplay: async () => { - const { userId } = appConfig.get().personState.data; - - if (!userId) { - logger.debug("User ID not found. Skipping."); - return; - } + const { userId } = config.get().personState.data; const api = new FormbricksAPI({ - apiHost: appConfig.get().apiHost, - environmentId: appConfig.get().environmentId, + apiHost: config.get().apiHost, + environmentId: config.get().environmentId, }); const res = await api.client.display.create({ surveyId: survey.id, - userId, + ...(userId && { userId }), }); if (!res.ok) { @@ -147,10 +141,10 @@ const renderWidget = async ( surveyState.updateDisplayId(id); responseQueue.updateSurveyState(surveyState); - const existingDisplays = appConfig.get().personState.data.displays; + const existingDisplays = config.get().personState.data.displays; const newDisplay = { surveyId: survey.id, createdAt: new Date() }; const displays = existingDisplays ? [...existingDisplays, newDisplay] : [newDisplay]; - const previousConfig = appConfig.get(); + const previousConfig = config.get(); const updatedPersonState: TJsPersonState = { ...previousConfig.personState, @@ -163,23 +157,21 @@ const renderWidget = async ( const filteredSurveys = filterSurveys(previousConfig.environmentState, updatedPersonState); - appConfig.update({ + config.update({ ...previousConfig, + environmentState: previousConfig.environmentState, personState: updatedPersonState, filteredSurveys, }); }, onResponse: (responseUpdate: TResponseUpdate) => { - const { userId } = appConfig.get().personState.data; - - if (!userId) { - logger.debug("User ID not found. Skipping."); - return; - } + const { userId } = config.get().personState.data; const isNewResponse = surveyState.responseId === null; - surveyState.updateUserId(userId); + if (userId) { + surveyState.updateUserId(userId); + } responseQueue.updateSurveyState(surveyState); responseQueue.add({ @@ -198,20 +190,20 @@ const renderWidget = async ( }); if (isNewResponse) { - const responses = appConfig.get().personState.data.responses; + const responses = config.get().personState.data.responses; const newPersonState: TJsPersonState = { - ...appConfig.get().personState, + ...config.get().personState, data: { - ...appConfig.get().personState.data, + ...config.get().personState.data, responses: [...responses, surveyState.surveyId], }, }; - const filteredSurveys = filterSurveys(appConfig.get().environmentState, newPersonState); + const filteredSurveys = filterSurveys(config.get().environmentState, newPersonState); - appConfig.update({ - ...appConfig.get(), - environmentState: appConfig.get().environmentState, + config.update({ + ...config.get(), + environmentState: config.get().environmentState, personState: newPersonState, filteredSurveys, }); @@ -220,8 +212,8 @@ const renderWidget = async ( onClose: closeSurvey, onFileUpload: async (file: TJsFileUploadParams["file"], params: TUploadFileConfig) => { const api = new FormbricksAPI({ - apiHost: appConfig.get().apiHost, - environmentId: appConfig.get().environmentId, + apiHost: config.get().apiHost, + environmentId: config.get().environmentId, }); return await api.client.storage.uploadFile( @@ -247,11 +239,11 @@ export const closeSurvey = async (): Promise => { removeWidgetContainer(); addWidgetContainer(); - const { environmentState, personState } = appConfig.get(); + const { environmentState, personState } = config.get(); const filteredSurveys = filterSurveys(environmentState, personState); - appConfig.update({ - ...appConfig.get(), + config.update({ + ...config.get(), environmentState, personState, filteredSurveys, @@ -262,12 +254,12 @@ export const closeSurvey = async (): Promise => { export const addWidgetContainer = (): void => { const containerElement = document.createElement("div"); - containerElement.id = containerId; + containerElement.id = CONTAINER_ID; document.body.appendChild(containerElement); }; export const removeWidgetContainer = (): void => { - document.getElementById(containerId)?.remove(); + document.getElementById(CONTAINER_ID)?.remove(); }; const loadFormbricksSurveysExternally = (): Promise => { @@ -276,7 +268,7 @@ const loadFormbricksSurveysExternally = (): Promise resolve(window.formbricksSurveys); script.onerror = (error) => { diff --git a/packages/js-core/src/shared/constants.ts b/packages/js-core/src/shared/constants.ts deleted file mode 100644 index 99df8d0ffc..0000000000 --- a/packages/js-core/src/shared/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const APP_SURVEYS_LOCAL_STORAGE_KEY = "formbricks-js-app"; -export const RN_ASYNC_STORAGE_KEY = "formbricks-react-native"; -export const WEBSITE_SURVEYS_LOCAL_STORAGE_KEY = "formbricks-js-website"; diff --git a/packages/js-core/src/website/index.ts b/packages/js-core/src/website/index.ts deleted file mode 100644 index 4d88916d66..0000000000 --- a/packages/js-core/src/website/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { TJsTrackProperties, TJsWebsiteConfigInput } from "@formbricks/types/js"; -// Shared imports -import { CommandQueue } from "../shared/commandQueue"; -import { ErrorHandler } from "../shared/errors"; -import { Logger } from "../shared/logger"; -// Website package specific imports -import { trackCodeAction } from "./lib/actions"; -import { resetConfig } from "./lib/common"; -import { initialize } from "./lib/initialize"; -import { checkPageUrl } from "./lib/noCodeActions"; - -const logger = Logger.getInstance(); - -logger.debug("Create command queue"); -const queue = new CommandQueue(); - -const init = async (initConfig: TJsWebsiteConfigInput) => { - ErrorHandler.init(initConfig.errorHandler); - queue.add(false, "website", initialize, initConfig); - await queue.wait(); -}; - -const reset = async (): Promise => { - queue.add(true, "website", resetConfig); - await queue.wait(); -}; - -const track = async (name: string, properties?: TJsTrackProperties): Promise => { - queue.add(true, "website", trackCodeAction, name, properties); - await queue.wait(); -}; - -const registerRouteChange = async (): Promise => { - queue.add(true, "website", checkPageUrl); - await queue.wait(); -}; - -const formbricks = { - init, - track, - reset, - registerRouteChange, -}; - -export type TFormbricksWebsite = typeof formbricks; -export default formbricks as TFormbricksWebsite; diff --git a/packages/js-core/src/website/lib/actions.ts b/packages/js-core/src/website/lib/actions.ts deleted file mode 100644 index fef6d027b7..0000000000 --- a/packages/js-core/src/website/lib/actions.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { TJsTrackProperties } from "@formbricks/types/js"; -import { InvalidCodeError, NetworkError, Result, err, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { WebsiteConfig } from "./config"; -import { triggerSurvey } from "./widget"; - -const logger = Logger.getInstance(); -const websiteConfig = WebsiteConfig.getInstance(); - -export const trackAction = async ( - name: string, - alias?: string, - properties?: TJsTrackProperties -): Promise> => { - const aliasName = alias || name; - logger.debug(`Formbricks: Action "${aliasName}" tracked`); - - // get a list of surveys that are collecting insights - const activeSurveys = websiteConfig.get().filteredSurveys; - - if (!!activeSurveys && activeSurveys.length > 0) { - for (const survey of activeSurveys) { - for (const trigger of survey.triggers) { - if (trigger.actionClass.name === name) { - await triggerSurvey(survey, name, properties); - } - } - } - } else { - logger.debug("No active surveys to display"); - } - - return okVoid(); -}; - -export const trackCodeAction = ( - code: string, - properties?: TJsTrackProperties -): Promise> | Result => { - const actionClasses = websiteConfig.get().environmentState.data.actionClasses; - - const codeActionClasses = actionClasses.filter((action) => action.type === "code"); - const action = codeActionClasses.find((action) => action.key === code); - - if (!action) { - return err({ - code: "invalid_code", - message: `${code} action unknown. Please add this action in Formbricks first in order to use it in your code.`, - }); - } - - return trackAction(action.name, code, properties); -}; - -export const trackNoCodeAction = (name: string): Promise> => { - return trackAction(name); -}; diff --git a/packages/js-core/src/website/lib/common.ts b/packages/js-core/src/website/lib/common.ts deleted file mode 100644 index 6dc0776ac8..0000000000 --- a/packages/js-core/src/website/lib/common.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NetworkError, Result, err, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { WebsiteConfig } from "./config"; -import { deinitalize, initialize } from "./initialize"; -import { closeSurvey } from "./widget"; - -const websiteConfig = WebsiteConfig.getInstance(); -const logger = Logger.getInstance(); - -export const resetWebsiteConfig = async (): Promise => { - deinitalize(); - websiteConfig.resetConfig(); -}; - -export const resetConfig = async (): Promise> => { - logger.debug("Resetting state & getting new state from backend"); - closeSurvey(); - - const syncParams = { - environmentId: websiteConfig.get().environmentId, - apiHost: websiteConfig.get().apiHost, - }; - - await resetWebsiteConfig(); - try { - await initialize(syncParams); - return okVoid(); - } catch (e) { - return err(e as NetworkError); - } -}; diff --git a/packages/js-core/src/website/lib/config.ts b/packages/js-core/src/website/lib/config.ts deleted file mode 100644 index 113eab2e2b..0000000000 --- a/packages/js-core/src/website/lib/config.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { TJsConfig, TJsConfigUpdateInput } from "@formbricks/types/js"; -import { WEBSITE_SURVEYS_LOCAL_STORAGE_KEY } from "../../shared/constants"; -import { Result, err, ok, wrapThrows } from "../../shared/errors"; - -export class WebsiteConfig { - private static instance: WebsiteConfig | undefined; - private config: TJsConfig | null = null; - - private constructor() { - const localConfig = this.loadFromLocalStorage(); - - if (localConfig.ok) { - this.config = localConfig.value; - } - } - - static getInstance(): WebsiteConfig { - if (!WebsiteConfig.instance) { - WebsiteConfig.instance = new WebsiteConfig(); - } - return WebsiteConfig.instance; - } - - public update(newConfig: TJsConfigUpdateInput): void { - if (newConfig) { - this.config = { - ...this.config, - ...newConfig, - status: { - value: newConfig.status?.value || "success", - expiresAt: newConfig.status?.expiresAt || null, - }, - }; - - this.saveToLocalStorage(); - } - } - - public get(): TJsConfig { - if (!this.config) { - throw new Error("config is null, maybe the init function was not called?"); - } - return this.config; - } - - public loadFromLocalStorage(): Result { - if (typeof window !== "undefined") { - const savedConfig = localStorage.getItem(WEBSITE_SURVEYS_LOCAL_STORAGE_KEY); - if (savedConfig) { - // TODO: validate config - // This is a hack to get around the fact that we don't have a proper - // way to validate the config yet. - const parsedConfig = JSON.parse(savedConfig) as TJsConfig; - - // check if the config has expired - - // TODO: Figure out the expiration logic - if ( - parsedConfig.environmentState && - parsedConfig.environmentState.expiresAt && - new Date(parsedConfig.environmentState.expiresAt) <= new Date() - ) { - return err(new Error("Config in local storage has expired")); - } - - return ok(parsedConfig); - } - } - - return err(new Error("No or invalid config in local storage")); - } - - private saveToLocalStorage(): Result { - return wrapThrows(() => - localStorage.setItem(WEBSITE_SURVEYS_LOCAL_STORAGE_KEY, JSON.stringify(this.config)) - )(); - } - - // reset the config - - public resetConfig(): Result { - this.config = null; - - return wrapThrows(() => localStorage.removeItem(WEBSITE_SURVEYS_LOCAL_STORAGE_KEY))(); - } -} diff --git a/packages/js-core/src/website/lib/eventListeners.ts b/packages/js-core/src/website/lib/eventListeners.ts deleted file mode 100644 index bfe5b74d66..0000000000 --- a/packages/js-core/src/website/lib/eventListeners.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - addEnvironmentStateExpiryCheckListener, - clearEnvironmentStateExpiryCheckListener, -} from "../../shared/environmentState"; -import { - addClickEventListener, - addExitIntentListener, - addPageUrlEventListeners, - addScrollDepthListener, - removeClickEventListener, - removeExitIntentListener, - removePageUrlEventListeners, - removeScrollDepthListener, -} from "../lib/noCodeActions"; -import { WebsiteConfig } from "./config"; - -let areRemoveEventListenersAdded = false; - -export const addEventListeners = (config: WebsiteConfig): void => { - addEnvironmentStateExpiryCheckListener("website", config); - clearEnvironmentStateExpiryCheckListener(); - addPageUrlEventListeners(); - addClickEventListener(); - addExitIntentListener(); - addScrollDepthListener(); -}; - -export const addCleanupEventListeners = (): void => { - if (areRemoveEventListenersAdded) return; - window.addEventListener("beforeunload", () => { - clearEnvironmentStateExpiryCheckListener(); - removePageUrlEventListeners(); - removeClickEventListener(); - removeExitIntentListener(); - removeScrollDepthListener(); - }); - areRemoveEventListenersAdded = true; -}; - -export const removeCleanupEventListeners = (): void => { - if (!areRemoveEventListenersAdded) return; - window.removeEventListener("beforeunload", () => { - clearEnvironmentStateExpiryCheckListener(); - removePageUrlEventListeners(); - removeClickEventListener(); - removeExitIntentListener(); - removeScrollDepthListener(); - }); - areRemoveEventListenersAdded = false; -}; - -export const removeAllEventListeners = (): void => { - clearEnvironmentStateExpiryCheckListener(); - removePageUrlEventListeners(); - removeClickEventListener(); - removeExitIntentListener(); - removeScrollDepthListener(); - removeCleanupEventListeners(); -}; diff --git a/packages/js-core/src/website/lib/initialize.ts b/packages/js-core/src/website/lib/initialize.ts deleted file mode 100644 index 4adfb713b7..0000000000 --- a/packages/js-core/src/website/lib/initialize.ts +++ /dev/null @@ -1,343 +0,0 @@ -import type { TJsConfig, TJsWebsiteConfigInput, TJsWebsiteState } from "@formbricks/types/js"; -import { WEBSITE_SURVEYS_LOCAL_STORAGE_KEY } from "../../shared/constants"; -import { fetchEnvironmentState } from "../../shared/environmentState"; -import { - ErrorHandler, - MissingFieldError, - MissingPersonError, - NetworkError, - NotInitializedError, - Result, - err, - okVoid, - wrapThrows, -} from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { DEFAULT_PERSON_STATE_WEBSITE } from "../../shared/personState"; -import { getIsDebug } from "../../shared/utils"; -import { filterSurveys as filterPublicSurveys } from "../../shared/utils"; -import { trackNoCodeAction } from "./actions"; -import { WebsiteConfig } from "./config"; -import { addCleanupEventListeners, addEventListeners, removeAllEventListeners } from "./eventListeners"; -import { checkPageUrl } from "./noCodeActions"; -import { addWidgetContainer, removeWidgetContainer, setIsSurveyRunning } from "./widget"; - -const logger = Logger.getInstance(); - -let isInitialized = false; - -export const setIsInitialized = (value: boolean) => { - isInitialized = value; -}; - -const migrateLocalStorage = (): { changed: boolean; newState?: TJsConfig } => { - const oldConfig = localStorage.getItem(WEBSITE_SURVEYS_LOCAL_STORAGE_KEY); - - let newWebsiteConfig: TJsConfig; - if (oldConfig) { - const parsedOldConfig = JSON.parse(oldConfig); - // if the old config follows the older structure, we need to migrate it - if (parsedOldConfig.state || parsedOldConfig.expiresAt) { - logger.debug("Migrating local storage"); - const { apiHost, environmentId, state, expiresAt } = parsedOldConfig as { - apiHost: string; - environmentId: string; - state: TJsWebsiteState; - expiresAt: Date; - }; - const { displays: displaysState, actionClasses, product, surveys, attributes } = state; - - const responses = displaysState - .filter((display) => display.responded) - .map((display) => display.surveyId); - - const displays = displaysState.map((display) => ({ - surveyId: display.surveyId, - createdAt: display.createdAt, - })); - const lastDisplayAt = displaysState - ? displaysState.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())[0] - .createdAt - : null; - - newWebsiteConfig = { - apiHost, - environmentId, - environmentState: { - data: { - surveys, - actionClasses, - product, - }, - expiresAt, - }, - personState: { - expiresAt, - data: { - userId: null, - segments: [], - displays, - responses, - attributes: attributes ?? {}, - lastDisplayAt, - }, - }, - filteredSurveys: surveys, - status: { - value: "success", - expiresAt: null, - }, - }; - - logger.debug("Migrated local storage to new format"); - - return { changed: true, newState: newWebsiteConfig }; - } - - return { changed: false }; - } - - return { changed: false }; -}; - -export const initialize = async ( - configInput: TJsWebsiteConfigInput -): Promise> => { - const isDebug = getIsDebug(); - if (isDebug) { - logger.configure({ logLevel: "debug" }); - } - - const { changed, newState } = migrateLocalStorage(); - let websiteConfig = WebsiteConfig.getInstance(); - - // If the state was changed due to migration, reset and reinitialize the configuration - if (changed && newState) { - // The state exists in the local storage, so this should not fail - websiteConfig.resetConfig(); // Reset the configuration - - // Re-fetch a new instance of WebsiteConfig after resetting - websiteConfig = WebsiteConfig.getInstance(); - - // Update the new instance with the migrated state - websiteConfig.update(newState); - } - - if (isInitialized) { - logger.debug("Already initialized, skipping initialization."); - return okVoid(); - } - - let existingConfig: TJsConfig | undefined; - try { - existingConfig = websiteConfig.get(); - logger.debug("Found existing configuration."); - } catch (e) { - logger.debug("No existing configuration found."); - } - - // formbricks is in error state, skip initialization - if (existingConfig?.status?.value === "error") { - if (isDebug) { - logger.debug( - "Formbricks is in error state, but debug mode is active. Resetting config and continuing." - ); - websiteConfig.resetConfig(); - return okVoid(); - } - - logger.debug("Formbricks was set to an error state."); - - if (existingConfig?.status?.expiresAt && new Date(existingConfig?.status?.expiresAt) > new Date()) { - logger.debug("Error state is not expired, skipping initialization"); - return okVoid(); - } else { - logger.debug("Error state is expired. Continue with initialization."); - } - } - - ErrorHandler.getInstance().printStatus(); - - logger.debug("Start initialize"); - - if (!configInput.environmentId) { - logger.debug("No environmentId provided"); - return err({ - code: "missing_field", - field: "environmentId", - }); - } - - if (!configInput.apiHost) { - logger.debug("No apiHost provided"); - - return err({ - code: "missing_field", - field: "apiHost", - }); - } - - logger.debug("Adding widget container to DOM"); - addWidgetContainer(); - - if ( - existingConfig && - existingConfig.environmentId === configInput.environmentId && - existingConfig.apiHost === configInput.apiHost && - existingConfig.environmentState - ) { - logger.debug("Configuration fits init parameters."); - if (existingConfig.environmentState.expiresAt < new Date()) { - logger.debug("Configuration expired."); - - try { - // fetch the environment state - - const environmentState = await fetchEnvironmentState( - { - apiHost: configInput.apiHost, - environmentId: configInput.environmentId, - }, - "website" - ); - - // filter the surveys with the default person state - - const filteredSurveys = filterPublicSurveys( - environmentState, - DEFAULT_PERSON_STATE_WEBSITE, - "website" - ); - - websiteConfig.update({ - apiHost: configInput.apiHost, - environmentId: configInput.environmentId, - environmentState, - personState: DEFAULT_PERSON_STATE_WEBSITE, - filteredSurveys, - }); - } catch (e) { - putFormbricksInErrorState(websiteConfig); - } - } else { - logger.debug("Configuration not expired. Extending expiration."); - websiteConfig.update(existingConfig); - } - } else { - logger.debug( - "No valid configuration found or it has been expired. Resetting config and creating new one." - ); - websiteConfig.resetConfig(); - logger.debug("Syncing."); - - try { - const environmentState = await fetchEnvironmentState( - { - apiHost: configInput.apiHost, - environmentId: configInput.environmentId, - }, - "website" - ); - - const filteredSurveys = filterPublicSurveys(environmentState, DEFAULT_PERSON_STATE_WEBSITE, "website"); - - websiteConfig.update({ - apiHost: configInput.apiHost, - environmentId: configInput.environmentId, - environmentState, - personState: DEFAULT_PERSON_STATE_WEBSITE, - filteredSurveys, - }); - } catch (e) { - handleErrorOnFirstInit(); - } - - if (configInput.attributes) { - const currentWebsiteConfig = websiteConfig.get(); - - websiteConfig.update({ - ...currentWebsiteConfig, - personState: { - ...currentWebsiteConfig.personState, - data: { - ...currentWebsiteConfig.personState.data, - attributes: { ...currentWebsiteConfig.personState.data.attributes, ...configInput.attributes }, - }, - }, - }); - } - - // and track the new session event - await trackNoCodeAction("New Session"); - } - - logger.debug("Adding event listeners"); - addEventListeners(websiteConfig); - addCleanupEventListeners(); - - setIsInitialized(true); - logger.debug("Initialized"); - - // check page url if initialized after page load - - checkPageUrl(); - return okVoid(); -}; - -export const handleErrorOnFirstInit = () => { - if (getIsDebug()) { - logger.debug("Not putting formbricks in error state because debug mode is active (no error state)"); - return; - } - - const initialErrorConfig: Partial = { - status: { - value: "error", - expiresAt: new Date(new Date().getTime() + 10 * 60000), // 10 minutes in the future - }, - }; - - // can't use config.update here because the config is not yet initialized - wrapThrows(() => - localStorage.setItem(WEBSITE_SURVEYS_LOCAL_STORAGE_KEY, JSON.stringify(initialErrorConfig)) - )(); - throw new Error("Could not initialize formbricks"); -}; - -export const checkInitialized = (): Result => { - logger.debug("Check if initialized"); - if (!isInitialized || !ErrorHandler.initialized) { - return err({ - code: "not_initialized", - message: "Formbricks not initialized. Call initialize() first.", - }); - } - - return okVoid(); -}; - -export const deinitalize = (): void => { - logger.debug("Deinitializing"); - removeWidgetContainer(); - setIsSurveyRunning(false); - removeAllEventListeners(); - setIsInitialized(false); -}; - -export const putFormbricksInErrorState = (websiteConfig: WebsiteConfig): void => { - if (getIsDebug()) { - logger.debug("Not putting formbricks in error state because debug mode is active (no error state)"); - return; - } - - logger.debug("Putting formbricks in error state"); - // change formbricks status to error - websiteConfig.update({ - ...websiteConfig.get(), - status: { - value: "error", - expiresAt: new Date(new Date().getTime() + 10 * 60000), // 10 minutes in the future - }, - }); - deinitalize(); -}; diff --git a/packages/js-core/src/website/lib/noCodeActions.ts b/packages/js-core/src/website/lib/noCodeActions.ts deleted file mode 100644 index 8188f086ed..0000000000 --- a/packages/js-core/src/website/lib/noCodeActions.ts +++ /dev/null @@ -1,189 +0,0 @@ -import type { TActionClass } from "@formbricks/types/action-classes"; -import { ErrorHandler, NetworkError, Result, err, match, okVoid } from "../../shared/errors"; -import { Logger } from "../../shared/logger"; -import { evaluateNoCodeConfigClick, handleUrlFilters } from "../../shared/utils"; -import { trackNoCodeAction } from "./actions"; -import { WebsiteConfig } from "./config"; - -const websiteConfig = WebsiteConfig.getInstance(); -const logger = Logger.getInstance(); -const errorHandler = ErrorHandler.getInstance(); - -// Event types for various listeners -const events = ["hashchange", "popstate", "pushstate", "replacestate", "load"]; - -// Page URL Event Handlers -let arePageUrlEventListenersAdded = false; - -export const checkPageUrl = async (): Promise> => { - logger.debug(`Checking page url: ${window.location.href}`); - const actionClasses = websiteConfig.get().environmentState.data.actionClasses; - - const noCodePageViewActionClasses = actionClasses.filter( - (action) => action.type === "noCode" && action.noCodeConfig?.type === "pageView" - ); - - for (const event of noCodePageViewActionClasses) { - const urlFilters = event.noCodeConfig?.urlFilters ?? []; - const isValidUrl = handleUrlFilters(urlFilters); - - if (!isValidUrl) continue; - - const trackResult = await trackNoCodeAction(event.name); - if (trackResult.ok !== true) return err(trackResult.error); - } - - return okVoid(); -}; - -const checkPageUrlWrapper = () => checkPageUrl(); - -export const addPageUrlEventListeners = (): void => { - if (typeof window === "undefined" || arePageUrlEventListenersAdded) return; - events.forEach((event) => window.addEventListener(event, checkPageUrlWrapper)); - arePageUrlEventListenersAdded = true; -}; - -export const removePageUrlEventListeners = (): void => { - if (typeof window === "undefined" || !arePageUrlEventListenersAdded) return; - events.forEach((event) => window.removeEventListener(event, checkPageUrlWrapper)); - arePageUrlEventListenersAdded = false; -}; - -// Click Event Handlers -let isClickEventListenerAdded = false; - -const checkClickMatch = (event: MouseEvent) => { - const { environmentState } = websiteConfig.get(); - if (!environmentState) return; - - const { actionClasses = [] } = environmentState.data; - const noCodeClickActionClasses = actionClasses.filter( - (action) => action.type === "noCode" && action.noCodeConfig?.type === "click" - ); - - const targetElement = event.target as HTMLElement; - - noCodeClickActionClasses.forEach((action: TActionClass) => { - if (evaluateNoCodeConfigClick(targetElement, action)) { - trackNoCodeAction(action.name).then((res) => { - match( - res, - (_value: unknown) => {}, - (err: any) => errorHandler.handle(err) - ); - }); - } - }); -}; - -const checkClickMatchWrapper = (e: MouseEvent) => checkClickMatch(e); - -export const addClickEventListener = (): void => { - if (typeof window === "undefined" || isClickEventListenerAdded) return; - document.addEventListener("click", checkClickMatchWrapper); - isClickEventListenerAdded = true; -}; - -export const removeClickEventListener = (): void => { - if (!isClickEventListenerAdded) return; - document.removeEventListener("click", checkClickMatchWrapper); - isClickEventListenerAdded = false; -}; - -// Exit Intent Handlers -let isExitIntentListenerAdded = false; - -const checkExitIntent = async (e: MouseEvent) => { - const actionClasses = websiteConfig.get().environmentState.data.actionClasses; - - const noCodeExitIntentActionClasses = actionClasses.filter( - (action) => action.type === "noCode" && action.noCodeConfig?.type === "exitIntent" - ); - - if (e.clientY <= 0 && noCodeExitIntentActionClasses.length > 0) { - for (const event of noCodeExitIntentActionClasses) { - const urlFilters = event.noCodeConfig?.urlFilters ?? []; - const isValidUrl = handleUrlFilters(urlFilters); - - if (!isValidUrl) continue; - - const trackResult = await trackNoCodeAction(event.name); - if (trackResult.ok !== true) return err(trackResult.error); - } - } -}; - -const checkExitIntentWrapper = (e: MouseEvent) => checkExitIntent(e); - -export const addExitIntentListener = (): void => { - if (typeof document !== "undefined" && !isExitIntentListenerAdded) { - document.querySelector("body")!.addEventListener("mouseleave", checkExitIntentWrapper); - isExitIntentListenerAdded = true; - } -}; - -export const removeExitIntentListener = (): void => { - if (isExitIntentListenerAdded) { - document.removeEventListener("mouseleave", checkExitIntentWrapper); - isExitIntentListenerAdded = false; - } -}; - -// Scroll Depth Handlers -let scrollDepthListenerAdded = false; -let scrollDepthTriggered = false; - -const checkScrollDepth = async () => { - const scrollPosition = window.scrollY; - const windowSize = window.innerHeight; - const bodyHeight = document.documentElement.scrollHeight; - - if (scrollPosition === 0) { - scrollDepthTriggered = false; - } - - if (!scrollDepthTriggered && scrollPosition / (bodyHeight - windowSize) >= 0.5) { - scrollDepthTriggered = true; - - const actionClasses = websiteConfig.get().environmentState.data.actionClasses; - - const noCodefiftyPercentScrollActionClasses = actionClasses.filter( - (action) => action.type === "noCode" && action.noCodeConfig?.type === "fiftyPercentScroll" - ); - - for (const event of noCodefiftyPercentScrollActionClasses) { - const urlFilters = event.noCodeConfig?.urlFilters ?? []; - const isValidUrl = handleUrlFilters(urlFilters); - - if (!isValidUrl) continue; - - const trackResult = await trackNoCodeAction(event.name); - if (trackResult.ok !== true) return err(trackResult.error); - } - } - - return okVoid(); -}; - -const checkScrollDepthWrapper = () => checkScrollDepth(); - -export const addScrollDepthListener = (): void => { - if (typeof window !== "undefined" && !scrollDepthListenerAdded) { - if (document.readyState === "complete") { - window.addEventListener("scroll", checkScrollDepthWrapper); - } else { - window.addEventListener("load", () => { - window.addEventListener("scroll", checkScrollDepthWrapper); - }); - } - scrollDepthListenerAdded = true; - } -}; - -export const removeScrollDepthListener = (): void => { - if (scrollDepthListenerAdded) { - window.removeEventListener("scroll", checkScrollDepthWrapper); - scrollDepthListenerAdded = false; - } -}; diff --git a/packages/js-core/src/website/lib/widget.ts b/packages/js-core/src/website/lib/widget.ts deleted file mode 100644 index 1118823ee2..0000000000 --- a/packages/js-core/src/website/lib/widget.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { FormbricksAPI } from "@formbricks/api"; -import { ResponseQueue } from "@formbricks/lib/responseQueue"; -import { SurveyState } from "@formbricks/lib/surveyState"; -import { getStyling } from "@formbricks/lib/utils/styling"; -import { TJsPersonState, TJsTrackProperties } from "@formbricks/types/js"; -import { TResponseHiddenFieldValue, TResponseUpdate } from "@formbricks/types/responses"; -import { TUploadFileConfig } from "@formbricks/types/storage"; -import { TSurvey } from "@formbricks/types/surveys/types"; -import { Logger } from "../../shared/logger"; -import { filterSurveys as filterPublicSurveys } from "../../shared/utils"; -import { getDefaultLanguageCode, getLanguageCode, handleHiddenFields } from "../../shared/utils"; -import { WebsiteConfig } from "./config"; - -const containerId = "formbricks-website-container"; - -const websiteConfig = WebsiteConfig.getInstance(); -const logger = Logger.getInstance(); - -let isSurveyRunning = false; -let setIsError = (_: boolean) => {}; -let setIsResponseSendingFinished = (_: boolean) => {}; - -export const setIsSurveyRunning = (value: boolean) => { - isSurveyRunning = value; -}; - -const shouldDisplayBasedOnPercentage = (displayPercentage: number) => { - const randomNum = Math.floor(Math.random() * 10000) / 100; - return randomNum <= displayPercentage; -}; - -export const triggerSurvey = async ( - survey: TSurvey, - action?: string, - properties?: TJsTrackProperties -): Promise => { - // Check if the survey should be displayed based on displayPercentage - if (survey.displayPercentage) { - const shouldDisplaySurvey = shouldDisplayBasedOnPercentage(survey.displayPercentage); - if (!shouldDisplaySurvey) { - logger.debug("Survey display skipped based on displayPercentage."); - return; // skip displaying the survey - } - } - - const hiddenFieldsObject: TResponseHiddenFieldValue = handleHiddenFields( - survey.hiddenFields, - properties?.hiddenFields - ); - - await renderWidget(survey, action, hiddenFieldsObject); -}; - -const renderWidget = async ( - survey: TSurvey, - action?: string, - hiddenFields: TResponseHiddenFieldValue = {} -) => { - if (isSurveyRunning) { - logger.debug("A survey is already running. Skipping."); - return; - } - setIsSurveyRunning(true); - - if (survey.delay) { - logger.debug(`Delaying survey by ${survey.delay} seconds.`); - } - - const product = websiteConfig.get().environmentState.data.product; - const attributes = websiteConfig.get().personState.data.attributes; - - const isMultiLanguageSurvey = survey.languages.length > 1; - let languageCode = "default"; - - if (isMultiLanguageSurvey && attributes) { - const displayLanguage = getLanguageCode(survey, attributes); - //if survey is not available in selected language, survey wont be shown - if (!displayLanguage) { - logger.debug("Survey not available in specified language."); - setIsSurveyRunning(true); - return; - } - languageCode = displayLanguage; - } - - const surveyState = new SurveyState(survey.id, null, null); - - const responseQueue = new ResponseQueue( - { - apiHost: websiteConfig.get().apiHost, - environmentId: websiteConfig.get().environmentId, - retryAttempts: 2, - onResponseSendingFailed: () => { - setIsError(true); - }, - onResponseSendingFinished: () => { - setIsResponseSendingFinished(true); - }, - }, - surveyState - ); - const productOverwrites = survey.productOverwrites ?? {}; - const clickOutside = productOverwrites.clickOutsideClose ?? product.clickOutsideClose; - const darkOverlay = productOverwrites.darkOverlay ?? product.darkOverlay; - const placement = productOverwrites.placement ?? product.placement; - const isBrandingEnabled = product.inAppSurveyBranding; - const formbricksSurveys = await loadFormbricksSurveysExternally(); - - setTimeout(() => { - formbricksSurveys.renderSurveyModal({ - survey, - isBrandingEnabled, - clickOutside, - darkOverlay, - languageCode, - placement, - styling: getStyling(product, survey), - getSetIsError: (f: (value: boolean) => void) => { - setIsError = f; - }, - getSetIsResponseSendingFinished: (f: (value: boolean) => void) => { - setIsResponseSendingFinished = f; - }, - onDisplay: async () => { - const api = new FormbricksAPI({ - apiHost: websiteConfig.get().apiHost, - environmentId: websiteConfig.get().environmentId, - }); - const res = await api.client.display.create({ - surveyId: survey.id, - }); - - if (!res.ok) { - throw new Error("Could not create display"); - } - - const { id } = res.data; - - const existingDisplays = websiteConfig.get().personState.data.displays; - const newDisplay = { surveyId: survey.id, createdAt: new Date() }; - const displays = existingDisplays ? [...existingDisplays, newDisplay] : [newDisplay]; - const previousConfig = websiteConfig.get(); - - const updatedPersonState: TJsPersonState = { - ...previousConfig.personState, - data: { - ...previousConfig.personState.data, - displays, - lastDisplayAt: new Date(), - }, - }; - - const filteredSurveys = filterPublicSurveys( - previousConfig.environmentState, - updatedPersonState, - "website" - ); - - websiteConfig.update({ - ...previousConfig, - environmentState: previousConfig.environmentState, - personState: updatedPersonState, - filteredSurveys, - }); - - surveyState.updateDisplayId(id); - responseQueue.updateSurveyState(surveyState); - }, - onResponse: (responseUpdate: TResponseUpdate) => { - const displays = websiteConfig.get().personState.data.displays; - const lastDisplay = displays && displays[displays.length - 1]; - if (!lastDisplay) { - throw new Error("No lastDisplay found"); - } - - const isNewResponse = surveyState.responseId === null; - - responseQueue.updateSurveyState(surveyState); - - responseQueue.add({ - data: responseUpdate.data, - ttc: responseUpdate.ttc, - finished: responseUpdate.finished, - language: - responseUpdate.language === "default" ? getDefaultLanguageCode(survey) : responseUpdate.language, - meta: { - url: window.location.href, - action, - }, - variables: responseUpdate.variables, - hiddenFields, - displayId: surveyState.displayId, - }); - - if (isNewResponse) { - const responses = websiteConfig.get().personState.data.responses; - const newPersonState: TJsPersonState = { - ...websiteConfig.get().personState, - data: { - ...websiteConfig.get().personState.data, - responses: [...responses, surveyState.surveyId], - }, - }; - - const filteredSurveys = filterPublicSurveys( - websiteConfig.get().environmentState, - newPersonState, - "website" - ); - - websiteConfig.update({ - ...websiteConfig.get(), - environmentState: websiteConfig.get().environmentState, - personState: newPersonState, - filteredSurveys, - }); - } - }, - onClose: closeSurvey, - onFileUpload: async ( - file: { type: string; name: string; base64: string }, - params: TUploadFileConfig - ) => { - const api = new FormbricksAPI({ - apiHost: websiteConfig.get().apiHost, - environmentId: websiteConfig.get().environmentId, - }); - - return await api.client.storage.uploadFile( - { - name: file.name, - type: file.type, - base64: file.base64, - }, - params - ); - }, - onRetry: () => { - setIsError(false); - responseQueue.processQueue(); - }, - hiddenFieldsRecord: hiddenFields, - }); - }, survey.delay * 1000); -}; - -export const closeSurvey = async (): Promise => { - // remove container element from DOM - removeWidgetContainer(); - addWidgetContainer(); - - const { environmentState, personState } = websiteConfig.get(); - const filteredSurveys = filterPublicSurveys(environmentState, personState, "website"); - websiteConfig.update({ - ...websiteConfig.get(), - environmentState, - personState, - filteredSurveys, - }); - setIsSurveyRunning(false); - return; -}; - -export const addWidgetContainer = (): void => { - const containerElement = document.createElement("div"); - containerElement.id = containerId; - document.body.appendChild(containerElement); -}; - -export const removeWidgetContainer = (): void => { - document.getElementById(containerId)?.remove(); -}; - -const loadFormbricksSurveysExternally = (): Promise => { - return new Promise((resolve, reject) => { - if (window.formbricksSurveys) { - resolve(window.formbricksSurveys); - } else { - const script = document.createElement("script"); - script.src = `${websiteConfig.get().apiHost}/api/packages/surveys`; - script.async = true; - script.onload = () => resolve(window.formbricksSurveys); - script.onerror = (error) => { - console.error("Failed to load Formbricks Surveys library:", error); - reject(error); - }; - document.head.appendChild(script); - } - }); -}; diff --git a/packages/js-core/app.vite.config.ts b/packages/js-core/vite.config.ts similarity index 91% rename from packages/js-core/app.vite.config.ts rename to packages/js-core/vite.config.ts index 98c3176dc6..17e4644304 100644 --- a/packages/js-core/app.vite.config.ts +++ b/packages/js-core/vite.config.ts @@ -16,10 +16,10 @@ const config = () => { minify: "terser", sourcemap: true, lib: { - entry: resolve(__dirname, "src/app/index.ts"), + entry: resolve(__dirname, "src/index.ts"), name: "formbricks", formats: ["umd"], - fileName: "app", + fileName: "index", }, }, plugins: [ diff --git a/packages/js-core/website.vite.config.ts b/packages/js-core/website.vite.config.ts deleted file mode 100644 index e08e44b1b5..0000000000 --- a/packages/js-core/website.vite.config.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { resolve } from "path"; -import { defineConfig } from "vite"; -import dts from "vite-plugin-dts"; -import webPackageJson from "../../apps/web/package.json"; - -const config = () => { - return defineConfig({ - define: { - "import.meta.env.VERSION": JSON.stringify(webPackageJson.version), - }, - build: { - rollupOptions: { - output: { inlineDynamicImports: true }, - }, - emptyOutDir: false, // keep the dist folder to avoid errors with pnpm go when folder is empty during build - minify: "terser", - sourcemap: true, - lib: { - entry: resolve(__dirname, "src/website/index.ts"), - name: "formbricks", - formats: ["umd"], - fileName: "website", - }, - }, - plugins: [ - dts({ - rollupTypes: true, - bundledPackages: ["@formbricks/api", "@formbricks/types"], - }), - ], - }); -}; - -export default config; diff --git a/packages/js/index.html b/packages/js/index.html index fc019e8f2e..e47487373f 100644 --- a/packages/js/index.html +++ b/packages/js/index.html @@ -2,12 +2,12 @@