New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ts-mongoose

Package Overview
Dependencies
Maintainers
2
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-mongoose - npm Package Compare versions

Comparing version 0.0.18 to 0.0.19-beta.0

7

createSchema.d.ts
import { SchemaOptions, Schema } from 'mongoose';
import { ConvertObject, TypeWithTimestamps } from './types';
declare type SchemaOpts = SchemaOptions & {
statics?: {
[x: string]: any;
};
};
declare type CreateSchema = <T extends {
[x: string]: any;
}, O extends SchemaOptions>(definition?: T, options?: O extends SchemaOptions ? SchemaOptions : O) => Schema & {
}, O extends SchemaOpts>(definition?: T, options?: O) => Schema & {
definition: ConvertObject<TypeWithTimestamps<O, T>>;

@@ -7,0 +12,0 @@ options: O;

"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var mongoose_1 = require("mongoose");
exports.createSchema = function (definition, options) {
return new mongoose_1.Schema(definition, options);
if (!options)
return new mongoose_1.Schema(definition, options);
var statics = options.statics, opts = __rest(options, ["statics"]);
var schema = new mongoose_1.Schema(definition, opts);
if (statics)
schema.statics = statics;
return schema;
};
import { SchemaOptions, Schema } from 'mongoose';
import { ConvertObject, TypeWithTimestamps } from './types';
declare type SchemaOpts = SchemaOptions & {
statics?: {
[x: string]: any;
};
};
declare type CreateSchema = <T extends {
[x: string]: any;
}, O extends SchemaOptions>(definition?: T, options?: O extends SchemaOptions ? SchemaOptions : O) => Schema & {
}, O extends SchemaOpts>(definition?: T, options?: O) => Schema & {
definition: ConvertObject<TypeWithTimestamps<O, T>>;

@@ -7,0 +12,0 @@ options: O;

@@ -0,4 +1,21 @@

var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { Schema } from 'mongoose';
export var createSchema = function (definition, options) {
return new Schema(definition, options);
if (!options)
return new Schema(definition, options);
var statics = options.statics, opts = __rest(options, ["statics"]);
var schema = new Schema(definition, opts);
if (statics)
schema.statics = statics;
return schema;
};

4

es/typedModel.d.ts
import { Schema, Document, Model } from 'mongoose';
import { Extract } from './types';
export declare function typedModel<T extends Schema>(name: string, schema?: T, collection?: string, skipInit?: boolean): Model<Document & Extract<T>>;
import { Extract, ExtractStatics } from './types';
export declare function typedModel<T extends Schema>(name: string, schema?: T, collection?: string, skipInit?: boolean): ExtractStatics<T, Model<Document & Extract<T>>, Document & Extract<T>>;

@@ -82,2 +82,13 @@ import { Types, Document } from 'mongoose';

export declare type TypeWithTimestamps<Opts, T> = Opts extends (TimestampsPresent | TimestampsEachPresent) ? T & CreatedAtType & UpdatedAtType : Opts extends TimestampCreatedByPresent ? T & CreatedAtType : Opts extends TimestampUpdatedByPresent ? T & UpdatedAtType : T;
export declare type ModelInstanceType = 'ModelInstanceType';
export declare type ModelInstancesType = 'ModelInstancesType';
declare type ArgumentTypes<T> = T extends (...args: infer U) => infer R ? U : never;
declare type ReplaceReturnType<T, TNewReturn> = (...a: ArgumentTypes<T>) => TNewReturn;
export declare type ExtractStatics<T, Rest, I> = T extends {
options: infer O;
} ? O extends {
statics: infer S;
} ? {
[P in keyof S]: S[P] extends (...args: any) => any ? ReturnType<S[P]> extends ModelInstanceType ? ReplaceReturnType<S[P], Promise<null | I>> : ReturnType<S[P]> extends ModelInstancesType ? ReplaceReturnType<S[P], Promise<I[]>> : S[P] : S[P];
} & Rest : Rest : Rest;
export {};
{
"name": "ts-mongoose",
"version": "0.0.18",
"version": "0.0.19-beta.0",
"description": "",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -15,7 +15,8 @@ # ts-mongoose

## The Problem
When using mongoose and Typescript, you must define schemas and interfaces. Both definitions must be maintained separately and must match each other. It can be error-prone during development and cause overhead.
When using mongoose and Typescript, you must define schemas and interfaces. Both definitions must be maintained separately and must match each other. It can be error-prone during development and cause overhead.
`ts-mongoose` is a very lightweight library that allows you to create a mongoose schema and a typescript type from a common definition.
All types as created from 1-liner functions and does not depend on decorators❗️.
For example:

@@ -31,51 +32,57 @@ `Type.string()` returns `{type: String, required: true}`, which is the same definition required in the original mongoose library.

const AddressSchema = new Schema({
city: { type: String, required: true },
country: String,
zip: String,
}, { _id: false, timestamps: true });
const AddressSchema = new Schema(
{
city: { type: String, required: true },
country: String,
zip: String,
},
{ _id: false, timestamps: true }
);
const PhoneSchema = new Schema({
phoneNumber: { type: Schema.Types.Number, required: true },
name: String
})
name: String,
});
const UserSchema = new Schema({
title: { type: String, required: true },
author: { type: String, required: true },
body: { type: String, required: true },
comments: [
{
body: { type: String, required: true },
date: { type: Date, required: true },
const UserSchema = new Schema(
{
title: { type: String, required: true },
author: { type: String, required: true },
body: { type: String, required: true },
comments: [
{
body: { type: String, required: true },
date: { type: Date, required: true },
},
],
date: { type: Date, default: Date.now, required: true },
hidden: { type: Boolean, required: true },
meta: {
votes: { type: Schema.Types.Number },
favs: { type: Schema.Types.Number },
},
],
date: { type: Date, default: Date.now, required: true },
hidden: { type: Boolean, required: true },
meta: {
votes: { type: Schema.Types.Number },
favs: { type: Schema.Types.Number },
m: {
type: Schema.Types.Mixed,
required: true,
},
gender: {
type: Schema.Types.String,
required: true,
enum: ['male', 'female'],
},
otherId: {
type: Schema.Types.ObjectId,
required: true,
},
address: {
type: AddressSchema,
required: true,
},
phones: {
type: [PhoneSchema],
required: true,
},
},
m: {
type: Schema.Types.Mixed,
required: true,
},
gender: {
type: Schema.Types.String,
required: true,
enum: ['male', 'female']
},
otherId: {
type: Schema.Types.ObjectId,
required: true,
},
address: {
type: AddressSchema,
required: true,
},
phones: {
type: [PhoneSchema],
required: true,
},
}, { timestamps: { createdAt: true } });
{ timestamps: { createdAt: true } }
);

@@ -90,3 +97,2 @@ interface UserProps extends Document {

const User: Model<UserProps> = model('User', UserSchema);
```

@@ -141,5 +147,6 @@

### API
### API
- Each type has two forms: required and optional
```ts

@@ -153,10 +160,14 @@ {

```
- Each type accepts the same options from mongoose
```ts
{
// same as {type: String, required: true, unique: true, index: true}
email: Type.string({unique: true, index: true})
email: Type.string({ unique: true, index: true });
}
```
- Note that enum values need to be readonly array to be treated as literals by typescript
```ts

@@ -166,31 +177,45 @@ const genders = ['male', 'female'] as const;

// same as {type: String, required: true, enum: ['male', 'female']}
gender: Type.string({enum: genders})
gender: Type.string({ enum: genders });
}
```
- `schema`, `object`, `array` types have a method `of` where you must provide a child type
```ts
{
// same as {type: [String], required: true}
tags: Type.array().of(Type.string())
tags: Type.array().of(Type.string());
}
```
- `schema.of(ExampleSchema)` has typical for Subdocument additional fields and methods. Setting `{ _id: false }` in SchemaOptions won't attach `_id` property in Subdocument
```ts
const AddressSchema = createSchema({city: Type.string()}, { _id: false, timestamps: true });
const AddressSchema = createSchema(
{ city: Type.string() },
{ _id: false, timestamps: true }
);
{
// same as {type: AddressSchema}
address: Type.schema().of(AddressSchema)
address: Type.schema().of(AddressSchema);
}
// address property has city property, other Subdocument methods and properties except '_id'
```
- `array.of(ExampleSchema)` will return DocumentArray instead of standard array
```ts
const PhoneSchema = createSchema({phoneNumber: Type.number()}, { _id: false });
const PhoneSchema = createSchema(
{ phoneNumber: Type.number() },
{ _id: false }
);
{
// same as {type: [PhoneSchema]}
phones: Type.schema().of(PhoneSchema)
phones: Type.schema().of(PhoneSchema);
}
// phones property has such methods as create(), id(), but also those typical for arrays like map(), filter() etc
```
- `ref` is a special type for creating references
```ts

@@ -204,11 +229,12 @@ {

```
- `populateTs(property: string)` use this function to populate a property and adjust the returned type automatically. Under the hood it calls only the native `populate` method.
Method will be available if you import a special plugin.
Method will be available if you import a special plugin.
```ts
// models.ts
import 'ts-mongoose/plugin'
import 'ts-mongoose/plugin';
User.find().populateTs('comments');
```

@@ -223,3 +249,9 @@

```ts
import { createSchema, Type, typedModel, ExtractDoc, ExtractProps } from 'ts-mongoose';
import {
createSchema,
Type,
typedModel,
ExtractDoc,
ExtractProps,
} from 'ts-mongoose';

@@ -236,5 +268,4 @@ export const UserSchema = createSchema({

// example function
// example function
async function blockUser(user: UserDoc) {

@@ -252,16 +283,15 @@ user.isBlocked = true;

username: 'user1',
}
};
}
```
## Refs
Refs and populations are supported.
Check code under `example/example4.ts`.
Check code under `example/example4.ts`.
![alt autocomplete](.github/refs.gif)
### Custom Field
### Custom Field
If you need to specify custom fields in the model, you can add a fake annotation.

@@ -281,11 +311,39 @@ It's only required if you add virtual fields or custom methods to the model.

```
Autocomplete popup:
![alt autocomplete](.github/custom.png)
### Static methods
If you need to have static custom methods on Model you can pass them in `statics` property, which is part of schema options. For functions returning instance/s of Model, use `ModelInstanceType` / `ModelInstancesType` interfaces as returning value.
```ts
const UserSchema = createSchema(
{
name: Type.string(),
age: Type.number(),
},
{
statics: {
findByName: function(name: string): ModelInstancesType {
return this.find({ name: name });
},
findOneByName: function(name: string): ModelInstanceType {
return this.findOne({ name: name });
},
countLetters: function(name: string, bonus?: number): number {
return name.length + (bonus ? bonus : 0);
},
},
}
);
const User = typedModel('User', UserSchema);
User.countLetters('a');
```
### TODO
- support types: Decimal128, Map
MIT
MIT
import { Schema, Document, Model } from 'mongoose';
import { Extract } from './types';
export declare function typedModel<T extends Schema>(name: string, schema?: T, collection?: string, skipInit?: boolean): Model<Document & Extract<T>>;
import { Extract, ExtractStatics } from './types';
export declare function typedModel<T extends Schema>(name: string, schema?: T, collection?: string, skipInit?: boolean): ExtractStatics<T, Model<Document & Extract<T>>, Document & Extract<T>>;

@@ -82,2 +82,13 @@ import { Types, Document } from 'mongoose';

export declare type TypeWithTimestamps<Opts, T> = Opts extends (TimestampsPresent | TimestampsEachPresent) ? T & CreatedAtType & UpdatedAtType : Opts extends TimestampCreatedByPresent ? T & CreatedAtType : Opts extends TimestampUpdatedByPresent ? T & UpdatedAtType : T;
export declare type ModelInstanceType = 'ModelInstanceType';
export declare type ModelInstancesType = 'ModelInstancesType';
declare type ArgumentTypes<T> = T extends (...args: infer U) => infer R ? U : never;
declare type ReplaceReturnType<T, TNewReturn> = (...a: ArgumentTypes<T>) => TNewReturn;
export declare type ExtractStatics<T, Rest, I> = T extends {
options: infer O;
} ? O extends {
statics: infer S;
} ? {
[P in keyof S]: S[P] extends (...args: any) => any ? ReturnType<S[P]> extends ModelInstanceType ? ReplaceReturnType<S[P], Promise<null | I>> : ReturnType<S[P]> extends ModelInstancesType ? ReplaceReturnType<S[P], Promise<I[]>> : S[P] : S[P];
} & Rest : Rest : Rest;
export {};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc