fix(regressions): client-bundle ioredis + Drizzle ANY() array bindings
Two regressions from yesterday's audit-tier-0 work that broke the dev
server and every clients API call.
- baseListQuerySchema lived in route-helpers.ts, which was made
server-only by the rate-limit import. Every validator imported it,
pulling ioredis (and dns/net/tls/fs/node:async_hooks) into the client
bundle — every form/detail page returned 500 in dev. Extracted the
schema to src/lib/api/list-query.ts and updated all 14 validators.
- clients.service.listClients and email-compose used raw SQL
ANY(\${jsArray}) which Drizzle binds as JSON — Postgres rejects with
42809 "op ANY/ALL (array) requires array on right side". Switched to
the inArray helper.
GET /api/v1/clients now returns 200 again. Affects every form/detail
page that imports a validator.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
import { BERTH_STATUSES } from '@/lib/constants';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
|
||||
// ─── Create Berth ────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import {
|
||||
optionalCountryIsoSchema,
|
||||
optionalIanaTimezoneSchema,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import { optionalCountryIsoSchema, optionalSubdivisionIsoSchema } from '@/lib/validators/i18n';
|
||||
|
||||
export const createCompanySchema = z.object({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import { VALID_MERGE_TOKENS } from '@/lib/templates/merge-fields';
|
||||
|
||||
const mergeFieldsSchema = z
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import { DOCUMENT_TYPES, DOCUMENT_STATUSES } from '@/lib/constants';
|
||||
|
||||
export const createDocumentSchema = z.object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import { EXPENSE_CATEGORIES, PAYMENT_METHODS } from '@/lib/constants';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
|
||||
export const uploadFileSchema = z.object({
|
||||
filename: z.string().min(1).max(255),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import { PIPELINE_STAGES, LEAD_CATEGORIES } from '@/lib/constants';
|
||||
import {
|
||||
optionalCountryIsoSchema,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
|
||||
export const INVOICE_KINDS = ['general', 'deposit'] as const;
|
||||
export type InvoiceKind = (typeof INVOICE_KINDS)[number];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
|
||||
export const createReminderSchema = z.object({
|
||||
title: z.string().min(1).max(300),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
|
||||
export const RESERVATION_STATUSES = ['pending', 'active', 'ended', 'cancelled'] as const;
|
||||
export const TENURE_TYPES = ['permanent', 'fixed_term', 'seasonal'] as const;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import {
|
||||
optionalCountryIsoSchema,
|
||||
optionalIanaTimezoneSchema,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
import { WEBHOOK_EVENTS } from '@/lib/services/webhook-event-map';
|
||||
|
||||
// ─── SSRF guards ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
import { baseListQuerySchema } from '@/lib/api/list-query';
|
||||
|
||||
export const ownerRefSchema = z.object({
|
||||
type: z.enum(['client', 'company']),
|
||||
|
||||
Reference in New Issue
Block a user