From bb63402ac9ab885361a6bca73fb370af3c2d6e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20St-Georges?= Date: Sat, 8 Mar 2025 10:29:17 -0500 Subject: [PATCH 01/12] Fix S3 integration custom endpoints usage --- packages/server/src/integrations/s3.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/server/src/integrations/s3.ts b/packages/server/src/integrations/s3.ts index 88d00724f1..32a44c838b 100644 --- a/packages/server/src/integrations/s3.ts +++ b/packages/server/src/integrations/s3.ts @@ -168,6 +168,7 @@ class S3Integration implements IntegrationBase { secretAccessKey: config.secretAccessKey, }, region: config.region, + endpoint: config.endpoint, } if (config.endpoint) { this.config.forcePathStyle = true From e55e73f004d78b9ae7675ed8b46a50de38487c83 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 3 Mar 2025 16:36:28 +0100 Subject: [PATCH 02/12] Remove unnecessary sort from api --- packages/frontend-core/src/fetch/TableFetch.ts | 4 +--- packages/frontend-core/src/fetch/ViewV2Fetch.ts | 7 +++---- packages/types/src/api/web/app/rows/search.ts | 8 +------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/frontend-core/src/fetch/TableFetch.ts b/packages/frontend-core/src/fetch/TableFetch.ts index a6f92c0ab3..59bfc588f5 100644 --- a/packages/frontend-core/src/fetch/TableFetch.ts +++ b/packages/frontend-core/src/fetch/TableFetch.ts @@ -29,8 +29,7 @@ export default class TableFetch extends BaseDataFetch { } async getData() { - const { datasource, limit, sortColumn, sortOrder, sortType, paginate } = - this.options + const { datasource, limit, sortColumn, sortOrder, paginate } = this.options const { tableId } = datasource const { cursor, query } = get(this.store) @@ -41,7 +40,6 @@ export default class TableFetch extends BaseDataFetch { limit, sort: sortColumn, sortOrder: sortOrder ?? SortOrder.ASCENDING, - sortType, paginate, bookmark: cursor, }) diff --git a/packages/frontend-core/src/fetch/ViewV2Fetch.ts b/packages/frontend-core/src/fetch/ViewV2Fetch.ts index fd2eab2d53..4495450a23 100644 --- a/packages/frontend-core/src/fetch/ViewV2Fetch.ts +++ b/packages/frontend-core/src/fetch/ViewV2Fetch.ts @@ -1,4 +1,5 @@ import { + SearchViewRowRequest, SortOrder, ViewDatasource, ViewV2Enriched, @@ -40,8 +41,7 @@ export default class ViewV2Fetch extends BaseDataFetch< } async getData() { - const { datasource, limit, sortColumn, sortOrder, sortType, paginate } = - this.options + const { datasource, limit, sortColumn, sortOrder, paginate } = this.options const { cursor, query, definition } = get(this.store) // If this is a calculation view and we have no calculations, return nothing @@ -68,14 +68,13 @@ export default class ViewV2Fetch extends BaseDataFetch< } try { - const request = { + const request: SearchViewRowRequest = { query, paginate, limit, bookmark: cursor, sort: sortColumn, sortOrder: sortOrder, - sortType, } if (paginate) { const res = await this.API.viewV2.fetch(datasource.id, { diff --git a/packages/types/src/api/web/app/rows/search.ts b/packages/types/src/api/web/app/rows/search.ts index 7ba23bceca..4d903d44b6 100644 --- a/packages/types/src/api/web/app/rows/search.ts +++ b/packages/types/src/api/web/app/rows/search.ts @@ -8,11 +8,7 @@ import { SearchFilterKey, } from "../../../../sdk" import { Row } from "../../../../documents" -import { - PaginationResponse, - SortOrder, - SortType, -} from "../../../../api/web/pagination" +import { PaginationResponse, SortOrder } from "../../../../api/web/pagination" import { z } from "zod" const fieldKey = z @@ -70,7 +66,6 @@ const searchRowRequest = z.object({ limit: z.number().optional(), sort: z.string().nullish(), sortOrder: z.nativeEnum(SortOrder).optional(), - sortType: z.nativeEnum(SortType).nullish(), version: z.string().optional(), disableEscaping: z.boolean().optional(), countRows: z.boolean().optional(), @@ -83,7 +78,6 @@ export type SearchViewRowRequest = Pick< SearchRowRequest, | "sort" | "sortOrder" - | "sortType" | "limit" | "bookmark" | "paginate" From a583b1adaa7ce2b4e04cf50dc85fbbb09e56c171 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 3 Mar 2025 23:11:55 +0100 Subject: [PATCH 03/12] Remove sortType from tests --- .../src/api/routes/tests/search.spec.ts | 126 ------------------ .../src/api/routes/tests/viewV2.spec.ts | 28 +--- 2 files changed, 1 insertion(+), 153 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index e115297ee9..a087284956 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -29,7 +29,6 @@ import { SearchResponse, SearchRowRequest, SortOrder, - SortType, Table, TableSchema, User, @@ -213,7 +212,6 @@ if (descriptions.length) { bookmark: this.query.bookmark ?? undefined, limit: this.query.limit, sortOrder: this.query.sortOrder, - sortType: this.query.sortType ?? undefined, version: this.query.version, disableEscaping: this.query.disableEscaping, countRows: this.query.countRows, @@ -1119,26 +1117,6 @@ if (descriptions.length) { }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) }) - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "name", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ name: "bar" }, { name: "foo" }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "name", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) - }) - }) - !isInternal && !isInMemory && // This test was added because we automatically add in a sort by the @@ -1318,26 +1296,6 @@ if (descriptions.length) { }).toMatchExactly([{ age: 10 }, { age: 1 }]) }) }) - - describe("sortType NUMBER", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "age", - sortType: SortType.NUMBER, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ age: 1 }, { age: 10 }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "age", - sortType: SortType.NUMBER, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ age: 10 }, { age: 1 }]) - }) - }) }) describe("dates", () => { @@ -1472,26 +1430,6 @@ if (descriptions.length) { sortOrder: SortOrder.DESCENDING, }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) }) - - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "dob", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "dob", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) - }) - }) }) }) @@ -1638,40 +1576,6 @@ if (descriptions.length) { { timeid: NULL_TIME__ID }, ]) }) - - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "time", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([ - { timeid: NULL_TIME__ID }, - { time: "00:00:00" }, - { time: "10:00:00" }, - { time: "10:45:00" }, - { time: "12:00:00" }, - { time: "15:30:00" }, - ]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "time", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([ - { time: "15:30:00" }, - { time: "12:00:00" }, - { time: "10:45:00" }, - { time: "10:00:00" }, - { time: "00:00:00" }, - { timeid: NULL_TIME__ID }, - ]) - }) - }) }) }) @@ -1846,34 +1750,6 @@ if (descriptions.length) { { dateid: NULL_DATE__ID }, ]) }) - - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "date", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([ - { dateid: NULL_DATE__ID }, - { date: JAN_1ST }, - { date: JAN_10TH }, - ]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "date", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([ - { date: JAN_10TH }, - { date: JAN_1ST }, - { dateid: NULL_DATE__ID }, - ]) - }) - }) }) } ) @@ -2298,7 +2174,6 @@ if (descriptions.length) { query: {}, sort: "auto", sortOrder: SortOrder.ASCENDING, - sortType: SortType.NUMBER, }).toMatchExactly([ { auto: 1 }, { auto: 2 }, @@ -2318,7 +2193,6 @@ if (descriptions.length) { query: {}, sort: "auto", sortOrder: SortOrder.DESCENDING, - sortType: SortType.NUMBER, }).toMatchExactly([ { auto: 10 }, { auto: 9 }, diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index ad41aa618c..2ac5a0f90b 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -24,7 +24,6 @@ import { SearchResponse, SearchViewRowRequest, SortOrder, - SortType, StaticQuotaName, Table, TableSchema, @@ -154,7 +153,6 @@ if (descriptions.length) { sort: { field: "fieldToSort", order: SortOrder.DESCENDING, - type: SortType.STRING, }, schema: { id: { visible: true }, @@ -217,7 +215,6 @@ if (descriptions.length) { sort: { field: "fieldToSort", order: SortOrder.DESCENDING, - type: SortType.STRING, }, schema: { id: { visible: true }, @@ -1147,7 +1144,6 @@ if (descriptions.length) { sort: { field: generator.word(), order: SortOrder.DESCENDING, - type: SortType.STRING, }, schema: { id: { visible: true }, @@ -3153,7 +3149,6 @@ if (descriptions.length) { { field: string order?: SortOrder - type?: SortType }, string[] ][] = [ @@ -3161,7 +3156,6 @@ if (descriptions.length) { { field: "name", order: SortOrder.ASCENDING, - type: SortType.STRING, }, ["Alice", "Bob", "Charly", "Danny"], ], @@ -3178,22 +3172,6 @@ if (descriptions.length) { }, ["Danny", "Charly", "Bob", "Alice"], ], - [ - { - field: "name", - order: SortOrder.DESCENDING, - type: SortType.STRING, - }, - ["Danny", "Charly", "Bob", "Alice"], - ], - [ - { - field: "age", - order: SortOrder.ASCENDING, - type: SortType.NUMBER, - }, - ["Danny", "Alice", "Charly", "Bob"], - ], [ { field: "age", @@ -3206,13 +3184,11 @@ if (descriptions.length) { field: "age", order: SortOrder.DESCENDING, }, - ["Bob", "Charly", "Alice", "Danny"], + ["Danny", "Alice", "Charly", "Bob"], ], [ { field: "age", - order: SortOrder.DESCENDING, - type: SortType.NUMBER, }, ["Bob", "Charly", "Alice", "Danny"], ], @@ -3299,7 +3275,6 @@ if (descriptions.length) { sort: { field: "name", order: SortOrder.ASCENDING, - type: SortType.STRING, }, schema: viewSchema, }) @@ -3307,7 +3282,6 @@ if (descriptions.length) { const response = await config.api.viewV2.search(view.id, { sort: sortParams.field, sortOrder: sortParams.order, - sortType: sortParams.type, query: {}, }) From d7ff47ff2ab156d3b95e345f160ef71c06a1009a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 10:02:32 +0100 Subject: [PATCH 04/12] Fix types --- packages/server/src/api/controllers/row/index.ts | 1 - packages/server/src/api/controllers/row/views.ts | 2 -- packages/server/src/sdk/app/rows/search.ts | 1 - packages/shared-core/src/filters.ts | 13 +++++++++++-- packages/types/src/sdk/row.ts | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/server/src/api/controllers/row/index.ts b/packages/server/src/api/controllers/row/index.ts index 8f4629a5b0..07ed4172ab 100644 --- a/packages/server/src/api/controllers/row/index.ts +++ b/packages/server/src/api/controllers/row/index.ts @@ -263,7 +263,6 @@ export async function search(ctx: Ctx) { limit: searchRequest.limit, sort: searchRequest.sort ?? undefined, sortOrder: searchRequest.sortOrder, - sortType: searchRequest.sortType ?? undefined, countRows: searchRequest.countRows, version: searchRequest.version, disableEscaping: searchRequest.disableEscaping, diff --git a/packages/server/src/api/controllers/row/views.ts b/packages/server/src/api/controllers/row/views.ts index 418aa462c4..78931c5d4d 100644 --- a/packages/server/src/api/controllers/row/views.ts +++ b/packages/server/src/api/controllers/row/views.ts @@ -63,14 +63,12 @@ function getSortOptions(request: SearchViewRowRequest, view: ViewV2) { return { sort: request.sort, sortOrder: request.sortOrder, - sortType: request.sortType ?? undefined, } } if (view.sort) { return { sort: view.sort.field, sortOrder: view.sort.order, - sortType: view.sort.type, } } diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index 3a582a46ea..8de46dc9fe 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -46,7 +46,6 @@ export async function search( query: options.query, sort: options.sort, sortOrder: options.sortOrder, - sortType: options.sortType, limit: options.limit, bookmark: options.bookmark, paginate: options.paginate, diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index afe99d9565..f08595158e 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -11,7 +11,6 @@ import { SortType, FieldConstraints, SortOrder, - RowSearchParams, EmptyFilterOption, SearchResponse, Table, @@ -25,6 +24,8 @@ import { isArraySearchOperator, isRangeSearchOperator, SearchFilter, + WithRequired, + SearchParams, } from "@budibase/types" import dayjs from "dayjs" import { OperatorOptions, SqlNumberTypeRangeMap } from "./constants" @@ -521,9 +522,17 @@ export function fixupFilterArrays(filters: SearchFilters) { return filters } +type SearchQuery = WithRequired< + Pick< + SearchParams, + "query" | "sort" | "sortOrder" | "sortType" | "limit" | "countRows" + >, + "query" +> + export function search>( docs: T[], - query: Omit + query: SearchQuery ): SearchResponse { let result = runQuery(docs, query.query) if (query.sort) { diff --git a/packages/types/src/sdk/row.ts b/packages/types/src/sdk/row.ts index 6328a80ba1..da5eb0b041 100644 --- a/packages/types/src/sdk/row.ts +++ b/packages/types/src/sdk/row.ts @@ -50,7 +50,7 @@ export interface SearchParams { // when searching for rows we want a more extensive search type that requires certain properties export interface RowSearchParams - extends WithRequired {} + extends WithRequired, "tableId" | "query"> {} export interface SearchResponse { rows: T[] From 4a9453e444304652ce49f65db635be36f1e5da81 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 10:18:31 +0100 Subject: [PATCH 05/12] Fix tests --- packages/server/src/api/routes/tests/viewV2.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index 2ac5a0f90b..274ed67705 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -3184,13 +3184,13 @@ if (descriptions.length) { field: "age", order: SortOrder.DESCENDING, }, - ["Danny", "Alice", "Charly", "Bob"], + ["Bob", "Charly", "Alice", "Danny"], ], [ { field: "age", }, - ["Bob", "Charly", "Alice", "Danny"], + ["Danny", "Alice", "Charly", "Bob"], ], ] From 2776510dc3ca98baa926acc230d48ed80faabbba Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 10:20:20 +0100 Subject: [PATCH 06/12] Reorder --- packages/server/src/api/routes/tests/viewV2.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index 274ed67705..3f1bb43016 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -3182,15 +3182,15 @@ if (descriptions.length) { [ { field: "age", - order: SortOrder.DESCENDING, }, - ["Bob", "Charly", "Alice", "Danny"], + ["Danny", "Alice", "Charly", "Bob"], ], [ { field: "age", + order: SortOrder.DESCENDING, }, - ["Danny", "Alice", "Charly", "Bob"], + ["Bob", "Charly", "Alice", "Danny"], ], ] From b5d887cafa9b6c7a0061d0ba3a1f1e1c3e2b3a28 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 11:02:39 +0100 Subject: [PATCH 07/12] Remove sort type --- packages/frontend-core/src/fetch/DataFetch.ts | 36 ++++--------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/packages/frontend-core/src/fetch/DataFetch.ts b/packages/frontend-core/src/fetch/DataFetch.ts index 298413b1e8..cbc9972484 100644 --- a/packages/frontend-core/src/fetch/DataFetch.ts +++ b/packages/frontend-core/src/fetch/DataFetch.ts @@ -8,7 +8,6 @@ import { Row, SearchFilters, SortOrder, - SortType, TableSchema, } from "@budibase/types" import { APIClient } from "../api/types" @@ -72,8 +71,6 @@ export default abstract class BaseDataFetch< options: DataFetchOptions & { datasource: TDatasource - sortType: SortType | null - // Client side feature customisation clientSideSearching: boolean clientSideSorting: boolean @@ -106,7 +103,6 @@ export default abstract class BaseDataFetch< // Sorting config sortColumn: null, sortOrder: SortOrder.ASCENDING, - sortType: null, // Pagination config paginate: true, @@ -227,31 +223,12 @@ export default abstract class BaseDataFetch< this.options.sortColumn = this.getDefaultSortColumn(definition, schema) } - // If we don't have a sort column specified then just ensure we don't set - // any sorting params - if (!this.options.sortColumn) { + // If no sort order, default to ascending + if (!this.options.sortOrder) { this.options.sortOrder = SortOrder.ASCENDING - this.options.sortType = null } else { - // Otherwise determine what sort type to use base on sort column - this.options.sortType = SortType.STRING - const fieldSchema = schema?.[this.options.sortColumn] - if ( - fieldSchema?.type === FieldType.NUMBER || - fieldSchema?.type === FieldType.BIGINT || - ("calculationType" in fieldSchema && fieldSchema?.calculationType) - ) { - this.options.sortType = SortType.NUMBER - } - - // If no sort order, default to ascending - if (!this.options.sortOrder) { - this.options.sortOrder = SortOrder.ASCENDING - } else { - // Ensure sortOrder matches the enum - this.options.sortOrder = - this.options.sortOrder.toLowerCase() as SortOrder - } + // Ensure sortOrder matches the enum + this.options.sortOrder = this.options.sortOrder.toLowerCase() as SortOrder } // Build the query @@ -294,7 +271,6 @@ export default abstract class BaseDataFetch< const { sortColumn, sortOrder, - sortType, limit, clientSideSearching, clientSideSorting, @@ -311,8 +287,8 @@ export default abstract class BaseDataFetch< } // If we don't support sorting, do a client-side sort - if (!this.features.supportsSort && clientSideSorting && sortType) { - rows = sort(rows, sortColumn as any, sortOrder, sortType) + if (!this.features.supportsSort && clientSideSorting && sortColumn) { + rows = sort(rows, sortColumn, sortOrder) } // If we don't support pagination, do a client-side limit From f770ef094006f7ea5b7d7d7c98f81edc751cfa9c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 12:29:31 +0100 Subject: [PATCH 08/12] Fix sorting autoids --- packages/server/src/sdk/app/rows/search/internal/sqs.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/server/src/sdk/app/rows/search/internal/sqs.ts b/packages/server/src/sdk/app/rows/search/internal/sqs.ts index 84162a67af..76b496f92a 100644 --- a/packages/server/src/sdk/app/rows/search/internal/sqs.ts +++ b/packages/server/src/sdk/app/rows/search/internal/sqs.ts @@ -1,5 +1,6 @@ import { Aggregation, + AutoFieldSubType, CalculationType, DocumentType, EnrichedQueryJson, @@ -420,7 +421,11 @@ export async function search( } } else if (sortField) { const sortType = - sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING + sortField.type === FieldType.NUMBER || + (sortField.type === FieldType.AUTO && + sortField.subtype === AutoFieldSubType.AUTO_ID) + ? SortType.NUMBER + : SortType.STRING request.sort = { [mapToUserColumn(sortField.name)]: { direction: params.sortOrder || SortOrder.ASCENDING, From 79111e190bea4d61d2fa9ca6d5bde5d8d42ebef3 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 14:47:17 +0100 Subject: [PATCH 09/12] Rename test files --- packages/shared-core/src/tests/{cron.test.ts => cron.spec.ts} | 0 packages/shared-core/src/tests/{themes.ts => themes.spec.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/shared-core/src/tests/{cron.test.ts => cron.spec.ts} (100%) rename packages/shared-core/src/tests/{themes.ts => themes.spec.ts} (100%) diff --git a/packages/shared-core/src/tests/cron.test.ts b/packages/shared-core/src/tests/cron.spec.ts similarity index 100% rename from packages/shared-core/src/tests/cron.test.ts rename to packages/shared-core/src/tests/cron.spec.ts diff --git a/packages/shared-core/src/tests/themes.ts b/packages/shared-core/src/tests/themes.spec.ts similarity index 100% rename from packages/shared-core/src/tests/themes.ts rename to packages/shared-core/src/tests/themes.spec.ts From 02e54bc248f98d0e0b549932dd82b17ce1f57abf Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 15:31:52 +0100 Subject: [PATCH 10/12] Fix inMemory test --- .../src/api/routes/tests/search.spec.ts | 156 ++++++++++++++++-- packages/shared-core/src/filters.ts | 2 + packages/shared-core/src/index.ts | 1 + 3 files changed, 144 insertions(+), 15 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index a087284956..278e5c810d 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -29,6 +29,7 @@ import { SearchResponse, SearchRowRequest, SortOrder, + SortType, Table, TableSchema, User, @@ -37,7 +38,7 @@ import { import _ from "lodash" import tk from "timekeeper" import { encodeJSBinding } from "@budibase/string-templates" -import { dataFilters } from "@budibase/shared-core" +import { dataFilters, InMemorySearchQuery } from "@budibase/shared-core" import { Knex } from "knex" import { generator, structures, mocks } from "@budibase/backend-core/tests" import { DEFAULT_EMPLOYEE_TABLE_SCHEMA } from "../../../db/defaultData/datasource_bb_default" @@ -199,30 +200,26 @@ if (descriptions.length) { const isView = sourceType === "view" class SearchAssertion { - constructor(private readonly query: SearchRowRequest) {} + constructor( + private readonly query: SearchRowRequest & { + sortType?: SortType + } + ) {} private async performSearch(): Promise> { if (isInMemory) { - const inMemoryQuery: RequiredKeys< - Omit - > = { + const inMemoryQuery: RequiredKeys = { sort: this.query.sort ?? undefined, query: { ...this.query.query }, - paginate: this.query.paginate, - bookmark: this.query.bookmark ?? undefined, limit: this.query.limit, sortOrder: this.query.sortOrder, - version: this.query.version, - disableEscaping: this.query.disableEscaping, + sortType: this.query.sortType ?? undefined, countRows: this.query.countRows, - viewId: undefined, - fields: undefined, - indexer: undefined, - rows: undefined, } return dataFilters.search(_.cloneDeep(rows), inMemoryQuery) } else { - return config.api.row.search(tableOrViewId, this.query) + const { sortType, ...query } = this.query + return config.api.row.search(tableOrViewId, query) } } @@ -398,7 +395,9 @@ if (descriptions.length) { } } - function expectSearch(query: SearchRowRequest) { + function expectSearch( + query: SearchRowRequest & { sortType?: SortType } + ) { return new SearchAssertion(query) } @@ -1117,6 +1116,27 @@ if (descriptions.length) { }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) }) + isInMemory && + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "name", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ name: "bar" }, { name: "foo" }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "name", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) + }) + }) + !isInternal && !isInMemory && // This test was added because we automatically add in a sort by the @@ -1296,6 +1316,27 @@ if (descriptions.length) { }).toMatchExactly([{ age: 10 }, { age: 1 }]) }) }) + + isInMemory && + describe("sortType NUMBER", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "age", + sortType: SortType.NUMBER, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ age: 1 }, { age: 10 }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "age", + sortType: SortType.NUMBER, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ age: 10 }, { age: 1 }]) + }) + }) }) describe("dates", () => { @@ -1430,6 +1471,27 @@ if (descriptions.length) { sortOrder: SortOrder.DESCENDING, }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) }) + + isInMemory && + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "dob", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "dob", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) + }) + }) }) }) @@ -1576,6 +1638,41 @@ if (descriptions.length) { { timeid: NULL_TIME__ID }, ]) }) + + isInMemory && + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "time", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([ + { timeid: NULL_TIME__ID }, + { time: "00:00:00" }, + { time: "10:00:00" }, + { time: "10:45:00" }, + { time: "12:00:00" }, + { time: "15:30:00" }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "time", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([ + { time: "15:30:00" }, + { time: "12:00:00" }, + { time: "10:45:00" }, + { time: "10:00:00" }, + { time: "00:00:00" }, + { timeid: NULL_TIME__ID }, + ]) + }) + }) }) }) @@ -1750,6 +1847,35 @@ if (descriptions.length) { { dateid: NULL_DATE__ID }, ]) }) + + isInMemory && + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "date", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([ + { dateid: NULL_DATE__ID }, + { date: JAN_1ST }, + { date: JAN_10TH }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "date", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([ + { date: JAN_10TH }, + { date: JAN_1ST }, + { dateid: NULL_DATE__ID }, + ]) + }) + }) }) } ) diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index f08595158e..5da5c34a4f 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -530,6 +530,8 @@ type SearchQuery = WithRequired< "query" > +export type InMemorySearchQuery = SearchQuery + export function search>( docs: T[], query: SearchQuery diff --git a/packages/shared-core/src/index.ts b/packages/shared-core/src/index.ts index a4f4208f4a..daf4601c03 100644 --- a/packages/shared-core/src/index.ts +++ b/packages/shared-core/src/index.ts @@ -1,5 +1,6 @@ export * from "./constants" export * as dataFilters from "./filters" +export type * from "./filters" export * as helpers from "./helpers" export * as utils from "./utils" export * as sdk from "./sdk" From 40c801085953dd84322032db57f1ddd7681406a1 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 4 Mar 2025 16:15:27 +0100 Subject: [PATCH 11/12] Fix tests --- .../src/api/routes/tests/search.spec.ts | 405 +++++++++--------- 1 file changed, 204 insertions(+), 201 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 278e5c810d..cf7c7cf9fa 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -1676,212 +1676,213 @@ if (descriptions.length) { }) }) - describe("datetime - date only", () => { - describe.each([true, false])( - "saved with timestamp: %s", - saveWithTimestamp => { - describe.each([true, false])( - "search with timestamp: %s", - searchWithTimestamp => { - const SAVE_SUFFIX = saveWithTimestamp - ? "T00:00:00.000Z" - : "" - const SEARCH_SUFFIX = searchWithTimestamp - ? "T00:00:00.000Z" - : "" + !isInMemory && + describe("datetime - date only", () => { + describe.each([true, false])( + "saved with timestamp: %s", + saveWithTimestamp => { + describe.each([true, false])( + "search with timestamp: %s", + searchWithTimestamp => { + const SAVE_SUFFIX = saveWithTimestamp + ? "T00:00:00.000Z" + : "" + const SEARCH_SUFFIX = searchWithTimestamp + ? "T00:00:00.000Z" + : "" - const JAN_1ST = `2020-01-01` - const JAN_10TH = `2020-01-10` - const JAN_30TH = `2020-01-30` - const UNEXISTING_DATE = `2020-01-03` - const NULL_DATE__ID = `null_date__id` + const JAN_1ST = `2020-01-01` + const JAN_10TH = `2020-01-10` + const JAN_30TH = `2020-01-30` + const UNEXISTING_DATE = `2020-01-03` + const NULL_DATE__ID = `null_date__id` - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - dateid: { - name: "dateid", - type: FieldType.STRING, - }, - date: { - name: "date", - type: FieldType.DATETIME, - dateOnly: true, - }, - }) - - await createRows([ - { dateid: NULL_DATE__ID, date: null }, - { date: `${JAN_1ST}${SAVE_SUFFIX}` }, - { date: `${JAN_10TH}${SAVE_SUFFIX}` }, - ]) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ - equal: { date: `${JAN_1ST}${SEARCH_SUFFIX}` }, - }).toContainExactly([{ date: JAN_1ST }]) - }) - - it("successfully finds an ISO8601 row", async () => { - await expectQuery({ - equal: { date: `${JAN_10TH}${SEARCH_SUFFIX}` }, - }).toContainExactly([{ date: JAN_10TH }]) - }) - - it("finds a row with ISO8601 timestamp", async () => { - await expectQuery({ - equal: { date: `${JAN_1ST}${SEARCH_SUFFIX}` }, - }).toContainExactly([{ date: JAN_1ST }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - equal: { - date: `${UNEXISTING_DATE}${SEARCH_SUFFIX}`, + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + dateid: { + name: "dateid", + type: FieldType.STRING, }, - }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ - notEqual: { - date: `${JAN_1ST}${SEARCH_SUFFIX}`, + date: { + name: "date", + type: FieldType.DATETIME, + dateOnly: true, }, - }).toContainExactly([ - { date: JAN_10TH }, - { dateid: NULL_DATE__ID }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - notEqual: { - date: `${JAN_30TH}${SEARCH_SUFFIX}`, - }, - }).toContainExactly([ - { date: JAN_1ST }, - { date: JAN_10TH }, - { dateid: NULL_DATE__ID }, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ - oneOf: { date: [`${JAN_1ST}${SEARCH_SUFFIX}`] }, - }).toContainExactly([{ date: JAN_1ST }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - oneOf: { - date: [`${UNEXISTING_DATE}${SEARCH_SUFFIX}`], - }, - }).toFindNothing() - }) - }) - - describe("range", () => { - it("successfully finds a row", async () => { - await expectQuery({ - range: { - date: { - low: `${JAN_1ST}${SEARCH_SUFFIX}`, - high: `${JAN_1ST}${SEARCH_SUFFIX}`, - }, - }, - }).toContainExactly([{ date: JAN_1ST }]) - }) - - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { - date: { - low: `${JAN_1ST}${SEARCH_SUFFIX}`, - high: `${JAN_10TH}${SEARCH_SUFFIX}`, - }, - }, - }).toContainExactly([ - { date: JAN_1ST }, - { date: JAN_10TH }, - ]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { - date: { - low: `${JAN_30TH}${SEARCH_SUFFIX}`, - high: `${JAN_30TH}${SEARCH_SUFFIX}`, - }, - }, - }).toFindNothing() - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "date", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([ - { dateid: NULL_DATE__ID }, - { date: JAN_1ST }, - { date: JAN_10TH }, - ]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "date", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([ - { date: JAN_10TH }, - { date: JAN_1ST }, - { dateid: NULL_DATE__ID }, - ]) - }) - - isInMemory && - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "date", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([ - { dateid: NULL_DATE__ID }, - { date: JAN_1ST }, - { date: JAN_10TH }, - ]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "date", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([ - { date: JAN_10TH }, - { date: JAN_1ST }, - { dateid: NULL_DATE__ID }, - ]) - }) }) - }) - } - ) - } - ) - }) + + await createRows([ + { dateid: NULL_DATE__ID, date: null }, + { date: `${JAN_1ST}${SAVE_SUFFIX}` }, + { date: `${JAN_10TH}${SAVE_SUFFIX}` }, + ]) + }) + + describe("equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ + equal: { date: `${JAN_1ST}${SEARCH_SUFFIX}` }, + }).toContainExactly([{ date: JAN_1ST }]) + }) + + it("successfully finds an ISO8601 row", async () => { + await expectQuery({ + equal: { date: `${JAN_10TH}${SEARCH_SUFFIX}` }, + }).toContainExactly([{ date: JAN_10TH }]) + }) + + it("finds a row with ISO8601 timestamp", async () => { + await expectQuery({ + equal: { date: `${JAN_1ST}${SEARCH_SUFFIX}` }, + }).toContainExactly([{ date: JAN_1ST }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + equal: { + date: `${UNEXISTING_DATE}${SEARCH_SUFFIX}`, + }, + }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { + date: `${JAN_1ST}${SEARCH_SUFFIX}`, + }, + }).toContainExactly([ + { date: JAN_10TH }, + { dateid: NULL_DATE__ID }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notEqual: { + date: `${JAN_30TH}${SEARCH_SUFFIX}`, + }, + }).toContainExactly([ + { date: JAN_1ST }, + { date: JAN_10TH }, + { dateid: NULL_DATE__ID }, + ]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { date: [`${JAN_1ST}${SEARCH_SUFFIX}`] }, + }).toContainExactly([{ date: JAN_1ST }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + oneOf: { + date: [`${UNEXISTING_DATE}${SEARCH_SUFFIX}`], + }, + }).toFindNothing() + }) + }) + + describe("range", () => { + it("successfully finds a row", async () => { + await expectQuery({ + range: { + date: { + low: `${JAN_1ST}${SEARCH_SUFFIX}`, + high: `${JAN_1ST}${SEARCH_SUFFIX}`, + }, + }, + }).toContainExactly([{ date: JAN_1ST }]) + }) + + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { + date: { + low: `${JAN_1ST}${SEARCH_SUFFIX}`, + high: `${JAN_10TH}${SEARCH_SUFFIX}`, + }, + }, + }).toContainExactly([ + { date: JAN_1ST }, + { date: JAN_10TH }, + ]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { + date: { + low: `${JAN_30TH}${SEARCH_SUFFIX}`, + high: `${JAN_30TH}${SEARCH_SUFFIX}`, + }, + }, + }).toFindNothing() + }) + }) + + describe("sort", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "date", + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([ + { dateid: NULL_DATE__ID }, + { date: JAN_1ST }, + { date: JAN_10TH }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "date", + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([ + { date: JAN_10TH }, + { date: JAN_1ST }, + { dateid: NULL_DATE__ID }, + ]) + }) + + isInMemory && + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "date", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([ + { dateid: NULL_DATE__ID }, + { date: JAN_1ST }, + { date: JAN_10TH }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "date", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([ + { date: JAN_10TH }, + { date: JAN_1ST }, + { dateid: NULL_DATE__ID }, + ]) + }) + }) + }) + } + ) + } + ) + }) isInternal && !isInMemory && @@ -2300,6 +2301,7 @@ if (descriptions.length) { query: {}, sort: "auto", sortOrder: SortOrder.ASCENDING, + sortType: SortType.NUMBER, }).toMatchExactly([ { auto: 1 }, { auto: 2 }, @@ -2319,6 +2321,7 @@ if (descriptions.length) { query: {}, sort: "auto", sortOrder: SortOrder.DESCENDING, + sortType: SortType.NUMBER, }).toMatchExactly([ { auto: 10 }, { auto: 9 }, From 17f737e545c7eb4b6cd8d297fd17b10e6239a01e Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Tue, 11 Mar 2025 11:00:27 +0000 Subject: [PATCH 12/12] Bump version to 3.5.0 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 10e7b8cdee..a0de97dc7a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.4.24", + "version": "3.5.0", "npmClient": "yarn", "concurrency": 20, "command": {