Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced Introspection - Accepted Proposal #7

Closed
DavidHancu opened this issue Nov 30, 2022 · 1 comment
Closed

Enhanced Introspection - Accepted Proposal #7

DavidHancu opened this issue Nov 30, 2022 · 1 comment

Comments

@DavidHancu
Copy link
Owner

Scope

The aim of this proposal is to provide a sneak-peek for the new feature that will be added to Prisma Util v2.0. In this issue, I'll be outlining the process of how you can use the new Enhanced Introspection features to manipulate your schema.

Introduction

This feature will be released under the enhancedIntrospection flag and will require manual activation. Because this feature uses Project Toolchain's Generation API, it will create the typings necessary for configuring the fields of this object. All Enhanced Introspection steps will be ran before the schema is generated, to allow you to modify the models before they are written to the final file.

Configuration

To configure the Enhanced Introspection feature, you're going to have to add an introspection property to your configuration object like this:

export default {
    // Other configuration options
    introspection: {
        modelPatterns: {
            // We'll come back to this option later on.
        }
    }
}

We've created a separate introspection object to facilitate a fieldPatterns option coming in the future.

Model Patterns

Model Patterns are used for defining rules that models should follow. To offer more granular control for your schema, we've implemented the following class that will be passed to your functions:

abstract class Model {
    /**
     * The name of this model. If this parameter hasn't been modified before, it will be the table name from the database.
     */
    public abstract get name();
    /**
     * Set the name for this model.
     */
    public abstract set name(name: string);
    /**
     * Add an attribute to this model.
     * @param attribute The attribute to add. You can use the `schema-creator` module for a list of attributes.
     */
    public abstract addAttribute(attribute: string);
}

The rules for Model Patterns are split into 3 categories:

  • Static Changes

Static changes edit models based on their name and are placed under the $static key. These can be configured in 2 ways:

  1. Using a String

Using a String is the easiest way to remap a table. To do it, add the following object to your introspection block:

export default {
    // Other configuration options
    introspection: {
        modelPatterns: {
            $static: {
                "table_name": "ModelName"
            }
        }
    }
}

In this example, ModelName will map to table_name.

  1. Using a Function

Using a function allows more granular control for this table. To do it, add the following object to your introspection block:

import { Constraints } from "prisma-util/schema-creator";

export default {
    // Other configuration options
    introspection: {
        modelPatterns: {
            $static: {
                "table_name": async (model: Model) => {
                    model.name = "ModelName";
                    model.addAttribute(Constraints.Model.UNIQUE(["name", "email"]));
                    return model;
                }
            }
        }
    }
}

In this example, ModelName will map to table_name and will add the @@unique([name, email]) attribute to the model.

  • Regex Changes

Regex changes use regexes to match model names. These regexes are ran with the gims flags and are placed under the $regex key. To configure a regex replacer, add a function like this:

export default {
    // Other configuration options
    introspection: {
        modelPatterns: {
            $regex: {
                "model_name(\\d)": async (model: Model, match: string, ...groups: string[]) => {
                    model.name = `ModelName${groups[1]}`;
                    return model;
                }
            }
        }
    }
}

One regex replacer can be called for multiple tables and will pass the correct model as a parameter. In this example, all tables that match the regex will have the underscore removed and will be changed to PascalCase.

  • Catch-all Changes

Catch-all replacers will be ran for all models. To configure a catch-all replacer, add a function like this:

export default {
    // Other configuration options
    introspection: {
        modelPatterns: {
            $all: async (model: Model) => {
                model.name = model.name.replace(/_/gims, "");
                return model;
            }
        }
    }
}

In this example, all tables will have the underscore removed.

Handling Conflicts

Because the Enhanced Introspection step is ran before the Conflict Manager has a chance to run, all models that will trigger a naming conflict will be flagged and the normal rename/skip dialog will be shown.

Prioritizing Changes

Replacers will be ran from the first key to the last key. A table can trigger multiple replacers, if the latter ones match the new name set by the previous replacers. You can use this to your advantage: by reordering the $static, $regex and $all keys you can create a powerful workflow that fits your use-case. One example of such workflow would be leaving the $all key as the last property of the object to enforce default naming conventions on all models.

@DavidHancu
Copy link
Owner Author

Feature implemented.

@DavidHancu DavidHancu changed the title [Proposal [v2.0.0] Enhanced Introspection Enhanced Introspection - Accepted Proposal Dec 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant