mirror of
https://github.com/supabase/supabase.git
synced 2026-06-17 13:14:06 +08:00
## Problem Because we have controller inputs and zod validation on numbers, many of them cannot be cleared correctly as deleting their value resets it to `0`. ## Solution Update the `Input` component to allow those editions by always storing and displaying the user entered value ## How to test - Open the webhook page and add/edit one - Clear its timeout value and observe that it is not reset to `0` - Same for: - Database network restrictions - API settings max rows - Disk size modal <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized numeric form input handling across examples, settings, and modals — inputs now rely on form bindings and schema coercion for consistent parsing and simplified behavior. * **Chores** * Added form resolver utilities and a user-event testing library to development dependencies. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
import { getKeyValueFieldArrayValidationIssues } from 'ui-patterns/form/KeyValueFieldArray/validation'
|
|
import { z } from 'zod'
|
|
|
|
import { httpEndpointUrlSchema } from '@/lib/validation/http-url'
|
|
|
|
const httpRequestSchema = z.object({
|
|
function_type: z.literal('http_request'),
|
|
http_url: httpEndpointUrlSchema({
|
|
requiredMessage: 'Please provide a URL',
|
|
invalidMessage: 'Please provide a valid URL',
|
|
prefixMessage: 'Please prefix your URL with http:// or https://',
|
|
}),
|
|
})
|
|
|
|
const supabaseFunctionSchema = z.object({
|
|
function_type: z.literal('supabase_function'),
|
|
http_url: z
|
|
.string()
|
|
.min(1, 'Please select an edge function')
|
|
.refine((val) => !val.includes('undefined'), 'No edge functions available for selection'),
|
|
})
|
|
|
|
const httpHeadersSchema = z.array(
|
|
z.object({ id: z.string(), name: z.string().trim(), value: z.string().trim() })
|
|
)
|
|
|
|
const httpParametersSchema = z.array(
|
|
z.object({ id: z.string(), name: z.string().trim(), value: z.string().trim() })
|
|
)
|
|
|
|
const addKeyValueIssues = (
|
|
rows: z.infer<typeof httpHeadersSchema> | z.infer<typeof httpParametersSchema>,
|
|
ctx: z.RefinementCtx,
|
|
pathPrefix: 'httpHeaders' | 'httpParameters'
|
|
) => {
|
|
const isHeaderField = pathPrefix === 'httpHeaders'
|
|
|
|
getKeyValueFieldArrayValidationIssues({
|
|
rows,
|
|
keyFieldName: 'name',
|
|
valueFieldName: 'value',
|
|
keyRequiredMessage: isHeaderField ? 'Header name is required' : 'Parameter name is required',
|
|
valueRequiredMessage: isHeaderField
|
|
? 'Header value is required'
|
|
: 'Parameter value is required',
|
|
}).forEach((issue) => {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: issue.message,
|
|
path: [pathPrefix, ...issue.path],
|
|
})
|
|
})
|
|
}
|
|
|
|
export const FormSchema = z
|
|
.object({
|
|
name: z.string().min(1, 'Please provide a name for your webhook'),
|
|
table_id: z.string().min(1, 'Please select a table'),
|
|
http_method: z.enum(['GET', 'POST']),
|
|
timeout_ms: z
|
|
.union([
|
|
z.literal(''),
|
|
z.coerce
|
|
.number()
|
|
.gte(1000, 'Timeout should be at least 1000ms')
|
|
.lte(10000, 'Timeout should not exceed 10,000ms'),
|
|
])
|
|
.refine((value) => value !== '', 'Timeout is required'),
|
|
events: z.array(z.string()).min(1, 'Please select at least one event'),
|
|
httpHeaders: httpHeadersSchema,
|
|
httpParameters: httpParametersSchema,
|
|
})
|
|
.and(z.discriminatedUnion('function_type', [httpRequestSchema, supabaseFunctionSchema]))
|
|
.superRefine((data, ctx) => {
|
|
addKeyValueIssues(data.httpHeaders, ctx, 'httpHeaders')
|
|
addKeyValueIssues(data.httpParameters, ctx, 'httpParameters')
|
|
})
|
|
|
|
export type WebhookFormValues = z.infer<typeof FormSchema>
|