Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support TypeORM #4136

Open
anurag-roy opened this issue Aug 12, 2023 · 11 comments
Open

Support TypeORM #4136

anurag-roy opened this issue Aug 12, 2023 · 11 comments
Labels
bug Something isn't working typescript Something for TypeScript

Comments

@anurag-roy
Copy link

anurag-roy commented Aug 12, 2023

What version of Bun is running?

0.7.3

What platform is your computer?

Linux 5.15.0-78-generic x86_64 x86_64

What steps can reproduce the bug?

  1. Clone this repo:

    git clone https://github.com/anurag-roy/bun-typeorm-issue
    

    This was generated using typeorm cli and I updated some stuff in tsconfig and dependencies.

  2. Install dependencies

    bun install
    
  3. (Optional) Setup a local mysql server at port 3306. This step is optional because we can reproduce the error before even typeorm attempts to connect to a db.

  4. Run file

    bun run src/index.ts
    

What is the expected behavior?

The file should run successfully and print some logs of adding a user (If db successfully setup) or show that the connection was not found.

What do you see instead?

❯ bun run src/index.ts
4 | class TypeORMError extends Error {
5 |     get name() {
6 |         return this.constructor.name;
7 |     }
8 |     constructor(message) {
9 |         super(message);
            ^
error: Column type for User#firstName is not defined and cannot be guessed. Make sure you have turned on an "emitDecoratorMetadata": true option in tsconfig.json. Also make sure you have imported "reflect-metadata" on top of the main entry file in your application (before any entity imported).If you are using JavaScript instead of TypeScript you must explicitly provide a column type.
      at new TypeORMError (/home/anurag/Developer/Hobby/bun-typeorm/node_modules/typeorm/error/TypeORMError.js:9:8)
      at new ColumnTypeUndefinedError (/home/anurag/Developer/Hobby/bun-typeorm/node_modules/typeorm/error/ColumnTypeUndefinedError.js:11:8)
      at /home/anurag/Developer/Hobby/bun-typeorm/node_modules/typeorm/decorator/columns/Column.js:52:22
      at /home/anurag/Developer/Hobby/bun-typeorm/src/entity/User.ts:9:2

Additional information

This is what my tsconfig.json looks like:

{
  "compilerOptions": {
    "lib": ["ESNext"],
    "module": "CommonJS",
    "target": "ESNext",
    "moduleResolution": "bundler",
    "moduleDetection": "force",
    "outDir": "./build",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "allowImportingTsExtensions": true,
    "strict": true,
    "downlevelIteration": true,
    "skipLibCheck": true,
    "jsx": "preserve",
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "allowJs": true,
    "noEmit": true,
    "types": [
      "bun-types" // add Bun global
    ]
  }
}

Looks like Bun is ignoring "emitDecoratorMetadata" present in my tsconfig. Or does it not support it?

@anurag-roy anurag-roy added the bug Something isn't working label Aug 12, 2023
@Electroid
Copy link
Contributor

Thanks for reporting, what's the error you run into?

@anurag-roy
Copy link
Author

anurag-roy commented Aug 12, 2023

Sorry @Electroid, I submitted the issue by mistake before completely filling it out. I have updated the comment now.

@bnussman
Copy link

bnussman commented Aug 12, 2023

I'm not sure how far Bun will support the TS decorators stuff. You may be able to "compile" your app with tsc and run the TSC's output with bun (bun run build/index.js).

I use Mikro-ORM and that's what I'm doing right now.

@anurag-roy anurag-roy changed the title TypeORM doesn't work Support TypeORM Aug 12, 2023
@crishoj
Copy link

crishoj commented Aug 25, 2023

I use Mikro-ORM and that's what I'm doing right now.

@bnussman, may I know how you init MikroORM with only .ts entities?
It seems to expect both .ts and .js files:

const orm = await MikroORM.init<SqliteDriver>({
    entities: ['./entities/**/*.ts'], // path to our JS entities (dist), relative to `baseDir`
    entitiesTs: ['./entities/**/*.ts'], // path to our TS entities (source), relative to `baseDir`
});

@bnussman
Copy link

Use JS for the entities. Like I said: build with tsc and run the outputted JS with bun.

const config: Options = {
  entities: ['./build/entities/*.js'],
  entitiesTs: ['./src/entities/*.ts'],
};

@Jarred-Sumner
Copy link
Collaborator

I think @dylan-conway will have an exciting update for you today

@bnussman
Copy link

OMG! Nevermind, seems like @Jarred-Sumner is here to save the day ❤️🚀

@ceopaludetto
Copy link

I was able to use Mikro-ORM by creating a plugin:

import type { BunPlugin } from "bun";

import { readFile } from "fs/promises";

import strip from "strip-comments";
import { transpileModule, type TranspileOptions } from "typescript";

// fix this import based on your tsconfig location
import config from "../../tsconfig.json";

const theFinder = /((?<![(\s]\s*['"])@\w[.[\]\w\d]*\s*(?![;])[((?=\s)])/;
const findDecorators = (fileContent: string) => theFinder.test(strip(fileContent));

export const bunDecorators: BunPlugin = {
  name: "bun-decorators",
  setup: (build) => {
    build.onLoad({ filter: /\.ts$/ }, async ({ path }) => {
      const fileContent = await readFile(path, "utf-8");
      const hasDecorators = findDecorators(fileContent);

      if (!hasDecorators) return { contents: fileContent };
      return { contents: transpileModule(fileContent, config as unknown as TranspileOptions).outputText };
    });
  },
};

This plugin parses files that contains decorators using typescript transpileModule. Now instead of using entities and entitiesTs options on MikroORM you should import your entities. I usually do:

src/
  entities/
    some.entity.ts
    another.entity.ts
    index.ts // export every entity here
  index.ts // MikroORM.init here
import * as entities from "./entities"

MikroORM.init({
  entities: [...Object.values(entities)]
})

@Zikoat
Copy link

Zikoat commented Jan 25, 2024

Current ts-node output with the above reproduction (after fixing some type errors):

$ ts-node ./src/index.ts
Error: connect ECONNREFUSED 127.0.0.1:3306
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16)
    --------------------
    at Protocol._enqueue (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/protocol/Protocol.js:144:48)
    at Protocol.handshake (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/protocol/Protocol.js:51:23)
    at PoolConnection.connect (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/Connection.js:116:18)
    at Pool.getConnection (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/Pool.js:48:16)
    at /home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/typeorm/src/driver/mysql/MysqlDriver.ts:1268:18
    at new Promise (<anonymous>)
    at MysqlDriver.createPool (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/typeorm/src/driver/mysql/MysqlDriver.ts:1265:16)
    at MysqlDriver.connect (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/typeorm/src/driver/mysql/MysqlDriver.ts:400:36)
    at DataSource.initialize (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/src/data-source/DataSource.ts:252:47)
    at Object.<anonymous> (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/src/index.ts:4:15) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 3306,
  fatal: true
}

Output with bun:

bun run ./src/index.ts
105 |   if (!callSiteStack || typeof callSiteStack !== 'string') {
106 |     // No recorded call site
107 |     return;
108 |   }
109 | 
110 |   if (err.stack.indexOf(LONG_STACK_DELIMITER) !== -1) {
            ^
TypeError: undefined is not an object (evaluating 'err.stack.indexOf')
      at _addLongStackTrace (/home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/protocol/sequences/Sequence.js:110:7)
      at /home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/protocol/sequences/Sequence.js:65:5
      at /home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/protocol/Protocol.js:369:5
      at /home/zikoat/dev/typerom-repro/bun-typeorm-issue/node_modules/mysql/lib/Connection.js:418:3
      at node:net:375:35

However, when fixing the undefined reference, we get the error:

bun run ./src/index.ts
ECONNREFUSED: Failed to connect
 syscall: "connect"

Which doesnt include the yrl, but the error looks a bit nicer. I guess this can be closed, unless you guys want to fix the differing behavior regarding the error.

@sfardiansyah-syky
Copy link

sfardiansyah-syky commented Mar 31, 2024

I think it's because net.Socket hasn't fully implemented in Bun. As shown in issues that uses socket connection: #7325, #7851, #8789

@sfardiansyah-syky
Copy link

This net.Socket connection issue still not resolved in Bun v1.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working typescript Something for TypeScript
Projects
None yet
Development

No branches or pull requests

8 participants