mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-11-09 08:17:31 +00:00
fix: improve filter schema
This commit is contained in:
parent
e651045ac5
commit
72e6177580
3 changed files with 76 additions and 8 deletions
|
|
@ -28,6 +28,7 @@ import {
|
|||
SettingsRequestSchema,
|
||||
UpdateContainerTagSettingsRequestSchema,
|
||||
} from "../validation/api"
|
||||
import { SearchFiltersSchema } from "../validation/schemas"
|
||||
|
||||
const UpdateSettingsResponseSchema = z.object({
|
||||
orgId: z.string(),
|
||||
|
|
@ -252,6 +253,7 @@ export const apiSchema = createSchema({
|
|||
page: z.number().optional(),
|
||||
status: z.string().optional(),
|
||||
containerTags: z.array(z.string()).optional(),
|
||||
filters: SearchFiltersSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
output: ListMemoriesResponseSchema,
|
||||
|
|
|
|||
|
|
@ -6,17 +6,11 @@ import {
|
|||
MemoryEntrySchema,
|
||||
OrganizationSettingsSchema,
|
||||
RequestTypeEnum,
|
||||
SearchFiltersSchema,
|
||||
} from "./schemas"
|
||||
|
||||
export const MetadataSchema = BaseMetadataSchema
|
||||
|
||||
export const SearchFiltersSchema = z
|
||||
.object({
|
||||
AND: z.array(z.unknown()).optional(),
|
||||
OR: z.array(z.unknown()).optional(),
|
||||
})
|
||||
.or(z.record(z.unknown()))
|
||||
|
||||
const exampleMetadata: Record<string, string | number | boolean> = {
|
||||
category: "technology",
|
||||
isPublic: true,
|
||||
|
|
@ -247,10 +241,18 @@ export const ListMemoriesQuerySchema = z
|
|||
"Optional tags this memory should be containerized by. This can be an ID for your user, a project ID, or any other identifier you wish to use to group memories.",
|
||||
example: ["user_123", "project_123"],
|
||||
}),
|
||||
// TODO: Improve filter schema
|
||||
filters: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((raw,ctx) => {
|
||||
if (!raw) return undefined
|
||||
try {
|
||||
return SearchFiltersSchema.parse(JSON.parse(raw))
|
||||
} catch {
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Invalid filters JSON" })
|
||||
return z.NEVER
|
||||
}
|
||||
})
|
||||
.openapi({
|
||||
description: "Optional filters to apply to the search",
|
||||
example: JSON.stringify({
|
||||
|
|
|
|||
|
|
@ -8,6 +8,70 @@ export type Metadata = z.infer<typeof MetadataSchema>
|
|||
export const VisibilityEnum = z.enum(["public", "private", "unlisted"])
|
||||
export type Visibility = z.infer<typeof VisibilityEnum>
|
||||
|
||||
const MetadataKeySchema = z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(64)
|
||||
.regex(/^[a-zA-Z0-9_.-]+$/, "Invalid metadata key")
|
||||
|
||||
const MetadataValueSchema = z.union([z.string(), z.number(), z.boolean()])
|
||||
|
||||
const StringEqualityFilterSchema = z.object({
|
||||
key: MetadataKeySchema,
|
||||
value: MetadataValueSchema,
|
||||
negate: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const StringContainsFilterSchema = z.object({
|
||||
filterType: z.literal("string_contains"),
|
||||
key: MetadataKeySchema,
|
||||
value: z.string(),
|
||||
negate: z.boolean().optional(),
|
||||
ignoreCase: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const NumericOperatorSchema = z.enum(["=", "!=", "<", "<=", ">", ">="])
|
||||
|
||||
const NumericFilterSchema = z.object({
|
||||
filterType: z.literal("numeric"),
|
||||
key: MetadataKeySchema,
|
||||
value: z.string(),
|
||||
numericOperator: NumericOperatorSchema,
|
||||
negate: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const ArrayContainsFilterSchema = z.object({
|
||||
filterType: z.literal("array_contains"),
|
||||
key: MetadataKeySchema,
|
||||
value: z.string(),
|
||||
negate: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const FilterConditionSchema = z.discriminatedUnion("filterType", [
|
||||
StringContainsFilterSchema,
|
||||
NumericFilterSchema,
|
||||
ArrayContainsFilterSchema,
|
||||
]).or(StringEqualityFilterSchema)
|
||||
|
||||
type FilterExpression =
|
||||
| z.infer<typeof FilterConditionSchema>
|
||||
| { AND: FilterExpression[] }
|
||||
| { OR: FilterExpression[] }
|
||||
|
||||
export const FilterExpressionSchema: z.ZodType<FilterExpression> = z.lazy(() =>
|
||||
z.union([
|
||||
FilterConditionSchema,
|
||||
z.object({ AND: z.array(FilterExpressionSchema).min(1) }),
|
||||
z.object({ OR: z.array(FilterExpressionSchema).min(1) }),
|
||||
])
|
||||
)
|
||||
|
||||
export const SearchFiltersSchema = z.union([
|
||||
z.object({ AND: z.array(FilterExpressionSchema).min(1) }),
|
||||
z.object({ OR: z.array(FilterExpressionSchema).min(1) }),
|
||||
])
|
||||
|
||||
|
||||
export const DocumentTypeEnum = z.enum([
|
||||
"text",
|
||||
"pdf",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue