alfateam / orange-orm

The ultimate ORM for Node and Typescript
https://orange-orm.io
ISC License
623 stars 20 forks source link

[BUG]: error ts2742 and error ts7056 with NestJS #95

Closed Kyryus closed 4 weeks ago

Kyryus commented 1 month ago

orange Version

4.0.0

Database

Postgres

Database Version

16

Operating System

MacOS

Description

Hello

When I try to create the database mapping, I got this error :

database/database_mapping.ts:4:7 - error TS2742: The inferred type of 'map' cannot be named without a reference to 'orange-orm/node_modules/ajv'. This is likely not portable. A type annotation is necessary.

4 const map = orange
        ~~~

on this lines :

const map = orange
  .map((x) => ({
    customer: x.table('customer').map(({ column }) => ({
      id: column('id').numeric().primary().notNullExceptInsert(),
      name: column('name').string(),
      balance: column('balance').numeric(),
      isActive: column('isActive').boolean(),
    })),

    order: x.table('_order').map(({ column }) => ({
      id: column('id').numeric().primary().notNullExceptInsert(),
      orderDate: column('orderDate').date().notNull(),
      customerId: column('customerId').numeric().notNullExceptInsert(),
    })),

    orderLine: x.table('orderLine').map(({ column }) => ({
      id: column('id').numeric().primary(),
      orderId: column('orderId').numeric(),
      product: column('product').string(),
      amount: column('amount').numeric(),
    })),

    package: x.table('package').map(({ column }) => ({
      id: column('packageId').numeric().primary().notNullExceptInsert(),
      lineId: column('lineId').numeric().notNullExceptInsert(),
      sscc: column('sscc').string(), //the barcode
    })),

    deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
      id: column('id').numeric().primary(),
      orderId: column('orderId').numeric(),
      name: column('name').string(),
      street: column('street').string(),
      postalCode: column('postalCode').string(),
      postalPlace: column('postalPlace').string(),
      countryCode: column('countryCode').string(),
    })),
  }))
  .map((x) => ({
    orderLine: x.orderLine.map(({ hasMany }) => ({
      packages: hasMany(x.package).by('lineId'),
    })),
  }))
  .map((x) => ({
    order: x.order.map((v) => ({
      customer: v.references(x.customer).by('customerId'),
      lines: v.hasMany(x.orderLine).by('orderId'),
      deliveryAddress: v.hasOne(x.deliveryAddress).by('orderId'),
    })),
  }));

export default map;

To fix it, I needed to give the type like that :

const map: MappedDbDef<object> = orange
  .map((x) => ({

I there any better way to fix this error when we want to code in "strict" mode ?

My tsconfig.json :

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2022",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./src",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictBindCallApply": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "paths": {
      "@shared/*": ["../../shared/*"]
    },

    "typeRoots": ["./src/types"]
  }
}

Expected Behavior

Avoid TS2742 error

lroal commented 1 month ago

Hello. Thank you for reporting the issue. Which version of typescript are you using ?

Kyryus commented 1 month ago

Hello. Thank you for reporting the issue. Which version of typescript are you using ?

"typescript": "^5.4.5"

lroal commented 1 month ago

can I see your package.json as well ? Does this happen on tsc or at design time in editor ?

Kyryus commented 1 month ago

can I see your package.json as well ? Does this happen on tsc or at design time in editor ?

{
  "name": "backend",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@fastify/secure-session": "^7.5.1",
    "@nestjs-modules/mailer": "^2.0.2",
    "@nestjs/common": "^10.3.8",
    "@nestjs/config": "^3.2.2",
    "@nestjs/core": "^10.3.8",
    "@nestjs/jwt": "^10.2.0",
    "@nestjs/platform-fastify": "^10.3.8",
    "bcrypt": "^5.1.1",
    "orange-orm": "^4.0.0",
    "pg": "^8.11.5",
    "reflect-metadata": "^0.2.2",
    "rxjs": "^7.8.1"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.3.2",
    "@nestjs/schematics": "^10.1.1",
    "@nestjs/testing": "^10.3.8",
    "@types/bcrypt": "^5.0.2",
    "@types/jest": "^29.5.12",
    "@types/node": "^20.12.13",
    "@types/pg": "^8.11.6",
    "@types/supertest": "^6.0.2",
    "@typescript-eslint/eslint-plugin": "^7.11.0",
    "@typescript-eslint/parser": "^7.11.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.1.3",
    "jest": "^29.7.0",
    "prettier": "^3.2.5",
    "source-map-support": "^0.5.21",
    "supertest": "^7.0.0",
    "ts-jest": "^29.1.4",
    "ts-loader": "^9.5.1",
    "ts-node": "^10.9.2",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.4.5"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

This message error show up when I start command : "npm run start:debug"

I am just on the basic setup of an application so I am not doing fancy stuff.

lroal commented 1 month ago

It could be due to conflicting versions of ajv. When running 'npm list ajv' you will see that. I am working on a solution. Maybe I will need to wrapper types for ajv instead of using it directly.

Kyryus commented 1 month ago
backend@0.0.1 /Users/kyryus/Dev/backend
├─┬ @nestjs/cli@10.3.2
│ ├─┬ @angular-devkit/core@17.1.2
│ │ ├─┬ ajv-formats@2.1.1
│ │ │ └── ajv@8.12.0 deduped
│ │ └── ajv@8.12.0
│ └─┬ fork-ts-checker-webpack-plugin@9.0.2
│   └─┬ schema-utils@3.3.0
│     ├─┬ ajv-keywords@3.5.2
│     │ └── ajv@6.12.6 deduped
│     └── ajv@6.12.6
├─┬ @nestjs/platform-fastify@10.3.8
│ └─┬ fastify@4.26.2
│   ├─┬ @fastify/ajv-compiler@3.5.0
│   │ └── ajv@8.12.0 deduped
│   └─┬ fast-json-stringify@5.14.1
│     ├─┬ ajv-formats@3.0.1
│     │ └── ajv@8.12.0 deduped
│     └── ajv@8.12.0 deduped
├─┬ @typescript-eslint/eslint-plugin@7.11.0
│ └─┬ eslint@8.57.0
│   ├─┬ @eslint/eslintrc@2.1.4
│   │ └── ajv@6.12.6
│   └── ajv@6.12.6
└─┬ orange-orm@4.0.0
  └── ajv@6.12.6

This is the result of the command. I see ajv version 8 and 6 are used. You think it is the problem ?

lroal commented 1 month ago

I suspect it - though I have not been able to reproduce. Does it stop reporting the error if you install ajv@^6.12.6 directly in your package.json. (You might need to import it as well) Not a good workaround, but helps me solve it.

Kyryus commented 1 month ago

Something is strange.

I deleted "node_module" folder and "dist" folder.

Then I saw your message and I did the command : npm install --save ajv@^6.12.6

And it looks like I do not have the error anymore even if I delete "ajv" and I remove folders "node_module" and "dist" again.

Basically I cannot reproduce it. I will try again later. Maybe the error is coming only on specific circumstances. If I can reproduce it, I will keep you in touch.

lroal commented 1 month ago

Good. Let me know if you have more problems

Kyryus commented 1 month ago

Hello Iroal,

Sorry to bother you again but I restarted computer and I again have the same problem. I tried delete "node-modules", "dist" and "package-lock.json" files and folders but nothing is working.

import orange from 'orange-orm';

const map = orange        <------- Error on this line
  .map((x) => ({
    // Table user
    user: x.table('user').map(({ column }) => ({
      id: column('id').numeric().primary().notNullExceptInsert(),
      email: column('email').string().notNull(),
      password: column('password').string().notNull(),
      name: column('name').string().notNull(),
      firstname: column('firstname').string().notNull(),
      country: column('country').string().notNull(),
      activation: column('activation').string(),
      pwdResetCode: column('pwdResetCode').string(),
      createdAt: column('createdAt').date(),
    })),
    ............

And I have the same error but another error appeared and maybe it can give you a hint about what is happening :

database/database_mapping.ts:3:7 - error TS2742: The inferred type of 'map' cannot be named without a reference to 'orange-orm/node_modules/ajv'. This is likely not portable. A type annotation is necessary.

3 const map = orange
        ~~~

database/database_mapping.ts:3:7 - error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.

3 const map = orange

I did not change the tsconfig and package.json that I attached you earlier.

Do you have an idea ? I tried install ajv@^6.12.6 but it doesn't solve the problem.

lroal commented 1 month ago

can you check if changing the first line of maps.d.ts in orange-orm to this helps: import { Options } from 'ajv';

As a last resort, is it possible to get read access to your repo so I can try to reproduce myself ?

Kyryus commented 1 month ago

can you check if changing the first line of maps.d.ts in orange-orm to this helps: import { Options } from 'ajv';

As a last resort, is it possible to get read access to your repo so I can try to reproduce myself ?

It is not working. I added you on my private repo to reproduce the problem.

lroal commented 1 month ago

I think I have found the source of the problem. Actually, there are two problems.

  1. This tsconfig setup does not handle ajv somehow. So I copied the respective ajv types directly into orange-orm. For testing, I published this branch to: https://github.com/alfateam/orange-orm/tree/ajv Then I changed the package.json to: "orange-orm": "github:alfateam/orange-orm#ajv"

  2. Then I got error: error TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed. This happens because declaration is set to true in tsconfig and the inferred types from orange-orm becomes too big. I think the declaration: true makes the compiler create d.ts files for every ts file. So I set the declaration to false. This removed the error, but then it was not able to find the main module Error: Cannot find module 'C:\Users\lars.roald\repos\orange-orm-debug\backend\dist\kyryus-backend\src\main' Then I checked if it is possible to exclude d.ts generation for certain files - and turns out this is not possible.

If you can figure out how to transpile the project with declaration set to false, it will work. The default value for declaration for tsconfig is false. so I am not sure why this nestjs setup insists it to be true.

Anyway, I will probably publish orange-orm with ajv types copied directly into it. That will at least solve one problem (though I have never experienced this problem in other tsconfig setups).

Kyryus commented 1 month ago

For the 1st problem, it would be nice if you can publish ajv types inside orange-orm. I will try the branch “ajv”.About second problem, I noticed that if I put “declaration” to “false” the problem disappear but when I read the doc https://www.typescriptlang.org/tsconfig/#declaration and it is said that this property is useful for intellisense. I can disable it but I hope it will not affect my dev experience with intellisense being less useful.

lroal commented 1 month ago

installing ts-watch and changing the following scripts in package.json, makes it work

  "start:debug": "tsc-watch -p tsconfig.build.json --onSuccess \"node --inspect-brk dist/src/main.js\"",
lroal commented 1 month ago

Just published orange-orm@4.0.1 with ajv as inhouse types.

For the 1st problem, it would be nice if you can publish ajv types inside orange-orm. I will try the branch “ajv”.About second problem, I noticed that if I put “declaration” to “false” the problem disappear but when I read the doc https://www.typescriptlang.org/tsconfig/#declaration and it is said that this property is useful for intellisense. I can disable it but I hope it will not affect my dev experience with intellisense being less useful.

Kyryus commented 1 month ago

Just published orange-orm@4.0.1 with ajv as inhouse types.

For the 1st problem, it would be nice if you can publish ajv types inside orange-orm. I will try the branch “ajv”.About second problem, I noticed that if I put “declaration” to “false” the problem disappear but when I read the doc https://www.typescriptlang.org/tsconfig/#declaration and it is said that this property is useful for intellisense. I can disable it but I hope it will not affect my dev experience with intellisense being less useful.

Thank you. So the error ts2742 disappeared completely.

For the error "TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.", it looks like the problem is coming from the fact that you have a lot of function into one namepace.

Maybe it is possible for you to separate functions like the guy did on this example : https://github.com/colinhacks/zod/issues/1040#issuecomment-1860690971

I am sorry to insist but I would like to keep "declaration" to "true" in tsconfig file.

Thank you again for your help. I cannot wait to use orange-orm :)

lroal commented 4 weeks ago

I tried splitting it up, but It did not help much as the size of the inferred type will depend on how many mappings you have in database_mappings.ts. I published it to https://github.com/alfateam/orange-orm/tree/splitTypes If you remove the some of the mappings (.e.g. the relations) , you will see it will work.

What I don't get, is why the default setup of nestjs wants to create d.ts files of the ts files. This seems to be only done in the dist folder. And in my eyes, is only relevant if you want to create a library.

However, another solution, if you still want declaration: true, is to have a separate tsconfig for the db_mappings. In this tsconfig, the declaration should be false (or just omitted). Then the db_mappings must reside in it's own folder and must be excluded from the main build. I think this means you have to have a two step build - but I am not 100 percent sure cause I have never tried multiple tsconfigs before.

lroal commented 4 weeks ago

Having declaration: true also slows down the transpile

Kyryus commented 4 weeks ago

I tried splitting it up, but It did not help much as the size of the inferred type will depend on how many mappings you have in database_mappings.ts. I published it to https://github.com/alfateam/orange-orm/tree/splitTypes If you remove the some of the mappings (.e.g. the relations) , you will see it will work.

What I don't get, is why the default setup of nestjs wants to create d.ts files of the ts files. This seems to be only done in the dist folder. And in my eyes, is only relevant if you want to create a library.

However, another solution, if you still want declaration: true, is to have a separate tsconfig for the db_mappings. In this tsconfig, the declaration should be false (or just omitted). Then the db_mappings must reside in it's own folder and must be excluded from the main build. I think this means you have to have a two step build - but I am not 100 percent sure cause I have never tried multiple tsconfigs before.

I think you are right and I will put "declaration" to "false". It is true that it is more used for people who create library which is not my case.

I did not try the separated tsconfig.json but it should work.

Thank you for the help, I think we can close the issue definitely.

lroal commented 4 weeks ago

Let me know if you run into more trouble. Also, I can add a Nestjs section in the FAQ

Kyryus commented 4 weeks ago

Let me know if you run into more trouble. Also, I can add a Nestjs section in the FAQ

It is true that when you check samples of NestJs, they put by default "declaration" to "true" so in the beginning I did not really want to change the value but I do not thing it is mandatory for NestJs. I will see by the usage.

Example of tsconfig for NestJs : https://github.com/nestjs/nest/blob/master/sample/10-fastify/tsconfig.json

lroal commented 4 weeks ago

Can you confirm it works - and then close the issue ?

Kyryus commented 4 weeks ago

It works perfectly now. Thank you for the fix included in 4.0.1 version.