From c5d9fa138c2dad7342105df3ed4946f17cbcd3e6 Mon Sep 17 00:00:00 2001 From: Mihael Konjevic Date: Mon, 15 Apr 2024 22:46:33 +0200 Subject: [PATCH] fix: simplify queryBuilder zod schema Dimensions and metrics are now validated with refine, instead of being exposed as enum --- src/__tests__/index.test.ts | 14 ++------------ src/lib/query-builder.ts | 25 +++++++++++-------------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index a212374..b7b1ca9 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -918,22 +918,12 @@ await describe("semantic layer", async () => { assert.deepEqual(jsonSchema, { type: "object", properties: { - dimensions: { - type: "array", - items: { - type: "string", - enum: [ - "customers.customer_id", - "invoices.invoice_id", - "invoices.customer_id", - ], - }, - }, + dimensions: { type: "array", items: { type: "string" } }, metrics: { type: "array", items: { anyOf: [ - { type: "string", enum: ["invoices.total"] }, + { type: "string" }, { type: "object", properties: { diff --git a/src/lib/query-builder.ts b/src/lib/query-builder.ts index f949577..7c411d7 100644 --- a/src/lib/query-builder.ts +++ b/src/lib/query-builder.ts @@ -23,16 +23,10 @@ import { findOptimalJoinGraph } from "./query-builder/optimal-join-graph.js"; import { processQueryAndExpandToSegments } from "./query-builder/process-query-and-expand-to-segments.js"; import type { AnyRepository } from "./repository.js"; -function isNonEmptyArray(arr: T[]): arr is [T, ...T[]] { - return arr.length > 0; -} - function getDimensionNamesSchema(dimensionPaths: string[]) { - if (isNonEmptyArray(dimensionPaths)) { - const [first, ...rest] = dimensionPaths; - return z.array(z.enum([first, ...rest])).optional(); - } - return z.array(z.string()).max(0).optional(); + return z + .array(z.string().refine((arg) => dimensionPaths.includes(arg))) + .optional(); } function getMetricNamesSchema(metricPaths: string[]) { @@ -41,11 +35,14 @@ function getMetricNamesSchema(metricPaths: string[]) { dimension: z.string(), }); - if (isNonEmptyArray(metricPaths)) { - const [first, ...rest] = metricPaths; - return z.array(z.enum([first, ...rest]).or(adHocMetricSchema)).optional(); - } - return z.array(adHocMetricSchema).optional(); + return z + .array( + z + .string() + .refine((arg) => metricPaths.includes(arg)) + .or(adHocMetricSchema), + ) + .optional(); } export function buildQuerySchema(repository: AnyRepository) {