Circular Dependency with Nestjs Swagger 4 - swagger

When I updated the #nest/swagger library to version 4, this error happened:
(node:16134) UnhandledPromiseRejectionWarning: Error: A circular dependency has been detected (property key: "customer"). Please, make sure that each side of a bidirectional relationships are using lazy resolvers ("type: () => ClassType").
at SchemaObjectFactory.createNotBuiltInTypeReference (/opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:182:19)
at SchemaObjectFactory.mergePropertyWithMetadata (/opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:117:25)
at /opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:66:35
at Array.map (<anonymous>)
at SchemaObjectFactory.exploreModelSchema (/opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:65:52)
at SchemaObjectFactory.createNotBuiltInTypeReference (/opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:187:37)
at SchemaObjectFactory.mergePropertyWithMetadata (/opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:117:25)
at /opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:66:35
at Array.map (<anonymous>)
at SchemaObjectFactory.exploreModelSchema (/opt/desenvolvimento/Haizen/projectx_back/node_modules/#nestjs/swagger/dist/services/schema-object-factory.js:65:52)
My model class seems to this:
#Entity()
export class Job {
.
.
.
#ManyToOne(type => Customer, customer => customer.jobs)
#ApiProperty({ type: Customer })
customer: Customer;
}

The solution that worked for me was to declare in #ApiProperty() the type with arrow function, like below:
#Entity()
export class Job {
.
.
.
#ManyToOne(type => Customer, customer => customer.jobs)
#ApiProperty({ type: () => Customer })
customer: Customer;
}

There are at least three more cases where you get the same error message, even though they have nothing to do with bidirectional relationships:
Enum as type
Wrong:
#ApiProperty({
type: Salutation
})
public salutation: Salutation;
Correct:
#ApiProperty({
enum: Salutation
})
public salutation: Salutation;
Anonymous types
Wrong:
#ApiProperty({
})
public address: {
street: string;
houseNumber: string;
};
Correct:
#ApiProperty({
type: Address
})
public address: Address;
null
Wrong:
#ApiProperty({
description: 'This always returns null for downward compatibility'
})
public someLegacyField: null;
Correct:
#ApiProperty({
description: 'This always returns null for downward compatibility',
type: String; // needed to avoid error
})
public someLegacyField: null;
I created an issue on Github for this: https://github.com/nestjs/swagger/issues/1475

For anyone who had this problem as well, you can change the type key to the enum key on the #ApiProperty. This worked for me.

I encountered this issue when I used type interfaces on nested properties of an entity
Incorrect:
export class BookLikes {
bookLikes: {
user: User;
book: Book;
}[];
}
Nest.js recommends using classes instead - even on nested properties:
Correct:
export class BookLikes {
bookLikes: BookLike[];
}
export class BookLike {
user: User;
book: Book;
}

Take a look at this bugfix
I managed to make my enum (ProcessCat) working like this:
#ApiProperty({
enum: ProcessCat,
enumName: 'ProcessCat',
isArray: true,
})
category: ProcessCat;
And thus the NestJS compiles properly.

I've also encountered this issue recently.
In my case, I've used a few validators in the same file in my custom-validations folder. The error "A circular dependency has been detected" only appears after nest build and node dist/main.
I'm not sure if this is an issue of NestJs + Swagger after generating a build or not. Apparently, my fix was to put the validators into several files (each file contains 1 validator), it works for me.

I had this problem using Swagger Ui Cli with Webpack every time I defined an Array property. My solution was to hardcode the ApiPropterty as Array because it seems like the plugin was not picking up on it for some reason.
import { ApiProperty } from '#nestjs/swagger'
export class CreateCatDto {
#ApiProperty({ type: [String] })
kittenNames: string[]
}
Docs: https://docs.nestjs.com/openapi/types-and-parameters#arrays
Also if everything else fails rename your files to something the plugin does not pick up. Default: remove entity or dto from the name.

Related

typeorm table name specified more than once

I have the next query:
const foundDeal: any = await dealRepository.findOne({
where: { id: dealId },
relations: ['negotiationPointsDeals', 'chosenInventoryToSubtractQuantity',
'chosenInventoryToSubtractQuantity.inventoryItemType',
'chosenInventoryToSubtractQuantity.inventoryItemType.quality', 'negotiationPointsDeals.negotiationPointsTemplate',
'chosenInventoryToSubtractQuantity.addressOfOriginId', 'chosenInventoryToSubtractQuantity.currentLocationAddress',
'chosenInventoryToSubtractQuantity.labAttestationDocs',
'chosenInventoryToSubtractQuantity.labAttestationDocs.storage',
'chosenInventoryToSubtractQuantity.proveDocuments', 'chosenInventoryToSubtractQuantity.proveDocuments.storage',
'chosenInventoryToSubtractQuantity.inventoryItemSavedFields', 'chosenInventoryToSubtractQuantity.inventoryItemSavedFields.proveDocuments',
'chosenInventoryToSubtractQuantity.inventoryItemSavedFields.proveDocuments.storage',
'sellerBroker', 'sellerBroker.users',
'seller', 'seller.users',
'buyerBroker', 'buyerBroker.users',
'buyer', 'buyer.users',
'order', 'order.inventory', 'order.inventory.inventoryItemType',
'order.inventory.inventoryItemType.quality',
'order.inventory.addressOfOriginId', 'order.inventory.currentLocationAddress',
'order.inventory.inventoryItemSavedFields', 'order.inventory.inventoryItemSavedFields.proveDocuments',
'order.inventory.inventoryItemSavedFields.proveDocuments.storage',
'order.inventory.labAttestationDocs', 'order.inventory.labAttestationDocs.storage',
// 'postTradeProcessingDeal', 'postTradeProcessingDeal.postTradeProcessingStepsDeal',
'order.inventory.proveDocuments',
'order.inventory.proveDocuments.storage',
'negotiationPointsDeals.negotiationPointsTemplate.negotiationPointsTemplateChoices',
'postTradeProcessing',
],
});
So, the error is next:
error: table name "Deal__chosenInventoryToSubtractQuantity_Deal__chosenInventoryTo" specified more than once.
But I can't see any doubles in query.
I ran into this issue when switching to start using the snake case naming strategy.
I think somehow the aliases that TypeORM generates by default do not collide if you "re-join" to existing eagerly-loaded relations.
However, under the new naming strategy it threw an error if I tried to add in a relation that was already eagerly loaded.
The solution for me was to find and eliminate places where I was doing relations: ["foo"] in a query where foo was already eagerly loaded by the entity.
The issue is documented in this TypeORM issue.
After some digging, I realized this error is due to TypeORM creating some kind of variable when using eager loading that is longer than Postgres limit for names.
For example, if you are eager loading products with customer, typeorm will create something along the lines of customer_products, connecting the two. If that name is longer than 63 bytes (Postgres limit) the query will crash.
Basically, it happens when your variable names are too long or there's too much nesting. Make your entity names shorter and it will work. Otherwise, you could join the tables manually using queryBuilder and assign aliases for them.
It looks like you are using Nestjs, typeorm, and the snakeNamingStrategy as well, so I'll show how I fixed this with my system. I use the SnakeNamingStrategy for Typeorm which might be creating more issues as well. Instead of removing it, I extended it and wrote an overwriting function for eager-loaded aliases.
Here is my solution:
// short-snake-naming.strategy.ts
import { SnakeNamingStrategy } from "typeorm-naming-strategies";
import { NamingStrategyInterface } from "typeorm";
export class ShortSnakeNamingStrategy
extends SnakeNamingStrategy
implements NamingStrategyInterface
{
eagerJoinRelationAlias(alias: string, propertyPath: string): string {
return `${alias.replace(
/[a-zA-Z]+(_[a-zA-Z]+)*/g,
(w) => `${w[0]}_`
)}_${propertyPath}`;
}
}
// read-database.configuration.ts
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from "#nestjs/typeorm";
import { SnakeNamingStrategy } from "typeorm-naming-strategies";
import { ShortSnakeNamingStrategy } from "./short-snake-naming.strategy";
export class ReadDatabaseConfiguration implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions | Promise<TypeOrmModuleOptions> {
return {
name: "read",
type: "postgres",
...
namingStrategy: new ShortSnakeNamingStrategy(),
};
}
}
The ShortSnakeNamingStrategy Class takes each eager-loaded relationship and shortens its name from Product__change_log___auth_user___roles__permissions to P_____c____a___r__permissions
So far this has generated no collisions and kept it below the 63 character max index length.

Entity metadata for Role#users was not found

Trying to make OneToMany and ManyToOne relationship with TypeORM but I get this error, I don't know what's wrong with my code.
I have the following User entity:
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { Field, ID, ObjectType } from 'type-graphql';
import { Role } from './';
#ObjectType()
#Entity()
export class User extends BaseEntity {
#Field(() => ID)
#PrimaryGeneratedColumn()
public id: number;
#Field()
#Column('text', { unique: true })
public userName: string;
#Column()
public password: string;
#Field()
#Column('boolean', { default: true })
public isActive: boolean;
#ManyToOne(() => Role, role => role.users)
#Field(() => Role, { nullable: true })
public role: Role;
}
Role entity:
import { BaseEntity, Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Field, ID, ObjectType } from 'type-graphql';
import { User } from '.';
#ObjectType()
#Entity()
export class Role extends BaseEntity {
#Field(() => ID)
#PrimaryGeneratedColumn()
public id: number;
#Field()
#Column('text', { unique: true })
public name: string;
#OneToMany(() => User, user => user.role, { lazy: false })
#Field(() => [User], { nullable: true })
public users: User[];
}
However I keep getting this error
(node:4541) UnhandledPromiseRejectionWarning: Error: Entity metadata
for Role#users was not found. Check if you specified a correct entity
object and if it's connected in the connection options. [1] at
/node_modules/typeorm/metadata-builder/EntityMetadataBuilder.js:571:23
[1] at Array.forEach (<anonymous>) [1] at
EntityMetadataBuilder.computeInverseProperties
(/node_modules/typeorm/metadata-builder/EntityMetadataBuilder.js:567:34)
[1] at
/node_modules/typeorm/metadata-builder/EntityMetadataBuilder.js:80:74
[1] at Array.forEach (<anonymous>) [1] at
EntityMetadataBuilder.build
(/node_modules/typeorm/metadata-builder/EntityMetadataBuilder.js:80:25)
[1] at ConnectionMetadataBuilder.buildEntityMetadatas
(/node_modules/typeorm/connection/ConnectionMetadataBuilder.js:57:141)
[1] at Connection.buildMetadatas
(/node_modules/typeorm/connection/Connection.js:494:57)
[1] at Connection.<anonymous>
(/node_modules/typeorm/connection/Connection.js:126:30)
[1] at step
(/node_modules/tslib/tslib.js:136:27) [1]
(node:4541) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an async
function without a catch block, or by rejecting a promise which was
not handled with .catch(). (rejection id: 1) [1] (node:4541) [DEP0018]
DeprecationWarning: Unhandled promise rejections are deprecated. In
the future, promise rejections that are not handled will terminate the
Node.js process with a non-zero exit code.
I am using NestJS with PostgreSQL and I had the same issue. The problem was by me is that I forgot to import the entity in the module with the TypeOrmModule.forFeature function.
#Module({
imports: [TypeOrmModule.forFeature([Users, ...])], <--- Importing the entity!
controllers: [...],
providers: [...],
exports: [...],
})
This just means that your entities are either not loading, or are loading incorrectly
You need to fix the loading of your entities. Entities will usually be loaded from the ormconfig.js file
Just create a file ormconfig.js and type something like this, emphasis on the entities
module.exports = {
"name": "default",
"type": "mongodb",
"host": "localhost",
"port": "27017",
"username": "root",
"password": "",
"database": "rocketlaunches",
"entities": [
__dirname + "entities/**/*.entity.ts"
]
}
Now obviously, you would load your entities from wherever they are on your project
If you still have the issue after applying the other solutions presented here. Check if your entities have the #Entity() decorator. I was missing this and after adding it it solved the issue.
Also adding autoLoadEntities: true in the connection options was needed.
I ran into the same issue.
TypeORM is very difficult to debug with args and meta data classes/collections all over the place. After many hours I was able to figure it out.
So this relationship is failing because EntityMetadataBuilder.ts is trying to tie the type of the ManyToOne column with a known entity type using "===".
var inverseEntityMetadata = entityMetadatas.find(function (m) { return m.target === relation.type || (typeof relation.type === "string" && m.targetName === relation.type); });
Looking at relation.type I could see that it is the same "type" as m.target however they were not pointing to the same reference of the defined type. It seemed to me as if my related class was being loaded by node more than once. After reading about how node caches modules I was able to fix my problem by making sure all of my import statements were referencing the same file including uppercase/lowercase letters in the string.
In one file I had
import { Transaction } from "./transaction";
and the other I had
import { Transaction } from "./Transaction";
Notice the uppercase "t". After replacing with a lowercase "T" everything worked as expected.
In my project TypeORM is initialized like this:
import { createConnection } from 'typeorm';
const conn = await createConnection({
// Make sure to specify all entities here
entities: [User, Role],
// ... More options
})
Just need to make sure that entities lists all your entities.
(This is the alternative if you're not using ormconfig.js to specify entities.)
in my case, I solved it by adding the Role entity. to the entity array in the main app.module class. I initially forgot to add it.
TypeOrmModule.forRoot({
type: process.env.DB_TYPE as any,
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
entities: [User, Role],
synchronize: true,
My problem was that I was using node-ts to run only the typescript files for my project. However, my build still emitted .js files that were ignored/hidden. I don't know why, but cleaning out the *.js and *.js.map compiled files worked. What's strange is my ormconfig only specifies .ts files.
I recommend adding the "noEmit": true to tsconfig.json compiler options to prevent any future headaches with a similar approach.
For my case, I was missing the #Entity() on top of my class,
check if all your classes have the #Entity() decorator
I faced this problem, in my case, the solution is to remove the dist folder inside the server
I had this problem because I accidentally deleted my RoleModule "role.module.ts". When I recreated the module the problem was easelly solved.
In my project deleting dist solves the issue.
After trying the solutions above ( delete the dist, put the #Entity() decorator, look for maybe a wrong import in the case of capital letter in one file and not in the other), I just disable the autoLoadEntities and import manually all of my entities in the entities field.
NB : In the config.ts file, I got a class AppConstant in which all of my useful constants are declared Like DB_CONFIG shown in this pic.
config.ts
And in the app.module.ts, I make this :
In sum, It's just an typeOrm import error so this is what I did to solve this issue
app.module.ts
In my case, I solved with:
autoLoadEntities: true,
in app.module.ts
in my case I forgot to add the .entity part to the file
file name was: user.ts
where it should have been: user.entity.ts
because in my config file I look for files ending with .entity.ts as my entities.
entities: [__dirname + '/**/*.entity.{ts,js}'],
I'm using NestJS and MySQL. I also faced this issue and I checked for #Entity, filenames etc.
What I found was that when we list all the entities for
TypeOrmModule.forRootAsync({
useFactory: () => ({
...remainingConfigs,
entities: [...allEntities],
})
})
The order in which entities are listed is a bit important in case when there exists a relationship between them.
For Example, if UserEntity contains #JoinColumn for DepartmentEntity, then DepartmentEntity should be listed before UserEntity.
I know this question isn't active, but I just wanted to share this possibility with everyone since it took quite some time.
I had the same issue. I correctly had place the TypeOrm.forFeature([Denom]) in the DenomModule, but I was missing the entity in the main module:
#Module({
imports: [
TypeOrmModule.forRoot({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "postgres",
database: "testnestjs",
entities: [.., Denom],
synchronize: true
}),
DenomModule,
...,
I keep doing the same mistake over and over. In typeorm config I specify to look for dist/**/*.model.js files.
But every now and then I have this brilliant idea to start using *.entity.ts suffix, resulting in the above error.
Renaming file to xx.model.ts fixes it.
In my case, I forgot to decorate one of my entities with #Entity decorator. Silly one but I thought it might help some one.
check that the files have the word entity in their name.
Although this question was already answered, I encountered the same problem using typeorm with NestJS and the problem was a combination of multiple factors. You have to ensure that multiple conditions are met, depending on whether you use TypeOrm with Nestjs or not.
Your entities must be decorated with #Entity decorator imported from typeorm library. (Which in the example above, is correct). This has to be ensured in both cases, with or without NestJS.
Steps for TypeOrm without NestJS:
Include all the entities in entities property in your typeorm connection. This could be in createConnection method or in DataSource constructor, depending on your typeorm version. You can either explicitly list them:
...
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
entities: [User, Role]
...
... or you can use a regex and name your files with entity.ts suffix, which in my opinion is the better way, because you don't have to change the file if you later add or delete an entity:
...
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
entities: [__dirname + '/**/*.entity.{js,ts}'],
...
This should do the work if you use TypeOrm without NestJS.
Steps for usage in NestJS:
Include the entities in TypeOrmModule.forRoot call, just like in step 2. of non-Nestjs approach.
Include entities in their respective TypeOrmModule.forFeature call in the module they belong to.
#Module({
imports: [TypeOrmModule.forFeature([User, Role...]), ...],
...
})
For me, the issue was that I was using the Entity decorator without the # so I just changed Entity(); to #Entity() and it worked.
This issue happened randomly to me between 2 file saves. I didn't solved it by updating entities key (it was set to [__dirname + '/**/*.entity{.ts,.js}']) or enabling autoLoadEntities, but by downgrading my typeorm version to 0.2.22.
Check this issue for more info : https://github.com/typeorm/typeorm/issues/5676
This could mean that your entities are either not loading, or are loading incorrectly. One mistake could be you are not including the word "entity" in your file name. The correct naming is "user.entity.ts" or "role.entity.ts"
When I had this issue, I had my entities missing one entity.
export const AppDataSource = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "postgres",
database: "typeormtest",
synchronize: true,
logging: false,
entities: [Member, Task, Committee ], // i had "committee" mia
subscribers: [],
migrations: [],
});
I faced a similar issue, just make sure the module that contains your entity is included in imports of AppModule like so:
#Module({
imports: [
XXModule,
YYModule
],
controllers: [],
providers: [],
})

Variable of required type was not provided

I am attempting to create a relationship in my Neo4j database with a GraphQL mutation. I have a number of other mutations already working except this one causing problems. It looks like this:
mutation(
$id: String!,
$recipe: String!,
$date: String!
) {
CreateUserRecipeRelation(id:$id, recipe:$recipe, date:$date) {
id
recipe {
name
}
}
}
I am passing in the following set of parameters:
{"id": "google-oauth2|yyyyremovedauthstuffyyyy", "recipe": "baked spaghetti", "date": "10/10/2018"}
But the GraphQL playground throws the following error:
"Variable \"$id\" of required type \"String!\" was not provided."
In my schema.graphql file I have the following defined:
CreateUserRecipeRelation (
id: String
recipe: String
date: String
): User #cypher(statement:
"MATCH (r:Recipe{name:$recipe}), (u:User{id:$id}) CREATE (r)-[c:Created_By{date:$date}]->(u) RETURN r,c,u")
And if I run that cypher query directly in Neo4j it works just fine. In this same project I have 5 or 6 other relationship-creating mutations currently working but this one is giving me pause.
UPDATE:
This is a mutation I currently have that is working, so you can see the similarity in structure:
CreateIngredientRelation (
name: String
recipe: String
quantity: String
): Ingredient #cypher(statement:
"MATCH (r:Recipe{name:$recipe}), (i:Ingredient{name:$name}) CREATE (r)-[c:Contains{quantity:$quantity}]->(i) RETURN r,c,i")
This one works great and creates tons of relationships with the quantity attached to them. This is why I am puzzled. If they both didn't work it would be easier to try and come up with a solution I think.
#BehemothDan, how are you calling this mutation? Are you using react-apollo? If yes, Let me provide you an example of how you should be handling this.
For example, if you have a form to create this UserRecipeRelation. You have your Mutation component from react-apollo. On this Mutation you have on renderProps CreateUserRecipeRelation, that you could pass to a function on onSubmit. In this function you pass your variables:
UserRecipeRelation({ variables: { id: 'your id', recipe: 'bla bla', date: '12/12/18' } });
Hope it helps! :)

No metadata for "User" was found using TypeOrm

I'm trying to get a basic setup working using TypeORM, and getting this error following the setup.
Here is a REPL (just do yarn install && yarn db:dev followed by yarn db:migrate && yarn start to reproduce the error)
Inserting a new user into the database...
{ EntityMetadataNotFound: No metadata for "User" was found.
at new EntityMetadataNotFoundError (/Users/admin/work/typeorm-naming-strategy/src/error/EntityMetadataNotFoundError.ts:9:9)
at Connection.getMetadata (/Users/admin/work/typeorm-naming-strategy/src/connection/Connection.ts:313:19)
at /Users/admin/work/typeorm-naming-strategy/src/persistence/EntityPersistExecutor.ts:77:55
at Array.forEach (<anonymous>)
at EntityPersistExecutor.<anonymous> (/Users/admin/work/typeorm-naming-strategy/src/persistence/EntityPersistExecutor.ts:71:30)
at step (/Users/admin/work/typeorm-naming-strategy/node_modules/typeorm/persistence/EntityPersistExecutor.js:32:23)
at Object.next (/Users/admin/work/typeorm-naming-strategy/node_modules/typeorm/persistence/EntityPersistExecutor.js:13:53)
at /Users/admin/work/typeorm-naming-strategy/node_modules/typeorm/persistence/EntityPersistExecutor.js:7:71
at new Promise (<anonymous>)
at __awaiter (/Users/admin/work/typeorm-naming-strategy/node_modules/typeorm/persistence/EntityPersistExecutor.js:3:12)
name: 'EntityMetadataNotFound',
message: 'No metadata for "User" was found.' }
Adding answer bit late but its very common error.
There are two main reasons for above error. In OrmConfig,
You have used *.ts instead of *.js. For example,
entities: [__dirname + '/../**/*.entity.ts'] <-- Wrong
It should be
entities: [__dirname + '/../**/*.entity.js']
entities path is wrong. Make sure, entities path is defined according to dist folder not src folder.
The problem is on ormConfig
Please try to use this:
entities: [__dirname + '/../**/*.entity.{js,ts}']
In my case I had forgotten to add new entity ( User in your case ) to app.module.ts .
Here is the solution that worked for me:
// app.module.ts
#Module({
imports: [
TypeOrmModule.forRoot({
...
entities: [User]
...
}),
...
],
})
Following will ensure that the file extensions used by TypeORM are both .js and .ts
entities: [__dirname + '/../**/*.entity.{js,ts}']
change this in your config file.
In my case i forgot to use connection.connect() method after creation of connection and got same error when using manager.find().
If your app is using the latest DataSource instead of OrmConfig (like apps using the latest version of typeorm (0.3.1 the moment i'm writing theses lines)), make sure to call initialize() method of your DataSource object inside your data-source.ts file before using it anywhere in your app.
in my case, i was changing one EmployeeSchema to EmployeeEntity, but i forgot the entity annotation on it:
#Entity()
export class Employee {
I got this err message, but i solved in a different way, it could also happen when you already have a table called "users" for example, and your model User is not with the same columns and configs as your table, in my case my table had a column called posts with a default value, and my model hadn't that default value set up, so before you check the entities directory on the ormconfig.json i highly recommend you check if your models are with the same properties and configs as your database table
I got the same issue and later found I haven't call the functionality to connect the DB. Just by calling the connection fixed my issue.
export const AppDataSource = new DataSource({
type: 'mysql',
host: process.env.MYSQL_HOST,
....
});
let dataSource: DataSource;
export const ConnectDb = async () => {
dataSource = await AppDataSource.initialize();
And use this to connect in your function.
Another occasion I got a similar message when I run $ npm test without properly mocking Jest.spyOn() method and fixed it by:
jest.spyOn(db, 'MySQLDbCon').mockReturnValueOnce(Promise.resolve());
const updateResult = {}
as UpdateResult;
jest.spyOn(db.SQLDataSource, 'getRepository').mockReturnValue({
update: jest.fn().mockResolvedValue(updateResult),
}
as unknown as Repository < unknown > );
I believe my issue was caused by accidentally having both ormconfig.json and ormconfig.ts
I'll contribute to this list of answers. In my case, I'm using a fancy-pants IDE that likes to auto-transpile the ts code into js without my knowledge. The issue I had was, the resulting js file was no bueno. Killing these auto-gen'd files was the answer.
The relevant bit of my ormconfig looks like:
{
...
"entities": ["src/entity/**/*.ts", "test/entity-mocks/**/*.ts"],
"migrations": ["src/migration/**/*.ts"],
"subscribers": ["src/subscriber/**/*.ts"]
...
}
Actually, I even tried the methods above to also include transpiled js files if they exist and I got other weird behavior.
I've tried all the solutions above, changing the typeORM version solved it for me.
enable autoLoadEntities in app.module.ts
imports: [UserModule,
TypeOrmModule.forRoot({
autoLoadEntities: true
})
]
Make sure you have established a connection with the database before using the entities. In my case, I was using the AppDataSource before it was initialized. Here is how I fixed it:
import "reflect-metadata";
import { DataSource } from "typeorm";
import { Season } from "src/models/Season";
const AppDataSource = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "postgres",
database: "test-db",
synchronize: false,
logging: false,
entities: [Season],
migrations: [],
subscribers: [],
});
AppDataSource.initialize()
.then(async () => {
console.log("Connection initialized with database...");
})
.catch((error) => console.log(error));
export const getDataSource = (delay = 3000): Promise<DataSource> => {
if (AppDataSource.isInitialized) return Promise.resolve(AppDataSource);
return new Promise((resolve, reject) => {
setTimeout(() => {
if (AppDataSource.isInitialized) resolve(AppDataSource);
else reject("Failed to create connection with database");
}, delay);
});
};
And in your services where you want to use the DataSource:
import { getDataSource } from "src/config/data-source";
import { Season } from "src/models/Season";
const init = async (event) => {
const AppDataSource = await getDataSource();
const seasonRepo = AppDataSource.getRepository(Season);
// Your business logic
};
You can also extend my function to add retry logic if required :)
Just in case someone runs into the same problem i had. I had to do two different things going against me:
I was missing the declaration of entity in ormConfig:
ormConfig={
...,
entities: [
...,
UserEntity
]
}
And since i was making changes (afterwards) to an existing entity, the cache was throwing a similar error. The solution for this was to remove the projects root folders: dist/ folder. Thou this might only be a Nest.js + TypeOrm issue.
In my case the entity in question was the only one giving the error. The rest of entities worked fine.
The automatic import failed to write correctly the name of the file.
import { BillingInfo } from "../entity/Billinginfo";
instead of
import { BillingInfo } from "../entity/BillingInfo";
The I for Info should be capital. The IDE also failed to show any errors on this import.
This error can also come up if you have a nodemon.json file in your project.
So after including your entity directory for both build and dev in the entities array
export const AppDataSource = new DataSource({
type: 'mysql',
host: DB_HOST_DEV,
port: Number(DB_PORT),
username: DB_USER_DEV,
password: DB_PASSWORD_DEV,
database: DB_NAME_DEV,
synchronize: false,
logging: false,
entities: [
process.env.NODE_ENV === "prod"
? "build/entity/*{.ts,.js}"
: "src/entity/*{.ts,.js}",
],
migrations: ["src/migration/*.ts"],
subscribers: [],
})
and still getting this error, remove the nodemon.json file if you have it in your project
Besides the #Entity() annotation, with typeorm version 0.3.0 and above also don't forget to put all your entities into your DataSource:
export const dataSource = new DataSource({
type: "sqlite",
database: 'data/my_database.db',
entities: [User],
...
...
})
https://github.com/typeorm/typeorm/blob/master/CHANGELOG.md#030-2022-03-17
my fail was that instead of using Models I used Requests. Requests are loaded earlier so it end it undefined. Try to move your Model Class to Models
Add your entity in orm.config.ts file.
entities: [empData,user],
I omitted this #Entity() decorator on the entity class. So immediately I fixed this, and it worked for me.
Example:
import { ObjectType, Field, ID } from '#nestjs/graphql';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
#ObjectType()
#Entity()
export class Message {
#Field((type) => ID)
#PrimaryGeneratedColumn('uuid')
id: string;
#Field()
#Column()
conversationId: string;
#Field()
#Column()
sender: string;
}
ForMe , i have set error path cause this problem
my error code like this
and then i check the entities path . i modify the path to correct. then the typeorm working
For me it was two things, while using it with NestJS:
There was two entities with the same name (but different tables)
Once I fixed it, the error still happened, then I got to point two:
Delete the dist/build directory
Not sure how the build process works for typeorm, but once I deleted that and ran the project again it worked. Seems like it was not updating the generated files.
In my case I've provided a wrong db password. Instead of receiving an error message like "connection to db failed" I've got the error message below.
EntityMetadataNotFound: No metadata for "User" was found.
Using TypeORM with NestJS, for me the issue was that I was setting the migrations property of the TypeOrmModuleOptions object for the TypeOrmModuleAsyncOptions useFactory method, when instead I should've only set it on the migrations config, which uses the standard TypeORM DataSource type.
This is what I ended up with:
typeorm.config.ts
import { DataSource } from 'typeorm';
import {
TypeOrmModuleAsyncOptions,
TypeOrmModuleOptions,
} from '#nestjs/typeorm';
const postgresDataSourceConfig: TypeOrmModuleOptions = {
...
// NO migrations property here
// Had to add this as well
autoLoadEntities: true,
...
};
export const typeormAsyncConfig: TypeOrmModuleAsyncOptions = {
useFactory: async (): Promise<TypeOrmModuleOptions> => {
return postgresDataSourceConfig;
},
};
// Needed to work with migrations, not used by NestJS itself
export const postgresDataSource = new DataSource({
...postgresDataSourceConfig,
type: 'postgres',
// Instead use it here, because the TypeORM Nest Module does not care for migrations
// They must be done outside of NestJS entirely
migrations: ['src/database/migrations/*.ts'],
});
migrations.config.ts
import { postgresDataSource } from './typeorm.config';
export default postgresDataSource;
And the script to run TypeORM CLI was
"typeorm-cli": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli -d ./src/database/migrations.config.ts"
I was facing a similar issue, in my case I was using NestJS version 9.0.0.
In app.module while importing typeORM module, one of the properties autoLoadEntities was turned to false. So locally when I was trying to connect to DB, it was throwing me this error while writing a find() query.
Correct way to import typeORM:
TypeOrmModule.forRoot({
type: 'mongodb',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 27017,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
ssl: false,
autoLoadEntities: true,
synchronize: true,
logging: true,
}),
Try this one. Should never fall
DB_ENTITIES=[dist/**/*.entity.js]
For me the only way of having the entities folder work in NestJS + TypeOrm v 0.3.11 was the following configuration:
const typeOrmConfig: TypeOrmModuleOptions = {
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT, 10),
name: process.env.DB_NAME,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
migrations: ['dist/migrations/*.{ts,js}', 'src/migrations/*.{ts,js}'],
entities: ['dist/entities/*.entity.{ts,js}', 'src/entities/*.entity.{ts,js}'],
migrationsRun: true,
autoLoadEntities: true,
};
if you get "Error: No metadata for Quiz was found" because different version. Here is my solution:
quiz.module.ts: imports: [TypeOrmModule.forFeature([Quiz])],
quiz.service.ts: constructor(#InjectRepository(Quiz) private quizRepository: Repository){}
I dont need quiz.repository.ts file
---- from a youtube comment and the solution worked for me.

Angular library - Type 'Subject<any[]>' is not assignable to type 'Subject<any[]>'

I've been following this guide to create a custom angular library but I've hit a wall with an issue rather odd.
The idea behind exercise is simple, create a skeleton for a particular piece of functionality (in this case a staff directory) where a developer can npm install it and provide a custom data source that implements our interface.
This interface is as follows
export interface ISDDataService {
refiners: Subject<Refiner[]>;
search(queryTxt: string): Observable<Staff[]>;
refine(refiner: Refiner): Observable<Staff[]>;
}
In the library project, this skeleton is a module referenced by the root module which is set up to provide the data source which inherits the ISDDataService
#Injectable()
export class AppService implements ISDDataService {
refiners: Subject<Refiner[]>;
staff: Staff[] = [];
constructor() {
this.staff.push(<Staff>{name: 'John Doe', role: 'xyz', group: 'A Team', image: ''});
this.staff.push(<Staff>{name: 'Jane Doe', role: 'xyz', group: 'B Team', image: ''});
}
search(queryTxt: string): Observable<Staff[]> {
return Observable.of(this.staff).map(o => this.staff);
}
refine(refiner: Refiner): Observable<Staff[]> {
return ;
}
}
This is how the service is provided (app.module.ts)
providers: [
{
provide: 'ISDDataService',
useClass: AppService
}
],
The skeleton module also has the results component which uses the data source to query the data
#Component({
selector: 'app-search-results',
templateUrl: './search-results.component.html',
styleUrls: ['./search-results.component.css']
})
export class SearchResultsComponent implements OnInit {
private results: Observable<Staff[]>;
private searchField: FormControl;
constructor(#Inject('ISDDataService') private service: ISDDataService) { }
ngOnInit() {
this.searchField = new FormControl();
this.results = this.searchField.valueChanges
.debounceTime(400)
.distinctUntilChanged()
.switchMap( term => this.service.search(term));
}
}
This set up works like a charm, so proceed to package up, create a tarball and create a new "test" app so I can import the module using npm install (all these steps as per the blog post). So far so good, no errors installing the module.
the test app is just an exact replica of what I used when building the library. Same AppServices inheriting the ISDDataService, same way of providing the service and etc. I try bulding it and it all goes to hell. The error couldn't be more bizarre
ERROR in src/app/app.service.ts(9,14): error TS2420: Class 'AppService' incorrectly implements interface 'ISDDataService'.
Types of property 'refiners' are incompatible.
Type 'Subject<Refiner[]>' is not assignable to type 'Subject<Refiner[]>'. Two different types with this name exist, but they are unrelated.
Types of property 'lift' are incompatible.
Type '<R>(operator: Operator<Refiner[], R>) => Observable<R>' is not assignable to type '<R>(operator: Operator<Refiner[], R>) => Observable<R>'. Two different types with this name exist, but they are unrelated.
Types of parameters 'operator' and 'operator' are incompatible.
Type 'Operator<Refiner[], R>' is not assignable to type 'Operator<Refiner[], R>'. Two different types with this name exist, but they are unrelated.
Types of property 'call' are incompatible.
Type '(subscriber: Subscriber<R>, source: any) => TeardownLogic' is not assignable to type '(subscriber: Subscriber<R>, source: any) => TeardownLogic'. Two different types with this name exist, but they are unrelated.
Types of parameters 'subscriber' and 'subscriber' are incompatible.
Type 'Subscriber<R>' is not assignable to type 'Subscriber<R>'. Two different types with this name exist,
but they are unrelated.
Property 'isStopped' is protected but type 'Subscriber<T>' is not a class derived from 'Subscriber<T>'.
How's something like this "Subject<Refiner[]>' is not assignable to type 'Subject<Refiner[]>'" make sense!!??
I've made a couple of changes here and there but nothing works
Note, this issue is not for the refiner property only. If I remove that, it'll cascade down to the functions and so.
I'm starting to think that perhaps this approach isn't the right one... and here I thought it was pretty clean
anyhow, if anyone can give a hand would be greatly appreciated

Resources