Skip to content

Commit

Permalink
feat(infra): orm f.enum() support (#9323)
Browse files Browse the repository at this point in the history
  • Loading branch information
CatsJuice committed Dec 31, 2024
1 parent 9c119e6 commit 7c41775
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 6 deletions.
12 changes: 12 additions & 0 deletions packages/common/infra/src/orm/core/__tests__/schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ describe('Entity validations', () => {
id: f.string().primaryKey().default(nanoid),
name: f.string(),
color: f.string(),
status: f.enum('active', 'inactive').optional(),
},
});

Expand Down Expand Up @@ -130,4 +131,15 @@ describe('Entity validations', () => {
expect(tag.info).toBe(null);
});
});

test('should throw when trying to create entity with invalid enum value', () => {
const client = createTagsClient();

expect(() =>
// @ts-expect-error test
client.tags.create({ name: 'test', status: 'not-active' })
).toThrow(
"[Table(tags)]: Field 'status' value 'not-active' is not valid. Expected one of [active, inactive]."
);
});
});
11 changes: 8 additions & 3 deletions packages/common/infra/src/orm/core/schema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export type FieldType = 'string' | 'number' | 'boolean' | 'json';
export type FieldType = 'string' | 'number' | 'boolean' | 'json' | 'enum';

export interface FieldSchema<Type = unknown> {
type: FieldType;
optional: boolean;
isPrimaryKey: boolean;
default?: () => Type;
values?: Type[];
}

export type TableSchema = Record<string, FieldSchema>;
Expand All @@ -28,10 +29,12 @@ export class FieldSchemaBuilder<
optional: false,
isPrimaryKey: false,
default: undefined,
values: undefined,
};

constructor(type: FieldType) {
constructor(type: FieldType, values?: string[]) {
this.schema.type = type;
this.schema.values = values;
}

optional() {
Expand All @@ -56,7 +59,9 @@ export const f = {
number: () => new FieldSchemaBuilder<number>('number'),
boolean: () => new FieldSchemaBuilder<boolean>('boolean'),
json: <T = any>() => new FieldSchemaBuilder<T>('json'),
} satisfies Record<FieldType, () => FieldSchemaBuilder<any>>;
enum: <T extends string>(...values: T[]) =>
new FieldSchemaBuilder<T>('enum', values),
} as const;

export const t = {
document: <T extends TableSchemaBuilder>(schema: T) => {
Expand Down
17 changes: 15 additions & 2 deletions packages/common/infra/src/orm/core/validators/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,14 @@ export const dataValidators = {
}

const typeGet = inputType(val);
if (!typeMatches(field.type, typeGet)) {

if (field.type === 'enum') {
if (!field.values?.includes(val)) {
throw new Error(
`[Table(${table.name})]: Field '${key}' value '${val}' is not valid. Expected one of [${field.values?.join(', ')}].`
);
}
} else if (!typeMatches(field.type, typeGet)) {
throw new Error(
`[Table(${table.name})]: Field '${key}' type mismatch. Expected ${field.type} got ${typeGet}.`
);
Expand Down Expand Up @@ -103,7 +110,13 @@ export const dataValidators = {
}

const typeGet = inputType(val);
if (!typeMatches(field.type, typeGet)) {
if (field.type === 'enum') {
if (!field.values?.includes(val)) {
throw new Error(
`[Table(${table.name})]: Field '${key}' value '${val}' is not valid. Expected one of [${field.values?.join(', ')}].`
);
}
} else if (!typeMatches(field.type, typeGet)) {
throw new Error(
`[Table(${table.name})]: Field '${key}' type mismatch. Expected type '${field.type}' but got '${typeGet}'.`
);
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/core/src/modules/db/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const AFFiNE_WORKSPACE_DB_SCHEMA = {
id: f.string().primaryKey().optional().default(nanoid),
name: f.string().optional(),
type: f.string(),
show: f.string().optional(),
show: f.enum('always-show', 'always-hide', 'hide-when-empty').optional(),
index: f.string().optional(),
icon: f.string().optional(),
additionalData: f.json().optional(),
Expand Down

0 comments on commit 7c41775

Please sign in to comment.