node.jssequelize.jsadmin-broadminjs

How to handle a composite primary key in adminbro/adminjs?


accounts

id email email_verified is_primary password picture_url social_account_id username created_at updated_at

users

id enabled created_at updated_at

user_accounts

account_id user_id created_at updated_at

As you notice my user_accounts table has a composite primary key (account_id, user_id) How do I manage this on adminbro/adminjs?

I think it currenty takes one of them as the primary key automatically

enter image description here

My main complaint is that I am unable to create any records for this table currently

enter image description here

My adminbro route

import { sequelize } from '../../data/models';

import AdminBro from 'adminjs';
import AdminBroExpress from '@adminjs/express';
import AdminBroSequelize from '@adminjs/sequelize';

AdminBro.registerAdapter(AdminBroSequelize);
const adminBro = new AdminBro({
  rootPath: '/admin',
  resources: [
    {
      resource: sequelize.models.Account,
      options: {
        parent: {
          name: 'Database',
          icon: 'Api',
        },
        listProperties: [
          'id',
          'email',
          'emailVerified',
          'isPrimary',
          'password',
          'pictureUrl',
          'socialAccountId',
          'username',
        ],
      },
    },
    {
      resource: sequelize.models.User,
      options: {
        parent: {
          name: 'Database',
          icon: 'Api',
        },
        listProperties: ['id', 'enabled'],
      },
    },
    {
      resource: sequelize.models.UserAccount,
      options: {
        parent: {
          name: 'Database',
          icon: 'Api',
        },
        listProperties: ['id', 'accountId', 'userId'],
      },
    },
  ],
  branding: {
    companyName: 'API',
    logo: false,
    favicon: 'https://imagine.ai/img/favicon.ico',
    withMadeWithLove: false,
  },
});
const adminbroRouter = AdminBroExpress.buildRouter(adminBro);

export default adminbroRouter;

EDIT 1

UserAccount.model.ts

/* eslint import/no-cycle: "off" */
import { DataTypes } from 'sequelize';
import {
  Model,
  PrimaryKey,
  Column,
  Table,
  Default,
  IsUUID,
  ForeignKey,
} from 'sequelize-typescript';
import { Account, User } from 'data/models';

@Table({
  freezeTableName: true,
  tableName: 'user_accounts',
})
export default class UserAccount extends Model {
  @ForeignKey(() => Account)
  @PrimaryKey
  @IsUUID(4)
  @Default(DataTypes.UUIDV4)
  @Column
  accountId: string;

  @ForeignKey(() => User)
  @PrimaryKey
  @IsUUID(4)
  @Default(DataTypes.UUIDV4)
  @Column
  userId: string;
}

Solution

  • According to Rafał Dzięgielewski:

    A single primary key is currently required, this is mostly because of how app routing works in AdminJS.

    AdminJS on Slack