Skip to content

Commit dc35584

Browse files
Merge pull request #666 from valentinpalkovic/feat/persist-original-type
feat: Persist original field type
2 parents f93713b + 5a288ba commit dc35584

File tree

4 files changed

+140
-5
lines changed

4 files changed

+140
-5
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ generator jsonSchema {
5050
keepRelationScalarFields = "true"
5151
schemaId = "some-schema-id"
5252
includeRequiredFields = "true"
53+
persistOriginalType = "true"
5354
}
5455
```
5556

@@ -59,7 +60,8 @@ The generator currently supports a few options
5960
| ------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
6061
| keepRelationScalarFields | "false" | By default, the JSON Schema that's generated will output only objects for related model records. If set to "true", this will cause the generator to also output foreign key fields for related records |
6162
| schemaId | undefined | Add an id to the generated schema. All references will include the schema id |
62-
| includeRequiredFields | "false" | If this flag is ```"true"``` all required scalar prisma fields that do not have a default value, will be added to the ```required``` properties field for that schema definition.
63+
| includeRequiredFields | "false" | If this flag is `"true"` all required scalar prisma fields that do not have a default value, will be added to the `required` properties field for that schema definition. |
64+
| persistOriginalType | "false" | If this flag is `"true"` the original type will be outputed under the property key "originalType" |
6365

6466
**3. Run generation**
6567

src/generator/properties.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,22 @@ function getFormatByDMMFType(
111111

112112
function getJSONSchemaForPropertyReference(
113113
field: DMMF.Field,
114-
{ schemaId }: TransformOptions,
114+
{ schemaId, persistOriginalType }: TransformOptions,
115115
): JSONSchema7 {
116116
const notNullable = field.isRequired || field.isList
117117

118118
assertFieldTypeIsString(field.type)
119119

120120
const typeRef = `${DEFINITIONS_ROOT}${field.type}`
121121
const ref = { $ref: schemaId ? `${schemaId}${typeRef}` : typeRef }
122-
return notNullable ? ref : { anyOf: [ref, { type: 'null' }] }
122+
return notNullable
123+
? ref
124+
: {
125+
anyOf: [ref, { type: 'null' }],
126+
...(persistOriginalType && {
127+
originalType: field.type,
128+
}),
129+
}
123130
}
124131

125132
function getItemsByDMMFType(
@@ -166,6 +173,9 @@ function getPropertyDefinition(
166173

167174
const definition: JSONSchema7Definition = {
168175
type,
176+
...(transformOptions.persistOriginalType && {
177+
originalType: field.type,
178+
}),
169179
...(isDefined(defaultValue) && { default: defaultValue }),
170180
...(isDefined(format) && { format }),
171181
...(isDefined(items) && { items }),

src/generator/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ export interface TransformOptions {
1818
keepRelationScalarFields?: 'true' | 'false'
1919
schemaId?: string
2020
includeRequiredFields?: 'true' | 'false'
21+
persistOriginalType?: 'true' | 'false'
2122
}

src/tests/generator.test.ts

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,124 @@ describe('JSON Schema Generator', () => {
360360
})
361361
})
362362

363+
it('adds original type if requested', async () => {
364+
const dmmf = await getDMMF({ datamodel: datamodelPostGresQL })
365+
expect(
366+
transformDMMF(dmmf, { persistOriginalType: 'true' }),
367+
).toEqual({
368+
$schema: 'http://json-schema.org/draft-07/schema#',
369+
definitions: {
370+
Post: {
371+
properties: {
372+
id: { originalType: 'Int', type: 'integer' },
373+
user: {
374+
anyOf: [
375+
{ $ref: '#/definitions/User' },
376+
{ type: 'null' },
377+
],
378+
originalType: 'User',
379+
},
380+
},
381+
type: 'object',
382+
},
383+
User: {
384+
properties: {
385+
biography: {
386+
originalType: 'Json',
387+
type: [
388+
'number',
389+
'string',
390+
'boolean',
391+
'object',
392+
'array',
393+
'null',
394+
],
395+
},
396+
createdAt: {
397+
originalType: 'DateTime',
398+
format: 'date-time',
399+
type: 'string',
400+
},
401+
email: {
402+
originalType: 'String',
403+
description:
404+
'Triple Slash Comment: Will show up in JSON schema [EMAIL]',
405+
type: 'string',
406+
},
407+
number: {
408+
type: 'integer',
409+
originalType: 'BigInt',
410+
default: '34534535435353',
411+
},
412+
bytes: {
413+
originalType: 'Bytes',
414+
description:
415+
'Triple Slash Inline Comment: Will show up in JSON schema [BYTES]',
416+
type: 'string',
417+
},
418+
favouriteDecimal: {
419+
default: 22.222222,
420+
originalType: 'Decimal',
421+
type: 'number',
422+
},
423+
id: { type: 'integer', originalType: 'Int' },
424+
is18: {
425+
default: false,
426+
type: ['boolean', 'null'],
427+
originalType: 'Boolean',
428+
},
429+
keywords: {
430+
items: { type: 'string' },
431+
originalType: 'String',
432+
type: 'array',
433+
},
434+
name: {
435+
default: 'Bela B',
436+
originalType: 'String',
437+
type: ['string', 'null'],
438+
},
439+
posts: {
440+
items: { $ref: '#/definitions/Post' },
441+
originalType: 'Post',
442+
type: 'array',
443+
},
444+
predecessor: {
445+
anyOf: [
446+
{ $ref: '#/definitions/User' },
447+
{ type: 'null' },
448+
],
449+
originalType: 'User',
450+
},
451+
role: {
452+
default: 'USER',
453+
originalType: 'Role',
454+
enum: ['USER', 'ADMIN'],
455+
type: 'string',
456+
},
457+
successor: {
458+
anyOf: [
459+
{ $ref: '#/definitions/User' },
460+
{ type: 'null' },
461+
],
462+
originalType: 'User',
463+
},
464+
weight: {
465+
default: 333.33,
466+
originalType: 'Float',
467+
type: ['number', 'null'],
468+
},
469+
},
470+
type: 'object',
471+
},
472+
},
473+
properties: {
474+
post: { $ref: '#/definitions/Post' },
475+
user: { $ref: '#/definitions/User' },
476+
},
477+
type: 'object',
478+
})
479+
})
480+
363481
it('adds schema id', async () => {
364482
const dmmf = await getDMMF({ datamodel: datamodelPostGresQL })
365483
expect(
@@ -471,11 +589,15 @@ describe('JSON Schema Generator', () => {
471589
// eslint-disable-next-line jest/expect-expect
472590
it('generated schema validates against input', async () => {
473591
const dmmf = await getDMMF({ datamodel: datamodelPostGresQL })
474-
const jsonSchema = transformDMMF(dmmf)
592+
const jsonSchema = transformDMMF(dmmf, {
593+
persistOriginalType: 'true',
594+
})
475595
const ajv = new Ajv({
476596
allowUnionTypes: true,
477-
})
597+
}).addKeyword('originalType')
598+
478599
addFormats(ajv)
600+
479601
const validate = ajv.compile(jsonSchema)
480602
const valid = validate({
481603
post: {

0 commit comments

Comments
 (0)