Skip to content

Commit

Permalink
Merge pull request #69 from CarterGrimmeisen/feat/config-import
Browse files Browse the repository at this point in the history
feat: Attempted alternative to code injection via a global utility file
  • Loading branch information
CarterGrimmeisen authored Jan 13, 2022
2 parents a6f6c49 + b69267b commit 65c70b7
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@types/fs-extra": "^9.0.11",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
"decimal.js": "^10.3.1",
"eslint": "^7.17.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-prettier": "^4.0.0",
Expand Down
22 changes: 19 additions & 3 deletions src/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,25 @@ export const getJSDocs = (docString?: string) => {
return lines
}

export const computeModifiers = (docString: string) => {
return docString
export const getZodDocElements = (docString: string) =>
docString
.split('\n')
.filter((line) => line.trimStart().startsWith('@zod'))
.map((line) => line.trim().split('@zod.').slice(-1)[0])
.flatMap((line) =>
Array.from(line.matchAll(/\.([^().]+\(.*?\))/g), (m) =>
m.slice(1)
).flat()
)

export const computeCustomSchema = (docString: string) => {
return getZodDocElements(docString)
.find((modifier) => modifier.startsWith('custom('))
?.slice(7)
.slice(0, -1)
}

export const computeModifiers = (docString: string) => {
return getZodDocElements(docString).filter(
(each) => !each.startsWith('custom(')
)
}
15 changes: 14 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const configSchema = z.object({
}),
modelSuffix: z.string().default('Model'),
modelCase: z.enum(['PascalCase', 'camelCase']).default('PascalCase'),
imports: z.string().optional(),
})

generatorHandler({
Expand Down Expand Up @@ -51,7 +52,8 @@ generatorHandler({
'Incorrect config provided. Please check the values you provided and try again.'
)

const { relationModel, modelSuffix, modelCase } = parsedConfig.data
const { relationModel, modelSuffix, modelCase, imports } =
parsedConfig.data

const formatModelName = (name: string, prefix = '') => {
if (modelCase === 'camelCase') {
Expand Down Expand Up @@ -140,6 +142,17 @@ generatorHandler({
})
}

if (imports) {
sourceFile.addImportDeclaration({
kind: StructureKind.ImportDeclaration,
moduleSpecifier: path.relative(
outputPath,
path.resolve(path.dirname(options.schemaPath), imports)
),
namespaceImport: 'imports',
})
}

sourceFile.addStatements((writer) =>
writeArray(writer, getJSDocs(model.documentation))
)
Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DMMF } from '@prisma/generator-helper'
import { computeModifiers } from './docs'
import { computeCustomSchema, computeModifiers } from './docs'

export const getZodConstructor = (
field: DMMF.Field,
Expand Down Expand Up @@ -48,6 +48,7 @@ export const getZodConstructor = (

if (field.isList) extraModifiers.push('array()')
if (field.documentation) {
zodType = computeCustomSchema(field.documentation) ?? zodType
extraModifiers.push(...computeModifiers(field.documentation))
}
if (!field.isRequired) extraModifiers.push('nullable()')
Expand Down
11 changes: 8 additions & 3 deletions test/docs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ import { computeModifiers, getJSDocs } from '../src/docs'
describe('docs Package', () => {
test('computeModifiers', () => {
const modifiers = computeModifiers(`
@zod.email()
@zod.email().optional()
@zod.url()
@zod.uuid()
Banana
@example something something
`)

expect(modifiers.length).toBe(3)
expect(modifiers).toStrictEqual(['email()', 'url()', 'uuid()'])
expect(modifiers.length).toBe(4)
expect(modifiers).toStrictEqual([
'email()',
'optional()',
'url()',
'uuid()',
])
})

test('getJSDocs', () => {
Expand Down
12 changes: 12 additions & 0 deletions test/functional/config-import/expected/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as z from "zod"
import * as imports from "../prisma/zod-utils"

export const DocumentModel = z.object({
id: z.string(),
filename: z.string(),
author: z.string(),
contents: z.string(),
size: imports.decimalSchema,
created: z.date(),
updated: z.date(),
})
1 change: 1 addition & 0 deletions test/functional/config-import/expected/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./document";
26 changes: 26 additions & 0 deletions test/functional/config-import/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

generator client {
provider = "prisma-client-js"
output = ".client"
}

generator zod {
provider = "../../../bin/cli.js"
output = "../actual/"
imports = "./zod-utils"
}

model Document {
id String @id @default(cuid())
filename String @unique
author String
contents String
size Decimal /// @zod.custom(imports.decimalSchema)
created DateTime @default(now())
updated DateTime @default(now())
}
6 changes: 6 additions & 0 deletions test/functional/config-import/prisma/zod-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { z } from 'zod'
import { Decimal } from 'decimal.js'

export const decimalSchema = z
.union([z.string(), z.number()])
.transform((value) => new Decimal(value))
1 change: 1 addition & 0 deletions test/functional/driver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ describe('Functional Tests', () => {
test.concurrent('relationModel = false', ftForDir('relation-false'))
test.concurrent('Imports', ftForDir('imports'))
test.concurrent('JSON', ftForDir('json'))
test.concurrent('Config Import', ftForDir('config-import'))
})
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2370,6 +2370,11 @@ decamelize@^1.2.0:
resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=

decimal.js@^10.3.1:
version "10.3.1"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==

decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz"
Expand Down

0 comments on commit 65c70b7

Please sign in to comment.