Code Monkey home page Code Monkey logo

crud's Introduction

Nestjsx Logo

A set of opinionated NestJS extensions and modules

Travis Coverage Status

Packages

  • @nestjsx/common - A set of NestJs decorators, interfaces and configuration for application modules bootstraping.

Tests

npm run test

crud's People

Contributors

0xflotus avatar asheliahut avatar bashleigh avatar bestori avatar davarga avatar debagger avatar diluka avatar duongleh avatar eugenio165 avatar frco9 avatar fwoelffel avatar greenkeeper[bot] avatar jdguzman avatar jdolieslager avatar joennlae avatar kamilmysliwiec avatar kereslas avatar klalex avatar michaelyali avatar renovate-bot avatar rjpkuyper avatar robotscribe avatar roland-chernov avatar samisammour avatar saulotoledo avatar splaktar avatar steeu avatar tbrannam avatar tomchinery avatar xtcry 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

crud's Issues

Mock RepositoryService Test

Hello,

Is it possible to mock my services with RepositoryService extended ?
Exemple I have a service and I want to test my customMethod

user.service.ts

@Injectable()
export class UsersService extends RepositoryService<User> {
  constructor(
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>,
  ) {
    super(usersRepository);
  }

  public findByCognitoId(cognitoId: string): Observable<User> {
    return from(
      this.usersRepository.findOneOrFail({ cognitoId: cognitoId }),
    );
  }
  
  public customMethod() {
    return null;
  }
}

user.service.spec.ts:

describe('UsersService', () => {
  let service: UsersService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UsersService,
        { provide: getRepositoryToken(User), useClass: Repository },
      ],
    }).compile();
    service = module.get<UsersService>(UsersService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

But I get an error : TypeError: Cannot read property 'columns' of undefined

thanks

Support Gateway just like Controller.

Please provide support for the gateways in same way controller works in this package with an option like enableControllers(default true), enableGateways(default false).

For example, we would emit 'heroes' and it would return the array of heroes and 'heroes::heroId' would return hero with the specified id.

This would allow accessing rest over WebSockets. If possible allow its usage with WsAdapter instead of socket.io for performance.

Mongoose

I started implementing the mongoose.

UpdateOne Override creates a record instead of updating a record

What works ?

Code

@Crud(Role)
@Controller('roles')
export class RolesController implements CrudController<RolesService, Role> {
  constructor(public service: RolesService) {}
}

Test

PATCH /roles/2 Works and returns { id:2, ...updatedFields}

What does not work ?

Code

@Crud(Role)
@Controller('roles')
export class RolesController implements CrudController<RolesService, Role> {
  constructor(public service: RolesService) {}

  get base(): CrudController<RolesService, Role> {
    return this;
  }

  @Override()
  updateOne(@Param('id') id, @Param() params, @Body() dto) {
    return this.base.updateOneBase(id, params, dto);
  }
}

Test

PATCH /roles/2 Does not work and returns { id:20, ...newField}

I think it might be correlated with this issue: #4

[Feature request] Allow to pass side-data param to typeorm

Motivation: #68

TypeORM has an ability to pass data as an additional free-shape param to repository operations, that is available on the query runner instance.

// user sends request during entity save
postRepository.save(post, { data: { request: request } });

// in logger you can access it this way:
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
    const requestUrl = queryRunner && queryRunner.data["request"] ? "(" + queryRunner.data["request"].url + ") " : "";
    console.log(requestUrl + "executing query: " + sql);
}

The example is from the end of:
https://github.com/typeorm/typeorm/blob/master/docs/logging.md#using-custom-logger

If the passed data will be configurable somehow (maybe an async callback that gets request context of something more high-level/) it will be possible to implement #68 with

Adding queries to the .save transaction

TL; DR;
I want to manually add/remove rows from other table in the public async updateOne( of a spesific entity, say, Brands, in the same transaction of the builtin .save operation,
With overriding little of code possible.

General motivation/background:
I have mysql database that the schema is created and managed manually.
I have Many To Many relations there, that i cannot express using TypeORM properly,
As TypeORM junction table is generated internally with a specific and and schema, and configureable.
So i can't teach it to use that table.
So, i've setup a OneToMany <-> ManyToOne relation between each of the entities and my custom Junction table.
(bt_brands <-> bt_brands_to_categories)
(bt_categories <-> bt_brands_to_categories)

Now the problem starts:
When posting new array to brands.categories (lets say empty array)
The generated query is
UPDATE bt_brands_to_categories SET bt_brand_id = null WHERE bt_brand_id = 123
My expectation is that to be a DELETE QUERY.
But ok, i left that (maybe you can help?)
i figured i can just DELETE / UPDATE rows myself, but i want to do it as part of the .save transaction.
And as i must completely override the updateOne operation, and i can't use the super.updateOne for that

Read only end points

It it possible to hide some endpoints from a Crud controller? For example, if I wanted to expose a read only API, could I disable all end points accept for the GET endpoints?

Eager relations

There is no option in the services or controller to specify eager relations? (include eager relations by default without specifying join in the query params?)

Seeing something weird with order of imports

Having a few issues starting with the example code outlined in the base readme.
It seems that when I import Crud before my entity in my controller I get a stack trace

TypeError: typeorm_1.Entity is not a function
    at Object.<anonymous> (\src\app\posts\post.entity.ts:3:2)
import { Crud } from '@nestjsx/crud';
import { Post } from './post.entity';

However, when I import Post entity before Crud it seems to work.
Additionally, when I try to POST { "content": "blah" } it returns with a 500 with stack trace

TypeError: Cannot read property 'createOne' of undefined
    at PostsController.createOneBase (\src\decorators\crud.decorator.ts:207:25)

Code:
Entity:

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Post {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({ length: 500 })
    content: string;
}

Controller

import { Post } from './post.entity';
import { Crud } from '@nestjsx/crud';
import { Controller } from '@nestjs/common';
import { PostsService } from './posts.service';

@Crud(Post)
@Controller('posts')
export class PostsController {
    constructor(private readonly postService: PostsService) {}
}

Am I missing something obvious?
Thanks!

Default id parameter present in the Swagger documentation of every route of a @Crud() controller

Hey,

I recently tried the demo project of nestjsx/crud (nestjsx/crud/integration/typeorm).
I recognized that the swagger documentation contains an additional id parameter for every route - even for "get all" or "create one", where it's not necessary to provide such an id at all.

Here is what I mean:
Bildschirmfoto 2019-04-09 um 12 08 52

In the code, the params attribute is explicitly set to {} (empty).
Is this a bug?

// ...
@Crud(Company, {
  params: {},
  routes: {},
  options: {
    join: {
      users: {
        exclude: ['password'],
      },
    },
    sort: [{ field: 'id', order: 'DESC' }],
    maxLimit: 5,
    cache: 10000,
  },
})
@ApiUseTags('companies')
@Controller('companies')
export class CompaniesController {
// ...

[EDIT]

In helpers.js in function setDefaultCrudOptions() the parameter id: number is used by default:

function setDefaultCrudOptions(crudOptions, target) {
    const check = (obj) => shared_utils_1.isNil(obj) || !shared_utils_1.isObject(obj) || !Object.keys(obj).length;
    if (check(crudOptions.params)) {
        crudOptions.params = { id: 'number' };
    }
    // ...
}

Is this really necessary? Since not every route has an id parameter.

[Help/Need Idea] Basic audit log - log user info with sql query

High level goal:

I want to log all the DB operations with the email of the user that made them. in the same line.

TypeORM can accept a custom logger, but of course, TYPEORM has no concept of request/active user/ what so ever.
I can log the email of the request start. but i have no guarantee that no concurrent sql queries from different request will mix in the log.

filter param generator helper

Is there any ready-made lib that will take query object, in a syntax similar to, say mongo query,
And will give the appropriate filter for it?
Screen Shot 2019-03-29 at 18 22 25
The syntax is very hard to write

validation error format

validation error shall be wrapped into an standard error object with fields name, message and other more rather than an array. In case, clients can decide the kind of the error easily.

[Request] Support for all typeOrm entity events (beforeUpdate etc)

Hi there, I was trying to implement some entity property modification method.
In this case, I was going to use @BeforeInsert and @BeforeUpdate decorators to add functionality to my entity to check if a new password was given, and if so, to hash it.

I have found a workaround by using @OverRide updateOne in controller.
But... I think it would be great if crud would support the entity events entirely.

What do you think about that? Are there plans to support these?

Don't suport MongoDb

I realized by prototyping your solution that it does not support mongodb through TypeOrm.
Would it be too much work for me to implement it on mongodb? What would be your suggestion?

bye and congratulations

Id of entity with UUID type instead of Number not working

When I define my model in TypeORM as:

@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ default: false })
  isActivated: boolean;
}

I can use POST without any problem. However when I use PATCH it is expecting the id to be a numeric string:

{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "Validation failed. Param 'id': numeric string is expected"
}

The body I've sent is:

{
    "id": "6aca65b8-ac87-4db8-a492-f4461655b5fa",
    "isActivated": true
}

forFeature is not working properly

crud/src/crud.module.ts

Lines 5 to 14 in e255120

export class CrudModule {
static forFeature(path: string, service: Function, entity: Function, dto?: any): Type<any> {
@Crud(entity)
@Controller(path)
class CrudGeneratedController {
constructor(@Inject(service) public service) {}
}
return CrudGeneratedController;
}

Only the last generated controller is effect. Previous controllers are ignored.

Swagger Is not working properly.

Swagger is not working properly. Body and query parameter details are not visible in swagger doc. Seems like it's not taking data from the crud controller properly.

image

how to join table?

Here we have class A, B and C

class A{
  a:string;
  b:B;
}
class B{
  b:string;
  c:C;
}
class C{
  c:string
}

I want to query A, but join B and C. I want a result like...

[
    {
        "a": "a1",
        "b": {
            "b": "b1",
            "c": {
                "c": "c1"
            }
        }
    },
    {
        "a": "a2",
        "b": {
            "b": "b2",
            "c": {
                "c": "c2"
            }
        }
    }
]

but I can only join table with 1 level, missing all the c in b

[Proposal] DeepPartial in createOne method's data param

As of now, createOne method in RepositoryService requires a data param to match EntityType. What I propose is using DeepPartial<EntityType> instead.

Current createOne:
createOne(data: EntityType, params: ...)

Using DeepPartial:
createOne(data: DeepPartial<EntityType>, params: ...)

Reasoning:

  1. Would allow a service class to be used by a different controller without any errors regarding required columns which would be auto-generated by the Entity class.
    Eg: AuthController using UsersService to create a new user. Now UsersService relies on UserEntity which has columns like createdAt and updatedAt which while are required columns but are auto-generated using the BeforeInsert decorator in TypeOrm

  2. Consistency with createMany({data: { bulk: DeepPartial<T>[] }} ...). There could be some reasoning behind it which I'm clearly not aware of but createMany uses DeepPartial

Response format options

This lib is very cool, but for my project I need to have a certain response format.
Currently, when we request a ressource, we have an array of this ressource as response.
Could we have for the futur some options like the total number of ressources, the number of pages, etc etc...
Because currently can't have a real pagination because we don't have this kind of information.

Thx.

Empty response from DELETE endpoint

Is it normal that the DELETE endpoint returns an empty response ? Shouldn't it return the deleted object or at least its id ? Tell me what you think.

Use Sequelize instead

Hello there,
You have made a great work in this so I was wondering if there's any way I can use sequelize instead of typeorm? and if so can you tell how and where to change? I've used sequelize many times and I'm aware of mostly all of its features and I'm not ready to try another ORM..

nested filter not working

consider this schema.
color:{ ..., car: { id: 1, . . . } }

when I query URL/color?join=car
it's give me joined objects but when I add the filter param to get color with specific car Id by query url/color?join=car&filter=car.id||eq|1 I get response { "statusCode": 400, "error": "Bad Request", "message": "Invalid column name 'car.id'" }

npm run serve is not working

Step 5 of example app is failing error given below. am I missing any step.


E:\git_clones\NestJS\crud\integration\typeorm>npm run serve

> [email protected] preserve E:\git_clones\NestJS\crud\integration\typeorm
> npm run db:sync -- -f=orm && npm run db:seeds -- -f=orm


> [email protected] db:sync E:\git_clones\NestJS\crud\integration\typeorm
> ts-node -r tsconfig-paths/register node_modules/.bin/typeorm schema:sync "-f=orm"

E:\git_clones\NestJS\crud\integration\typeorm\node_modules\.bin\typeorm:2
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
          ^^^^^^^

SyntaxError: missing ) after argument list
    at new Script (vm.js:79:7)
    at createScript (vm.js:251:10)
    at Object.runInThisContext (vm.js:303:10)
    at Module._compile (internal/modules/cjs/loader.js:657:28)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at Object.<anonymous> (E:\git_clones\NestJS\crud\integration\typeorm\node_modules\ts-node\src\bin.ts:157:12)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] db:sync: `ts-node -r tsconfig-paths/register node_modules/.bin/typeorm schema:sync "-f=orm"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] db:sync script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\TJ\AppData\Roaming\npm-cache\_logs\2019-02-01T07_35_46_818Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] preserve: `npm run db:sync -- -f=orm && npm run db:seeds -- -f=orm`
npm ERR! Exit status 1

POST

Hello,
nice job dude!

i have a problem with the POST route.
i'm trying to send a json to the POST endpoint using the Postman app, the json looks like this:
{
"login": "nature",
"senha": "123",
"nome": "Nature"
}

but i receive a 400 error saying this:
{
"statusCode": 400,
"error": "Bad Request",
"message": "null value in column "login" violates not-null constraint"
}

it looks like the json that i'm trying to send is not being understood by the app server.
Can you help ?

PS: the other endpoints (GET) are working pretty well

UpdateOne Override creates a new record instead of updating a record

What works ?

Code

@Crud(Role)
@Controller('roles')
export class RolesController implements CrudController<RolesService, Role> {
  constructor(public service: RolesService) {}
}

Test

PATCH /roles/2 Works and returns { id:2, ...updatedFields}

What does not work ?

Code

@Crud(Role)
@Controller('roles')
export class RolesController implements CrudController<RolesService, Role> {
  constructor(public service: RolesService) {}

  get base(): CrudController<RolesService, Role> {
    return this;
  }

  @Override()
  updateOne(@Param('id') id, @Param() params, @Body() dto) {
    // id, params and dto are good here
    return this.base.updateOneBase(id, params, dto);
  }
}

Test

PATCH /roles/2 Does not work because it returns a new record { id:14, ...newField}

I think it might be correlated with this issue: #4

Join is not working

The library is awesome it's working really well. Fields, Filters, they are working really well. but I tried join it didn't work.

Request:

http://localhost:3000/companies?join=users

Response:

[
    {
        "id": 1,
        "name": null,
        "description": null
    },
    {
        "id": 2,
        "name": null,
        "description": null
    },
    {
        "id": 3,
        "name": "Sampath Bank",
        "description": null
    }
]

There is a users relation in the company entity.

  @OneToMany(type => User, a => a.company)
  users?: User[];

Tried Filter, Fields and others. They are working. And there is data too. It worked when I try with typeorm directly.

Can't inject services which extend RepositoryService

I tried to implement a custom validator with class-validator https://github.com/typestack/class-validator#custom-validation-classes. I used the example project from this repository.

I added the following class:

import { ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';
import { Injectable } from '@nestjs/common';
import { UsersService } from './users.service';

@ValidatorConstraint({ name: 'doesUserAlreadyExist', async: true })
@Injectable()
export class DoesUserAlreadyExist implements ValidatorConstraintInterface {
  constructor(private usersService: UsersService) {}

  async validate(text: string) {
    const users = await this.usersService.getMany({
        filter: [
            {
                field: 'email',
                operator: 'eq',
                value: text
            }
        ]
    });
    return users.length === 0 ? true : false;
  }
}

And added the validator to the User class (Entity):

...
  @Validate(DoesUserAlreadyExist, {
    message: 'User already exists',
  })
  @Column({ type: 'varchar', length: 255, nullable: false, unique: true })
  email: string;
...

I get the following error:

/Users/kai/Development/NodeJS/crud/integration/typeorm/node_modules/@nestjs/typeorm/dist/common/typeorm.utils.js:8
    return `${entity.name}Repository`;
                     ^
TypeError: Cannot read property 'name' of undefined
    at Object.getRepositoryToken (/Users/kai/Development/NodeJS/crud/integration/typeorm/node_modules/@nestjs/typeorm/dist/common/typeorm.utils.js:8:22)
    at Object.exports.InjectRepository (/Users/kai/Development/NodeJS/crud/integration/typeorm/node_modules/@nestjs/typeorm/dist/common/typeorm.decorators.js:5:72)
    at Object.<anonymous> (/Users/kai/Development/NodeJS/crud/integration/typeorm/src/users/users.service.ts:12:16)
    at Module._compile (internal/modules/cjs/loader.js:738:30)
    at Module.m._compile (/Users/kai/Development/NodeJS/crud/integration/typeorm/node_modules/ts-node/src/index.ts:439:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:749:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/Users/kai/Development/NodeJS/crud/integration/typeorm/node_modules/ts-node/src/index.ts:442:12)
    at Module.load (internal/modules/cjs/loader.js:630:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:570:12)
    at Function.Module._load (internal/modules/cjs/loader.js:562:3)

If I remove the injected UsersService dependency injection from the DoesUserAlreadyExist class everything works again.
Is it not possible to use the services which extends the RepositoryService service? Or is there another way to execute the repository methods (getMany, getOne, etc.)?

data types in filters

query param ?filter=isOn||false will generate sql isOn = 'false' due to the false being traded as string

routing-controllers can even support json in query parameters.
Maybe we can do something like this when content-type is application/json:

try {
  value = JSON.parse(value);
} catch (ignored) {}

How to set role to use rest api?

This is really cool library.
I have some question.
I already have some role pipe to check user can access some api.
How to do this on this library??
My think is override method and set pipe to do this?
please give me some idea.
thanks!!

How to reuse queries in 3.x?

@zMotivat0r In my projects, it's often export file. And it shall be equivalent to table query. So I reuse getMany method.
Do you have better solution?

this is 2.1.0 version

  @ApiProduces(mime.getType('.xlsx'))
  @UseInterceptors(RestfulQueryInterceptor)
  @Get('/export/list.xlsx')
  async export(@Res() res: any, @Param() params: ObjectLiteral, @Query() query: RestfulParamsDto) {

    delete query.page;
    delete query.limit;

    const list = await this.base.getManyBase(params, query);
    // do something e.g. generate an excel file
  }

Nested resources

I have entity relations:

  • one User => many Reservations
  • one Reservation => many Borrowing

I have GET /users/:user/reservations/:reservation/borrowings endpoint.

BorrowingsController is looking for a field named user in the Borrowing entity, which doesn't exist. So I get Invalid column name 'user' error.

How can I achieve this ?

Swagger Models is empty

Hello~
I use this library and with swagger
I create a User entity with id and name fields
But I found the Models in swagger will shown User Model, but no any field in it.
How to fix it?
Thanks!

[HELP] Not uniq Alias on nested joins

Hello everyone, need help to solve this problem
image

In my case a have a table budgets, with two OneToMany relation for materials and works, this last two tables have a relation to units, so i want to do join of everything

image

but i assume that RepositoryService use the last key as alias and they repeat, and return the error of the first pic.

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.