Breeze / breeze-client

Breeze for JavaScript clients
MIT License
38 stars 16 forks source link

Cannot create property 'lt' on number 'x' #43

Closed iulianb closed 3 years ago

iulianb commented 3 years ago

The UI library we're using (DevExtreme) generates a where predicate that seems to cause some serialization issues in breeze. I'm attaching a test that reproduces the exception.

import { breeze } from 'breeze-client';
import { ModelLibraryBackingStoreAdapter } from 'breeze-client/adapter-model-library-backing-store';
import { TestFns } from './test-fns';

ModelLibraryBackingStoreAdapter.register();

TestFns.initNonServerEnv();

describe("complex predicate testing", () => {

    beforeEach(function () {
        TestFns.initSampleMetadataStore();
    });

    test("should serialize complex predicate", () => {
        const equals = new breeze.Predicate('productID', breeze.FilterQueryOp.Equals, 1);
        const lessThan = new breeze.Predicate('productID', breeze.FilterQueryOp.LessThan, 1);
        const predicate = breeze.Predicate.and(equals, lessThan);

        const ms = TestFns.sampleMetadataStore;
        const et = ms.getAsEntityType('Product');
        const context = {
            entityType: et,
            propertyPathFn: <any>null
        };

        context.propertyPathFn = et.clientPropertyPathToServer.bind(context.entityType);

        // throws: Cannot create property 'lt' on number '1'
        const serialized = predicate.toJSONExt(context);

        expect(serialized).not.toBe(null);
    });
});

Haven't looked into what causes it but I'm willing to investigate and submit a PR if needed.

steveschmitt commented 3 years ago

Interesting. Thanks for the test.

I haven't tried running it yet, but I'm looking at these lines:

const equals = new breeze.Predicate('productID', breeze.FilterQueryOp.Equals, 1);
const lessThan = new breeze.Predicate('productID', breeze.FilterQueryOp.LessThan, 1);
const predicate = breeze.Predicate.and(equals, lessThan);

The predicate is looking for any productID that is both equal to 1 AND less than one, which is impossible. If it should be OR instead of AND, then the code should just be

const predicate = breeze.Predicate('productID', breeze.FilterQueryOp.LessThanOrEqual, 1);

Of course, none of this explains the strange error that you got, and it probably won't help with your DevExtreme problem. I'll see what's going on in your test.

iulianb commented 3 years ago

Yes, the predicate doesn't really make sense (it's actually just the troublesome part of a more branchy one) and I should probably also check why DevExtreme generates it but breeze crashed because of it and I thought it might be a bug.

steveschmitt commented 3 years ago

Yep, it was a bug. The error was in some code that attempts to combine predicates. It'll be fixed in the next release.

Out of curiosity, is DevExtreme creating Breeze predicates? Or have you written something that converts DevExtreme's queries into Breeze?

Thanks again for finding this.

steveschmitt commented 3 years ago

Fixed in release 2.0.9

iulianb commented 3 years ago

DevExtreme has an adapter that translates the internal filter data structure into breeze predicates. It can be found here: https://github.com/DevExpress/DevExtreme-Data-BreezeJS.

Thank you for the fix!

marcelgood commented 3 years ago

@iulianb the DevExtreme adapter has been archived and is no longer maintained. It actually has a number of issues that we've reported to them, but never heard anything back. Just something to be aware of. We have used DevExtreme on several projects ourselves, but have resorted to writing our own layer to interact with Breeze. We do offer consulting if you are interested in a more robust and supported integration between DevExtreme and Breeze.

iulianb commented 3 years ago

@marcelgood Yes, I'm aware of that. We did change some of the stuff in there to suit our needs. I'll discuss your offer with the managers. Thank you!