Coder Social home page Coder Social logo

andreww2012 / mongoose-zod Goto Github PK

View Code? Open in Web Editor NEW
44.0 44.0 7.0 1.67 MB

A library which allows to author mongoose ("a MongoDB object modeling tool") schemas using zod ("a TypeScript-first schema declaration and validation library").

License: MIT License

JavaScript 16.11% TypeScript 83.89%
mongodb mongoose zod

mongoose-zod's People

Contributors

andreww2012 avatar harm-nullix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

mongoose-zod's Issues

Is Mongoose 7 supported?

Hi

I'm new to Mongoose and thought I try to use mongoose-zod, as it looks pretty nice :D

However, npm is reporting only version 6 of Mongoose is supported. Is this correct / will it break if I use Mongoose 7 instead?
Is it a problem to use Mongoose 6? I like to have the newest versions if possible ๐Ÿ˜…

Type Inference not working correctly for static methods, virtuals etc.

I am trying your library and I get TypeScript errors in everything related to mongoose model extension (like statics, virtuals).

  1. Static methods do not show up in Model
  2. Instance methods can not be defined (compiler complains that only those properties already defined are allowed)
  3. Virtuals do not show up in model, neither is this bound correctly

I thought it was because I am using TS 5 in my project. So I checked out your repo and installed all dependencies. Still the same. Basically the type inference does not work correctly.

CleanShot 2023-09-21 at 19 31 43@2x

Types not working

I tried the basic example but types are not recognized.
Using Node 18
mongoose-zod: 0.1.1
mongoose: 6.6.5
zod 3.22.4

export const zodSchema = z
  .object({
    tenantId: z.string(), // make unique
    name: z.string(),
  })
  .mongoose({
    schemaOptions: {
      collection: 'MyModel',
    },
    typeOptions: {
      tenantId: { unique: true },
    },
  })

export const MyModel = mongoose.model('MyModel', toMongooseSchema(zodSchema))
const myModel = new MyModel({ ten })

I would expect auto complete support on the last line, it should complete the ten with tenant, right?

Btw, with skipLibCheck: false I get some errors:

node_modules/zod/lib/types.d.ts:490:22 - error TS2428: All declarations of 'ZodObject' must have identical type parameters.

490 export declare class ZodObject<T extends ZodRawShape, UnknownKeys extends UnknownKeysParam = UnknownKeysParam, Catchall extends ZodTypeAny = ZodTypeAny, Output = objectOutputType<T, Catchall, UnknownKeys>, Input = objectInputType<T, Catchall, UnknownKeys>> extends ZodType<Output, ZodObjectDef<T, UnknownKeys, Catchall>, Input> {
                         ~~~~~~~~~

node_modules/mongoose-zod/dist/index.d.ts:1:8 - error TS1192: Module '"/Users/didierhartong/Projects/Stedin/lsis-functions/node_modules/zod/index"' has no default export.

1 import z$1, { z, ZodObject, ZodTypeAny } from 'zod';
         ~~~

  node_modules/zod/index.d.ts:1:1
    1 export * from "./lib";
      ~~~~~~~~~~~~~~~~~~~~~~
    'export *' does not re-export a default.

node_modules/mongoose-zod/dist/index.d.ts:34:15 - error TS2428: All declarations of 'ZodObject' must have identical type parameters.

But when I set skipLibCheck: true those errors are gone, but this may be related to the issue?

Code TS error on node 18

I want to thank you for this great work; I ran into trouble using this code.

I used ts-node-dev and tried configuring my tsconfig and adding ESM support - output failed.

ts-node-dev --loader ts-node/esm --no-warnings --inspect=0.0.0.0:9229 --project ./tsconfig.json --respawn --rs false --exit-child --watch ./src -- ./src/index.ts

my tsconfig

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig to read more about this file */
    /* Language and Environment */
    "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    "paths": {
      "@/package/*": [
        "./../*"
      ], /* alias for vscode, see {@link} packages/api/src/aliases.ts for alias ts-node */
      "@/lib/*": [
        "./../../lib/*"
      ], /* alias for vscode, see {@link} packages/api/src/aliases.ts for alias ts-node */
    },
    /* Modules */
    "module": "Node16", /* Specify what module code is generated. */
    "typeRoots": [
      "./node_modules/@types",
      "./@types"
    ], /* Specify multiple folders that act like './node_modules/@types'. */
    "types": [
      "node",
      "express"
    ], /* Specify type package names to be included without being referenced in a source file. */
    "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
    /* Type Checking */
    "strict": true, /* Enable all strict type-checking options. */
    "skipLibCheck": true, /* Skip type checking all .d.ts files. */
    "jsx": "react" /* allow to use other packages tsx|jsx */
  }
}

My environment doesn't like `import.meta'

// const mlvPlugin = tryImportModule('mongoose-lean-virtuals', import.meta);
// const mldPlugin = tryImportModule('mongoose-lean-defaults', import.meta);
// const mlgPlugin = tryImportModule('mongoose-lean-getters', import.meta);

import mlvPlugin from 'mongoose-lean-virtuals';
import mldPlugin from 'mongoose-lean-defaults';
import mlgPlugin from 'mongoose-lean-getters';

Changing the code in to-monggose, and not sure what it does by disabling it

Using mongoose-zod with superforms

I'm working with superforms and mongoose. When I use the config in the readme I see the error: Error: Only Zod schema objects can be used with superValidate. Define the schema with z.object({ ... }) and optionally refine/superRefine/transform at the end.

Any idea on how to get these 2 to play nicely together?

Strange issue using "z" namespace from mongoose-zod package

image
image

I get this strange issue when using z namespace from [email protected] package.
If I use it from [email protected] package (which is a peer dep of mongoose-zod), it's all good!

This was driving me nuts for 1 day.
I was just using a Zod schema as I normally do in a Vue (Nuxt) component to use the parse method to validate the forms.

This is my schema:

import { z as zod } from 'zod'

export const authenticateZodSchema = zod.object({
  email: zod.string().min(1).email(),
  password: zod.string().min(6)
})


export const registerZodSchema = zod.object({
  email: zod.string().min(1).email(),
  password: zod.string().min(6),
  username: zod.string().min(6),
  lastname: zod.string().optional(),
  firstname: zod.string().min(1)

})

Vue component:

<script lang="ts" setup>
import { AuthenticateData } from '~/shared/auth/auth.type'
import { authenticateZodSchema } from '~/shared/auth/auth.zod'
import { ref } from 'vue'
import { useValidation } from '~/utils/validation/use-validation'

const authenticateForm = ref<AuthenticateData>({
  email: '',
  password: ''
})

const validations = useValidation(authenticateZodSchema)
</script>

<template>
  <div class="column q-pa-md">
   <pre>{{validations.email.name}}</pre>
    <span class="text-h6">Authenticate</span>
    <q-form class="q-gutter-md q-mt-md column q-gutter-y-sm">
      <q-input
        filled
        type="email"
        label="Email"
        lazy-rules
        :rules="[]"
        v-model="authenticateForm.email"
      />
      <q-input
        filled
        type="password"
        label="Password"
        lazy-rules
        :rules="[]"
        v-model="authenticateForm.password"
      />
    </q-form>
  </div>
</template>

<style scoped>

</style>

I did a lot of steps based on the assumption it was a mongoose issue, installing mongoose explicitly, reinstalling all deps, deleting .nuxt to generate the types and Vue components from scratch, sigh...

Until I realized the error is only present when using the z namespace from mongoose-zod.

Any info will be appreciated.

[question] Swagger (OpenAPI)

Hello!

Anyone knows how to create the Swagger api descriptions from the zod schema (or from the mongoose schema)?

Any info will be appreciated.

[question] Missing pick, extend, and omit

Hello!

In a normal z.object, we can use .pick, .extend, and .omit. I usually use const LoginSchema = UserSchema.pick({email: true, password: true}) and const RegisterSchema = UserSchema.omit({id: true}).

But after using z from mongoose-zod, I can't do that anymore.

Any info will be appreciated.

Addressing I get the error: `.mongooseTypeOptions/.mongoose is not a function`

The error is caused because the z.ZObject prototype is extended

Because is some cases there can be multiple imports of z it is impossible to tell if the right prototype is extended. It is a bad practice because you have no control over the z object as an user of this library.

It would be useful if the z object of mongoose-zod is exposed or we can pass a zObject by reference instead of extending the prototype

Unable to use unions in any way, causes validation to think field is undefined

Hello There,

I really like this library and as a big user of zod, I was quite happy when I found a type safe way to deal with mongoose, so thank you for making it.

That being said, I have ran into a problem which I can not for the life of me figure out how to get around, that is if I try to use unions for my return objects the validation seems to think the field is empty.

initial schema

export const IssueSchema = z.object({
  id: IdentifierSchema,
  title: z.string(),
  type: z.nativeEnum(IssueType),
  content: z.string(),
  user: z.string(),
  metadata: MediaProviderUnionSchema,
});
export type Issue = z.infer<typeof IssueSchema>;

This schema is acts like a base schema, that is later extended by my DTO schema that is returned from the database, you'll notice that this schema has user set to just a string (this represents the reference from the db).

export const IssueDTOSchema = IssueSchema.extend({
  user: z.union([UserSchema, z.string()]),
});
export type IssueDTO = z.infer<typeof IssueDTOSchema>;

//
export const IssueDTOMongoSchema = IssueDTOSchema
  .mongoose({
    schemaOptions: {
      collection: 'issues',
      virtuals: {
        user: {
          options: {
            ref: 'user',
            localField: 'user',
            foreignField: 'id',
          }
        }
      }
    },
    typeOptions: {
      user: {
        ref: 'user',
      }
    }
  });
export type IssueDTOMongo = z.infer<typeof IssueDTOMongoSchema>;

The reason for extending was to get around the circular dependency issue, which I solved in this way by just extending it and overriding the initial field with a union, so the user schema can be be returned if it's populate method is used when pulling the data from the database, else it will just return the string as it would normally.

The problem is that no matter the combination, the validation errors out thinking the user field is undefined? Not sure if I have missed something in the documentation, or something long those lines.

  {
    "code": "invalid_union",
    "unionErrors": [
      {
        "issues": [
          {
            "code": "invalid_type",
            "expected": "object",
            "received": "undefined",
            "path": [
              "user"
            ],
            "message": "Required"
          }
        ],
        "name": "ZodError"
      },
      {
        "issues": [
          {
            "code": "invalid_type",
            "expected": "string",
            "received": "undefined",
            "path": [
              "user"
            ],
            "message": "Required"
          }
        ],
        "name": "ZodError"
      }
    ],
    "path": [
      "user"
    ],
    "message": "Invalid input"
  }
]

Here is also the seed data I am using to test with.

const IssueData: Issue[] = [
  {
    id: "8I6u5mg53wd0YXEHtCewb",
    title: "Problem with playing content",
    type: IssueType.BadVideo,
    content: "I am unable to play movie",
    user: 'H9ITrq4x2GQ2E_-XKUlIM',
    metadata: {
      tmdbId: 615656,
    }
  }
];

Any help with this is appreciated. Thanks.

SchemaTypes.Boolean

I have been trying to debug this for a week. Using sveltekit and mongoose 6.6.5 and for some schemas, I am getting this runtime error in the browser

TypeError: Cannot read properties of undefined (reading 'Boolean')
From this line in:

var MongooseZodBoolean = class extends M.SchemaTypes.Boolean {
  constructor() {
    super(...arguments);
    this.cast = noCastFn;
  }
};

I thought perhaps a mismatch dependency, but using the same version libs as mongoose-zod. I can't figure out what is making it through this error only on some schemas.

z.nullable() not respected

It seems that mongoose-zod does not respect the z.nullable() (https://zod.dev/?id=nullables)
When I use this schema:

z.object({
  someParam: z.nullable(z.string()),
})

And create a record like this: await SomeModel.create({someParam: null}) I receive the error: ValidationError: SomeModel validation failed: someParam: Path 'someParam' is required.

Alternatively if I change the definition of someParam to: z.string().nullable().optional() and create the record with the same code I get the following error:

ValidationError: SomeModel validation failed: someParam: [
 {
    "code": "invalid_type",
    "expected": "string",
    "received": "null",
    "path": [],
    "message": "Expected string, received null"
 }
]

I think the culprit is this line of code, but I'm not entirely sure.
https://github.com/andreww2012/mongoose-zod/blob/main/src/to-mongoose.ts#L88

const isRequired = !schemaFeatures.isOptional && !isZodType(zodSchemaFinal, 'ZodNull');

Could you point out if I'm doing something wrong or what is needed to respect the .nullable() option?

TypeScript 2536 error with genTimestampsSchema

Hello,

first of all: Thanks for this great package! I work with mongoose for some years now and started using zod a week ago. I found your package and in general it works pretty well!

I just ran into troubles when trying to transpile an ExpressJS service from TypeScript to JavaScript. The issue is on line 71 of index.d.ts, in the declaration if genTimestampsSchema. I get the following error messages:

- Type 'k_2' cannot be used to index type '{ [_ in StringLiteral<CrAt & {}> | StringLiteral<UpAt & {}>]: ZodDefault<ZodDate>; }'
- Type 'k_1' cannot be used to index type 'addQuestionMarks<{ [_ in StringLiteral<CrAt & {}> | StringLiteral<UpAt & {}>]: ZodDefault<ZodDate>; } extends infer T_1 extends ZodRawShape ? { [k in keyof T_1]: { [_ in StringLiteral<...> | StringLiteral<...>]: ZodDefault<...>; }[k]["_output"]; } : never>'.
- Type 'k' cannot be used to index type '{ [_ in StringLiteral<CrAt & {}> | StringLiteral<UpAt & {}>]: ZodDefault<ZodDate>; }'.
- Type 'k_2_1' cannot be used to index type '{ [_ in StringLiteral<CrAt & {}> | StringLiteral<UpAt & {}>]: ZodDefault<ZodDate>; }'.
- Type 'k_3' cannot be used to index type 'addQuestionMarks<{ [_ in StringLiteral<CrAt & {}> | StringLiteral<UpAt & {}>]: ZodDefault<ZodDate>; } extends infer T_4 extends ZodRawShape ? { [k_2 in keyof T_4]: { [_ in StringLiteral<...> | StringLiteral<...>]: ZodDefault<...>; }[k_2]["_input"]; } : never>'.
- Type 'k_2' cannot be used to index type '{ [_ in StringLiteral<CrAt & {}> | StringLiteral<UpAt & {}>]: ZodDefault<ZodDate>; }'.

Did this issue occur to you? Do you know what could be the problem? I sticked to the exact dependicies as stated in your package.json. This is how my package.json looks:

{
  "scripts": {
    "build:tsc": "npm-run-all tsc",
    "build:post": "cp package*.json dist && cp .npmrc dist 2>/dev/null || : && cd dist && npm ci --production",
    "build": "npm-run-all build:tsc build:post",
  },
  "dependencies": {
    "dotenv": "^16.0.0",
    "express": "^4.18.1",
    "mongoose-zod": "^0.1.1",
    "pool-ts-node": "^2.9.0",
    "pool-ts-utils": "^1.37.0",
    "zod": "3.19"
  },
  "devDependencies": {
    "@types/chai": "^4.3.1",
    "@types/cors": "^2.8.12",
    "@types/express": "^4.17.13",
    "@types/mocha": "^9.1.1",
    "@types/node": "^16.18.28",
    "@typescript-eslint/eslint-plugin": "^5.24.0",
    "@typescript-eslint/parser": "^5.24.0",
    "chai": "^4.3.6",
    "chai-http": "^4.3.0",
    "cors": "^2.8.5",
    "eslint": "^8.15.0",
    "mocha": "^10.0.0",
    "npm-run-all": "^4.1.5",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4"
  }
}

When I comment line 71 out (and don't use genTimestamsSchema), everything compiles fine. This of course should only be a temporary workaround.

I hope you have some ideas and thank you in advance!

All the best!
Jonathan

refs?

A question: how do you define refs (https://mongoosejs.com/docs/populate.html) with mongoose-zod? I know I can set the type of the relationship field to mongooseZodCustomType("ObjectId"), but how do I specify the related model?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.