diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml index 0fb8a5fea0..024b97597f 100644 --- a/.github/workflows/deploy-release.yml +++ b/.github/workflows/deploy-release.yml @@ -68,6 +68,13 @@ jobs: ] env: KUBECONFIG_FILE: '${{ secrets.RELEASE_KUBECONFIG }}' + + - name: Re roll the services + uses: actions-hub/kubectl@master + env: + KUBE_CONFIG: ${{ secrets.RELEASE_KUBECONFIG }} + with: + args: rollout restart deployment proxy-service -n budibase && kubectl rollout restart deployment app-service -n budibase && kubectl rollout restart deployment worker-service -n budibase - name: Discord Webhook Action uses: tsickert/discord-webhook@v4.0.0 diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml index 772fcf933d..067d0eb0dd 100644 --- a/.github/workflows/release-develop.yml +++ b/.github/workflows/release-develop.yml @@ -121,6 +121,13 @@ jobs: env: KUBECONFIG_FILE: '${{ secrets.RELEASE_KUBECONFIG }}' + - name: Re roll the services + uses: actions-hub/kubectl@master + env: + KUBE_CONFIG: ${{ secrets.RELEASE_KUBECONFIG }} + with: + args: rollout restart deployment proxy-service -n budibase && kubectl rollout restart deployment app-service -n budibase && kubectl rollout restart deployment worker-service -n budibase + - name: Discord Webhook Action uses: tsickert/discord-webhook@v4.0.0 with: diff --git a/lerna.json b/lerna.json index 389d00264d..2ad36f4f7f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 93484c3b11..575c3357f3 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -20,7 +20,7 @@ "test:watch": "jest --watchAll" }, "dependencies": { - "@budibase/types": "1.2.39-alpha.5", + "@budibase/types": "1.2.39-alpha.7", "@techpass/passport-openidconnect": "0.3.2", "aws-sdk": "2.1030.0", "bcrypt": "5.0.1", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index cedd4722a4..0b8c664def 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "^1.2.1", - "@budibase/string-templates": "1.2.39-alpha.5", + "@budibase/string-templates": "1.2.39-alpha.7", "@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/avatar": "^3.0.2", diff --git a/packages/bbui/src/Form/Core/Multiselect.svelte b/packages/bbui/src/Form/Core/Multiselect.svelte index 9dd5a25a4f..eb39e39042 100644 --- a/packages/bbui/src/Form/Core/Multiselect.svelte +++ b/packages/bbui/src/Form/Core/Multiselect.svelte @@ -23,7 +23,7 @@ $: toggleOption = makeToggleOption(selectedLookupMap, value) const getFieldText = (value, map, placeholder) => { - if (value?.length) { + if (Array.isArray(value) && value.length > 0) { if (!map) { return "" } @@ -36,7 +36,7 @@ const getSelectedLookupMap = value => { let map = {} - if (value?.length) { + if (Array.isArray(value) && value.length > 0) { value.forEach(option => { if (option) { map[option] = true diff --git a/packages/builder/package.json b/packages/builder/package.json index 82ae021e12..224541f838 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "license": "GPL-3.0", "private": true, "scripts": { @@ -69,10 +69,10 @@ } }, "dependencies": { - "@budibase/bbui": "1.2.39-alpha.5", - "@budibase/client": "1.2.39-alpha.5", - "@budibase/frontend-core": "1.2.39-alpha.5", - "@budibase/string-templates": "1.2.39-alpha.5", + "@budibase/bbui": "1.2.39-alpha.7", + "@budibase/client": "1.2.39-alpha.7", + "@budibase/frontend-core": "1.2.39-alpha.7", + "@budibase/string-templates": "1.2.39-alpha.7", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 37742626cd..7cb368830e 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -167,6 +167,7 @@ {/if} diff --git a/packages/builder/src/components/backend/DataTable/buttons/ImportButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/ImportButton.svelte index 6b9c3dd6dd..99d39a0d48 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/ImportButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/ImportButton.svelte @@ -3,11 +3,12 @@ import ImportModal from "../modals/ImportModal.svelte" export let tableId + export let disabled let modal - + Import diff --git a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte index fcec0e35ac..9bd66a4cb1 100644 --- a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte +++ b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterDrawer.svelte @@ -3,6 +3,7 @@ Body, Button, Combobox, + Multiselect, DatePicker, DrawerContent, Icon, @@ -97,6 +98,16 @@ if (expression.noValue) { expression.value = null } + if ( + operator === Constants.OperatorOptions.In.value && + !Array.isArray(expression.value) + ) { + if (expression.value) { + expression.value = [expression.value] + } else { + expression.value = [] + } + } } const getFieldOptions = field => { @@ -169,7 +180,13 @@ /> {:else if ["string", "longform", "number", "formula"].includes(filter.type)} - {:else if ["options", "array"].includes(filter.type)} + {:else if filter.type === "array" || (filter.type === "options" && filter.operator === "oneOf")} + + {:else if filter.type === "options"} { } else if (type === "number") { return numOps } else if (type === "options") { - return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] + return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty, Op.In] } else if (type === "array") { - return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty] + return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty, Op.ContainsAny] } else if (type === "boolean") { return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] } else if (type === "longform") { @@ -96,6 +96,7 @@ export const buildLuceneQuery = filter => { contains: {}, notContains: {}, oneOf: {}, + containsAny: {}, } if (Array.isArray(filter)) { filter.forEach(expression => { @@ -128,6 +129,13 @@ export const buildLuceneQuery = filter => { if (type === "boolean") { value = `${value}`?.toLowerCase() === "true" } + if ( + ["contains", "notContains", "containsAny"].includes(operator) && + type === "array" && + typeof value === "string" + ) { + value = value.split(",") + } if (operator.startsWith("range")) { const minint = SqlNumberTypeRangeMap[externalType]?.min || Number.MIN_SAFE_INTEGER @@ -244,6 +252,18 @@ export const runLuceneQuery = (docs, query) => { return !testValue?.includes(docValue) }) + const containsAny = match("containsAny", (docValue, testValue) => { + return !docValue?.includes(...testValue) + }) + + const contains = match("contains", (docValue, testValue) => { + return !testValue?.every(item => docValue?.includes(item)) + }) + + const notContains = match("notContains", (docValue, testValue) => { + return testValue?.every(item => docValue?.includes(item)) + }) + // Match a document against all criteria const docMatch = doc => { return ( @@ -254,7 +274,10 @@ export const runLuceneQuery = (docs, query) => { notEqualMatch(doc) && emptyMatch(doc) && notEmptyMatch(doc) && - oneOf(doc) + oneOf(doc) && + contains(doc) && + containsAny(doc) && + notContains(doc) ) } diff --git a/packages/server/package.json b/packages/server/package.json index 894e67030f..6165cf495e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -77,11 +77,11 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", - "@budibase/backend-core": "1.2.39-alpha.5", - "@budibase/client": "1.2.39-alpha.5", - "@budibase/pro": "1.2.39-alpha.5", - "@budibase/string-templates": "1.2.39-alpha.5", - "@budibase/types": "1.2.39-alpha.5", + "@budibase/backend-core": "1.2.39-alpha.7", + "@budibase/client": "1.2.39-alpha.7", + "@budibase/pro": "1.2.39-alpha.7", + "@budibase/string-templates": "1.2.39-alpha.7", + "@budibase/types": "1.2.39-alpha.7", "@bull-board/api": "3.7.0", "@bull-board/koa": "3.9.4", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/server/src/api/controllers/row/internalSearch.js b/packages/server/src/api/controllers/row/internalSearch.js index 5708cd85f3..3cf60fbcc0 100644 --- a/packages/server/src/api/controllers/row/internalSearch.js +++ b/packages/server/src/api/controllers/row/internalSearch.js @@ -21,6 +21,8 @@ class QueryBuilder { notEmpty: {}, oneOf: {}, contains: {}, + notContains: {}, + containsAny: {}, ...base, } this.limit = 50 @@ -126,6 +128,16 @@ class QueryBuilder { return this } + addNotContains(key, value) { + this.query.notContains[key] = value + return this + } + + addContainsAny(key, value) { + this.query.containsAny[key] = value + return this + } + /** * Preprocesses a value before going into a lucene search. * Transforms strings to lowercase and wraps strings and bools in quotes. @@ -171,11 +183,29 @@ class QueryBuilder { return `${key}:${builder.preprocess(value, allPreProcessingOpts)}` } - const contains = (key, value) => { - if (!value && value !== 0) { + const contains = (key, value, mode = "AND") => { + if (Array.isArray(value) && value.length === 0) { return null } - return `${key}:${builder.preprocess(value, { escape: true })}` + if (!Array.isArray(value)) { + return `${key}:${value}` + } + let statement = `${builder.preprocess(value[0], { escape: true })}` + for (let i = 1; i < value.length; i++) { + statement += ` ${mode} ${builder.preprocess(value[i], { + escape: true, + })}` + } + return `${key}:(${statement})` + } + + const notContains = (key, value) => { + const allPrefix = allOr === "" ? "*:* AND" : "" + return allPrefix + "NOT " + contains(key, value) + } + + const containsAny = (key, value) => { + return contains(key, value, "OR") } const oneOf = (key, value) => { @@ -278,6 +308,12 @@ class QueryBuilder { if (this.query.contains) { build(this.query.contains, contains) } + if (this.query.notContains) { + build(this.query.notContains, notContains) + } + if (this.query.containsAny) { + build(this.query.containsAny, containsAny) + } // make sure table ID is always added as an AND if (tableId) { query = `(${query})` diff --git a/packages/server/src/api/routes/tests/internalSearch.spec.js b/packages/server/src/api/routes/tests/internalSearch.spec.js index 50ee2b26ac..3b478eda17 100644 --- a/packages/server/src/api/routes/tests/internalSearch.spec.js +++ b/packages/server/src/api/routes/tests/internalSearch.spec.js @@ -129,9 +129,10 @@ describe("internal search", () => { const response = await search.paginatedSearch({ contains: { "column": "a", + "colArr": [1, 2, 3], }, }, PARAMS) - checkLucene(response, `*:* AND column:a`, PARAMS) + checkLucene(response, `*:* AND column:a AND colArr:(1 AND 2 AND 3)`, PARAMS) }) it("test multiple of same column", async () => { @@ -154,4 +155,22 @@ describe("internal search", () => { }, PARAMS) checkLucene(response, `*:* AND 1\\:column:"a"`, PARAMS) }) + + it("test containsAny query", async () => { + const response = await search.paginatedSearch({ + containsAny: { + "column": ["a", "b", "c"] + }, + }, PARAMS) + checkLucene(response, `*:* AND column:(a OR b OR c)`, PARAMS) + }) + + it("test notContains query", async () => { + const response = await search.paginatedSearch({ + notContains: { + "column": ["a", "b", "c"] + }, + }, PARAMS) + checkLucene(response, `*:* AND NOT column:(a AND b AND c)`, PARAMS) + }) }) \ No newline at end of file diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 1eb0dc5292..f18e9d1d98 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -159,6 +159,61 @@ class InternalBuilder { } } + const contains = (mode: object, any: boolean = false) => { + const fnc = allOr ? "orWhere" : "where" + const rawFnc = `${fnc}Raw` + const not = mode === filters?.notContains ? "NOT " : "" + function stringifyArray(value: Array, quoteStyle = '"'): string { + for (let i in value) { + if (typeof value[i] === "string") { + value[i] = `${quoteStyle}${value[i]}${quoteStyle}` + } + } + return `[${value.join(",")}]` + } + if (this.client === SqlClient.POSTGRES) { + iterate(mode, (key: string, value: Array) => { + const wrap = any ? "" : "'" + const containsOp = any ? "\\?| array" : "@>" + const fieldNames = key.split(/\./g) + const tableName = fieldNames[0] + const columnName = fieldNames[1] + // @ts-ignore + query = query[rawFnc]( + `${not}"${tableName}"."${columnName}"::jsonb ${containsOp} ${wrap}${stringifyArray( + value, + any ? "'" : '"' + )}${wrap}` + ) + }) + } else if (this.client === SqlClient.MY_SQL) { + const jsonFnc = any ? "JSON_OVERLAPS" : "JSON_CONTAINS" + iterate(mode, (key: string, value: Array) => { + // @ts-ignore + query = query[rawFnc]( + `${not}${jsonFnc}(${key}, '${stringifyArray(value)}')` + ) + }) + } else { + const andOr = mode === filters?.containsAny ? " OR " : " AND " + iterate(mode, (key: string, value: Array) => { + let statement = "" + for (let i in value) { + if (typeof value[i] === "string") { + value[i] = `%"${value[i]}"%` + } else { + value[i] = `%${value[i]}%` + } + statement += + (statement ? andOr : "") + + `LOWER(${likeKey(this.client, key)}) LIKE ?` + } + // @ts-ignore + query = query[rawFnc](`${not}(${statement})`, value) + }) + } + } + if (!filters) { return query } @@ -229,32 +284,13 @@ class InternalBuilder { }) } if (filters.contains) { - const fnc = allOr ? "orWhere" : "where" - const rawFnc = `${fnc}Raw` - if (this.client === SqlClient.POSTGRES) { - iterate(filters.contains, (key: string, value: any) => { - const fieldNames = key.split(/\./g) - const tableName = fieldNames[0] - const columnName = fieldNames[1] - if (typeof value === "string") { - value = `"${value}"` - } - // @ts-ignore - query = query[rawFnc]( - `"${tableName}"."${columnName}"::jsonb @> '[${value}]'` - ) - }) - } else if (this.client === SqlClient.MY_SQL) { - iterate(filters.contains, (key: string, value: any) => { - if (typeof value === "string") { - value = `"${value}"` - } - // @ts-ignore - query = query[rawFnc](`JSON_CONTAINS(${key}, '${value}')`) - }) - } else { - iterate(filters.contains, like) - } + contains(filters.contains) + } + if (filters.notContains) { + contains(filters.notContains) + } + if (filters.containsAny) { + contains(filters.containsAny, true) } return query } diff --git a/packages/server/src/integrations/tests/sql.spec.js b/packages/server/src/integrations/tests/sql.spec.js index 3d748a03c0..3cc9f0fb3e 100644 --- a/packages/server/src/integrations/tests/sql.spec.js +++ b/packages/server/src/integrations/tests/sql.spec.js @@ -240,18 +240,18 @@ describe("SQL query builder", () => { }) }) - it("should use like expression for MS-SQL when filter is contains", () => { + it("should use AND like expression for MS-SQL when filter is contains", () => { const query = new Sql(SqlClient.MS_SQL, 10)._query(generateReadJson({ filters: { contains: { - age: 20, - name: "John" + age: [20, 25], + name: ["John", "Mary"] } } })) expect(query).toEqual({ - bindings: [10, "%20%", "%John%"], - sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where LOWER(${TABLE_NAME}.age) LIKE @p1 and LOWER(${TABLE_NAME}.name) LIKE @p2) as [${TABLE_NAME}]` + bindings: [10, "%20%", "%25%", `%"John"%`, `%"Mary"%`], + sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where (LOWER(${TABLE_NAME}.age) LIKE @p1 AND LOWER(${TABLE_NAME}.age) LIKE @p2) and (LOWER(${TABLE_NAME}.name) LIKE @p3 AND LOWER(${TABLE_NAME}.name) LIKE @p4)) as [${TABLE_NAME}]` }) }) @@ -259,14 +259,14 @@ describe("SQL query builder", () => { const query = new Sql(SqlClient.MY_SQL, 10)._query(generateReadJson({ filters: { contains: { - age: 20, - name: "John" + age: [20], + name: ["John"] } } })) expect(query).toEqual({ bindings: [10], - sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_CONTAINS(${TABLE_NAME}.age, '20') and JSON_CONTAINS(${TABLE_NAME}.name, '"John"') limit ?) as \`${TABLE_NAME}\`` + sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_CONTAINS(${TABLE_NAME}.age, '[20]') and JSON_CONTAINS(${TABLE_NAME}.name, '["John"]') limit ?) as \`${TABLE_NAME}\`` }) }) @@ -274,8 +274,8 @@ describe("SQL query builder", () => { const query = new Sql(SqlClient.POSTGRES, 10)._query(generateReadJson({ filters: { contains: { - age: 20, - name: "John" + age: [20], + name: ["John"] } } })) @@ -284,4 +284,94 @@ describe("SQL query builder", () => { sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb @> '[20]' and \"${TABLE_NAME}\".\"name\"::jsonb @> '["John"]' limit $1) as \"${TABLE_NAME}\"` }) }) + + it("should use NOT like expression for MS-SQL when filter is notContains", () => { + const query = new Sql(SqlClient.MS_SQL, 10)._query(generateReadJson({ + filters: { + notContains: { + age: [20], + name: ["John"] + } + } + })) + expect(query).toEqual({ + bindings: [10, "%20%", `%"John"%`], + sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where NOT (LOWER(${TABLE_NAME}.age) LIKE @p1) and NOT (LOWER(${TABLE_NAME}.name) LIKE @p2)) as [${TABLE_NAME}]` + }) + }) + + it("should use NOT JSON_CONTAINS expression for MySQL when filter is notContains", () => { + const query = new Sql(SqlClient.MY_SQL, 10)._query(generateReadJson({ + filters: { + notContains: { + age: [20], + name: ["John"] + } + } + })) + expect(query).toEqual({ + bindings: [10], + sql: `select * from (select * from \`${TABLE_NAME}\` where NOT JSON_CONTAINS(${TABLE_NAME}.age, '[20]') and NOT JSON_CONTAINS(${TABLE_NAME}.name, '["John"]') limit ?) as \`${TABLE_NAME}\`` + }) + }) + + it("should use jsonb operator NOT expression for PostgreSQL when filter is notContains", () => { + const query = new Sql(SqlClient.POSTGRES, 10)._query(generateReadJson({ + filters: { + notContains: { + age: [20], + name: ["John"] + } + } + })) + expect(query).toEqual({ + bindings: [10], + sql: `select * from (select * from \"${TABLE_NAME}\" where NOT \"${TABLE_NAME}\".\"age\"::jsonb @> '[20]' and NOT \"${TABLE_NAME}\".\"name\"::jsonb @> '["John"]' limit $1) as \"${TABLE_NAME}\"` + }) + }) + + it("should use OR like expression for MS-SQL when filter is containsAny", () => { + const query = new Sql(SqlClient.MS_SQL, 10)._query(generateReadJson({ + filters: { + containsAny: { + age: [20, 25], + name: ["John", "Mary"] + } + } + })) + expect(query).toEqual({ + bindings: [10, "%20%", "%25%", `%"John"%`, `%"Mary"%`], + sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where (LOWER(${TABLE_NAME}.age) LIKE @p1 OR LOWER(${TABLE_NAME}.age) LIKE @p2) and (LOWER(${TABLE_NAME}.name) LIKE @p3 OR LOWER(${TABLE_NAME}.name) LIKE @p4)) as [${TABLE_NAME}]` + }) + }) + + it("should use JSON_OVERLAPS expression for MySQL when filter is containsAny", () => { + const query = new Sql(SqlClient.MY_SQL, 10)._query(generateReadJson({ + filters: { + containsAny: { + age: [20, 25], + name: ["John", "Mary"] + } + } + })) + expect(query).toEqual({ + bindings: [10], + sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_OVERLAPS(${TABLE_NAME}.age, '[20,25]') and JSON_OVERLAPS(${TABLE_NAME}.name, '["John","Mary"]') limit ?) as \`${TABLE_NAME}\`` + }) + }) + + it("should use ?| operator expression for PostgreSQL when filter is containsAny", () => { + const query = new Sql(SqlClient.POSTGRES, 10)._query(generateReadJson({ + filters: { + containsAny: { + age: [20, 25], + name: ["John", "Mary"] + } + } + })) + expect(query).toEqual({ + bindings: [10], + sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb ?| array [20,25] and \"${TABLE_NAME}\".\"name\"::jsonb ?| array ['John','Mary'] limit $1) as \"${TABLE_NAME}\"` + }) + }) }) diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index b3bfe2e529..7fd0fde8b3 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1094,12 +1094,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.2.39-alpha.5": - version "1.2.39-alpha.5" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.39-alpha.5.tgz#fbadac10657e44fb05641a43aa8d9481b86418e9" - integrity sha512-bZPmKqWUnQ+OVwf2z35WXPfPuxwuL0vlZJNyTgLX7hdhjYfPB4LA0vMftPbvtRFO9k6SdB0XpBOJCm2u5k5KsQ== +"@budibase/backend-core@1.2.39-alpha.7": + version "1.2.39-alpha.7" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.39-alpha.7.tgz#79c2b3c1b02b6e5c9a42f5bf7e76ea6b2498a971" + integrity sha512-1UVfEetO3sbfa7tC7rOXTWrYjpaTZtYpijZMz1CtdOYJKzCimHVbIWWCmEO8BgSOejtWTvIARjoqCfy6oWFM6w== dependencies: - "@budibase/types" "1.2.39-alpha.5" + "@budibase/types" "1.2.39-alpha.7" "@techpass/passport-openidconnect" "0.3.2" aws-sdk "2.1030.0" bcrypt "5.0.1" @@ -1178,13 +1178,13 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/pro@1.2.39-alpha.5": - version "1.2.39-alpha.5" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.39-alpha.5.tgz#cd652a06bf691ae00c2bf8cd9351e46b684939a5" - integrity sha512-6M0Mj+AbJi+HpFRJJD1bZDwuWlCq1I3m8vrG4A3Rm/VnJigb1Zi7XTMlwzgCiUaWvowstiJVGHG6Af0Mix4zdQ== +"@budibase/pro@1.2.39-alpha.7": + version "1.2.39-alpha.7" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.39-alpha.7.tgz#e913b91168f73859ffc78824dc7bd2c4cb7514ef" + integrity sha512-HHlAoH4A35p/5nepHVtQ79IrGAG4U3fPzaX6/gz0Ws/tutYRS8vfvGG0OCXom9mBy8X1xcO/X8+KPrHi0oVpQg== dependencies: - "@budibase/backend-core" "1.2.39-alpha.5" - "@budibase/types" "1.2.39-alpha.5" + "@budibase/backend-core" "1.2.39-alpha.7" + "@budibase/types" "1.2.39-alpha.7" "@koa/router" "8.0.8" joi "17.6.0" node-fetch "^2.6.1" @@ -1207,10 +1207,10 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" -"@budibase/types@1.2.39-alpha.5": - version "1.2.39-alpha.5" - resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.39-alpha.5.tgz#632ef72b248d105cb69f4a133d78d3a293e5404e" - integrity sha512-MgJayPh6t7VGB6ErUwM0sJmJoxG91h3z24fWSE+q3bbH2MKbnkpuNCbOh1wlKyFWqzdRofuFpJGK/O9zWXvRwg== +"@budibase/types@1.2.39-alpha.7": + version "1.2.39-alpha.7" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.39-alpha.7.tgz#d68d5c83d7368a7a5596c0fa70dea3cc1f8629f0" + integrity sha512-R5zOze0jD68M6zbEMRCCy46jBjbktcD9cb/U0YPbaHSQNILPgmrsEdXEhHK7JGByfLtPsmPVd9ccDGWV9kaqNw== "@bull-board/api@3.7.0": version "3.7.0" diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 36854f3642..f4a6995318 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/types/package.json b/packages/types/package.json index 7455926201..472e727ff1 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/types", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "description": "Budibase types", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/types/src/sdk/search.ts b/packages/types/src/sdk/search.ts index 6721fe6b55..954ad42ac9 100644 --- a/packages/types/src/sdk/search.ts +++ b/packages/types/src/sdk/search.ts @@ -31,7 +31,13 @@ export interface SearchFilters { [key: string]: any[] } contains?: { - [key: string]: any + [key: string]: any[] + } + notContains?: { + [key: string]: any[] + } + containsAny?: { + [key: string]: any[] } } diff --git a/packages/worker/package.json b/packages/worker/package.json index aaeff3c56d..bfb28ccaaa 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "1.2.39-alpha.5", + "version": "1.2.39-alpha.7", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -35,10 +35,10 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "1.2.39-alpha.5", - "@budibase/pro": "1.2.39-alpha.5", - "@budibase/string-templates": "1.2.39-alpha.5", - "@budibase/types": "1.2.39-alpha.5", + "@budibase/backend-core": "1.2.39-alpha.7", + "@budibase/pro": "1.2.39-alpha.7", + "@budibase/string-templates": "1.2.39-alpha.7", + "@budibase/types": "1.2.39-alpha.7", "@koa/router": "8.0.8", "@sentry/node": "6.17.7", "@techpass/passport-openidconnect": "0.3.2", diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 380d80a741..c6d779b37a 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -291,12 +291,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.2.39-alpha.5": - version "1.2.39-alpha.5" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.39-alpha.5.tgz#fbadac10657e44fb05641a43aa8d9481b86418e9" - integrity sha512-bZPmKqWUnQ+OVwf2z35WXPfPuxwuL0vlZJNyTgLX7hdhjYfPB4LA0vMftPbvtRFO9k6SdB0XpBOJCm2u5k5KsQ== +"@budibase/backend-core@1.2.39-alpha.7": + version "1.2.39-alpha.7" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.2.39-alpha.7.tgz#79c2b3c1b02b6e5c9a42f5bf7e76ea6b2498a971" + integrity sha512-1UVfEetO3sbfa7tC7rOXTWrYjpaTZtYpijZMz1CtdOYJKzCimHVbIWWCmEO8BgSOejtWTvIARjoqCfy6oWFM6w== dependencies: - "@budibase/types" "1.2.39-alpha.5" + "@budibase/types" "1.2.39-alpha.7" "@techpass/passport-openidconnect" "0.3.2" aws-sdk "2.1030.0" bcrypt "5.0.1" @@ -325,21 +325,21 @@ uuid "8.3.2" zlib "1.0.5" -"@budibase/pro@1.2.39-alpha.5": - version "1.2.39-alpha.5" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.39-alpha.5.tgz#cd652a06bf691ae00c2bf8cd9351e46b684939a5" - integrity sha512-6M0Mj+AbJi+HpFRJJD1bZDwuWlCq1I3m8vrG4A3Rm/VnJigb1Zi7XTMlwzgCiUaWvowstiJVGHG6Af0Mix4zdQ== +"@budibase/pro@1.2.39-alpha.7": + version "1.2.39-alpha.7" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.2.39-alpha.7.tgz#e913b91168f73859ffc78824dc7bd2c4cb7514ef" + integrity sha512-HHlAoH4A35p/5nepHVtQ79IrGAG4U3fPzaX6/gz0Ws/tutYRS8vfvGG0OCXom9mBy8X1xcO/X8+KPrHi0oVpQg== dependencies: - "@budibase/backend-core" "1.2.39-alpha.5" - "@budibase/types" "1.2.39-alpha.5" + "@budibase/backend-core" "1.2.39-alpha.7" + "@budibase/types" "1.2.39-alpha.7" "@koa/router" "8.0.8" joi "17.6.0" node-fetch "^2.6.1" -"@budibase/types@1.2.39-alpha.5": - version "1.2.39-alpha.5" - resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.39-alpha.5.tgz#632ef72b248d105cb69f4a133d78d3a293e5404e" - integrity sha512-MgJayPh6t7VGB6ErUwM0sJmJoxG91h3z24fWSE+q3bbH2MKbnkpuNCbOh1wlKyFWqzdRofuFpJGK/O9zWXvRwg== +"@budibase/types@1.2.39-alpha.7": + version "1.2.39-alpha.7" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.2.39-alpha.7.tgz#d68d5c83d7368a7a5596c0fa70dea3cc1f8629f0" + integrity sha512-R5zOze0jD68M6zbEMRCCy46jBjbktcD9cb/U0YPbaHSQNILPgmrsEdXEhHK7JGByfLtPsmPVd9ccDGWV9kaqNw== "@cspotcode/source-map-consumer@0.8.0": version "0.8.0"