question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Regression] v1.6.3 introduces entity__customFields error with custom field relations

See original GitHub issue

Describe the bug

In v1.6.3 I made commit https://github.com/vendure-ecommerce/vendure/commit/9834225 which was an attempt to solve #1636. Unfortunately that commit introduced a regression when defining custom field relations on certain ChannelAware entities:

TypeORMError: "entity__customFields" alias was not found. Maybe you forgot to join it?

To Reproduce

Repro instructions courtesy of @vrosa:

I’m getting the same entity__customFields error after upgrading to v1.6.3. It fails when trying to edit a product in the Admin UI - GetProductWithVariants query. I’ve added 2 custom fields to Product, one of type “relation”, which is public, and a non-public “number”.

config.customFields.Product.push({
  name: 'vendor',
  label: [{ languageCode: LanguageCode.en_AU, value: 'Vendor' }],
  type: 'relation',
  entity: Vendor,
  eager: true,
  nullable: false,
  defaultValue: null,
  ui: {
    component: 'cp-product-vendor-selector',
  },
});

config.customFields.Product.push({
  name: 'shopifyId',
  type: 'float',
  public: false,
});

Vendor is a custom entity that has a one-to-many relationship with Product:

@OneToMany(() => Product, (product) => product.customFields.vendor)
products: Product[];
query
query GetProductWithVariants(
  $id: ID!
  $variantListOptions: ProductVariantListOptions
) {
  product(id: $id) {
    ...ProductDetail
    variantList(options: $variantListOptions) {
      items {
        ...ProductVariant
        __typename
      }
      totalItems
      __typename
    }
    __typename
  }
}

fragment ProductDetail on Product {
  id
  createdAt
  updatedAt
  enabled
  languageCode
  name
  slug
  description
  featuredAsset {
    ...Asset
    __typename
  }
  assets {
    ...Asset
    __typename
  }
  translations {
    id
    languageCode
    name
    slug
    description
    __typename
  }
  optionGroups {
    ...ProductOptionGroup
    __typename
  }
  facetValues {
    id
    code
    name
    facet {
      id
      name
      __typename
    }
    __typename
  }
  channels {
    id
    code
    __typename
  }
  customFields {
    vendor {
      id
      createdAt
      updatedAt
      name
      __typename
    }
    __typename
  }
  __typename
}

fragment ProductOptionGroup on ProductOptionGroup {
  id
  createdAt
  updatedAt
  code
  languageCode
  name
  translations {
    id
    languageCode
    name
    __typename
  }
  __typename
}

fragment Asset on Asset {
  id
  createdAt
  updatedAt
  name
  fileSize
  mimeType
  type
  preview
  source
  width
  height
  focalPoint {
    x
    y
    __typename
  }
  __typename
}

fragment ProductVariant on ProductVariant {
  id
  createdAt
  updatedAt
  enabled
  languageCode
  name
  price
  currencyCode
  priceWithTax
  stockOnHand
  stockAllocated
  trackInventory
  outOfStockThreshold
  useGlobalOutOfStockThreshold
  taxRateApplied {
    id
    name
    value
    __typename
  }
  taxCategory {
    id
    name
    __typename
  }
  sku
  options {
    ...ProductOption
    __typename
  }
  facetValues {
    id
    code
    name
    facet {
      id
      name
      __typename
    }
    __typename
  }
  featuredAsset {
    ...Asset
    __typename
  }
  assets {
    ...Asset
    __typename
  }
  translations {
    id
    languageCode
    name
    __typename
  }
  channels {
    id
    code
    __typename
  }
  customFields {
    __typename
  }
  __typename
}

fragment ProductOption on ProductOption {
  id
  createdAt
  updatedAt
  code
  languageCode
  name
  groupId
  translations {
    id
    languageCode
    name
    __typename
  }
  __typename
}
{
  "id": "5",
  "variantListOptions": {
    "take": 10
  }
}

Expected behavior No error

Environment (please complete the following information):

  • @vendure/core version: 1.6.3
  • Nodejs version: any
  • Database (mysql/postgres etc): any?

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:10 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
michaelbromleycommented, Jul 20, 2022

Oh my that was a tough one. I’ve implemented a “fix” - more of a work-around of a TypeORM issue for now. Will release a patch with this in the coming day or so.

2reactions
vrosacommented, Jul 20, 2022

@michaelbromley It took me a while but I found the trigger:

- import { LanguageCode, PluginCommonModule, Product, VendureEntity, VendurePlugin } from '@vendure/core';
+ import { LanguageCode, PluginCommonModule, Product, Translation, VendureEntity, VendurePlugin } from '@vendure/core'; 
import gql from 'graphql-tag';
import { Column, Entity, OneToMany } from 'typeorm';

@Entity()
class Vendor extends VendureEntity {
    constructor(input: Partial<Vendor>) {
        super(input);
    }
+
+  description: LocaleString;

    @Column()
    name: string;

    @OneToMany(() => Product, product => (product.customFields as any).vendor)
    products: Product[];
+
+ @OneToMany(() => VendorTranslation, (translation) => translation.base, { eager: true })
+ translations: Array<Translation<Vendor>>;
}
+
+ @Entity()
+ export class VendorTranslation extends VendureEntity implements Translation<Vendor> {
+   constructor(input?: Partial<Translation<Vendor>>) {
+     super(input);
+   }
+ 
+   @Column('varchar')
+   languageCode: LanguageCode;
+ 
+   @Column('text')
+   description: string;
+ 
+   @ManyToOne(() => Vendor, (vendor) => vendor.translations, { onDelete: 'CASCADE' })
+   base: Vendor;
+ }

const schema = gql`
    type Vendor implements Node {
        id: ID!
        createdAt: DateTime!
        updatedAt: DateTime!
        name: String!
+       description: String!
    }
`;

@VendurePlugin({
    imports: [PluginCommonModule],
-    entities: [Vendor],
+    entities: [Vendor, VendorTranslation],
    shopApiExtensions: { schema, resolvers: [] },
    adminApiExtensions: { schema, resolvers: [] },
    configuration: config => {
        config.customFields.Product.push({
            name: 'vendor',
            label: [{ languageCode: LanguageCode.en_AU, value: 'Vendor' }],
            type: 'relation',
            entity: Vendor,
            eager: true,
            nullable: false,
            defaultValue: null,
            ui: {
                component: 'cp-product-vendor-selector',
            },
        });

        config.customFields.Product.push({
            name: 'shopifyId',
            type: 'float',
            public: false,
        });
        return config;
    },
})
export class Test1664Plugin {}

Seems like the problem happens when the entity associated to a custom field has relationships of its own and loads those relations eagerly. Unfortunately I haven’t found a fix but FindOptionsUtils.joinEagerRelations is what throws the error.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Detect if an object allows creation of custom fields
EntityDefinition object has an attribute IsCustomizable which tells if custom fields can be defined for the entity.
Read more >
Customizing Models With Custom Fields - Vendure docs
Custom fields allow you to add your own custom data properties to many of the Vendure entities. The entities which may have custom...
Read more >
fatal error when viewing custom fields with money > 1000 ...
To replicate - create a custom field of type money - mine was against entity contribution. Create a contribution (or whatever) with the...
Read more >
NetSuite Applications Suite - Creating a Custom Field
2.1 Script Debugger Overview · Introduction to Chrome DevTools for SuiteScript 2.1 Script Debugging · On-Demand Debugging of SuiteScript 2.1 Scripts.
Read more >
Adding and Editing Fields - iCIMS
Adding a Custom Field to a Profile Tab Section; Editing Existing Fields. Understanding Field Terminology. Profile Organization and Terminology. Profiles are ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found