e01b641a05
## 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.
77 lines
2.5 KiB
TypeScript
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(),
|
|
});
|
|
};
|