4
3

More than 3 years have passed since last update.

NextJS + TypeORM 設定

Last updated at Posted at 2021-03-14

package

yarn add typeorm
yarn add -D babel-plugin-transform-typescript-metadata @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators ts-node

env

env.development.local
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USERNAME=root
DATABASE_PASSWORD=
DATABASE_NAME=testdb

ormconfig.js作成

ormconfig.js
require('dotenv').config({ path: '.env.development.local' });

module.exports = {
  type: process.env.DATABASE_TYPE,
  host: process.env.DATABASE_HOST,
  port: process.env.DATABASE_PORT,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
  database: process.env.DATABASE_NAME,
  synchronize: false,
  logging: true,
  entities: ['db/entities/**/*.ts'],
  migrations: ['db/migrations/**/*.ts'],
  subscribers: ['db/subscribers/**/*.ts'],
  cli: {
    entitiesDir: 'db/entities',
    migrationsDir: 'db/migrations',
    subscribersDir: 'db/subscribers'
  }
};

tsconfig.json一部オプション追加

tsconfig.json
{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
  }
}

babel plugin 追加

.babelrc.js
module.exports = {
  presets: ['next/babel'],
  plugins: [
    'babel-plugin-transform-typescript-metadata',
    ['@babel/plugin-proposal-decorators', { legacy: true }],
  ]
};

こうしないと吐かれるれるエラー

Syntax error: Support for the experimental syntax 'decorators-legacy' isn't currently enabled:
ColumnTypeUndefinedError: Column type for User#** 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.

Entity作成

db/entities/User.ts
import { Entity, BaseEntity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm';
import { UserProfile } from './index';

@Entity({ name: 'users' })
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  readonly id: number;

  @OneToOne(() => UserProfile, (userProfile: UserProfile) => userProfile.user)
  @JoinColumn()
  userProfile: UserProfile;
}
db/entities/UserProfile.ts
import {
  Entity,
  BaseEntity,
  PrimaryGeneratedColumn,
  Column,
  OneToOne,
  JoinColumn
} from 'typeorm';
import { User } from './index';

@Entity({ name: 'userProfiles' })
export class UserProfile extends BaseEntity {
  @PrimaryGeneratedColumn()
  readonly id: number;

  @OneToOne(() => User, (user: User) => user.userProfile)
  @JoinColumn()
  user: User;

importするときは、以下のようにまとめてこのファイルからimportするようにしないとエラーになる

db/entities/index.ts
import { User } from './User';
import { UserProfile } from './UserProfile';

export { User, UserProfile };

こうしないと吐かれるれるエラー

ReferenceError: Cannot access 'User' before initialization

migration実行

package.json

package.json
{
  "scripts": {
    "typeorm": "ts-node ./node_modules/typeorm/cli.js",
    "db:migrate:create": "yarn typeorm migration:generate -n",
    "db:migrate:run": "yarn typeorm migration:run",
    "db:reset:init": "yarn typeorm schema:drop; rm -rf db/migrations/*; yarn db:migrate:create init; yarn db:migrate:run"
  }
}

yarn db:reset:init

connection

db/db.ts
import 'reflect-metadata';
import { getConnection, createConnection, Connection } from 'typeorm';
import { User, UserProfile } from '@db/entities';

const host = process.env.DATABASE_HOST || '';
const port = Number(process.env.DATABASE_PORT) || 3306;
const username = process.env.DATABASE_USERNAME || '';
const password = process.env.DATABASE_PASSWORD || '';
const database = process.env.DATABASE_NAME || '';

let connectionReadyPromise: Promise<Connection> | null = null;

export const prepareConnection = () => {
  if (!connectionReadyPromise) {
    connectionReadyPromise = (async () => {
      // clean up old connection that references outdated hot-reload classes
      try {
        const staleConnection = getConnection();
        await staleConnection.close();
      } catch (error) {
        // no stale connection to clean up
      }

      // wait for new default connection
      const connection = await createConnection({
        type: 'mysql',
        host,
        port,
        username,
        password,
        database,
        entities: [User, UserProfile],
        synchronize: false,
        logging: true
      });

      return connection;
    })();
  }

  return connectionReadyPromise;
};

使い方

import { prepareConnection } from '@db/db';
import { User } from '@db/entities';

(async () => {
  const db = await prepareConnection();
  const user = await db.getRepository(User).find();
  console.log(user);
})();

参考

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3