valentinpalkovic / prisma-json-schema-generator

A generator for Prisma 2 to generate a valid JSON Schema (v7)
MIT License
279 stars 32 forks source link

ignoreRelatedModels (but include foreign key fields) #504

Open Flax95 opened 2 years ago

Flax95 commented 2 years ago

Great work on this!

I was thinking of using a generated schema as a starting point for user input validation. In most cases, I would have no use for the relations.

model agedivision {
  id                  Int                   @id @default(autoincrement())
  ageDivName          String               @db.VarChar(30)
  agedivision_athlete agedivision_athlete[]
  athlete             athlete[]
}

Currently produces:

{
  "agedivision": {
    "type": "object",
    "properties": {
      "id": {
        "type": "integer"
      },
      "name": {
        "type": "string"
      },
      "agedivision_athlete": {
        "type": "array",
        "items": {
          "$ref": "#/definitions/agedivision_athlete"
        }
      },
      "athlete": {
        "type": "array",
        "items": {
          "$ref": "#/definitions/athlete"
        }
      }
    }
  }
}

I would have liked:

{
  "agedivision": {
    "type": "object",
    "properties": {
      "id": {
        "type": "integer"
      },
      "name": {
        "type": "string"
      }
    }
  }
}

Foreign keys would be included.

Is this a feature that you have plans for?

dimaip commented 2 years ago

I also really need this. My usecase: I want to generate Mongo $jsonSchema out of Prisma schema.

valentinpalkovic commented 2 years ago

@Flax95 Thank you for opening up this issue!

Should the relations only be dropped, If they are not available in the schema or always?

Flax95 commented 2 years ago

Always.


Let me take the opportunity to further explain my use case:

I am working on an Express REST api. In my project I divided the different parts of my API into modules. My user module looks like this: image

.routes contains routes where, if needed, a validator is called as middleware. After the validator ran (and if no validation/parsing errors where thrown), the controller calls a service that interacts with prisma.

user.routes.js example:

  import userValidators from './user.validation';
  ...
  userRouter.post('/', userValidators.createUser, createUser);

  userRouter.get('/', getAllUsers);

user.validation.js example:

import { createUserSchema } from './schemas';
import { validateJsonSchema } from '../../utils/validation.util';

const createUser = (req, res, next) => {
  const user = {
    ...req.body,
    userRoleId: parseInt(req.body.userRoleId, 10),
  };

  validateJsonSchema(createUserSchema, user);

  req.body.user = user;
  next();
};

const userValidators = {
  createUser,
};

export default userValidators;

createUserSchema.json example:

{
  "type": "object",
  "properties": {
    "firstName": { "type": "string" },
    "lastName": { "type": "string" },
    "email": { "type": "string", "format": "email" },
    "password": { "type": "string", "minLength": 8 },
    "userRoleId": { "type": "integer", "minimum": 1 }
  },
  "additionalProperties": false,
  "required": ["firstName", "lastName", "email", "password", "userRoleId"]
}

validateJsonSchema(schema, data) is using the Ajv schema validator to validate an object of user inputs against a JSON schema.

What I wish to do is generate something as close to createUserSchema as possible. Currently the JSON schema generated from my Prisma schema contains userRole[] instead of userRoleId.

"user": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "firstName": {
          "type": ["string", "null"]
        },
        "lastName": {
          "type": ["string", "null"]
        },
        "email": {
          "type": ["string", "null"]
        },
        "password": {
          "type": ["string", "null"]
        },
        "userRole": {
          "anyOf": [
            {
              "$ref": "#/definitions/userRole"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
valentinpalkovic commented 2 years ago

You are already able to also generate the relational scalar fields by enabling it in the settings:

generator jsonSchema {
  provider = "prisma-json-schema-generator"
  keepRelationScalarFields = "true"
}

Then userRoleId will be generated as well. And the only feature you would like to have is to ditch the relation fields. Am I right?

Flax95 commented 2 years ago

Correct.


Edit: I am clearly having problems explaining myself in plain English this week, my apologies. 😅

dimaip commented 2 years ago

I actually ended up forking your plugin to make it produce the output suitable for Mongo $jsonSchema. Will publish it later (giving the credit of course).