Merge branch 'master' of github.com:Budibase/budibase into grid-layout-improved

This commit is contained in:
Andrew Kingston 2024-07-31 16:45:13 +01:00
commit 391294f7a1
No known key found for this signature in database
38 changed files with 635 additions and 204 deletions

View File

@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "2.29.25",
"version": "2.29.27",
"npmClient": "yarn",
"packages": [
"packages/*",

View File

@ -10,7 +10,7 @@
"@types/proper-lockfile": "^4.1.4",
"@typescript-eslint/parser": "6.9.0",
"esbuild": "^0.18.17",
"esbuild-node-externals": "^1.8.0",
"esbuild-node-externals": "^1.14.0",
"eslint": "^8.52.0",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-jest": "^27.9.0",

@ -1 +1 @@
Subproject commit b03e584e465f620b49a1b688ff4afc973e6c0758
Subproject commit 32b8fa4643b4f0f74ee89760deffe431ab347ad9

View File

@ -308,8 +308,12 @@ export class DatabaseImpl implements Database {
}
async bulkDocs(documents: AnyDocument[]) {
const now = new Date().toISOString()
return this.performCall(db => {
return () => db.bulk({ docs: documents })
return () =>
db.bulk({
docs: documents.map(d => ({ createdAt: now, ...d, updatedAt: now })),
})
})
}

View File

@ -0,0 +1,118 @@
import tk from "timekeeper"
import { DatabaseImpl } from ".."
import { generator, structures } from "../../../../tests"
const initialTime = new Date()
tk.freeze(initialTime)
describe("DatabaseImpl", () => {
const db = new DatabaseImpl(structures.db.id())
beforeEach(() => {
tk.freeze(initialTime)
})
describe("put", () => {
it("persists createdAt and updatedAt fields", async () => {
const id = generator.guid()
await db.put({ _id: id })
expect(await db.get(id)).toEqual({
_id: id,
_rev: expect.any(String),
createdAt: initialTime.toISOString(),
updatedAt: initialTime.toISOString(),
})
})
it("updates updated at fields", async () => {
const id = generator.guid()
await db.put({ _id: id })
tk.travel(100)
await db.put({ ...(await db.get(id)), newValue: 123 })
expect(await db.get(id)).toEqual({
_id: id,
_rev: expect.any(String),
newValue: 123,
createdAt: initialTime.toISOString(),
updatedAt: new Date().toISOString(),
})
})
})
describe("bulkDocs", () => {
it("persists createdAt and updatedAt fields", async () => {
const ids = generator.unique(() => generator.guid(), 5)
await db.bulkDocs(ids.map(id => ({ _id: id })))
for (const id of ids) {
expect(await db.get(id)).toEqual({
_id: id,
_rev: expect.any(String),
createdAt: initialTime.toISOString(),
updatedAt: initialTime.toISOString(),
})
}
})
it("updates updated at fields", async () => {
const ids = generator.unique(() => generator.guid(), 5)
await db.bulkDocs(ids.map(id => ({ _id: id })))
tk.travel(100)
const docsToUpdate = await Promise.all(
ids.map(async id => ({ ...(await db.get(id)), newValue: 123 }))
)
await db.bulkDocs(docsToUpdate)
for (const id of ids) {
expect(await db.get(id)).toEqual({
_id: id,
_rev: expect.any(String),
newValue: 123,
createdAt: initialTime.toISOString(),
updatedAt: new Date().toISOString(),
})
}
})
it("keeps existing createdAt", async () => {
const ids = generator.unique(() => generator.guid(), 2)
await db.bulkDocs(ids.map(id => ({ _id: id })))
tk.travel(100)
const newDocs = generator
.unique(() => generator.guid(), 3)
.map(id => ({ _id: id }))
const docsToUpdate = await Promise.all(
ids.map(async id => ({ ...(await db.get(id)), newValue: 123 }))
)
await db.bulkDocs([...newDocs, ...docsToUpdate])
for (const { _id } of docsToUpdate) {
expect(await db.get(_id)).toEqual({
_id,
_rev: expect.any(String),
newValue: 123,
createdAt: initialTime.toISOString(),
updatedAt: new Date().toISOString(),
})
}
for (const { _id } of newDocs) {
expect(await db.get(_id)).toEqual({
_id,
_rev: expect.any(String),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
})
}
})
})
})

View File

@ -54,6 +54,7 @@
</div>
<div class="controls">
<div
class:disabled={!$selectedAutomation?.definition?.trigger}
on:click={() => {
testDataModal.show()
}}
@ -80,6 +81,7 @@
automation._id,
automation.disabled
)}
disabled={!$selectedAutomation?.definition?.trigger}
value={!automation.disabled}
/>
</div>

View File

@ -54,7 +54,7 @@
name: "Edit",
keyBind: null,
visible: true,
disabled: false,
disabled: !automation.definition.trigger,
callback: updateAutomationDialog.show,
},
{
@ -62,7 +62,9 @@
name: "Duplicate",
keyBind: null,
visible: true,
disabled: automation.definition.trigger.name === "Webhook",
disabled:
!automation.definition.trigger ||
automation.definition.trigger?.name === "Webhook",
callback: duplicateAutomation,
},
]
@ -74,7 +76,7 @@
name: automation.disabled ? "Activate" : "Pause",
keyBind: null,
visible: true,
disabled: false,
disabled: !automation.definition.trigger,
callback: () => {
automationStore.actions.toggleDisabled(
automation._id,

View File

@ -20,7 +20,7 @@
.map(automation => ({
...automation,
displayName:
$automationStore.automationDisplayData[automation._id].displayName ||
$automationStore.automationDisplayData[automation._id]?.displayName ||
automation.name,
}))
.sort((a, b) => {
@ -30,12 +30,13 @@
})
$: groupedAutomations = filteredAutomations.reduce((acc, auto) => {
acc[auto.definition.trigger.event] ??= {
icon: auto.definition.trigger.icon,
name: (auto.definition.trigger?.name || "").toUpperCase(),
const catName = auto.definition?.trigger?.event || "No Trigger"
acc[catName] ??= {
icon: auto.definition?.trigger?.icon || "AlertCircle",
name: (auto.definition?.trigger?.name || "No Trigger").toUpperCase(),
entries: [],
}
acc[auto.definition.trigger.event].entries.push(auto)
acc[catName].entries.push(auto)
return acc
}, {})

View File

@ -21,7 +21,9 @@
$: nameError =
nameTouched && !name ? "Please specify a name for the automation." : null
$: triggers = Object.entries($automationStore.blockDefinitions.TRIGGER)
$: triggers = Object.entries(
$automationStore.blockDefinitions.CREATABLE_TRIGGER
)
async function createAutomation() {
try {

View File

@ -13,7 +13,7 @@
const { datasource } = getContext("grid")
$: triggers = $automationStore.blockDefinitions.TRIGGER
$: triggers = $automationStore.blockDefinitions.CREATABLE_TRIGGER
$: table = $tables.list.find(table => table._id === $datasource.tableId)

View File

@ -100,51 +100,43 @@
async function handleFile(e) {
loading = true
error = null
const previousValidation = validation
validation = {}
try {
const response = await parseFile(e)
rows = response.rows
fileName = response.fileName
const newValidateHash = JSON.stringify(rows)
if (newValidateHash === validateHash) {
validation = previousValidation
} else {
await validate(rows)
validateHash = newValidateHash
}
} catch (e) {
error = e.message || e
} finally {
loading = false
error = e
}
}
async function validate(rows) {
loading = true
error = null
validation = {}
allValid = false
try {
if (rows.length > 0) {
const response = await API.validateExistingTableImport({
rows,
tableId,
})
if (rows.length > 0) {
const response = await API.validateExistingTableImport({
rows,
tableId,
})
validation = response.schemaValidation
invalidColumns = response.invalidColumns
allValid = response.allValid
}
} catch (e) {
error = e.message
validation = response.schemaValidation
invalidColumns = response.invalidColumns
allValid = response.allValid
}
loading = false
}
$: {
// binding in consumer is causing double renders here
const newValidateHash = JSON.stringify(rows)
if (newValidateHash !== validateHash) {
validate(rows)
}
validateHash = newValidateHash
}
</script>

View File

@ -5,14 +5,16 @@ import { generate } from "shortid"
import { createHistoryStore } from "stores/builder/history"
import { notifications } from "@budibase/bbui"
import { updateReferencesInObject } from "dataBinding"
import { AutomationTriggerStepId } from "@budibase/types"
const initialAutomationState = {
automations: [],
testResults: null,
showTestPanel: false,
blockDefinitions: {
TRIGGER: [],
ACTION: [],
TRIGGER: {},
CREATABLE_TRIGGER: {},
ACTION: {},
},
selectedAutomationId: null,
automationDisplayData: {},
@ -46,14 +48,29 @@ const updateStepReferences = (steps, modifiedIndex, action) => {
})
}
const getFinalDefinitions = (triggers, actions) => {
const creatable = {}
Object.entries(triggers).forEach(entry => {
if (entry[0] === AutomationTriggerStepId.ROW_ACTION) {
return
}
creatable[entry[0]] = entry[1]
})
return {
TRIGGER: triggers,
CREATABLE_TRIGGER: creatable,
ACTION: actions,
}
}
const automationActions = store => ({
definitions: async () => {
const response = await API.getAutomationDefinitions()
store.update(state => {
state.blockDefinitions = {
TRIGGER: response.trigger,
ACTION: response.action,
}
state.blockDefinitions = getFinalDefinitions(
response.trigger,
response.action
)
return state
})
return response
@ -69,10 +86,10 @@ const automationActions = store => ({
return a.name < b.name ? -1 : 1
})
state.automationDisplayData = automationResponse.builderData
state.blockDefinitions = {
TRIGGER: definitions.trigger,
ACTION: definitions.action,
}
state.blockDefinitions = getFinalDefinitions(
definitions.trigger,
definitions.action
)
return state
})
},
@ -87,8 +104,6 @@ const automationActions = store => ({
disabled: false,
}
const response = await store.actions.save(automation)
await store.actions.fetch()
store.actions.select(response._id)
return response
},
duplicate: async automation => {
@ -98,14 +113,13 @@ const automationActions = store => ({
_id: undefined,
_ref: undefined,
})
await store.actions.fetch()
store.actions.select(response._id)
return response
},
save: async automation => {
const response = await API.updateAutomation(automation)
await store.actions.fetch()
store.actions.select(response._id)
return response.automation
},
delete: async automation => {
@ -113,18 +127,22 @@ const automationActions = store => ({
automationId: automation?._id,
automationRev: automation?._rev,
})
store.update(state => {
// Remove the automation
state.automations = state.automations.filter(
x => x._id !== automation._id
)
// Select a new automation if required
if (automation._id === state.selectedAutomationId) {
store.actions.select(state.automations[0]?._id)
state.selectedAutomationId = state.automations[0]?._id || null
}
// Clear out automationDisplayData for the automation
delete state.automationDisplayData[automation._id]
return state
})
await store.actions.fetch()
},
toggleDisabled: async automationId => {
let automation
@ -381,7 +399,7 @@ export const selectedAutomation = derived(automationStore, $automationStore => {
export const selectedAutomationDisplayData = derived(
[automationStore, selectedAutomation],
([$automationStore, $selectedAutomation]) => {
if (!$selectedAutomation._id) {
if (!$selectedAutomation?._id) {
return null
}
return $automationStore.automationDisplayData[$selectedAutomation._id]

View File

@ -14,16 +14,20 @@ import { events, HTTPError } from "@budibase/backend-core"
import {
BulkImportRequest,
BulkImportResponse,
CsvToJsonRequest,
CsvToJsonResponse,
FetchTablesResponse,
MigrateRequest,
MigrateResponse,
Row,
SaveTableRequest,
SaveTableResponse,
Table,
TableResponse,
TableSourceType,
UserCtx,
ValidateNewTableImportRequest,
ValidateTableImportRequest,
ValidateTableImportResponse,
} from "@budibase/types"
import sdk from "../../../sdk"
import { jsonFromCsvString } from "../../../utilities/csv"
@ -144,7 +148,9 @@ export async function bulkImport(
ctx.body = { message: `Bulk rows created.` }
}
export async function csvToJson(ctx: UserCtx) {
export async function csvToJson(
ctx: UserCtx<CsvToJsonRequest, CsvToJsonResponse>
) {
const { csvString } = ctx.request.body
const result = await jsonFromCsvString(csvString)
@ -153,8 +159,10 @@ export async function csvToJson(ctx: UserCtx) {
ctx.body = result
}
export async function validateNewTableImport(ctx: UserCtx) {
const { rows, schema }: { rows: unknown; schema: unknown } = ctx.request.body
export async function validateNewTableImport(
ctx: UserCtx<ValidateNewTableImportRequest, ValidateTableImportResponse>
) {
const { rows, schema } = ctx.request.body
if (isRows(rows) && isSchema(schema)) {
ctx.status = 200
@ -164,8 +172,10 @@ export async function validateNewTableImport(ctx: UserCtx) {
}
}
export async function validateExistingTableImport(ctx: UserCtx) {
const { rows, tableId }: { rows: Row[]; tableId?: string } = ctx.request.body
export async function validateExistingTableImport(
ctx: UserCtx<ValidateTableImportRequest, ValidateTableImportResponse>
) {
const { rows, tableId } = ctx.request.body
let schema = null
if (tableId) {

View File

@ -14,6 +14,7 @@ import sdk from "../../../sdk"
import { Automation, FieldType, Table } from "@budibase/types"
import { mocks } from "@budibase/backend-core/tests"
import { FilterConditions } from "../../../automations/steps/filter"
import { removeDeprecated } from "../../../automations/utils"
const MAX_RETRIES = 4
let {
@ -69,14 +70,15 @@ describe("/automations", () => {
.expect("Content-Type", /json/)
.expect(200)
let definitionsLength = Object.keys(BUILTIN_ACTION_DEFINITIONS).length
definitionsLength-- // OUTGOING_WEBHOOK is deprecated
let definitionsLength = Object.keys(
removeDeprecated(BUILTIN_ACTION_DEFINITIONS)
).length
expect(Object.keys(res.body.action).length).toBeGreaterThanOrEqual(
definitionsLength
)
expect(Object.keys(res.body.trigger).length).toEqual(
Object.keys(TRIGGER_DEFINITIONS).length
Object.keys(removeDeprecated(TRIGGER_DEFINITIONS)).length
)
})
})

View File

@ -15,6 +15,7 @@ import {
Table,
TableSchema,
SupportedSqlTypes,
JsonFieldSubType,
} from "@budibase/types"
import { DatabaseName, getDatasource } from "../../../integrations/tests/utils"
import { tableForDatasource } from "../../../tests/utilities/structures"
@ -288,7 +289,10 @@ describe("/datasources", () => {
name: "options",
type: FieldType.OPTIONS,
constraints: {
presence: { allowEmpty: false },
presence: {
allowEmpty: false,
},
inclusion: [],
},
},
[FieldType.NUMBER]: {
@ -302,6 +306,10 @@ describe("/datasources", () => {
[FieldType.ARRAY]: {
name: "array",
type: FieldType.ARRAY,
constraints: {
type: JsonFieldSubType.ARRAY,
inclusion: [],
},
},
[FieldType.DATETIME]: {
name: "datetime",

View File

@ -32,6 +32,7 @@ import {
TableSourceType,
UpdatedRowEventEmitter,
TableSchema,
JsonFieldSubType,
} from "@budibase/types"
import { generator, mocks } from "@budibase/backend-core/tests"
import _, { merge } from "lodash"
@ -102,7 +103,7 @@ describe.each([
): SaveTableRequest {
const defaultSchema: TableSchema = {
id: {
type: FieldType.AUTO,
type: FieldType.NUMBER,
name: "id",
autocolumn: true,
constraints: {
@ -384,7 +385,7 @@ describe.each([
const arrayField: FieldSchema = {
type: FieldType.ARRAY,
constraints: {
type: "array",
type: JsonFieldSubType.ARRAY,
presence: false,
inclusion: ["One", "Two", "Three"],
},

View File

@ -5,12 +5,12 @@ import {
knexClient,
} from "../../../integrations/tests/utils"
import {
db as dbCore,
context,
db as dbCore,
MAX_VALID_DATE,
MIN_VALID_DATE,
utils,
SQLITE_DESIGN_DOC_ID,
utils,
} from "@budibase/backend-core"
import * as setup from "./utilities"
@ -20,6 +20,7 @@ import {
Datasource,
EmptyFilterOption,
FieldType,
JsonFieldSubType,
RelationshipType,
Row,
RowSearchParams,
@ -1494,7 +1495,10 @@ describe.each([
numbers: {
name: "numbers",
type: FieldType.ARRAY,
constraints: { inclusion: ["one", "two", "three"] },
constraints: {
type: JsonFieldSubType.ARRAY,
inclusion: ["one", "two", "three"],
},
},
})
await createRows([{ numbers: ["one", "two"] }, { numbers: ["three"] }])
@ -2560,4 +2564,48 @@ describe.each([
}).toContainExactly([{ name: "foo" }])
})
})
!isInMemory &&
describe("search by _id", () => {
let row: Row
beforeAll(async () => {
const toRelateTable = await createTable({
name: {
name: "name",
type: FieldType.STRING,
},
})
table = await createTable({
name: {
name: "name",
type: FieldType.STRING,
},
rel: {
name: "rel",
type: FieldType.LINK,
relationshipType: RelationshipType.MANY_TO_MANY,
tableId: toRelateTable._id!,
fieldName: "rel",
},
})
const [row1, row2] = await Promise.all([
config.api.row.save(toRelateTable._id!, { name: "tag 1" }),
config.api.row.save(toRelateTable._id!, { name: "tag 2" }),
])
row = await config.api.row.save(table._id!, {
name: "product 1",
rel: [row1._id, row2._id],
})
})
it("can filter by the row ID with limit 1", async () => {
await expectSearch({
query: {
equal: { _id: row._id },
},
limit: 1,
}).toContainExactly([row])
})
})
})

View File

@ -398,6 +398,7 @@ describe.each([
name: "auto",
autocolumn: true,
type: FieldType.AUTO,
subtype: AutoFieldSubType.AUTO_ID,
},
},
},

View File

@ -56,7 +56,7 @@ describe.each([
primary: ["id"],
schema: {
id: {
type: FieldType.AUTO,
type: FieldType.NUMBER,
name: "id",
autocolumn: true,
constraints: {
@ -241,7 +241,7 @@ describe.each([
schema: {
id: {
name: "id",
type: FieldType.AUTO,
type: FieldType.NUMBER,
autocolumn: true,
visible: true,
},
@ -1555,7 +1555,7 @@ describe.each([
schema: {
id: {
name: "id",
type: FieldType.AUTO,
type: FieldType.NUMBER,
autocolumn: true,
},
name: {

View File

@ -3,11 +3,15 @@ import { definitions } from "./triggerInfo"
import { automationQueue } from "./bullboard"
import { updateEntityMetadata } from "../utilities"
import { MetadataTypes } from "../constants"
import { db as dbCore, context, utils } from "@budibase/backend-core"
import { context, db as dbCore, utils } from "@budibase/backend-core"
import { getAutomationMetadataParams } from "../db/utils"
import { cloneDeep } from "lodash/fp"
import { quotas } from "@budibase/pro"
import { Automation, AutomationJob } from "@budibase/types"
import {
Automation,
AutomationJob,
AutomationStepSchema,
} from "@budibase/types"
import { automationsEnabled } from "../features"
import { helpers, REBOOT_CRON } from "@budibase/shared-core"
import tracer from "dd-trace"
@ -111,7 +115,9 @@ export async function updateTestHistory(
)
}
export function removeDeprecated(definitions: any) {
export function removeDeprecated(
definitions: Record<string, AutomationStepSchema>
) {
const base = cloneDeep(definitions)
for (let key of Object.keys(base)) {
if (base[key].deprecated) {

View File

@ -17,6 +17,7 @@ import {
AutoFieldSubType,
Datasource,
FieldType,
JsonFieldSubType,
RelationshipType,
Row,
SourceName,
@ -131,7 +132,7 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
"Item Tags": {
type: FieldType.ARRAY,
constraints: {
type: FieldType.ARRAY,
type: JsonFieldSubType.ARRAY,
presence: {
allowEmpty: false,
},
@ -153,7 +154,7 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
Status: {
type: FieldType.ARRAY,
constraints: {
type: FieldType.ARRAY,
type: JsonFieldSubType.ARRAY,
presence: {
allowEmpty: false,
},
@ -291,7 +292,7 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
"Employee Level": {
type: FieldType.ARRAY,
constraints: {
type: FieldType.ARRAY,
type: JsonFieldSubType.ARRAY,
presence: false,
inclusion: ["Manager", "Junior", "Senior", "Apprentice", "Contractor"],
},
@ -535,7 +536,7 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
"Expense Tags": {
type: FieldType.ARRAY,
constraints: {
type: FieldType.ARRAY,
type: JsonFieldSubType.ARRAY,
presence: {
allowEmpty: false,
},

View File

@ -77,7 +77,7 @@ export async function startContainer(container: GenericContainer) {
container = container
.withReuse()
.withLabels({ "com.budibase": "true" })
.withName(key)
.withName(`${key}_testcontainer`)
let startedContainer: StartedTestContainer | undefined = undefined
let lastError = undefined

View File

@ -150,22 +150,28 @@ export function generateColumnDefinition(config: {
}).internal
}
const constraints: {
presence: boolean
inclusion?: string[]
} = {
presence,
}
let schema: FieldSchema
if (foundType === FieldType.OPTIONS) {
constraints.inclusion = options
}
const schema: FieldSchema = {
type: foundType,
externalType,
autocolumn,
name,
constraints,
schema = {
type: foundType,
externalType,
autocolumn,
name,
constraints: {
presence,
inclusion: options!,
},
}
} else {
schema = {
type: foundType,
externalType,
autocolumn,
name,
constraints: {
presence,
},
}
}
if (schema.type === FieldType.DATETIME) {
schema.dateOnly = SQL_DATE_ONLY_TYPES.includes(lowerCaseType)

View File

@ -87,10 +87,10 @@ export async function fetch() {
include_docs: true,
})
)
return response.rows
.map(row => row.doc)
.filter(doc => !!doc)
.map(trimUnexpectedObjectFields)
const automations: PersistedAutomation[] = response.rows
.filter(row => !!row.doc)
.map(row => row.doc!)
return automations.map(trimUnexpectedObjectFields)
}
export async function get(automationId: string) {

View File

@ -29,8 +29,7 @@ export async function getBuilderData(
const rowActionNameCache: Record<string, TableRowActions> = {}
async function getRowActionName(tableId: string, rowActionId: string) {
if (!rowActionNameCache[tableId]) {
const rowActions = await sdk.rowActions.get(tableId)
rowActionNameCache[tableId] = rowActions
rowActionNameCache[tableId] = await sdk.rowActions.get(tableId)
}
return rowActionNameCache[tableId].actions[rowActionId]?.name
@ -45,9 +44,11 @@ export async function getBuilderData(
}
const { tableId, rowActionId } = automation.definition.trigger.inputs
if (!tableId || !rowActionId) {
continue
}
const tableName = await getTableName(tableId)
const rowActionName = await getRowActionName(tableId, rowActionId)
result[automation._id!] = {

View File

@ -22,21 +22,21 @@ import { HTTPError } from "@budibase/backend-core"
import pick from "lodash/pick"
import { outputProcessing } from "../../../../utilities/rowProcessor"
import sdk from "../../../"
import { isSearchingByRowID } from "./utils"
export async function search(
options: RowSearchParams,
table: Table
): Promise<SearchResponse<Row>> {
const { tableId } = options
const { countRows, paginate, query, ...params } = options
const { limit } = params
let bookmark =
(params.bookmark && parseInt(params.bookmark as string)) || undefined
if (paginate && !bookmark) {
bookmark = 0
}
function getPaginationAndLimitParameters(
filters: SearchFilters,
paginate: boolean | undefined,
bookmark: number | undefined,
limit: number | undefined
): PaginationJson | undefined {
let paginateObj: PaginationJson | undefined
// only try set limits/pagination if we aren't doing a row ID search
if (isSearchingByRowID(filters)) {
return
}
if (paginate && !limit) {
throw new Error("Cannot paginate query without a limit")
}
@ -49,11 +49,35 @@ export async function search(
if (bookmark) {
paginateObj.offset = limit * bookmark
}
} else if (params && limit) {
} else if (limit) {
paginateObj = {
limit: limit,
}
}
return paginateObj
}
export async function search(
options: RowSearchParams,
table: Table
): Promise<SearchResponse<Row>> {
const { tableId } = options
const { countRows, paginate, query, ...params } = options
const { limit } = params
let bookmark =
(params.bookmark && parseInt(params.bookmark as string)) || undefined
if (paginate && !bookmark) {
bookmark = 0
}
let paginateObj = getPaginationAndLimitParameters(
query,
paginate,
bookmark,
limit
)
let sort: SortJson | undefined
if (params.sort) {
const direction =

View File

@ -42,6 +42,8 @@ import {
getTableIDList,
} from "./filters"
import { dataFilters, PROTECTED_INTERNAL_COLUMNS } from "@budibase/shared-core"
import { isSearchingByRowID } from "./utils"
import tracer from "dd-trace"
const builder = new sql.Sql(SqlClient.SQL_LITE)
const MISSING_COLUMN_REGEX = new RegExp(`no such column: .+`)
@ -71,10 +73,14 @@ function buildInternalFieldList(
}
if (isRelationship) {
const linkCol = col as RelationshipFieldMetadata
const relatedTable = tables.find(table => table._id === linkCol.tableId)!
const relatedTable = tables.find(table => table._id === linkCol.tableId)
// no relationships provided, don't go more than a layer deep
fieldList = fieldList.concat(buildInternalFieldList(relatedTable, tables))
addJunctionFields(relatedTable, ["doc1.fieldName", "doc2.fieldName"])
if (relatedTable) {
fieldList = fieldList.concat(
buildInternalFieldList(relatedTable, tables)
)
addJunctionFields(relatedTable, ["doc1.fieldName", "doc2.fieldName"])
}
} else {
fieldList.push(`${table._id}.${mapToUserColumn(col.name)}`)
}
@ -220,7 +226,11 @@ async function runSqlQuery(
}
const db = context.getAppDB()
return await db.sql<Row>(sql, bindings)
return await tracer.trace("sqs.runSqlQuery", async span => {
span?.addTags({ sql })
return await db.sql<Row>(sql, bindings)
})
}
const response = await alias.queryWithAliasing(json, processSQLQuery)
if (opts?.countTotalRows) {
@ -264,6 +274,10 @@ export async function search(
const relationships = buildInternalRelationships(table)
const searchFilters: SearchFilters = {
...cleanupFilters(query, table, allTables),
documentType: DocumentType.ROW,
}
const request: QueryJson = {
endpoint: {
// not important, we query ourselves
@ -271,10 +285,7 @@ export async function search(
entityId: table._id!,
operation: Operation.READ,
},
filters: {
...cleanupFilters(query, table, allTables),
documentType: DocumentType.ROW,
},
filters: searchFilters,
table,
meta: {
table,
@ -304,7 +315,8 @@ export async function search(
}
const bookmark: number = (params.bookmark as number) || 0
if (params.limit) {
// limits don't apply if we doing a row ID search
if (!isSearchingByRowID(searchFilters) && params.limit) {
paginate = true
request.paginate = {
limit: params.limit + 1,

View File

@ -55,7 +55,7 @@ describe.each([
schema: {
id: {
name: "id",
type: FieldType.AUTO,
type: FieldType.NUMBER,
autocolumn: true,
},
name: {

View File

@ -108,3 +108,18 @@ export function searchInputMapping(table: Table, options: RowSearchParams) {
}
return options
}
export function isSearchingByRowID(query: SearchFilters): boolean {
for (let searchField of Object.values(query)) {
if (typeof searchField !== "object") {
continue
}
const hasId = Object.keys(searchField).find(
key => dbCore.removeKeyNumbering(key) === "_id" && searchField[key]
)
if (hasId) {
return true
}
}
return false
}

View File

@ -2,12 +2,12 @@ import { Automation, AutomationTriggerStepId } from "@budibase/types"
export function isRowAction(automation: Automation) {
const result =
automation.definition.trigger.stepId === AutomationTriggerStepId.ROW_ACTION
automation.definition.trigger?.stepId === AutomationTriggerStepId.ROW_ACTION
return result
}
export function isAppAction(automation: Automation) {
const result =
automation.definition.trigger.stepId === AutomationTriggerStepId.APP
automation.definition.trigger?.stepId === AutomationTriggerStepId.APP
return result
}

View File

@ -37,7 +37,7 @@ export interface PaginatedSearchRowResponse
PaginationResponse {}
export interface ExportRowsRequest {
rows: string[]
rows?: string[]
columns?: string[]
query?: SearchFilters
sort?: string

View File

@ -1,4 +1,4 @@
import { Row, Table, TableRequest, View } from "../../../documents"
import { Row, Table, TableRequest, TableSchema, View } from "../../../documents"
import { ViewV2Enriched } from "../../../sdk"
export type TableViewsResponse = { [key: string]: View | ViewV2Enriched }
@ -32,3 +32,28 @@ export interface MigrateRequest {
export interface MigrateResponse {
message: string
}
export interface ValidateNewTableImportRequest {
rows: Row[]
schema: TableSchema
}
export interface ValidateTableImportRequest {
tableId?: string
rows: Row[]
}
export interface ValidateTableImportResponse {
schemaValidation: {
[field: string]: boolean
}
allValid: boolean
invalidColumns: Array<string>
errors: Record<string, string>
}
export interface CsvToJsonRequest {
csvString: string
}
export type CsvToJsonResponse = any[]

View File

@ -174,9 +174,7 @@ export interface AutomationStepSchema {
deprecated?: boolean
stepId: AutomationTriggerStepId | AutomationActionStepId
blockToLoop?: string
inputs: {
[key: string]: any
}
inputs: Record<string, any>
schema: {
inputs: InputOutputBlock
outputs: InputOutputBlock

View File

@ -64,7 +64,7 @@ export interface AutoColumnFieldMetadata
extends Omit<BaseFieldSchema, "subtype"> {
type: FieldType.AUTO
autocolumn: true
subtype?: AutoFieldSubType
subtype: AutoFieldSubType
lastID?: number
// if the column was turned to an auto-column for SQL, explains why (primary, foreign etc)
autoReason?: AutoReason
@ -157,6 +157,21 @@ export interface FieldConstraints {
}
}
export interface OptionsFieldMetadata extends BaseFieldSchema {
type: FieldType.OPTIONS
constraints: FieldConstraints & {
inclusion: string[]
}
}
export interface ArrayFieldMetadata extends BaseFieldSchema {
type: FieldType.ARRAY
constraints: FieldConstraints & {
type: JsonFieldSubType.ARRAY
inclusion: string[]
}
}
interface BaseFieldSchema extends UIFieldMetadata {
type: FieldType
name: string
@ -182,6 +197,8 @@ interface OtherFieldMetadata extends BaseFieldSchema {
| FieldType.BB_REFERENCE_SINGLE
| FieldType.ATTACHMENTS
| FieldType.STRING
| FieldType.ARRAY
| FieldType.OPTIONS
>
}
@ -198,6 +215,8 @@ export type FieldSchema =
| JsonFieldMetadata
| AttachmentFieldMetadata
| BBReferenceSingleFieldMetadata
| ArrayFieldMetadata
| OptionsFieldMetadata
export interface TableSchema {
[key: string]: FieldSchema

View File

@ -1,6 +0,0 @@
if [ -d "packages/pro/src" ]; then
cd packages/pro
yarn
lerna bootstrap
fi

View File

@ -51,20 +51,6 @@ async function runBuild(entry, outfile) {
fs.readFileSync(tsconfig, "utf-8")
)
if (
!fs.existsSync(path.join(__dirname, "../packages/pro/src")) &&
tsconfigPathPluginContent.compilerOptions?.paths
) {
// If we don't have pro, we cannot bundle backend-core.
// Otherwise, the main context will not be shared between libraries
delete tsconfigPathPluginContent?.compilerOptions?.paths?.[
"@budibase/backend-core"
]
delete tsconfigPathPluginContent?.compilerOptions?.paths?.[
"@budibase/backend-core/*"
]
}
const sharedConfig = {
entryPoints: [entry],
bundle: true,
@ -75,7 +61,7 @@ async function runBuild(entry, outfile) {
svelteCompilePlugin,
TsconfigPathsPlugin({ tsconfig: tsconfigPathPluginContent }),
nodeExternalsPlugin({
allowList: ["@budibase/frontend-core", "svelte"],
allowList: ["@budibase/frontend-core", "@budibase/pro", "svelte"],
}),
],
preserveSymlinks: true,

View File

@ -1,11 +1,5 @@
#!/bin/bash
# Check if the pro submodule is loaded
if [ ! -d "./packages/pro/src" ]; then
echo "[ERROR] Submodule is not loaded. This is only allowed with loaded submodules."
exit 1
fi
yarn build:apps
docker compose -f hosting/docker-compose.build.yaml -f hosting/docker-compose.dev.yaml --env-file hosting/.env up --build --scale proxy-service=0

221
yarn.lock
View File

@ -1987,13 +1987,20 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12"
integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.13.10":
version "7.25.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb"
integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
@ -2185,9 +2192,9 @@
"@bull-board/api" "5.10.2"
"@camunda8/sdk@^8.5.3":
version "8.6.7"
resolved "https://registry.yarnpkg.com/@camunda8/sdk/-/sdk-8.6.7.tgz#9a8d5fbe38a53ae1ab13ff59c24cf6747c20f575"
integrity sha512-YpMsrBz5SlnagV8kei53WmB7es09ejNoOg3c6Dta+zGnSumClwGjL4IEGKqSjFk0Z4eVNIBIbRYl1i8gXRdvJg==
version "8.6.10"
resolved "https://registry.yarnpkg.com/@camunda8/sdk/-/sdk-8.6.10.tgz#61fdadc6bc89a234648ba4bc622b0db10f283de9"
integrity sha512-FzSoLYd0yFFElC2G3NX93GnP7r53uQDR+6njV1EEAGPhz4QQfZeEW07vMNZ9BFeNn5jhtv9IWmHdHxYwJxxmcw==
dependencies:
"@grpc/grpc-js" "1.10.9"
"@grpc/proto-loader" "0.7.13"
@ -3362,6 +3369,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
"@jridgewell/trace-mapping@0.3.9":
version "0.3.9"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
@ -4144,81 +4156,161 @@
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27"
integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==
"@rollup/rollup-android-arm-eabi@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz#7746deb85e4a8fb54fbfda8ac5c102692f102476"
integrity sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==
"@rollup/rollup-android-arm64@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203"
integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==
"@rollup/rollup-android-arm64@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz#93de4d867709d3313794723b5afd91e1e174f906"
integrity sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==
"@rollup/rollup-darwin-arm64@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096"
integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==
"@rollup/rollup-darwin-arm64@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz#e41e6a81673260ab196e0f59462b9940a6ac03cd"
integrity sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==
"@rollup/rollup-darwin-x64@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c"
integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==
"@rollup/rollup-darwin-x64@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz#2b0a0aef6e8c5317d494cfc9076d7a16b099bdcb"
integrity sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==
"@rollup/rollup-linux-arm-gnueabihf@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8"
integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==
"@rollup/rollup-linux-arm-gnueabihf@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz#e22319deb5367384ef315e66bc6de80d2bf2b3ae"
integrity sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==
"@rollup/rollup-linux-arm-musleabihf@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549"
integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==
"@rollup/rollup-linux-arm-musleabihf@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz#d5dd68f5d7ae21b345a5c87208c94e5c813f54b8"
integrity sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==
"@rollup/rollup-linux-arm64-gnu@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577"
integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==
"@rollup/rollup-linux-arm64-gnu@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz#1703d3a418d33f8f025acaf93f39ca1efcd5b645"
integrity sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==
"@rollup/rollup-linux-arm64-musl@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c"
integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==
"@rollup/rollup-linux-arm64-musl@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz#3f59c2c6e60f75ce8b1090bd841c555e3bb01f0e"
integrity sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==
"@rollup/rollup-linux-powerpc64le-gnu@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf"
integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==
"@rollup/rollup-linux-powerpc64le-gnu@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz#3f99a0921596a6f539121a312df29af52a205f15"
integrity sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==
"@rollup/rollup-linux-riscv64-gnu@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9"
integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==
"@rollup/rollup-linux-riscv64-gnu@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz#c08fb3e629d50d2eac31329347cfc559a1cf81d1"
integrity sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==
"@rollup/rollup-linux-s390x-gnu@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec"
integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==
"@rollup/rollup-linux-s390x-gnu@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz#173722cd745779d730d4b24d21386185e0e12de8"
integrity sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==
"@rollup/rollup-linux-x64-gnu@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942"
integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==
"@rollup/rollup-linux-x64-gnu@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz#0af2b6541ab0f4954d2c4f96bcdc7947420dd28c"
integrity sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==
"@rollup/rollup-linux-x64-musl@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d"
integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==
"@rollup/rollup-linux-x64-musl@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz#f973f9552744764b221128f7c3629222216ace69"
integrity sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==
"@rollup/rollup-win32-arm64-msvc@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf"
integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==
"@rollup/rollup-win32-arm64-msvc@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz#21ac5ed84d914bc31821fec3dd909f7257cfb17b"
integrity sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==
"@rollup/rollup-win32-ia32-msvc@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54"
integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==
"@rollup/rollup-win32-ia32-msvc@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz#0cfe740063b35dcd5a62c4e243226631a846ce11"
integrity sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==
"@rollup/rollup-win32-x64-msvc@4.18.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4"
integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==
"@rollup/rollup-win32-x64-msvc@4.19.1":
version "4.19.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz#5f2c40d3f1b53ede80fb4e6964f840c0f8936832"
integrity sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==
"@roxi/routify@2.18.0":
version "2.18.0"
resolved "https://registry.yarnpkg.com/@roxi/routify/-/routify-2.18.0.tgz#8f88bedd936312d0dbe44cbc11ab179b1f938ec2"
@ -5699,11 +5791,11 @@
integrity sha512-7GgtHCs/QZrBrDzgIJnQtuSvhFSwhyYSI2uafSwZoNt1iOGhEN5fwNrQMjtONyHm9+/LoA4453jH0CMYcr06Pg==
"@types/node@>=8.1.0":
version "20.14.9"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420"
integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==
version "22.0.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.0.0.tgz#04862a2a71e62264426083abe1e27e87cac05a30"
integrity sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==
dependencies:
undici-types "~5.26.4"
undici-types "~6.11.1"
"@types/node@^18.11.18":
version "18.19.10"
@ -9131,11 +9223,16 @@ dateformat@^4.6.3:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5"
integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==
dayjs@^1.10.8, dayjs@^1.8.15:
dayjs@^1.10.8:
version "1.11.11"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
dayjs@^1.8.15:
version "1.11.12"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.12.tgz#5245226cc7f40a15bf52e0b99fd2a04669ccac1d"
integrity sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==
dc-polyfill@^0.1.2:
version "0.1.3"
resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.3.tgz#fe9eefc86813439dd46d6f9ad9582ec079c39720"
@ -10332,10 +10429,10 @@ es6-promise@^4.2.4:
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
esbuild-node-externals@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/esbuild-node-externals/-/esbuild-node-externals-1.8.0.tgz#878fbe458d4e58337753c2eacfd7200dc1077bd1"
integrity sha512-pYslmT8Bl383UnfxzHQQRpCgBNIOwAzDaYheuIeI4CODxelsN/eQroVn5STDow5QOpRalMgWUR+R8LfSgUROcw==
esbuild-node-externals@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/esbuild-node-externals/-/esbuild-node-externals-1.14.0.tgz#fc2950c67a068dc2b538fd1381ad7d8e20a6f54d"
integrity sha512-jMWnTlCII3cLEjR5+u0JRSTJuP+MgbjEHKfwSIAI41NgLQ0ZjfzjchlbEn0r7v2u5gCBMSEYvYlkO7GDG8gG3A==
dependencies:
find-up "^5.0.0"
tslib "^2.4.1"
@ -10933,7 +11030,14 @@ fast-xml-parser@4.2.5:
dependencies:
strnum "^1.0.5"
fast-xml-parser@^4.1.3, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5:
fast-xml-parser@^4.1.3:
version "4.4.1"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f"
integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==
dependencies:
strnum "^1.0.5"
fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5:
version "4.4.0"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz#341cc98de71e9ba9e651a67f41f1752d1441a501"
integrity sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==
@ -11706,9 +11810,9 @@ glob@^10.0.0, glob@^10.2.2:
path-scurry "^1.11.1"
glob@^10.3.7:
version "10.4.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.2.tgz#bed6b95dade5c1f80b4434daced233aee76160e5"
integrity sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==
version "10.4.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
dependencies:
foreground-child "^3.1.0"
jackspeak "^3.1.2"
@ -15144,13 +15248,20 @@ magic-string@^0.26.7:
dependencies:
sourcemap-codec "^1.4.8"
magic-string@^0.30.3, magic-string@^0.30.4, magic-string@^0.30.5:
magic-string@^0.30.3, magic-string@^0.30.4:
version "0.30.10"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15"
magic-string@^0.30.5:
version "0.30.11"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954"
integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
make-dir@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e"
@ -17813,9 +17924,9 @@ postcss@^8.1.7, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12, postcss@^8.4.2
source-map-js "^1.2.0"
postcss@^8.4.39:
version "8.4.39"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.39.tgz#aa3c94998b61d3a9c259efa51db4b392e1bde0e3"
integrity sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==
version "8.4.40"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8"
integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.1"
@ -17852,9 +17963,9 @@ posthog-js@^1.118.0:
preact "^10.19.3"
posthog-js@^1.13.4:
version "1.144.1"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.144.1.tgz#a665f324be3e78a140ec1cf9488be8e8947c052b"
integrity sha512-CdhKH+gTFJgVEDVdeuhD2Mm4yMRr6qhVSPNDUQ7naJfj/HMhcZjF/ImobluD4YGd85dLq9nqImEIcf4Twd9h6g==
version "1.150.1"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.150.1.tgz#ce2e0aa0dc30369bf1b1b9a38b9fbf25e5c01ba0"
integrity sha512-jHSnqtAWkUQkiedQgHpD00+z8RUF0loDq7ORakBKfQjdntTJIEk16ewqTNRxnpE86guWDoy2J3iAqLgAYfFaLA==
dependencies:
fflate "^0.4.8"
preact "^10.19.3"
@ -18440,9 +18551,9 @@ q@^1.1.2:
integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
qs@^6.10.3:
version "6.12.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.2.tgz#5443b587f3bf73ac68968de491e5b25bafe04478"
integrity sha512-x+NLUpx9SYrcwXtX7ob1gnkSems4i/mGZX5SlYxwIau6RrUSODO89TR/XDGGpn5RPWSYIB+aSfuSlV5+CmbTBg==
version "6.12.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754"
integrity sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==
dependencies:
side-channel "^1.0.6"
@ -18956,9 +19067,9 @@ requirejs-config-file@^4.0.0:
stringify-object "^3.2.1"
requirejs@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
version "2.3.7"
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.7.tgz#0b22032e51a967900e0ae9f32762c23a87036bd0"
integrity sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==
requires-port@^1.0.0:
version "1.0.0"
@ -19093,9 +19204,9 @@ rimraf@^4.4.1:
glob "^9.2.0"
rimraf@^5.0.7:
version "5.0.7"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74"
integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==
version "5.0.9"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.9.tgz#c3baa1b886eadc2ec7981a06a593c3d01134ffe9"
integrity sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==
dependencies:
glob "^10.3.7"
@ -19261,7 +19372,32 @@ rollup@^3.27.1:
optionalDependencies:
fsevents "~2.3.2"
rollup@^4.13.0, rollup@^4.9.4, rollup@^4.9.6:
rollup@^4.13.0:
version "4.19.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.19.1.tgz#21d865cd60d4a325172ce8b082e60caccd97b309"
integrity sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==
dependencies:
"@types/estree" "1.0.5"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.19.1"
"@rollup/rollup-android-arm64" "4.19.1"
"@rollup/rollup-darwin-arm64" "4.19.1"
"@rollup/rollup-darwin-x64" "4.19.1"
"@rollup/rollup-linux-arm-gnueabihf" "4.19.1"
"@rollup/rollup-linux-arm-musleabihf" "4.19.1"
"@rollup/rollup-linux-arm64-gnu" "4.19.1"
"@rollup/rollup-linux-arm64-musl" "4.19.1"
"@rollup/rollup-linux-powerpc64le-gnu" "4.19.1"
"@rollup/rollup-linux-riscv64-gnu" "4.19.1"
"@rollup/rollup-linux-s390x-gnu" "4.19.1"
"@rollup/rollup-linux-x64-gnu" "4.19.1"
"@rollup/rollup-linux-x64-musl" "4.19.1"
"@rollup/rollup-win32-arm64-msvc" "4.19.1"
"@rollup/rollup-win32-ia32-msvc" "4.19.1"
"@rollup/rollup-win32-x64-msvc" "4.19.1"
fsevents "~2.3.2"
rollup@^4.9.4, rollup@^4.9.6:
version "4.18.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda"
integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==
@ -21424,6 +21560,11 @@ undici-types@~5.26.4:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
undici-types@~6.11.1:
version "6.11.1"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.11.1.tgz#432ea6e8efd54a48569705a699e62d8f4981b197"
integrity sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==
undici@^4.14.1:
version "4.16.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-4.16.0.tgz#469bb87b3b918818d3d7843d91a1d08da357d5ff"
@ -21777,9 +21918,9 @@ vite-plugin-static-copy@^0.17.0:
fsevents "~2.3.2"
vite@^5.0.0:
version "5.3.3"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.3.tgz#5265b1f0a825b3b6564c2d07524777c83e3c04c2"
integrity sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==
version "5.3.5"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.5.tgz#b847f846fb2b6cb6f6f4ed50a830186138cb83d8"
integrity sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.39"
@ -21914,9 +22055,9 @@ web-streams-polyfill@^3.2.1:
integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
web-vitals@^4.0.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.1.tgz#67eec387ddd0ef4c25574a01ab9dae723eee2b97"
integrity sha512-U6bAxeudnhDqcXNl50JC4hLlqox9DZnngxfISZm3DMZnonW35xtJOVUc091L+DOY+6hVZVpKXoiCP0RiT6339Q==
version "4.2.2"
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.2.tgz#e883245180b95e175eb75a5ca8903b1a11597d7a"
integrity sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw==
webfinger@^0.4.2:
version "0.4.2"