From 3d0d633bc88605ba545579ea4ee00dce50d52644 Mon Sep 17 00:00:00 2001 From: Matti Nannt Date: Mon, 31 Jul 2023 16:40:21 +0200 Subject: [PATCH] Fix new Session event not triggered every time a new session is created (#624) * Fix new Session event not triggered every time a new session is created * make syncWithBackend method private --- .changeset/young-snails-drum.md | 5 +++ apps/web/Dockerfile | 2 + apps/web/app/api/v1/js/sync/route.ts | 11 ++++++ .../lib/responses/questionResponseMapping.ts | 2 +- packages/js/src/lib/init.ts | 37 +++---------------- packages/js/src/lib/person.ts | 24 +++--------- packages/js/src/lib/sync.ts | 22 +++++++++-- packages/js/src/lib/widget.ts | 18 +++------ 8 files changed, 55 insertions(+), 66 deletions(-) create mode 100644 .changeset/young-snails-drum.md diff --git a/.changeset/young-snails-drum.md b/.changeset/young-snails-drum.md new file mode 100644 index 0000000000..b48d6a06e7 --- /dev/null +++ b/.changeset/young-snails-drum.md @@ -0,0 +1,5 @@ +--- +"@formbricks/js": patch +--- + +Fix new Session event not triggered every time a new session is created diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index b22ebe0016..8b0cf565eb 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -36,6 +36,8 @@ COPY --from=installer --chown=nextjs:nodejs /app/packages/database/migrations ./ ENV NEXTAUTH_SECRET=$NEXTAUTH_SECRET +EXPOSE 3000 + CMD if [ "$NEXTAUTH_SECRET" != "RANDOM_STRING" ]; then \ pnpm dlx prisma migrate deploy && node apps/web/server.js; \ else \ diff --git a/apps/web/app/api/v1/js/sync/route.ts b/apps/web/app/api/v1/js/sync/route.ts index 4d9ee4ccf9..11010f3ce1 100644 --- a/apps/web/app/api/v1/js/sync/route.ts +++ b/apps/web/app/api/v1/js/sync/route.ts @@ -2,6 +2,7 @@ import { getSurveys } from "@/app/api/v1/js/surveys"; import { responses } from "@/lib/api/response"; import { transformErrorToDetails } from "@/lib/api/validator"; import { getActionClasses } from "@formbricks/lib/services/actionClass"; +import { getEnvironment } from "@formbricks/lib/services/environment"; import { createPerson, getPerson } from "@formbricks/lib/services/person"; import { getProductByEnvironmentId } from "@formbricks/lib/services/product"; import { createSession, extendSession, getSession } from "@formbricks/lib/services/session"; @@ -31,6 +32,16 @@ export async function POST(req: Request): Promise { const { environmentId, personId, sessionId } = inputValidation.data; + // check if environment exists + const environment = await getEnvironment(environmentId); + if (!environment) { + return responses.badRequestResponse( + "Environment does not exist", + { environmentId: "Environment with this ID does not exist" }, + true + ); + } + if (!personId) { // create a new person const person = await createPerson(environmentId); diff --git a/apps/web/lib/responses/questionResponseMapping.ts b/apps/web/lib/responses/questionResponseMapping.ts index 724b76d864..0466434f07 100644 --- a/apps/web/lib/responses/questionResponseMapping.ts +++ b/apps/web/lib/responses/questionResponseMapping.ts @@ -12,7 +12,7 @@ export const getQuestionResponseMapping = ( questionResponseMapping.push({ question: question.headline, - answer: answer.toString(), + answer: typeof answer !== "undefined" ? answer.toString() : "", }); } diff --git a/packages/js/src/lib/init.ts b/packages/js/src/lib/init.ts index 68544816b0..f5e6c91cb7 100644 --- a/packages/js/src/lib/init.ts +++ b/packages/js/src/lib/init.ts @@ -35,12 +35,7 @@ const addSyncEventListener = (debug?: boolean): void => { } syncIntervalId = window.setInterval(async () => { logger.debug("Syncing."); - const syncResult = await sync(); - if (syncResult.ok !== true) { - return err(syncResult.error); - } - const state = syncResult.value; - config.update({ state }); + await sync(); }, updateInverval); // clear interval on page unload window.addEventListener("beforeunload", () => { @@ -95,21 +90,13 @@ export const initialize = async ( if (isExpired(existingSession)) { logger.debug("Session expired. Resyncing."); - const syncResult = await sync(); - - // if create sync fails, clear config and start from scratch - if (syncResult.ok !== true) { + try { + await sync(); + } catch (e) { + logger.debug("Sync failed. Clearing config and starting from scratch."); await resetPerson(); return await initialize(c); } - - const state = syncResult.value; - - config.update({ state }); - - const trackActionResult = await trackAction("New Session"); - - if (trackActionResult.ok !== true) return err(trackActionResult.error); } else { logger.debug("Session valid. Continuing."); // continue for now - next sync will check complete state @@ -120,19 +107,7 @@ export const initialize = async ( config.update({ environmentId: c.environmentId, apiHost: c.apiHost, state: undefined }); logger.debug("Syncing."); - const syncResult = await sync(); - - if (syncResult.ok !== true) { - return err(syncResult.error); - } - - const state = syncResult.value; - - config.update({ state }); - - const trackActionResult = await trackAction("New Session"); - - if (trackActionResult.ok !== true) return err(trackActionResult.error); + await sync(); } logger.debug("Add session event listeners"); diff --git a/packages/js/src/lib/person.ts b/packages/js/src/lib/person.ts index 580d5792bd..a08f8299ad 100644 --- a/packages/js/src/lib/person.ts +++ b/packages/js/src/lib/person.ts @@ -179,26 +179,12 @@ export const setPersonAttribute = async ( export const resetPerson = async (): Promise> => { logger.debug("Resetting state & getting new state from backend"); config.update({ state: undefined }); - const syncResult = await sync(); - - let error: NetworkError; - - match( - syncResult, - (state) => { - config.update({ state }); - }, - (err) => { - // pass error to outer scope - error = err; - } - ); - - if (error) { - return err(error); + try { + await sync(); + return okVoid(); + } catch (e) { + return err(e); } - - return okVoid(); }; export const getPerson = (): TPerson => { diff --git a/packages/js/src/lib/sync.ts b/packages/js/src/lib/sync.ts index 537411b645..f60d4dac9d 100644 --- a/packages/js/src/lib/sync.ts +++ b/packages/js/src/lib/sync.ts @@ -1,12 +1,11 @@ import { TJsState } from "@formbricks/types/v1/js"; +import { trackAction } from "./actions"; import { Config } from "./config"; import { NetworkError, Result, err, ok } from "./errors"; -import { Logger } from "./logger"; -const logger = Logger.getInstance(); const config = Config.getInstance(); -export const sync = async (): Promise> => { +const syncWithBackend = async (): Promise> => { const url = `${config.get().apiHost}/api/v1/js/sync`; const response = await fetch(url, { @@ -34,3 +33,20 @@ export const sync = async (): Promise> => { return ok((await response.json()).data as TJsState); }; + +export const sync = async (): Promise => { + const syncResult = await syncWithBackend(); + if (syncResult.ok !== true) { + throw syncResult.error; + } + const state = syncResult.value; + const oldState = config.get().state; + config.update({ state }); + // if session is new, track action + if (!oldState?.session || oldState.session.id !== state.session.id) { + const trackActionResult = await trackAction("New Session"); + if (trackActionResult.ok !== true) { + throw trackActionResult.error; + } + } +}; diff --git a/packages/js/src/lib/widget.ts b/packages/js/src/lib/widget.ts index a63e9b7929..68f7f41253 100644 --- a/packages/js/src/lib/widget.ts +++ b/packages/js/src/lib/widget.ts @@ -36,18 +36,12 @@ export const closeSurvey = async (): Promise => { document.getElementById(containerId).remove(); addWidgetContainer(); - const syncResult = await sync(); - - match( - syncResult, - (value) => { - config.update({ state: value }); - surveyRunning = false; - }, - (error) => { - errorHandler.handle(error); - } - ); + try { + await sync(); + surveyRunning = false; + } catch (e) { + errorHandler.handle(e); + } }; export const addWidgetContainer = (): void => {