chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,82 @@
import { z } from 'zod'
import { defineRouteContract } from '@/lib/api/contracts/types'
import { isFreeEmailDomain } from '@/lib/messaging/email/free-email'
import { NO_EMAIL_HEADER_CONTROL_CHARS_REGEX } from '@/lib/messaging/email/utils'
import { quickValidateEmail } from '@/lib/messaging/email/validation'
export const DEMO_REQUEST_COMPANY_SIZE_VALUES = [
'1_10',
'11_50',
'51_200',
'201_500',
'501_1000',
'1001_10000',
'10000_plus',
] as const
export const DEMO_REQUEST_COMPANY_SIZE_OPTIONS = [
{ value: '1_10', label: '110' },
{ value: '11_50', label: '1150' },
{ value: '51_200', label: '51200' },
{ value: '201_500', label: '201500' },
{ value: '501_1000', label: '5011,000' },
{ value: '1001_10000', label: '1,00110,000' },
{ value: '10000_plus', label: '10,000+' },
] as const
export const demoRequestSchema = z.object({
firstName: z
.string()
.trim()
.min(1, 'First name is required')
.max(100)
.regex(NO_EMAIL_HEADER_CONTROL_CHARS_REGEX, 'Invalid characters'),
lastName: z
.string()
.trim()
.min(1, 'Last name is required')
.max(100)
.regex(NO_EMAIL_HEADER_CONTROL_CHARS_REGEX, 'Invalid characters'),
companyEmail: z
.string()
.trim()
.min(1, 'Company email is required')
.max(320)
.transform((value) => value.toLowerCase())
.refine((value) => quickValidateEmail(value).isValid, 'Enter a valid work email')
.refine((value) => !isFreeEmailDomain(value), 'Please use your work email address'),
phoneNumber: z
.string()
.trim()
.max(50, 'Phone number must be 50 characters or less')
.optional()
.transform((value) => (value && value.length > 0 ? value : undefined)),
companySize: z.enum(DEMO_REQUEST_COMPANY_SIZE_VALUES, {
error: 'Please select company size',
}),
details: z.string().trim().min(1, 'Details are required').max(2000),
})
export type DemoRequestPayload = z.infer<typeof demoRequestSchema>
export type DemoRequestBody = z.input<typeof demoRequestSchema>
export function getDemoRequestCompanySizeLabel(value: DemoRequestPayload['companySize']): string {
return DEMO_REQUEST_COMPANY_SIZE_OPTIONS.find((option) => option.value === value)?.label ?? value
}
export const demoRequestResponseSchema = z.object({
success: z.literal(true),
message: z.string(),
})
export type DemoRequestResult = z.output<typeof demoRequestResponseSchema>
export const submitDemoRequestContract = defineRouteContract({
method: 'POST',
path: '/api/demo-requests',
body: demoRequestSchema,
response: {
mode: 'json',
schema: demoRequestResponseSchema,
},
})