From 47a6431a5d08fd8288787e001fd26f819b0a6f02 Mon Sep 17 00:00:00 2001 From: Mike Cornwell Date: Wed, 24 Sep 2025 10:01:40 -0400 Subject: [PATCH 1/2] feat(query): update query interface to have NOT and includes --- package.json | 2 +- src/orm/query.ts | 3 +++ src/orm/types.ts | 37 ++++++++++++++++++++++--------------- test/src/orm/query.test.ts | 7 +++++++ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 7e2f7e2..71ce4d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "functional-models", - "version": "3.1.0", + "version": "3.2.0", "description": "Functional models is ooey gooey framework for building and using awesome models EVERYWHERE.", "main": "index.js", "types": "index.d.ts", diff --git a/src/orm/query.ts b/src/orm/query.ts index a081a99..49fcf8a 100644 --- a/src/orm/query.ts +++ b/src/orm/query.ts @@ -159,6 +159,7 @@ const property = ( caseSensitive, startsWith, endsWith, + includes, type, } = options const typeToUse = type || DatastoreValueType.string @@ -167,6 +168,7 @@ const property = ( } if ( equalitySymbol !== EqualitySymbol.eq && + equalitySymbol !== EqualitySymbol.ne && typeToUse === DatastoreValueType.string ) { throw new Error(`Cannot use a non = symbol for a string type`) @@ -182,6 +184,7 @@ const property = ( ..._objectize('caseSensitive', caseSensitive), ..._objectize('startsWith', startsWith), ..._objectize('endsWith', endsWith), + ..._objectize('includes', includes), }, } return propertyEntry diff --git a/src/orm/types.ts b/src/orm/types.ts index 060e005..49e685b 100644 --- a/src/orm/types.ts +++ b/src/orm/types.ts @@ -28,6 +28,8 @@ enum EqualitySymbol { gt = '>', // Equal to or greater than gte = '>=', + // Not equal to + ne = '!=', } /** @@ -453,22 +455,18 @@ type PropertyQuery = Readonly<{ /** * Options for additional matching. */ - options: { - /** - * Should this be a case sensitive search. (for text) - */ - caseSensitive?: boolean - /** - * Indicates that the value is a "startsWith" query. - */ - startsWith?: boolean - /** - * Indicates that the value is a "endsWith" query. - */ - endsWith?: boolean - } + options: PropertyOptions }> +/** + * A property search for a string value. + */ +type StringPropertyQuery = PropertyQuery & { + valueType: DatastoreValueType.string + equalitySymbol: EqualitySymbol.eq | EqualitySymbol.nq + options: PropertyOptions +} + /** * A search that looks at dated objects after the given date. * @interface @@ -575,6 +573,10 @@ type PropertyOptions = { * Is the value a endsWith query? */ endsWith?: boolean + /** + * Is the value a includes query? + */ + includes?: boolean /** * The type of value */ @@ -660,7 +662,11 @@ type OrmSearch = { /** * Statements that make up the meat of QueryTokens */ -type Query = PropertyQuery | DatesAfterQuery | DatesBeforeQuery +type Query = + | PropertyQuery + | DatesAfterQuery + | DatesBeforeQuery + | StringPropertyQuery /** * A token type that links two queries together. @@ -815,4 +821,5 @@ export { QueryTokens, InnerBuilderV2, SortOrder, + StringPropertyQuery, } diff --git a/test/src/orm/query.test.ts b/test/src/orm/query.test.ts index 85acaf9..14fe111 100644 --- a/test/src/orm/query.test.ts +++ b/test/src/orm/query.test.ts @@ -425,6 +425,13 @@ describe('/src/orm/query.ts', () => { }) }, 'blah is not a valid symbol') }) + it('should NOT throw an exception if the type is string and equalitySymbol is ne', () => { + assert.doesNotThrow(() => { + property('my-name', 'my-value', { + equalitySymbol: EqualitySymbol.ne, + }) + }) + }) }) describe('#and()', () => { it('should return AND', () => { From 84386678cab10e97923d1c8797f64a017ea29c19 Mon Sep 17 00:00:00 2001 From: Mike Cornwell Date: Wed, 24 Sep 2025 10:02:25 -0400 Subject: [PATCH 2/2] fix(bug): fix issue --- src/orm/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orm/types.ts b/src/orm/types.ts index 49e685b..4c1c5c9 100644 --- a/src/orm/types.ts +++ b/src/orm/types.ts @@ -463,7 +463,7 @@ type PropertyQuery = Readonly<{ */ type StringPropertyQuery = PropertyQuery & { valueType: DatastoreValueType.string - equalitySymbol: EqualitySymbol.eq | EqualitySymbol.nq + equalitySymbol: EqualitySymbol.eq | EqualitySymbol.ne options: PropertyOptions }