node.js + typescript で typeorm を使おうとするといろいろハマったのでメモを残しておきます

Webアプリ開発

環境

  • OS: Windows 10 Pro
  • WSL2
    • ディストリビューション: Ubuntu20.04
  • node.js と npm はインストール済み
    • node.js: v16.15.1
    • npm: 8.12.1
  • npm にて以下をグローバルインストール済み
    • yarn
    • typescript
    • sqlite3

やろうとしていること

sqlite に対してORマッパーを適用しようと思い、Typescript では typeorm というライブラリがアツいということがわかったので、それを導入しようとしました。

とりあえずチュートリアル的に、以下を実行しようとしました。

  1. データベースに接続し、
  2. テーブルを作成し、
  3. 適当にレコードを書いて、
  4. 書いたレコードを読み込む

起きたこと

上記の動作が、なかなかうまくいきませんでした。

使用したライブりのバージョン

  • sqlite3: 5.0.8
  • typeorm: 0.3.6
  • typescript: 4.7.4

ディレクトリ構成

データベース周りを抜粋すると以下のような感じです。

- hoge
    |─ src
    |   |─databse
    |   |   └─ ormconfig.ts
    |   |   └─ testRepository.ts
    |   └─ entity
    |       └─ Test.ts
    |─ pacakge.json
    └─ test.db

参考にしたドキュメント

こちらをみてトライしてみました。

うまくいかなかったソース

以下、関連場所のみ抜粋

// Test.ts
import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity()
export default class Test {
  @PrimaryGeneratedColumn()
  readonly id: number;

  @Column('text', { nullable: false })
  text: string;

  @CreateDateColumn()
  readonly created_at?: Date;

  @UpdateDateColumn()
  readonly updated_at?: Date;

  constructor(text: string) {
    this.text = text;
  }
}
// ormconfig.ts
import { DataSource } from 'typeorm';
import path from 'path'

const dataSource = new DataSource({
    type: 'sqlite',
    database: path.join(process.cwd(), 'test.db'),
    entities: [{__dirname} + "../entity/*.{js,ts}"],
    synchronize: true
})

export default dataSource
// testRepository.ts
import { DataSource } from "typeorm";
import Test from "@/entity/Test";
import dataSource from './ormconfig';

export default class testRepository {

    public async add(text: string) {
        dataSource.initialize()
            .then(async () => {
                console.log("Data Source has been initialized!")
                const manager = dataSource.manager;
                const test = new Test(text);
                await manager.save(test);
                console.log("Saved a new test with text: " + test.text);

                console.log("Loading tests from the database...");
                const tests = await manager.find(Test);
                console.log("Loaded tests: ", tests);
            })
            .catch(err => {
                console.error("Error during Data Source initialization", err)
            });
    }
}

実行結果

上記で実行すると以下のようになりました。

$ npm run start
Data Source has been initialized!
Error during Data Source initialization EntityMetadataNotFoundError: No metadata for "Test" was found.
    at DataSource.getMetadata (/home/tashima/separate_vue_express/backend/node_modules/src/data-source/DataSource.ts:422:30)
    at /home/tashima/separate_vue_express/backend/node_modules/src/persistence/EntityPersistExecutor.ts:84:56
    at Array.forEach (<anonymous>)
    at /home/tashima/separate_vue_express/backend/node_modules/src/persistence/EntityPersistExecutor.ts:77:30
    at Array.map (<anonymous>)
    at EntityPersistExecutor.execute (/home/tashima/separate_vue_express/backend/node_modules/src/persistence/EntityPersistExecutor.ts:73:34)
    at async /home/tashima/separate_vue_express/backend/src/database/testRepository.ts:16:17

このエラー、そこそこ発生しているらしく、ググったらたくさん症例が出ています。
しかし、どの解決策を試しても自分の環境ではうまくいきませんでした・・・

解決方法

手さぐりでしたが、以下のように ormconfig.ts を変更すると解決しました。

import { DataSource } from 'typeorm';
import path from 'path'
+ import Test from "../entity/Test";

const dataSource = new DataSource({
    type: 'sqlite',
    database: path.join(process.cwd(), 'test.db'),
-    entities: [{ __dirname } + "../entity/*.{js,ts}"],
+    entities: [Test],
    synchronize: true
})

export default dataSource

結構きつかった・・・

コメント

タイトルとURLをコピーしました