Model Representation

Models and columns are represented in a confusing way for new developers, and as such we have decided to create this page with the purpose of clarifying uncertainties.

Naturally, when dealing with multiple schemas that have have multiple models, we need a way to identify each item correctly. To do this, we've created a format that can be understood by Prisma Util and can safely represent unique identifiers for Models and Columns. Going forwards, we're going to use some definitions that will be required for understanding this article. To familiarize yourself, here is a rundown of the terms that we are going to use:

  • We are going to refer to Path as a relative path to a Prisma schema file. Across all examples and explanations, Path will be used as a placeholder for the path to said file, and should be replaced by you so it applies to your current file structure.

  • We are going to refer to ModelName as the name for a model in a specific file. Across all examples and explanations, ModelName will be used as a placeholder for said model name, and should be replaced by you so it applies to your current schema.

  • We are going to refer to ColumnName as the name for a column in a model. Across all examples and explanations, ColumnName will be used as a placeholder for said column name, and should be replaced by you so it applies to your current schema.

  • We use Field and Column synonymously to avoid repetition.

Abstraction

The general format of the format we created is shown below. Everything between square brackets is considered optional, everything outside square brackets is required:

Abstract Association
Path[:ModelName[.ColumnName]]

To understand the abstraction better, we've broken it into 3 branches based on the amount of data that you need and what you should add:

  • You need the path to a specific file - The association will be Path.

  • You need a specific model from a specific file - The association will be Path:ModelName.

  • You need a specific column from a specific model from a specific file - The association will be Path:ModelName.ColumnName

Using this split, you can verify that the association you're using is correct based on the requirements of the field that you are currently configuring. Every required type is defined in the API Documentation.

Easier Associations

Now that we've gotten the abstractions out of the way, let's focus on what matters the most: the developer experience. We understand that these associations are pretty complex to define, and as such we have created a built-in module that defines them for you using the parameters you pass.

The module in question is called Schema Creator, and can be imported from prisma-util/schema-creator. It provides a very useful function called constantModel. The next parts of this article will be focusing on how this function operates and how it can help you create associations easier based on the 3 branches we've created above.

Case 1. You need the path to a specific file

If you need to represent a file in your configuration (two fields that require a path are baseSchema and includeFiles), you should use the function like this:

prisma-util.config.mjs
// The imports and JSDocs are skipped in this code block
// for organization and clarity.

// Use the constantModel function to create an association.
// The constantModel function will always take one parameter.
// This parameter represents the Path to a file and just that.
// You shouldn't try to define the association yourself, you
// should just provide the Path to the file.
const BaseDefinition = constantModel("Path");

export default {
    // Other configuration lines

    // Prisma Util allows you to use direct definitions without
    // having to call the function.
    baseSchema: BaseDefinition
}

As you can see, creating a definition for a Path is very easy.

Case 2. You need a specific model from a specific file

If you need to represent a model in your configuration (one field that requires a model is excludeModels), you should use the function like this:

prisma-util.config.mjs
// The imports and JSDocs are skipped in this code block
// for organization and clarity.

// Use the constantModel function to create an association.
// The constantModel function will always take one parameter.
// This parameter represents the Path to a file and just that.
// You shouldn't try to define the association yourself, you
// should just provide the Path to the file.
const BaseDefinition = constantModel("Path");

export default {
    // Other configuration lines

    // To generate a file-model association, we just have to call
    // the definition function we've defined and pass the ModelName
    // as the first parameter.
    excludeModels: [BaseDefinition("ModelName")]
}

As you can see, creating a definition for a Model is just as easy as creating a definition for a Path.

Case 3. You need a specific column from a specific model from a specific file

If you need to represent a column in your configuration (one field that requires a model is relations), you should use the function like this:

prisma-util.config.mjs
// The imports and JSDocs are skipped in this code block
// for organization and clarity.

// Use the constantModel function to create an association.
// The constantModel function will always take one parameter.
// This parameter represents the Path to a file and just that.
// You shouldn't try to define the association yourself, you
// should just provide the Path to the file.
const BaseDefinition = constantModel("Path");
// This definition is here just to satisfy the relations field, as
// it requires a mapping between a column and a model from a different
// file. We define Extra as a different path than the one specified
// above (Path).
const ExtraDefinition = constantModel("Extra");

export default {
    // Other configuration lines

    relations: {
        // To generate a file-model-column association, we just have to call
        // the definition function we've defined and pass the ModelName
        // as the first parameter and the ColumnName as the second.
        // In this example, we define ExtraModel as a different model name
        // than the one specified before (ModelName). It is created for the sole
        // purpose of providing a valid schema configuration object.
        [BaseDefinition("ModelName", "ColumnName")]: ExtraDefinition("ExtraModel")
    }
}

As you can see, creating a definition for a Column is just as easy as creating a definition for a Path or creating a definition for a Model.

Generator

Generators follow the same format as Models, the only exception being that they don't accept a column as the second parameter to their constant function and use constantGenerator instead.

Wrapping Up

We hope that this article has cleared up some confusions on how File-Model-Column Associations work in Prisma Util and how you can use the utility functions provided by the Schema Creator built-in module to simplify creating these definitions.

Last updated