SoftwareBrothers / adminjs-sequelizejs

Sequelizejs adapter for AdminBro
MIT License
27 stars 34 forks source link

Cannot create a record whose PK isn't autoincrement #110

Open fabiosantoscode opened 1 year ago

fabiosantoscode commented 1 year ago

Hello there! I'm using adminJS together with sequelize, and I have to say, thanks for saving me from tedious admin code! :heart:

I have a country table with a countryCode PK that I'm not able to fill in using adminjs.

I understand it shouldn't be editable (it's a primary key after all) but I noticed that creating a new country resulted in a SQL query that didn't have a countryCode.

Here are the relevant bits of my Country model:

class Country extends Sequelize.Model {
  static init(sequelize, DataTypes) {
    return super.init(
      {
        countryCode: {
          type: DataTypes.CHAR(3),
          allowNull: false,
          primaryKey: true,
        },
        // ...
      },
      {
        // ...
        indexes: [
          {
            name: 'PRIMARY',
            unique: true,
            using: 'BTREE',
            fields: [{ name: 'countryCode' }],
          },
        ],
      }
    )
  }
}

After some digging, I noticed that in property.ts there is a isEditable function that returns false if the field is a primary key.

I fixed the issue using patch-package, by making isEditable not check isId during creation. The patch is below:


diff --git a/node_modules/@adminjs/sequelize/src/property.ts b/node_modules/@adminjs/sequelize/src/property.ts
index a135452..b586e15 100644
--- a/node_modules/@adminjs/sequelize/src/property.ts
+++ b/node_modules/@adminjs/sequelize/src/property.ts
@@ -43,14 +43,14 @@ class Property extends BaseProperty {
     return this.fieldName;
   }

-  isEditable(): boolean {
+  isEditable({ forCreate }: { forCreate?: boolean } = {}): boolean {
     if ((this.sequelizePath as any)._autoGenerated) {
       return false;
     }
     if (this.sequelizePath.autoIncrement) {
       return false;
     }
-    if (this.isId()) {
+    if (!forCreate && this.isId()) {
       return false;
     }
     return true;
diff --git a/node_modules/@adminjs/sequelize/src/resource.ts b/node_modules/@adminjs/sequelize/src/resource.ts
index e36a0e0..89562c1 100644
--- a/node_modules/@adminjs/sequelize/src/resource.ts
+++ b/node_modules/@adminjs/sequelize/src/resource.ts
@@ -156,7 +156,7 @@ class Resource extends BaseResource {
   }

   async create(params): Promise<Record<string, any>> {
-    const parsedParams = this.parseParams(params);
+    const parsedParams = this.parseParams(params, { forCreate: true });
     const unflattedParams = flat.unflatten<any, any>(parsedParams);
     try {
       const record = await this.SequelizeModel.create(unflattedParams);
@@ -215,7 +215,7 @@ class Resource extends BaseResource {
    *
    * @return  {Object}          converted params
    */
-  parseParams(params) {
+  parseParams(params, { forCreate }: { forCreate?: boolean } = {}) {
     const parsedParams = { ...params };
     this.properties().forEach((property) => {
       const value = parsedParams[property.name()];
@@ -224,7 +224,7 @@ class Resource extends BaseResource {
           delete parsedParams[property.name()];
         }
       }
-      if (!property.isEditable()) {
+      if (!property.isEditable({ forCreate })) {
         delete parsedParams[property.name()];
       }
     });