From 1aa213d342a66fe30d061a5c77f815bc6c441475 Mon Sep 17 00:00:00 2001 From: Harry Oosterveen Date: Wed, 12 Mar 2025 17:58:21 +0100 Subject: [PATCH 01/11] Localized time in SessionActivity --- .../[websiteId]/sessions/[sessionId]/SessionActivity.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx index a59d3a92..8fb418d2 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx @@ -39,7 +39,7 @@ export function SessionActivity({
- {formatTimezoneDate(createdAt, 'h:mm:ss aaa')} + {formatTimezoneDate(createdAt, 'pp')}
{eventName ? : } From fa15a470fd94c94fd2dc6f7973c52a5f29712681 Mon Sep 17 00:00:00 2001 From: Harry Oosterveen Date: Wed, 12 Mar 2025 18:26:15 +0100 Subject: [PATCH 02/11] Localized date and time in charts --- src/components/charts/BarChartTooltip.tsx | 2 +- src/lib/charts.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/charts/BarChartTooltip.tsx b/src/components/charts/BarChartTooltip.tsx index af31c874..8bcbad8f 100644 --- a/src/components/charts/BarChartTooltip.tsx +++ b/src/components/charts/BarChartTooltip.tsx @@ -7,7 +7,7 @@ const formats = { millisecond: 'T', second: 'pp', minute: 'p', - hour: 'h:mm aaa - PP', + hour: 'p - PP', day: 'PPPP', week: 'PPPP', month: 'LLLL yyyy', diff --git a/src/lib/charts.ts b/src/lib/charts.ts index d805eefe..d6917c83 100644 --- a/src/lib/charts.ts +++ b/src/lib/charts.ts @@ -11,11 +11,11 @@ export function renderDateLabels(unit: string, locale: string) { switch (unit) { case 'minute': - return formatDate(d, 'h:mm', locale); + return formatDate(d, 'p', locale).split(' ')[0]; case 'hour': return formatDate(d, 'p', locale); case 'day': - return formatDate(d, 'MMM d', locale); + return formatDate(d, 'PP', locale).replace(/\W*20\d{2}\W*/, ''); // Remove year case 'month': return formatDate(d, 'MMM', locale); case 'year': From 32d44e6c65cf624cd7fd7897af509c3d63ad5e2d Mon Sep 17 00:00:00 2001 From: Harry Oosterveen Date: Wed, 12 Mar 2025 17:59:08 +0100 Subject: [PATCH 03/11] Fix key in SessionActivity There is no eventId --- .../[websiteId]/sessions/[sessionId]/SessionActivity.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx index a59d3a92..080088c8 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx @@ -27,16 +27,16 @@ export function SessionActivity({ return (
- {data.map(({ eventId, createdAt, urlPath, eventName, visitId }) => { + {data.map(({ id, createdAt, urlPath, eventName, visitId }) => { const showHeader = !lastDay || !isSameDay(new Date(lastDay), new Date(createdAt)); lastDay = createdAt; return ( - + {showHeader && (
{formatTimezoneDate(createdAt, 'PPPP')}
)} -
+
{formatTimezoneDate(createdAt, 'h:mm:ss aaa')} From 5120805e0b44a3708b237ceaf9222a68ef95c039 Mon Sep 17 00:00:00 2001 From: Harry Oosterveen Date: Wed, 12 Mar 2025 20:44:29 +0100 Subject: [PATCH 04/11] Fix counting _other domain groups --- src/components/metrics/ReferrersTable.tsx | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/components/metrics/ReferrersTable.tsx b/src/components/metrics/ReferrersTable.tsx index 4d5a87c3..89729418 100644 --- a/src/components/metrics/ReferrersTable.tsx +++ b/src/components/metrics/ReferrersTable.tsx @@ -60,19 +60,24 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) { ); }; + const getDomain = (x: string) => { + for (const { domain, match } of GROUPED_DOMAINS) { + if (Array.isArray(match) ? match.some(str => x.includes(str)) : x.includes(match)) { + return domain; + } + } + return '_other'; + }; + const groupedFilter = (data: any[]) => { const groups = { _other: 0 }; for (const { x, y } of data) { - for (const { domain, match } of GROUPED_DOMAINS) { - if (Array.isArray(match) ? match.some(str => x.includes(str)) : x.includes(match)) { - if (!groups[domain]) { - groups[domain] = 0; - } - groups[domain] += +y; - } + const domain = getDomain(x); + if (!groups[domain]) { + groups[domain] = 0; } - groups._other += +y; + groups[domain] += +y; } return Object.keys(groups) From 4888ecbceee3d5e45b5b0428e28bad70d17328d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:00:37 +0000 Subject: [PATCH 05/11] Bump next from 15.0.4 to 15.2.3 Bumps [next](https://github.com/vercel/next.js) from 15.0.4 to 15.2.3. - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](https://github.com/vercel/next.js/compare/v15.0.4...v15.2.3) --- updated-dependencies: - dependency-name: next dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 127 ++++++++++++++++++++++++--------------------------- 2 files changed, 60 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index db146e9a..a0228788 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "kafkajs": "^2.1.0", "maxmind": "^4.3.24", "md5": "^2.3.0", - "next": "15.0.4", + "next": "15.2.3", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "prisma": "6.1.0", diff --git a/yarn.lock b/yarn.lock index bf1a180e..ab79d86e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2408,10 +2408,10 @@ resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-5.9.3.tgz#164d20dba170a5ef2531e24f5cd9f9ea1b6a4eed" integrity sha512-760YvPaw6tSPmmX/2sqRzqBehPOfTD6lJoUb+bW+yZhQNyfLyCJR9/cRQP0+fFN2CCmdRWECX4nbi76Qne5/FQ== -"@next/env@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.4.tgz#97da0fe3bae2f2b2968c4c925d7936660f5b3836" - integrity sha512-WNRvtgnRVDD4oM8gbUcRc27IAhaL4eXQ/2ovGbgLnPGUvdyDr8UdXP4Q/IBDdAdojnD2eScryIDirv0YUCjUVw== +"@next/env@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.2.3.tgz#037ee37c4d61fcbdbb212694cc33d7dcf6c7975a" + integrity sha512-a26KnbW9DFEUsSxAxKBORR/uD9THoYoKbkpFywMN/AFvboTt94b8+g/07T8J6ACsdLag8/PDU60ov4rPxRAixw== "@next/eslint-plugin-next@14.2.23": version "14.2.23" @@ -2420,45 +2420,45 @@ dependencies: glob "10.3.10" -"@next/swc-darwin-arm64@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.4.tgz#66087f397564d6ece4c5493536d30bc2b158a80e" - integrity sha512-QecQXPD0yRHxSXWL5Ff80nD+A56sUXZG9koUsjWJwA2Z0ZgVQfuy7gd0/otjxoOovPVHR2eVEvPMHbtZP+pf9w== +"@next/swc-darwin-arm64@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.3.tgz#2688c185651ef7a16e5642c85048cc4e151159fa" + integrity sha512-uaBhA8aLbXLqwjnsHSkxs353WrRgQgiFjduDpc7YXEU0B54IKx3vU+cxQlYwPCyC8uYEEX7THhtQQsfHnvv8dw== -"@next/swc-darwin-x64@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.4.tgz#6eb098e183dfed72d8f3c4b281a323ad17d72446" - integrity sha512-pb7Bye3y1Og3PlCtnz2oO4z+/b3pH2/HSYkLbL0hbVuTGil7fPen8/3pyyLjdiTLcFJ+ymeU3bck5hd4IPFFCA== +"@next/swc-darwin-x64@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.3.tgz#3e802259b2c9a4e2ad55ff827f41f775b726fc7d" + integrity sha512-pVwKvJ4Zk7h+4hwhqOUuMx7Ib02u3gDX3HXPKIShBi9JlYllI0nU6TWLbPT94dt7FSi6mSBhfc2JrHViwqbOdw== -"@next/swc-linux-arm64-gnu@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.4.tgz#3c082ad1a4c8060a5c56127fdefb82a149d3b94e" - integrity sha512-12oSaBFjGpB227VHzoXF3gJoK2SlVGmFJMaBJSu5rbpaoT5OjP5OuCLuR9/jnyBF1BAWMs/boa6mLMoJPRriMA== +"@next/swc-linux-arm64-gnu@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.3.tgz#315d7b54b89153f125bdc3e40bcb7ccf94ef124b" + integrity sha512-50ibWdn2RuFFkOEUmo9NCcQbbV9ViQOrUfG48zHBCONciHjaUKtHcYFiCwBVuzD08fzvzkWuuZkd4AqbvKO7UQ== -"@next/swc-linux-arm64-musl@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.4.tgz#c4e18c89ea4dab6b150b889643ec19896aebc1eb" - integrity sha512-QARO88fR/a+wg+OFC3dGytJVVviiYFEyjc/Zzkjn/HevUuJ7qGUUAUYy5PGVWY1YgTzeRYz78akQrVQ8r+sMjw== +"@next/swc-linux-arm64-musl@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.3.tgz#a1a458eb7cf19c59d2014ee388a7305e9a77973f" + integrity sha512-2gAPA7P652D3HzR4cLyAuVYwYqjG0mt/3pHSWTCyKZq/N/dJcUAEoNQMyUmwTZWCJRKofB+JPuDVP2aD8w2J6Q== -"@next/swc-linux-x64-gnu@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.4.tgz#f81c3952a60f3075b48e0b5a862f4deecd550c2d" - integrity sha512-Z50b0gvYiUU1vLzfAMiChV8Y+6u/T2mdfpXPHraqpypP7yIT2UV9YBBhcwYkxujmCvGEcRTVWOj3EP7XW/wUnw== +"@next/swc-linux-x64-gnu@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.3.tgz#a3cf22eda7601536ccd68e8ba4c1bfb4a1a33460" + integrity sha512-ODSKvrdMgAJOVU4qElflYy1KSZRM3M45JVbeZu42TINCMG3anp7YCBn80RkISV6bhzKwcUqLBAmOiWkaGtBA9w== -"@next/swc-linux-x64-musl@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.4.tgz#f14c9730599985538d4d01d6da825b4e41fea0c1" - integrity sha512-7H9C4FAsrTAbA/ENzvFWsVytqRYhaJYKa2B3fyQcv96TkOGVMcvyS6s+sj4jZlacxxTcn7ygaMXUPkEk7b78zw== +"@next/swc-linux-x64-musl@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.3.tgz#0e33c1224c76aa3078cc2249c80ef583f9d7a943" + integrity sha512-ZR9kLwCWrlYxwEoytqPi1jhPd1TlsSJWAc+H/CJHmHkf2nD92MQpSRIURR1iNgA/kuFSdxB8xIPt4p/T78kwsg== -"@next/swc-win32-arm64-msvc@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.4.tgz#14297572feedcd5b14388be8a7ea8c50accb4c96" - integrity sha512-Z/v3WV5xRaeWlgJzN9r4PydWD8sXV35ywc28W63i37G2jnUgScA4OOgS8hQdiXLxE3gqfSuHTicUhr7931OXPQ== +"@next/swc-win32-arm64-msvc@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.3.tgz#4e0583fb981b931915a9ad22e579f9c9d5b803dd" + integrity sha512-+G2FrDcfm2YDbhDiObDU/qPriWeiz/9cRR0yMWJeTLGGX6/x8oryO3tt7HhodA1vZ8r2ddJPCjtLcpaVl7TE2Q== -"@next/swc-win32-x64-msvc@15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.4.tgz#d25953baffb92721f0fb96c8be71d7efb37a57b7" - integrity sha512-NGLchGruagh8lQpDr98bHLyWJXOBSmkEAfK980OiNBa7vNm6PsNoPvzTfstT78WyOeMRQphEQ455rggd7Eo+Dw== +"@next/swc-win32-x64-msvc@15.2.3": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.3.tgz#727b90c7dcc2279344115a94b99d93d452956f02" + integrity sha512-gHYS9tc+G2W0ZC8rBL+H6RdtXIyk40uLiaos0yj5US85FNhbFEndMA2nW3z47nzOWiSvXTZ5kBClc3rD0zJg0w== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -2846,12 +2846,12 @@ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/helpers@0.5.13": - version "0.5.13" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.13.tgz#33e63ff3cd0cade557672bd7888a39ce7d115a8c" - integrity sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w== +"@swc/helpers@0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.15.tgz#79efab344c5819ecf83a43f3f9f811fc84b516d7" + integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g== dependencies: - tslib "^2.4.0" + tslib "^2.8.0" "@tanstack/query-core@5.62.16": version "5.62.16" @@ -8153,27 +8153,27 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@15.0.4: - version "15.0.4" - resolved "https://registry.yarnpkg.com/next/-/next-15.0.4.tgz#7ddad7299204f16c132d7e524cf903f1a513588e" - integrity sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA== +next@15.2.3: + version "15.2.3" + resolved "https://registry.yarnpkg.com/next/-/next-15.2.3.tgz#1ac803c08076d47eb5b431cb625135616c6bec7e" + integrity sha512-x6eDkZxk2rPpu46E1ZVUWIBhYCLszmUY6fvHBFcbzJ9dD+qRX6vcHusaqqDlnY+VngKzKbAiG2iRCkPbmi8f7w== dependencies: - "@next/env" "15.0.4" + "@next/env" "15.2.3" "@swc/counter" "0.1.3" - "@swc/helpers" "0.5.13" + "@swc/helpers" "0.5.15" busboy "1.6.0" caniuse-lite "^1.0.30001579" postcss "8.4.31" styled-jsx "5.1.6" optionalDependencies: - "@next/swc-darwin-arm64" "15.0.4" - "@next/swc-darwin-x64" "15.0.4" - "@next/swc-linux-arm64-gnu" "15.0.4" - "@next/swc-linux-arm64-musl" "15.0.4" - "@next/swc-linux-x64-gnu" "15.0.4" - "@next/swc-linux-x64-musl" "15.0.4" - "@next/swc-win32-arm64-msvc" "15.0.4" - "@next/swc-win32-x64-msvc" "15.0.4" + "@next/swc-darwin-arm64" "15.2.3" + "@next/swc-darwin-x64" "15.2.3" + "@next/swc-linux-arm64-gnu" "15.2.3" + "@next/swc-linux-arm64-musl" "15.2.3" + "@next/swc-linux-x64-gnu" "15.2.3" + "@next/swc-linux-x64-musl" "15.2.3" + "@next/swc-win32-arm64-msvc" "15.2.3" + "@next/swc-win32-x64-msvc" "15.2.3" sharp "^0.33.5" nice-try@^1.0.4: @@ -8558,7 +8558,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== -picocolors@^1.0.1, picocolors@^1.1.1: +picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -9166,16 +9166,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.1.10, postcss@^8.4.21, postcss@^8.4.28: - version "8.4.41" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.41.tgz#d6104d3ba272d882fe18fc07d15dc2da62fa2681" - integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.1" - source-map-js "^1.2.0" - -postcss@^8.4.31: +postcss@^8.1.10, postcss@^8.4.21, postcss@^8.4.28, postcss@^8.4.31: version "8.4.49" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== @@ -10107,7 +10098,7 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== -source-map-js@^1.2.0, source-map-js@^1.2.1: +source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -10745,7 +10736,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@2, tslib@^2.1.0, tslib@^2.4.0: +tslib@2, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== From 85d89de072c70f116b8214bca38aa4c6d5dbe30e Mon Sep 17 00:00:00 2001 From: Cibiyanna26 Date: Sun, 23 Mar 2025 13:24:41 +0530 Subject: [PATCH 06/11] Added tests for /lib/charts --- jest.config.ts | 9 ++++ src/lib/__tests__/charts.test.ts | 76 ++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/lib/__tests__/charts.test.ts diff --git a/jest.config.ts b/jest.config.ts index 73738651..3a9741cf 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -4,4 +4,13 @@ export default { transform: { '^.+\\.(ts|tsx)$': 'ts-jest', }, + moduleNameMapper: { + '^assets/(.*)$': '/src/assets/$1', + '^components/(.*)$': '/src/components/$1', + '^lib/(.*)$': '/src/lib/$1', + '^pages/(.*)$': '/src/pages/$1', + '^queries/(.*)$': '/src/queries/$1', + '^store/(.*)$': '/src/store/$1', + '^styles/(.*)$': '/src/styles/$1', + }, }; diff --git a/src/lib/__tests__/charts.test.ts b/src/lib/__tests__/charts.test.ts new file mode 100644 index 00000000..49e27c90 --- /dev/null +++ b/src/lib/__tests__/charts.test.ts @@ -0,0 +1,76 @@ +import { renderNumberLabels, renderDateLabels } from 'lib/charts'; +import { formatDate } from 'lib/date'; + +// test for renderNumberLabels + +describe('renderNumberLabels', () => { + test.each([ + ['1000000', '1.0m'], + ['2500000', '2.5m'], + ])("formats numbers ≥ 1 million as 'Xm' (%s → %s)", (input, expected) => { + expect(renderNumberLabels(input)).toBe(expected); + }); + + test.each([['150000', '150k']])("formats numbers ≥ 100K as 'Xk' (%s → %s)", (input, expected) => { + expect(renderNumberLabels(input)).toBe(expected); + }); + + test.each([['12500', '12.5k']])( + "formats numbers ≥ 10K as 'X.Xk' (%s → %s)", + (input, expected) => { + expect(renderNumberLabels(input)).toBe(expected); + }, + ); + + test.each([['1500', '1.50k']])("formats numbers ≥ 1K as 'X.XXk' (%s → %s)", (input, expected) => { + expect(renderNumberLabels(input)).toBe(expected); + }); + + test.each([['999', '999']])( + 'calls formatNumber for values < 1000 (%s → %s)', + (input, expected) => { + expect(renderNumberLabels(input)).toBe(expected); + }, + ); + + test.each([ + ['0', '0'], + ['-5000', '-5000'], + ])('handles edge cases correctly (%s → %s)', (input, expected) => { + expect(renderNumberLabels(input)).toBe(expected); + }); +}); + +// test for renderDateLabels + +jest.spyOn(require('lib/date'), 'formatDate'); // Spy on formatDate but use real implementation + +describe('renderDateLabels', () => { + const mockValues = [{ value: '2024-03-23T10:00:00Z' }, { value: '2024-03-24T15:30:00Z' }]; + + test.each([ + ['minute', 'h:mm', 'en-US'], + ['hour', 'p', 'en-US'], + ['day', 'MMM d', 'en-US'], + ['month', 'MMM', 'en-US'], + ['year', 'YYY', 'en-US'], + ])('formats date correctly for unit: %s', (unit, expectedFormat, locale) => { + const formatLabel = renderDateLabels(unit, locale); + const formatted = formatLabel('label', 0, mockValues); + + expect(formatDate).toHaveBeenCalledWith(new Date(mockValues[0].value), expectedFormat, locale); + expect(formatted).toBe(formatDate(new Date(mockValues[0].value), expectedFormat, locale)); + }); + + test('returns label for unknown unit', () => { + const formatLabel = renderDateLabels('unknown', 'en-US'); + expect(formatLabel('original-label', 0, mockValues)).toBe('original-label'); + }); + + test('handles invalid date gracefully', () => { + const invalidValues = [{ value: 'invalid-date' }]; + const formatLabel = renderDateLabels('day', 'en-US'); + + expect(() => formatLabel('label', 0, invalidValues)).toThrow(); + }); +}); From 42739c660e4aa304279c259f05dd712811d0a4b9 Mon Sep 17 00:00:00 2001 From: Cibiyanna26 Date: Tue, 25 Mar 2025 14:01:03 +0530 Subject: [PATCH 07/11] modifing yyy label, spy reset after each test gets finished --- src/lib/__tests__/charts.test.ts | 16 ++++++++++------ src/lib/charts.ts | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lib/__tests__/charts.test.ts b/src/lib/__tests__/charts.test.ts index 49e27c90..cd9e8651 100644 --- a/src/lib/__tests__/charts.test.ts +++ b/src/lib/__tests__/charts.test.ts @@ -41,19 +41,23 @@ describe('renderNumberLabels', () => { }); }); -// test for renderDateLabels - -jest.spyOn(require('lib/date'), 'formatDate'); // Spy on formatDate but use real implementation - describe('renderDateLabels', () => { const mockValues = [{ value: '2024-03-23T10:00:00Z' }, { value: '2024-03-24T15:30:00Z' }]; + beforeEach(() => { + jest.spyOn(require('lib/date'), 'formatDate'); + }); + + afterEach(() => { + jest.restoreAllMocks(); // Reset spy to prevent interference + }); + test.each([ ['minute', 'h:mm', 'en-US'], ['hour', 'p', 'en-US'], ['day', 'MMM d', 'en-US'], ['month', 'MMM', 'en-US'], - ['year', 'YYY', 'en-US'], + ['year', 'yyyy', 'en-US'], ])('formats date correctly for unit: %s', (unit, expectedFormat, locale) => { const formatLabel = renderDateLabels(unit, locale); const formatted = formatLabel('label', 0, mockValues); @@ -67,7 +71,7 @@ describe('renderDateLabels', () => { expect(formatLabel('original-label', 0, mockValues)).toBe('original-label'); }); - test('handles invalid date gracefully', () => { + test('throws error for invalid date input', () => { const invalidValues = [{ value: 'invalid-date' }]; const formatLabel = renderDateLabels('day', 'en-US'); diff --git a/src/lib/charts.ts b/src/lib/charts.ts index 8939b3c1..1fb329be 100644 --- a/src/lib/charts.ts +++ b/src/lib/charts.ts @@ -19,7 +19,7 @@ export function renderDateLabels(unit: string, locale: string) { case 'month': return formatDate(d, 'MMM', locale); case 'year': - return formatDate(d, 'YYY', locale); + return formatDate(d, 'yyyy', locale); default: return label; } From 53d6adf29998e1103de4f04cda37d034b63a260e Mon Sep 17 00:00:00 2001 From: Yo Sev Date: Thu, 27 Mar 2025 08:38:10 +0100 Subject: [PATCH 08/11] fix(docker): add cors support when using a custom endpoint --- docker/middleware.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docker/middleware.js b/docker/middleware.js index 85fe96d2..25fcc348 100644 --- a/docker/middleware.js +++ b/docker/middleware.js @@ -3,6 +3,24 @@ import { NextResponse } from 'next/server'; export const config = { matcher: '/:path*', }; +const apiHeaders = [ + { + key: 'Access-Control-Allow-Origin', + value: '*', + }, + { + key: 'Access-Control-Allow-Headers', + value: '*', + }, + { + key: 'Access-Control-Allow-Methods', + value: 'GET, DELETE, POST, PUT', + }, + { + key: 'Access-Control-Max-Age', + value: process.env.CORS_MAX_AGE || '86400', + }, +]; function customCollectEndpoint(req) { const collectEndpoint = process.env.COLLECT_API_ENDPOINT; @@ -13,7 +31,9 @@ function customCollectEndpoint(req) { if (pathname.endsWith(collectEndpoint)) { url.pathname = '/api/send'; - return NextResponse.rewrite(url); + const resp = NextResponse.rewrite(url); + apiHeaders.forEach(({ key, value }) => resp.headers.append(key, value)); + return resp; } } } From 7f9f4957d381746d18bd84f5dbce5c7c0bceff62 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Fri, 28 Mar 2025 08:58:21 +0100 Subject: [PATCH 09/11] Update Docker middleware --- docker/middleware.js | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/docker/middleware.js b/docker/middleware.js index 25fcc348..85dab890 100644 --- a/docker/middleware.js +++ b/docker/middleware.js @@ -3,24 +3,18 @@ import { NextResponse } from 'next/server'; export const config = { matcher: '/:path*', }; -const apiHeaders = [ - { - key: 'Access-Control-Allow-Origin', - value: '*', - }, - { - key: 'Access-Control-Allow-Headers', - value: '*', - }, - { - key: 'Access-Control-Allow-Methods', - value: 'GET, DELETE, POST, PUT', - }, - { - key: 'Access-Control-Max-Age', - value: process.env.CORS_MAX_AGE || '86400', - }, -]; + +const apiHeaders = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': '*', + 'Access-Control-Allow-Methods': 'GET, DELETE, POST, PUT', + 'Access-Control-Max-Age': process.env.CORS_MAX_AGE || '86400', +}; + +const trackerHeaders = { + 'Access-Control-Allow-Origin': '*', + 'Cache-Control': 'public, max-age=86400, must-revalidate', +}; function customCollectEndpoint(req) { const collectEndpoint = process.env.COLLECT_API_ENDPOINT; @@ -31,9 +25,7 @@ function customCollectEndpoint(req) { if (pathname.endsWith(collectEndpoint)) { url.pathname = '/api/send'; - const resp = NextResponse.rewrite(url); - apiHeaders.forEach(({ key, value }) => resp.headers.append(key, value)); - return resp; + return NextResponse.rewrite(url, { headers: apiHeaders }); } } } @@ -48,7 +40,7 @@ function customScriptName(req) { if (names.find(name => pathname.endsWith(name))) { url.pathname = '/script.js'; - return NextResponse.rewrite(url); + return NextResponse.rewrite(url, { headers: trackerHeaders }); } } } From eafd08b4ee4d704079d379a2ba51466418860e7d Mon Sep 17 00:00:00 2001 From: Oleh Astappiev <4512729+astappiev@users.noreply.github.com> Date: Mon, 31 Mar 2025 22:56:52 +0200 Subject: [PATCH 10/11] fix: move isbot check after body parsing --- src/app/api/send/route.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index bd255eaf..482aad5c 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -34,11 +34,6 @@ const schema = z.object({ export async function POST(request: Request) { try { - // Bot check - if (!process.env.DISABLE_BOT_CHECK && isbot(request.headers.get('user-agent'))) { - return json({ beep: 'boop' }); - } - const { body, error } = await parseRequest(request, schema, { skipAuth: true }); if (error) { @@ -86,6 +81,11 @@ export async function POST(request: Request) { const { ip, userAgent, device, browser, os, country, subdivision1, subdivision2, city } = await getClientInfo(request, payload); + // Bot check + if (!process.env.DISABLE_BOT_CHECK && isbot(userAgent)) { + return json({ beep: 'boop' }); + } + // IP block if (hasBlockedIp(ip)) { return forbidden(); From 97b7a14a295ce4b227187b8a538833856f406d1a Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 31 Mar 2025 22:49:34 -0500 Subject: [PATCH 11/11] Fix test. --- jest.config.ts | 8 +------- jsconfig.json | 6 ------ src/lib/__tests__/charts.test.ts | 7 ++++--- tsconfig.json | 1 + 4 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 jsconfig.json diff --git a/jest.config.ts b/jest.config.ts index 3a9741cf..d06ac09a 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -5,12 +5,6 @@ export default { '^.+\\.(ts|tsx)$': 'ts-jest', }, moduleNameMapper: { - '^assets/(.*)$': '/src/assets/$1', - '^components/(.*)$': '/src/components/$1', - '^lib/(.*)$': '/src/lib/$1', - '^pages/(.*)$': '/src/pages/$1', - '^queries/(.*)$': '/src/queries/$1', - '^store/(.*)$': '/src/store/$1', - '^styles/(.*)$': '/src/styles/$1', + '^@/(.*)$': '/src/$1', }, }; diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 5875dc5b..00000000 --- a/jsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "src" - }, - "include": ["src"] -} diff --git a/src/lib/__tests__/charts.test.ts b/src/lib/__tests__/charts.test.ts index cd9e8651..e330fadd 100644 --- a/src/lib/__tests__/charts.test.ts +++ b/src/lib/__tests__/charts.test.ts @@ -1,5 +1,5 @@ -import { renderNumberLabels, renderDateLabels } from 'lib/charts'; -import { formatDate } from 'lib/date'; +import { renderNumberLabels, renderDateLabels } from '../charts'; +import { formatDate } from '../date'; // test for renderNumberLabels @@ -45,7 +45,8 @@ describe('renderDateLabels', () => { const mockValues = [{ value: '2024-03-23T10:00:00Z' }, { value: '2024-03-24T15:30:00Z' }]; beforeEach(() => { - jest.spyOn(require('lib/date'), 'formatDate'); + // eslint-disable-next-line @typescript-eslint/no-require-imports + jest.spyOn(require('@/lib/date'), 'formatDate'); }); afterEach(() => { diff --git a/tsconfig.json b/tsconfig.json index efe4861d..1e4f0ae5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,7 @@ "incremental": false, "types": ["jest"], "typeRoots": ["node_modules/@types"], + "baseUrl": ".", "paths": { "@/*": ["./src/*"] },