Skip to content

Commit aeb4c8a

Browse files
authored
Merge pull request #13 from ShtibsDev:version-1-0-0
Version-1-0-0
2 parents 6e5e0fe + bc4e467 commit aeb4c8a

File tree

6 files changed

+114
-76
lines changed

6 files changed

+114
-76
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"cSpell.words": ["datamodel", "Ofir", "Stiber", "Voronzov"]
2+
"cSpell.words": ["datamodel", "dmmf", "Ofir", "Stiber", "Voronzov"]
33
}

README.md

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
This package will generate enum validation methods from your `schema.prisma` file.
44

5+
1. [Installation](#installation)
6+
2. [Usage](#usage)
7+
3. [Configuration](#configuration)
8+
1. [Using With Javascript](#using-with-javascript)
9+
510
## Installation
611

712
```bash
@@ -25,7 +30,8 @@ npx prisma generate
2530
The following enum:
2631

2732
```prisma
28-
enum Colors {RED
33+
enum Colors {
34+
RED
2935
BLUE
3036
GREEN
3137
}
@@ -44,3 +50,67 @@ export function isColors(value: string | null | undefined): value is Colors {
4450
return Object.values(Colors).includes(value as Colors);
4551
}
4652
```
53+
54+
## Usage
55+
56+
To use the validation functions you simply import the one you need from the generated file.
57+
The functions are [type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates), which means that their return value is `boolean` but they also modify the type of the the argument that you pass.
58+
59+
```typescript
60+
import { isColors } from '../prisma/enum-validators';
61+
62+
function someFunction(str: string | null) {
63+
if (isColors(str)) {
64+
// str: Colors
65+
}
66+
67+
// str: string | null
68+
}
69+
```
70+
71+
## Configuration
72+
73+
The generator provides the following configurations:
74+
75+
```prisma
76+
generator erd {
77+
provider = "prisma-enum-validator-generator"
78+
output = string //Specifies where the validators file will be generated. Defaults to 'enum-validators.ts'.
79+
isTs = boolean //Specifies whether the output is targeted for typescript or javascript. Defaults to true.
80+
}
81+
```
82+
83+
### Using with Javascript
84+
85+
The generator also supports outputting to javascript format.
86+
By setting `isTs` to `false`, all typescript exclusive syntax will be removed, allowing you to use the validation functions in your javascript project.
87+
88+
Typescript output:
89+
90+
```typescript
91+
/**
92+
* A function to validate if a string is of type {@link Colors}.
93+
* @param {string | null | undefined} value The value to test.
94+
* @returns {boolean} `true` if {@link value} is of type {@link Colors}. Otherwise `false`.
95+
*/
96+
export function isColors(value: string | null | undefined): value is Colors {
97+
if (!value) return false;
98+
return Object.values(Colors).includes(value as Colors);
99+
}
100+
```
101+
102+
Javascript output:
103+
104+
```javascript
105+
/**
106+
* A function to validate if a string is of type {@link Colors}.
107+
* @param {string | null | undefined} value The value to test.
108+
* @returns {boolean} `true` if {@link value} is of type {@link Colors}. Otherwise `false`.
109+
*/
110+
export function isColors(value) {
111+
if (!value) return false;
112+
return Object.values(Colors).includes(value);
113+
}
114+
```
115+
116+
\*\* Note that setting `isTs` to `false`, will change any output filename extension to `.js`

package-lock.json

Lines changed: 21 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
"test": "test"
1515
},
1616
"keywords": [
17-
"Enums",
17+
"Enum",
1818
"Typescript",
19-
"Prisma"
19+
"Prisma",
20+
"Generator"
2021
],
2122
"author": "Ofir Stiber Voronzov",
2223
"repository": {
@@ -25,12 +26,12 @@
2526
},
2627
"license": "MIT",
2728
"devDependencies": {
28-
"prisma": "^4.15.0",
29+
"prisma": "^4.16.2",
2930
"typescript": "^5.1.6"
3031
},
3132
"dependencies": {
32-
"@prisma/client": "^4.15.0",
33+
"@prisma/client": "^4.16.2",
3334
"@prisma/generator-helper": "^4.16.2",
3435
"dotenv": "^16.3.1"
3536
}
36-
}
37+
}

prisma/schema.prisma

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ enum Numbers {
1919
TWO
2020
}
2121

22-
enum Colors {RED
22+
enum Colors {
23+
RED
2324
BLUE
2425
GREEN
2526
}

src/generate.ts

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,15 @@
1-
import { GeneratorOptions } from '@prisma/generator-helper';
2-
import path from 'path';
1+
import { DMMF, GeneratorOptions } from '@prisma/generator-helper';
32
import fs from 'fs';
4-
import * as child_process from 'child_process';
5-
import os from 'os';
63

7-
type SchemaEnum = {
8-
name: string;
9-
values: string[];
10-
};
11-
12-
const enumRegex = /enum [\s\S]*?\}/g;
13-
const modelRegex = /model [\s\S]*?\}/g;
14-
const curlyBracesRegex = /\{([^{}]+)\}/g;
15-
16-
function parseEnums(dataModel: string) {
17-
const enumStrings = dataModel.match(enumRegex);
18-
const modelStrings = dataModel.match(modelRegex);
19-
20-
const enums: string[] =
21-
enumStrings?.map((enumString) => {
22-
const name = enumString.split(' ')[1];
23-
24-
// const valueString = enumString.substring(enumString.indexOf('{')).replace('{', '').replace('}', '').trim();
25-
// const values = valueString.split(/\s/).filter(Boolean);
26-
27-
return name;
28-
}) ?? [];
4+
function extractEnums(dataModel: DMMF.Datamodel): string[] {
5+
const enums = dataModel.enums.map((e) => e.name);
296

30-
const enumUsage: any = {};
7+
const enumUsage: Record<string, number> = {};
318
enums.forEach((e) => (enumUsage[e] = 0));
329

33-
const ignoreTokens = ['@@', '//'];
34-
35-
for (const modelString of modelStrings ?? []) {
36-
const fieldsString = modelString.substring(modelString.indexOf('{')).replace('{', '').replace('}', '').trim();
37-
const fields = fieldsString
38-
.split('\n')
39-
.map((f) => f.trim())
40-
.filter((f) => f && !ignoreTokens.some((it) => f.startsWith(it)));
41-
for (const field of fields) {
42-
const tokens = field.split(/\s/).filter(Boolean);
43-
44-
const fieldType = tokens[1] ?? null;
45-
46-
if (!fieldType) continue;
47-
48-
if (enums.includes(fieldType)) {
49-
enumUsage[fieldType]++;
50-
}
10+
for (const model of dataModel.models) {
11+
for (const field of model.fields) {
12+
if (enums.includes(field.type)) enumUsage[field.type]++;
5113
}
5214
}
5315

@@ -84,9 +46,13 @@ export default async (options: GeneratorOptions) => {
8446

8547
const isTs = !!config.useTs ? config.useTs === 'true' : true;
8648

87-
const output = options.generator.output?.value || `./prisma/enum-validators.${isTs ? 'ts' : 'js'}`;
88-
const enums = parseEnums(options.datamodel);
49+
let output = options.generator.output?.value || `./prisma/enum-validators.${isTs ? 'ts' : 'js'}`;
50+
51+
if (!isTs && !output.endsWith('.js')) {
52+
output = `${output.substring(0, output.lastIndexOf('.'))}.js`;
53+
}
8954

55+
const enums = extractEnums(options.dmmf.datamodel);
9056
const fileContent = generateFileContent(enums, isTs);
9157

9258
fs.writeFileSync(output, fileContent);

0 commit comments

Comments
 (0)