mirror of
https://github.com/umami-software/umami.git
synced 2026-02-13 09:05:36 +01:00
Updated zod validation on date range.
This commit is contained in:
parent
6c793325e2
commit
fb6fd293fb
10 changed files with 36 additions and 31 deletions
|
|
@ -11,7 +11,7 @@
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3002 --turbo",
|
"dev": "next dev -p 3009 --turbo",
|
||||||
"build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app",
|
"build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"build-docker": "npm-run-all build-db build-tracker build-geo build-app",
|
"build-docker": "npm-run-all build-db build-tracker build-geo build-app",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { json, unauthorized } from '@/lib/response';
|
import { json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, filterParams } from '@/lib/schema';
|
import { filterParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import { getWebsiteEventStats } from '@/queries/sql/events/getWebsiteEventStats';
|
import { getWebsiteEventStats } from '@/queries/sql/events/getWebsiteEventStats';
|
||||||
|
|
||||||
|
|
@ -9,8 +8,7 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
...dateRangeParams,
|
|
||||||
...filterParams,
|
...filterParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
import Papa from 'papaparse';
|
import Papa from 'papaparse';
|
||||||
import { z } from 'zod';
|
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { json, unauthorized } from '@/lib/response';
|
import { json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, pagingParams } from '@/lib/schema';
|
import { pagingParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import { getEventMetrics, getPageviewMetrics, getSessionMetrics } from '@/queries/sql';
|
import { getEventMetrics, getPageviewMetrics, getSessionMetrics } from '@/queries/sql';
|
||||||
|
|
||||||
|
|
@ -11,8 +10,7 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
...dateRangeParams,
|
|
||||||
...pagingParams,
|
...pagingParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { z } from 'zod';
|
||||||
import { EVENT_COLUMNS, EVENT_TYPE, SESSION_COLUMNS } from '@/lib/constants';
|
import { EVENT_COLUMNS, EVENT_TYPE, SESSION_COLUMNS } from '@/lib/constants';
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { badRequest, json, unauthorized } from '@/lib/response';
|
import { badRequest, json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, filterParams, searchParams } from '@/lib/schema';
|
import { filterParams, searchParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import {
|
import {
|
||||||
getChannelExpandedMetrics,
|
getChannelExpandedMetrics,
|
||||||
|
|
@ -15,11 +15,10 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
limit: z.coerce.number().optional(),
|
limit: z.coerce.number().optional(),
|
||||||
offset: z.coerce.number().optional(),
|
offset: z.coerce.number().optional(),
|
||||||
...dateRangeParams,
|
|
||||||
...searchParams,
|
...searchParams,
|
||||||
...filterParams,
|
...filterParams,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { z } from 'zod';
|
||||||
import { EVENT_COLUMNS, EVENT_TYPE, SESSION_COLUMNS } from '@/lib/constants';
|
import { EVENT_COLUMNS, EVENT_TYPE, SESSION_COLUMNS } from '@/lib/constants';
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { badRequest, json, unauthorized } from '@/lib/response';
|
import { badRequest, json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, filterParams, searchParams } from '@/lib/schema';
|
import { filterParams, searchParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import {
|
import {
|
||||||
getChannelMetrics,
|
getChannelMetrics,
|
||||||
|
|
@ -15,11 +15,10 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
limit: z.coerce.number().optional(),
|
limit: z.coerce.number().optional(),
|
||||||
offset: z.coerce.number().optional(),
|
offset: z.coerce.number().optional(),
|
||||||
...dateRangeParams,
|
|
||||||
...searchParams,
|
...searchParams,
|
||||||
...filterParams,
|
...filterParams,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { getCompareDate } from '@/lib/date';
|
import { getCompareDate } from '@/lib/date';
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { json, unauthorized } from '@/lib/response';
|
import { json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, filterParams } from '@/lib/schema';
|
import { filterParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import { getPageviewStats, getSessionStats } from '@/queries/sql';
|
import { getPageviewStats, getSessionStats } from '@/queries/sql';
|
||||||
|
|
||||||
|
|
@ -10,8 +9,7 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
...dateRangeParams,
|
|
||||||
...filterParams,
|
...filterParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { json, unauthorized } from '@/lib/response';
|
import { json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, filterParams, pagingParams, searchParams } from '@/lib/schema';
|
import { filterParams, pagingParams, searchParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import { getWebsiteSessions } from '@/queries/sql';
|
import { getWebsiteSessions } from '@/queries/sql';
|
||||||
|
|
||||||
|
|
@ -9,8 +8,7 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
...dateRangeParams,
|
|
||||||
...filterParams,
|
...filterParams,
|
||||||
...pagingParams,
|
...pagingParams,
|
||||||
...searchParams,
|
...searchParams,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { getCompareDate } from '@/lib/date';
|
import { getCompareDate } from '@/lib/date';
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { json, unauthorized } from '@/lib/response';
|
import { json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, filterParams } from '@/lib/schema';
|
import { filterParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import { getWebsiteStats } from '@/queries/sql';
|
import { getWebsiteStats } from '@/queries/sql';
|
||||||
|
|
||||||
|
|
@ -10,8 +9,7 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
...dateRangeParams,
|
|
||||||
...filterParams,
|
...filterParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { EVENT_COLUMNS, FILTER_COLUMNS, SEGMENT_TYPES, SESSION_COLUMNS } from '@/lib/constants';
|
import { EVENT_COLUMNS, FILTER_COLUMNS, SEGMENT_TYPES, SESSION_COLUMNS } from '@/lib/constants';
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { badRequest, json, unauthorized } from '@/lib/response';
|
import { badRequest, json, unauthorized } from '@/lib/response';
|
||||||
import { dateRangeParams, fieldsParam, searchParams } from '@/lib/schema';
|
import { fieldsParam, searchParams, withDateRange } from '@/lib/schema';
|
||||||
import { canViewWebsite } from '@/permissions';
|
import { canViewWebsite } from '@/permissions';
|
||||||
import { getWebsiteSegments } from '@/queries/prisma';
|
import { getWebsiteSegments } from '@/queries/prisma';
|
||||||
import { getValues } from '@/queries/sql';
|
import { getValues } from '@/queries/sql';
|
||||||
|
|
@ -11,9 +10,8 @@ export async function GET(
|
||||||
request: Request,
|
request: Request,
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = withDateRange({
|
||||||
type: fieldsParam,
|
type: fieldsParam,
|
||||||
...dateRangeParams,
|
|
||||||
...searchParams,
|
...searchParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,25 @@ export const dateRangeParams = {
|
||||||
compare: z.enum(['prev', 'yoy']).optional(),
|
compare: z.enum(['prev', 'yoy']).optional(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function withDateRange<T extends z.ZodRawShape>(shape?: T) {
|
||||||
|
return z
|
||||||
|
.object({
|
||||||
|
...dateRangeParams,
|
||||||
|
...shape,
|
||||||
|
})
|
||||||
|
.superRefine((data: Record<string, unknown>, ctx) => {
|
||||||
|
const hasTimestamps = data.startAt != null && data.endAt != null;
|
||||||
|
const hasDates = data.startDate != null && data.endDate != null;
|
||||||
|
|
||||||
|
if (!hasTimestamps && !hasDates) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: 'Either startAt+endAt or startDate+endDate must be provided',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const filterParams = {
|
export const filterParams = {
|
||||||
path: z.string().optional(),
|
path: z.string().optional(),
|
||||||
referrer: z.string().optional(),
|
referrer: z.string().optional(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue