Skip to content

Commit

Permalink
Merge branch 'master' into server-ts-2
Browse files Browse the repository at this point in the history
  • Loading branch information
samwho authored Jan 16, 2025
2 parents 177005e + bfc5b49 commit d7b741e
Show file tree
Hide file tree
Showing 34 changed files with 440 additions and 225 deletions.
4 changes: 2 additions & 2 deletions packages/backend-core/src/db/couch/connections.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import env from "../../environment"

export const getCouchInfo = (connection?: string) => {
export const getCouchInfo = (connection?: string | null) => {
// clean out any auth credentials
const urlInfo = getUrlInfo(connection)
let username
Expand Down Expand Up @@ -45,7 +45,7 @@ export const getCouchInfo = (connection?: string) => {
}
}

export const getUrlInfo = (url = env.COUCH_DB_URL) => {
export const getUrlInfo = (url: string | null = env.COUCH_DB_URL) => {
let cleanUrl, username, password, host
if (url) {
// Ensure the URL starts with a protocol
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require("../../../tests")
const getUrlInfo = require("../couch").getUrlInfo

import { getUrlInfo } from "../couch"

describe("pouch", () => {
describe("Couch DB URL parsing", () => {
Expand Down
30 changes: 17 additions & 13 deletions packages/backend-core/src/sql/sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1172,20 +1172,22 @@ class InternalBuilder {
nulls = value.direction === SortOrder.ASCENDING ? "first" : "last"
}

const composite = `${aliased}.${key}`
let identifier

if (this.isAggregateField(key)) {
query = query.orderBy(key, direction, nulls)
identifier = this.rawQuotedIdentifier(key)
} else if (this.client === SqlClient.ORACLE) {
identifier = this.convertClobs(composite)
} else {
let composite = `${aliased}.${key}`
if (this.client === SqlClient.ORACLE) {
query = query.orderByRaw(`?? ?? nulls ??`, [
this.convertClobs(composite),
this.knex.raw(direction),
this.knex.raw(nulls as string),
])
} else {
query = query.orderBy(composite, direction, nulls)
}
identifier = this.rawQuotedIdentifier(composite)
}

query = query.orderByRaw(`?? ?? ${nulls ? "nulls ??" : ""}`, [
identifier,
this.knex.raw(direction),
...(nulls ? [this.knex.raw(nulls as string)] : []),
])
}
}

Expand Down Expand Up @@ -1344,14 +1346,16 @@ class InternalBuilder {

// add the correlation to the overall query
subQuery = subQuery.where(
correlatedTo,
this.rawQuotedIdentifier(correlatedTo),
"=",
this.rawQuotedIdentifier(correlatedFrom)
)

const standardWrap = (select: Knex.Raw): Knex.QueryBuilder => {
subQuery = subQuery
.select(relationshipFields)
.select(
relationshipFields.map(field => this.rawQuotedIdentifier(field))
)
.limit(getRelationshipLimit())
// @ts-ignore - the from alias syntax isn't in Knex typing
return knex.select(select).from({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
const _ = require("lodash/fp")
const { structures } = require("../../../tests")
import { range } from "lodash/fp"
import { structures } from "../.."

jest.mock("../../../src/context")
jest.mock("../../../src/db")

const context = require("../../../src/context")
const db = require("../../../src/db")
import * as context from "../../../src/context"
import * as db from "../../../src/db"

const { getCreatorCount } = require("../../../src/users/users")
import { getCreatorCount } from "../../../src/users/users"

describe("Users", () => {
let getGlobalDBMock
let paginationMock
let getGlobalDBMock: jest.SpyInstance
let paginationMock: jest.SpyInstance

beforeEach(() => {
jest.resetAllMocks()
Expand All @@ -22,11 +22,10 @@ describe("Users", () => {
jest.spyOn(db, "getGlobalUserParams")
})

it("Retrieves the number of creators", async () => {
const getUsers = (offset, limit, creators = false) => {
const range = _.range(offset, limit)
it("retrieves the number of creators", async () => {
const getUsers = (offset: number, limit: number, creators = false) => {
const opts = creators ? { builder: { global: true } } : undefined
return range.map(() => structures.users.user(opts))
return range(offset, limit).map(() => structures.users.user(opts))
}
const page1Data = getUsers(0, 8)
const page2Data = getUsers(8, 12, true)
Expand Down
79 changes: 52 additions & 27 deletions packages/client/src/components/app/DataProvider.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
<script>
<script lang="ts">
import { getContext } from "svelte"
import { Pagination, ProgressCircle } from "@budibase/bbui"
import { fetchData, QueryUtils } from "@budibase/frontend-core"
import { LogicalOperator, EmptyFilterOption } from "@budibase/types"
import {
LogicalOperator,
EmptyFilterOption,
TableSchema,
SortOrder,
SearchFilters,
UISearchFilter,
DataFetchDatasource,
UserDatasource,
GroupUserDatasource,
DataFetchOptions,
} from "@budibase/types"
import { SDK, Component } from "../../index"
export let dataSource
export let filter
export let sortColumn
export let sortOrder
export let limit
export let paginate
export let autoRefresh
type ProviderDatasource = Exclude<
DataFetchDatasource,
UserDatasource | GroupUserDatasource
>
const { styleable, Provider, ActionTypes, API } = getContext("sdk")
const component = getContext("component")
export let dataSource: ProviderDatasource
export let filter: UISearchFilter
export let sortColumn: string
export let sortOrder: SortOrder
export let limit: number
export let paginate: boolean
export let autoRefresh: number
let interval
let queryExtensions = {}
const { styleable, Provider, ActionTypes, API } = getContext<SDK>("sdk")
const component = getContext<Component>("component")
let interval: ReturnType<typeof setInterval>
let queryExtensions: Record<string, any> = {}
$: defaultQuery = QueryUtils.buildQuery(filter)
Expand Down Expand Up @@ -49,8 +66,14 @@
},
{
type: ActionTypes.SetDataProviderSorting,
callback: ({ column, order }) => {
let newOptions = {}
callback: ({
column,
order,
}: {
column: string
order: SortOrder | undefined
}) => {
let newOptions: Partial<DataFetchOptions> = {}
if (column) {
newOptions.sortColumn = column
}
Expand All @@ -63,6 +86,7 @@
},
},
]
$: dataContext = {
rows: $fetch.rows,
info: $fetch.info,
Expand All @@ -75,14 +99,12 @@
id: $component?.id,
state: {
query: $fetch.query,
sortColumn: $fetch.sortColumn,
sortOrder: $fetch.sortOrder,
},
limit,
primaryDisplay: $fetch.definition?.primaryDisplay,
primaryDisplay: ($fetch.definition as any)?.primaryDisplay,
}
const createFetch = datasource => {
const createFetch = (datasource: ProviderDatasource) => {
return fetchData({
API,
datasource,
Expand All @@ -96,7 +118,7 @@
})
}
const sanitizeSchema = schema => {
const sanitizeSchema = (schema: TableSchema | null) => {
if (!schema) {
return schema
}
Expand All @@ -109,14 +131,14 @@
return cloned
}
const addQueryExtension = (key, extension) => {
const addQueryExtension = (key: string, extension: any) => {
if (!key || !extension) {
return
}
queryExtensions = { ...queryExtensions, [key]: extension }
}
const removeQueryExtension = key => {
const removeQueryExtension = (key: string) => {
if (!key) {
return
}
Expand All @@ -125,11 +147,14 @@
queryExtensions = newQueryExtensions
}
const extendQuery = (defaultQuery, extensions) => {
const extendQuery = (
defaultQuery: SearchFilters,
extensions: Record<string, any>
): SearchFilters => {
if (!Object.keys(extensions).length) {
return defaultQuery
}
const extended = {
const extended: SearchFilters = {
[LogicalOperator.AND]: {
conditions: [
...(defaultQuery ? [defaultQuery] : []),
Expand All @@ -140,12 +165,12 @@
}
// If there are no conditions applied at all, clear the request.
return extended[LogicalOperator.AND]?.conditions?.length > 0
return (extended[LogicalOperator.AND]?.conditions?.length ?? 0) > 0
? extended
: null
: {}
}
const setUpAutoRefresh = autoRefresh => {
const setUpAutoRefresh = (autoRefresh: number) => {
clearInterval(interval)
if (autoRefresh) {
interval = setInterval(fetch.refresh, Math.max(10000, autoRefresh * 1000))
Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { APIClient } from "@budibase/frontend-core"
import type { ActionTypes } from "./constants"
import { Readable } from "svelte/store"

export interface SDK {
API: APIClient
styleable: any
Provider: any
ActionTypes: typeof ActionTypes
}

export type Component = Readable<{
id: string
styles: any
}>
2 changes: 1 addition & 1 deletion packages/client/src/stores/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { screenStore } from "./screens"
import { builderStore } from "./builder"
import Router from "../components/Router.svelte"
import * as AppComponents from "../components/app/index.js"
import { ScreenslotType } from "../constants.js"
import { ScreenslotType } from "../constants"

export const BudibasePrefix = "@budibase/standard-components/"

Expand Down
34 changes: 23 additions & 11 deletions packages/frontend-core/src/components/grid/stores/datasource.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// TODO: datasource and defitions are unions of the different implementations. At this point, the datasource does not know what type is being used, and the assignations will cause TS exceptions. Casting it "as any" for now. This should be fixed improving the type usages.

import { derived, get, Readable, Writable } from "svelte/store"
import { getDatasourceDefinition, getDatasourceSchema } from "../../../fetch"
import {
DataFetchDefinition,
getDatasourceDefinition,
getDatasourceSchema,
} from "../../../fetch"
import { enrichSchemaWithRelColumns, memo } from "../../../utils"
import { cloneDeep } from "lodash"
import {
Expand All @@ -18,7 +22,7 @@ import { Store as StoreContext, BaseStoreProps } from "."
import { DatasourceActions } from "./datasources"

interface DatasourceStore {
definition: Writable<UIDatasource | null>
definition: Writable<DataFetchDefinition | null>
schemaMutations: Writable<Record<string, UIFieldMutation>>
subSchemaMutations: Writable<Record<string, Record<string, UIFieldMutation>>>
}
Expand Down Expand Up @@ -131,11 +135,17 @@ export const deriveStores = (context: StoreContext): DerivedDatasourceStore => {
[datasource, definition],
([$datasource, $definition]) => {
let type = $datasource?.type
// @ts-expect-error
if (type === "provider") {
type = ($datasource as any).value?.datasource?.type // TODO: see line 1
}
// Handle calculation views
if (type === "viewV2" && $definition?.type === ViewV2Type.CALCULATION) {
if (
type === "viewV2" &&
$definition &&
"type" in $definition &&
$definition.type === ViewV2Type.CALCULATION
) {
return false
}
return !!type && ["table", "viewV2", "link"].includes(type)
Expand Down Expand Up @@ -197,7 +207,7 @@ export const createActions = (context: StoreContext): ActionDatasourceStore => {
) => {
// Update local state
const originalDefinition = get(definition)
definition.set(newDefinition as UIDatasource)
definition.set(newDefinition)

// Update server
if (get(config).canSaveSchema) {
Expand Down Expand Up @@ -225,13 +235,15 @@ export const createActions = (context: StoreContext): ActionDatasourceStore => {
// Update primary display
newDefinition.primaryDisplay = column

// Sanitise schema to ensure field is required and has no default value
if (!newDefinition.schema[column].constraints) {
newDefinition.schema[column].constraints = {}
}
newDefinition.schema[column].constraints.presence = { allowEmpty: false }
if ("default" in newDefinition.schema[column]) {
delete newDefinition.schema[column].default
if (newDefinition.schema) {
// Sanitise schema to ensure field is required and has no default value
if (!newDefinition.schema[column].constraints) {
newDefinition.schema[column].constraints = {}
}
newDefinition.schema[column].constraints.presence = { allowEmpty: false }
if ("default" in newDefinition.schema[column]) {
delete newDefinition.schema[column].default
}
}
return await saveDefinition(newDefinition as any) // TODO: see line 1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { get } from "svelte/store"
import { Store as StoreContext } from ".."
import { DatasourceTableActions } from "."
import TableFetch from "../../../../fetch/TableFetch"

const SuppressErrors = true

Expand Down Expand Up @@ -119,7 +120,7 @@ export const initialise = (context: StoreContext) => {
unsubscribers.push(
allFilters.subscribe($allFilters => {
// Ensure we're updating the correct fetch
const $fetch = get(fetch)
const $fetch = get(fetch) as TableFetch | null
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
return
}
Expand All @@ -133,7 +134,7 @@ export const initialise = (context: StoreContext) => {
unsubscribers.push(
sort.subscribe($sort => {
// Ensure we're updating the correct fetch
const $fetch = get(fetch)
const $fetch = get(fetch) as TableFetch | null
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
return
}
Expand Down
Loading

0 comments on commit d7b741e

Please sign in to comment.