diff --git a/package.json b/package.json index 82b1be07..fd31320e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "3.0.0", + "version": "3.0.1", "description": "A modern, privacy-focused alternative to Google Analytics.", "author": "Umami Software, Inc. ", "license": "MIT", @@ -78,7 +78,7 @@ "@react-spring/web": "^10.0.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.90.5", - "@umami/react-zen": "^0.206.0", + "@umami/react-zen": "^0.207.0", "@umami/redis-client": "^0.29.0", "bcryptjs": "^3.0.2", "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7e9b49c..c4d0c432 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.90.5 version: 5.90.5(react@19.2.0) '@umami/react-zen': - specifier: ^0.206.0 - version: 0.206.0(@babel/core@7.28.3)(@types/react@19.2.2)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) + specifier: ^0.207.0 + version: 0.207.0(@babel/core@7.28.3)(@types/react@19.2.2)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) '@umami/redis-client': specifier: ^0.29.0 version: 0.29.0 @@ -2935,8 +2935,8 @@ packages: resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.206.0': - resolution: {integrity: sha512-9XM3Oj1akdyuwkMT1SldrJOyrMACP9TLJApZ/9ocmPuET4B7vpPxRoxv8OpEVlBaDw5nmlJfIvefsNMBLt1OQg==} + '@umami/react-zen@0.207.0': + resolution: {integrity: sha512-TUllF5mKQ+IBepIgT0xvJo/bGBEdPDfGiATyjuuxe2/SwO3LDINbmPUSFpWrjxtUaigiEI0JaQsklSLkirEKPg==} '@umami/redis-client@0.29.0': resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==} @@ -10697,7 +10697,7 @@ snapshots: '@typescript-eslint/types': 8.46.2 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.206.0(@babel/core@7.28.3)(@types/react@19.2.2)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.2.0)(use-sync-external-store@1.6.0(react@19.2.0))': + '@umami/react-zen@0.207.0(@babel/core@7.28.3)(@types/react@19.2.2)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.2.0)(use-sync-external-store@1.6.0(react@19.2.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.8 '@internationalized/date': 3.10.0 diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index 652b9d11..4880e122 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -51,12 +51,12 @@ function getUTCString(date?: Date | string | number) { return formatInTimeZone(date || new Date(), 'UTC', 'yyyy-MM-dd HH:mm:ss'); } -function getDateStringSQL(field: string, unit: string, timezone?: string) { +function getDateStringSQL(data: any, unit: string = 'utc', timezone?: string) { if (timezone) { - return `formatDateTime(${field}, '${CLICKHOUSE_DATE_FORMATS[unit]}', '${timezone}')`; + return `formatDateTime(${data}, '${CLICKHOUSE_DATE_FORMATS[unit]}', '${timezone}')`; } - return `formatDateTime(${field}, '${CLICKHOUSE_DATE_FORMATS[unit]}')`; + return `formatDateTime(${data}, '${CLICKHOUSE_DATE_FORMATS[unit]}')`; } function getDateSQL(field: string, unit: string, timezone?: string) { diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts index 5f5404d5..cc5f2e6f 100644 --- a/src/queries/prisma/website.ts +++ b/src/queries/prisma/website.ts @@ -135,26 +135,31 @@ export async function resetWebsite(websiteId: string) { const { client, transaction } = prisma; const cloudMode = !!process.env.CLOUD_MODE; - return transaction([ - client.eventData.deleteMany({ - where: { websiteId }, - }), - client.sessionData.deleteMany({ - where: { websiteId }, - }), - client.websiteEvent.deleteMany({ - where: { websiteId }, - }), - client.session.deleteMany({ - where: { websiteId }, - }), - client.website.update({ - where: { id: websiteId }, - data: { - resetAt: new Date(), - }, - }), - ]).then(async data => { + return transaction( + [ + client.eventData.deleteMany({ + where: { websiteId }, + }), + client.sessionData.deleteMany({ + where: { websiteId }, + }), + client.websiteEvent.deleteMany({ + where: { websiteId }, + }), + client.session.deleteMany({ + where: { websiteId }, + }), + client.website.update({ + where: { id: websiteId }, + data: { + resetAt: new Date(), + }, + }), + ], + { + timeout: 30000, + }, + ).then(async data => { if (cloudMode) { await redis.client.set( `website:${websiteId}`, diff --git a/src/queries/sql/reports/getRetention.ts b/src/queries/sql/reports/getRetention.ts index 15984cd3..d99098c0 100644 --- a/src/queries/sql/reports/getRetention.ts +++ b/src/queries/sql/reports/getRetention.ts @@ -133,7 +133,7 @@ async function clickhouseQuery( user_activities AS ( select distinct website_event.session_id, - (${getDateSQL('created_at', unit, timezone)} - cohort_items.cohort_date) / 86400 as day_number + toInt32((${getDateSQL('created_at', unit, timezone)} - cohort_items.cohort_date) / 86400) as day_number from website_event join cohort_items on website_event.session_id = cohort_items.session_id diff --git a/src/tracker/index.js b/src/tracker/index.js index 18b3ff89..a9966198 100644 --- a/src/tracker/index.js +++ b/src/tracker/index.js @@ -18,6 +18,7 @@ const _false = 'false'; const _true = 'true'; const attr = currentScript.getAttribute.bind(currentScript); + const website = attr(_data + 'website-id'); const hostUrl = attr(_data + 'host-url'); const beforeSend = attr(_data + 'before-send'); @@ -27,6 +28,8 @@ const excludeSearch = attr(_data + 'exclude-search') === _true; const excludeHash = attr(_data + 'exclude-hash') === _true; const domain = attr(_data + 'domains') || ''; + const credentials = attr(_data + 'fetch-credentials') || 'omit'; + const domains = domain.split(',').map(n => n.trim()); const host = hostUrl || '__COLLECT_API_HOST__' || currentScript.src.split('/').slice(0, -1).join('/'); @@ -165,7 +168,7 @@ 'Content-Type': 'application/json', ...(typeof cache !== 'undefined' && { 'x-umami-cache': cache }), }, - credentials: 'omit', + credentials, }); const data = await res.json();