Skip to content

Commit af35e2a

Browse files
committed
fix: schema generation for unsupported field type
1 parent 72de807 commit af35e2a

File tree

5 files changed

+1148
-31
lines changed

5 files changed

+1148
-31
lines changed

packages/sdk/src/schema/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export type FieldDef = {
5959
unique?: boolean;
6060
updatedAt?: boolean;
6161
attributes?: AttributeApplication[];
62-
default?: MappedBuiltinType | Expression;
62+
default?: MappedBuiltinType | Expression | unknown[];
6363
relation?: RelationInfo;
6464
foreignKeyFor?: string[];
6565
computed?: boolean;

packages/sdk/src/ts-schema-generator.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -284,12 +284,7 @@ export class TsSchemaGenerator {
284284
}
285285

286286
private createDataModelFieldObject(field: DataModelField) {
287-
const objectFields = [
288-
ts.factory.createPropertyAssignment(
289-
'type',
290-
ts.factory.createStringLiteral(field.type.type ?? field.type.reference!.$refText),
291-
),
292-
];
287+
const objectFields = [ts.factory.createPropertyAssignment('type', this.generateFieldTypeLiteral(field))];
293288

294289
if (isIdField(field)) {
295290
objectFields.push(ts.factory.createPropertyAssignment('id', ts.factory.createTrue()));
@@ -325,7 +320,7 @@ export class TsSchemaGenerator {
325320

326321
const defaultValue = this.getMappedDefault(field);
327322
if (defaultValue !== undefined) {
328-
if (typeof defaultValue === 'object') {
323+
if (typeof defaultValue === 'object' && !Array.isArray(defaultValue)) {
329324
if ('call' in defaultValue) {
330325
objectFields.push(
331326
ts.factory.createPropertyAssignment(
@@ -371,18 +366,20 @@ export class TsSchemaGenerator {
371366
throw new Error(`Unsupported default value type for field ${field.name}`);
372367
}
373368
} else {
374-
objectFields.push(
375-
ts.factory.createPropertyAssignment(
376-
'default',
377-
typeof defaultValue === 'string'
378-
? ts.factory.createStringLiteral(defaultValue)
379-
: typeof defaultValue === 'number'
380-
? ts.factory.createNumericLiteral(defaultValue)
381-
: defaultValue === true
382-
? ts.factory.createTrue()
383-
: ts.factory.createFalse(),
384-
),
385-
);
369+
if (Array.isArray(defaultValue)) {
370+
objectFields.push(
371+
ts.factory.createPropertyAssignment(
372+
'default',
373+
ts.factory.createArrayLiteralExpression(
374+
defaultValue.map((item) => this.createLiteralNode(item as any)),
375+
),
376+
),
377+
);
378+
} else {
379+
objectFields.push(
380+
ts.factory.createPropertyAssignment('default', this.createLiteralNode(defaultValue)),
381+
);
382+
}
386383
}
387384
}
388385

@@ -440,7 +437,7 @@ export class TsSchemaGenerator {
440437

441438
private getMappedDefault(
442439
field: DataModelField,
443-
): string | number | boolean | { call: string; args: any[] } | { authMember: string[] } | undefined {
440+
): string | number | boolean | unknown[] | { call: string; args: any[] } | { authMember: string[] } | undefined {
444441
const defaultAttr = getAttribute(field, '@default');
445442
if (!defaultAttr) {
446443
return undefined;
@@ -456,6 +453,8 @@ export class TsSchemaGenerator {
456453
: ['Int', 'Float', 'Decimal', 'BigInt'].includes(field.type.type!)
457454
? Number(lit)
458455
: lit;
456+
} else if (isArrayExpr(defaultValue)) {
457+
return defaultValue.items.map((item) => this.getLiteral(item));
459458
} else if (isReferenceExpr(defaultValue) && isEnumField(defaultValue.target.ref)) {
460459
return defaultValue.target.ref.name;
461460
} else if (isInvocationExpr(defaultValue)) {
@@ -681,9 +680,17 @@ export class TsSchemaGenerator {
681680
return ts.factory.createObjectLiteralExpression(properties, true);
682681
}
683682

684-
private generateFieldTypeLiteral(field: DataModelField): ts.Expression {
685-
invariant(field.type.type || field.type.reference, 'Field type must be a primitive or reference');
686-
return ts.factory.createStringLiteral(field.type.type ?? field.type.reference!.$refText);
683+
private generateFieldTypeLiteral(field: DataModelField | ProcedureParam): ts.Expression {
684+
invariant(
685+
field.type.type || field.type.reference || field.type.unsupported,
686+
'Field type must be a primitive, reference, or Unsupported',
687+
);
688+
689+
return field.type.type
690+
? ts.factory.createStringLiteral(field.type.type)
691+
: field.type.reference
692+
? ts.factory.createStringLiteral(field.type.reference.$refText)
693+
: ts.factory.createStringLiteral('unknown');
687694
}
688695

689696
private createEnumObject(e: Enum) {

tests/e2e/cal.com/cal-com.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { generateTsSchema } from '@zenstackhq/testtools';
2-
import { describe, it } from 'vitest';
2+
import { describe, expect, it } from 'vitest';
33
import fs from 'node:fs';
44
import path from 'node:path';
55

66
describe('Cal.com e2e tests', () => {
77
it('has a working schema', async () => {
8-
const generated = await generateTsSchema(
9-
fs.readFileSync(path.join(__dirname, 'schema.zmodel'), 'utf8'),
10-
'postgresql',
11-
'cal-com',
12-
);
13-
console.log(generated);
8+
await expect(
9+
generateTsSchema(fs.readFileSync(path.join(__dirname, 'schema.zmodel'), 'utf8'), 'postgresql', 'cal-com'),
10+
).resolves.toBeTruthy();
1411
});
1512
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { generateTsSchema } from '@zenstackhq/testtools';
2+
import { describe, expect, it } from 'vitest';
3+
import fs from 'node:fs';
4+
import path from 'node:path';
5+
6+
describe('Formbricks e2e tests', () => {
7+
it('has a working schema', async () => {
8+
await expect(
9+
generateTsSchema(fs.readFileSync(path.join(__dirname, 'schema.zmodel'), 'utf8'), 'postgresql', 'cal-com'),
10+
).resolves.toBeTruthy();
11+
});
12+
});

0 commit comments

Comments
 (0)