Files
twenty/packages/twenty-front/src/modules/object-metadata/validation-schemas/fieldMetadataItemSchema.ts
T
Charles Bochet e01b641a05 Introduce npx nx mock:generate twenty-front (#18237)
## Add codegen script for frontend test mock data

### Summary

- Adds a new `npx nx mock:generate twenty-front` and
`generate-mock-data.ts` script that fetches object metadata from a
running server's `/metadata` endpoint, authenticates with default seeds,
and writes the result to a generated TypeScript file
(`src/testing/mock-data/generated/mock-metadata-query-result.ts`). This
replaces hand-maintained mock metadata with server-sourced data,
ensuring tests always reflect the real schema.
- Updates all frontend tests to be compatible with the newly generated
metadata, fixing hard-coded GraphQL queries, Zod validation schemas,
snapshot expectations, and Apollo mock mismatches.

### What changed

**New files**
- `scripts/generate-mock-data.ts` — codegen script that authenticates
against the server, queries `/metadata` for all object metadata (with
explicit `__typename` at every level), and writes a typed `.ts` file.
- `project.json` — added `mock:generate` Nx target (`dotenv npx tsx
scripts/generate-mock-data.ts`).

**Schema validation updates**
- `objectMetadataItemSchema.ts` — added `universalIdentifier`, made
`duplicateCriteria` nullable.
- `fieldMetadataItemSchema.ts` — added `universalIdentifier`, `morphId`,
`morphRelations`, restructured relation schema.
- `indexMetadataItemSchema.ts` — added optional `isCustom` field.
2026-02-25 21:40:05 +01:00

77 lines
2.5 KiB
TypeScript

import { z } from 'zod';
import { metadataLabelSchema } from '@/object-metadata/validation-schemas/metadataLabelSchema';
import { themeColorSchema } from 'twenty-ui/theme';
import { FieldMetadataType, RelationType } from '~/generated-metadata/graphql';
import { camelCaseStringSchema } from '~/utils/validation-schemas/camelCaseStringSchema';
export const fieldMetadataItemSchema = (existingLabels?: string[]) => {
const relationObjectSchema = z.object({
__typename: z.literal('Relation').optional(),
type: z.enum(RelationType),
sourceFieldMetadata: z.object({
__typename: z.literal('Field').optional(),
id: z.uuid(),
name: z.string().trim().min(1),
}),
sourceObjectMetadata: z.object({
__typename: z.literal('Object').optional(),
id: z.uuid(),
namePlural: z.string().trim().min(1),
nameSingular: z.string().trim().min(1),
}),
targetFieldMetadata: z.object({
__typename: z.literal('Field').optional(),
id: z.uuid(),
name: z.string().trim().min(1),
}),
targetObjectMetadata: z.object({
__typename: z.literal('Object').optional(),
id: z.uuid(),
namePlural: z.string().trim().min(1),
nameSingular: z.string().trim().min(1),
}),
});
return z.object({
__typename: z.literal('Field').optional(),
createdAt: z.iso.datetime(),
defaultValue: z.any().optional(),
description: z.string().trim().nullable().optional(),
icon: z
.union([z.string().startsWith('Icon').trim(), z.literal('')])
.nullable()
.optional(),
id: z.uuid(),
universalIdentifier: z.string(),
applicationId: z.uuid(),
isActive: z.boolean(),
isCustom: z.boolean(),
isNullable: z.boolean(),
isUnique: z.boolean(),
isSystem: z.boolean(),
isUIReadOnly: z.boolean(),
label: metadataLabelSchema(existingLabels),
isLabelSyncedWithName: z.boolean(),
morphId: z.string().nullable().optional(),
morphRelations: z.array(relationObjectSchema).nullable().optional(),
name: camelCaseStringSchema,
options: z
.array(
z.object({
color: themeColorSchema,
id: z.uuid(),
label: z.string().trim().min(1),
position: z.number(),
value: z.string().trim().min(1),
}),
)
.nullable()
.optional(),
settings: z.any().optional(),
relation: relationObjectSchema.nullable().optional(),
type: z.enum(FieldMetadataType),
updatedAt: z.iso.datetime(),
});
};