Merge branch 'frontend-core-ts-2' of github.com:Budibase/budibase into frontend-core-ts-2

This commit is contained in:
Andrew Kingston 2024-12-02 10:47:25 +00:00
commit accd21dd92
No known key found for this signature in database
28 changed files with 364 additions and 259 deletions

View File

@ -121,7 +121,7 @@ const identifyInstallationGroup = async (
const identifyTenantGroup = async ( const identifyTenantGroup = async (
tenantId: string, tenantId: string,
account: Account | undefined, hosting: Hosting,
timestamp?: string | number timestamp?: string | number
): Promise<void> => { ): Promise<void> => {
const id = await getEventTenantId(tenantId) const id = await getEventTenantId(tenantId)
@ -129,26 +129,12 @@ const identifyTenantGroup = async (
const installationId = await getInstallationId() const installationId = await getInstallationId()
const environment = getDeploymentEnvironment() const environment = getDeploymentEnvironment()
let hosting: Hosting
let profession: string | undefined
let companySize: string | undefined
if (account) {
profession = account.profession
companySize = account.size
hosting = account.hosting
} else {
hosting = getHostingFromEnv()
}
const group: TenantGroup = { const group: TenantGroup = {
id, id,
type, type,
hosting, hosting,
environment, environment,
installationId, installationId,
profession,
companySize,
} }
await identifyGroup(group, timestamp) await identifyGroup(group, timestamp)

View File

@ -266,12 +266,14 @@ export class FlagSet<V extends Flag<any>, T extends { [key: string]: V }> {
// new flag, add it here and use the `fetch` and `get` functions to access it. // new flag, add it here and use the `fetch` and `get` functions to access it.
// All of the machinery in this file is to make sure that flags have their // All of the machinery in this file is to make sure that flags have their
// default values set correctly and their types flow through the system. // default values set correctly and their types flow through the system.
export const flags = new FlagSet({ const flagsConfig: Record<FeatureFlag, Flag<any>> = {
[FeatureFlag.DEFAULT_VALUES]: Flag.boolean(true), [FeatureFlag.DEFAULT_VALUES]: Flag.boolean(true),
[FeatureFlag.AUTOMATION_BRANCHING]: Flag.boolean(true), [FeatureFlag.AUTOMATION_BRANCHING]: Flag.boolean(true),
[FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(true), [FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(true),
[FeatureFlag.BUDIBASE_AI]: Flag.boolean(true), [FeatureFlag.BUDIBASE_AI]: Flag.boolean(true),
}) [FeatureFlag.USE_ZOD_VALIDATOR]: Flag.boolean(env.isDev()),
}
export const flags = new FlagSet(flagsConfig)
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
export type FeatureFlags = UnwrapPromise<ReturnType<typeof flags.fetch>> export type FeatureFlags = UnwrapPromise<ReturnType<typeof flags.fetch>>

View File

@ -129,7 +129,8 @@
"uuid": "^8.3.2", "uuid": "^8.3.2",
"validate.js": "0.13.1", "validate.js": "0.13.1",
"worker-farm": "1.7.0", "worker-farm": "1.7.0",
"xml2js": "0.6.2" "xml2js": "0.6.2",
"zod-validation-error": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.22.5", "@babel/core": "^7.22.5",
@ -175,7 +176,8 @@
"tsconfig-paths": "4.0.0", "tsconfig-paths": "4.0.0",
"typescript": "5.5.2", "typescript": "5.5.2",
"update-dotenv": "1.1.1", "update-dotenv": "1.1.1",
"yargs": "13.2.4" "yargs": "^13.2.4",
"zod": "^3.23.8"
}, },
"nx": { "nx": {
"targets": { "targets": {

View File

@ -19,6 +19,7 @@ import {
isRelationshipField, isRelationshipField,
PatchRowRequest, PatchRowRequest,
PatchRowResponse, PatchRowResponse,
RequiredKeys,
Row, Row,
RowAttachment, RowAttachment,
RowSearchParams, RowSearchParams,
@ -239,7 +240,8 @@ export async function search(ctx: Ctx<SearchRowRequest, SearchRowResponse>) {
await context.ensureSnippetContext(true) await context.ensureSnippetContext(true)
let { query } = ctx.request.body const searchRequest = ctx.request.body
let { query } = searchRequest
if (query) { if (query) {
const allTables = await sdk.tables.getAllTables() const allTables = await sdk.tables.getAllTables()
query = replaceTableNamesInFilters(tableId, query, allTables) query = replaceTableNamesInFilters(tableId, query, allTables)
@ -249,11 +251,22 @@ export async function search(ctx: Ctx<SearchRowRequest, SearchRowResponse>) {
user: sdk.users.getUserContextBindings(ctx.user), user: sdk.users.getUserContextBindings(ctx.user),
}) })
const searchParams: RowSearchParams = { const searchParams: RequiredKeys<RowSearchParams> = {
...ctx.request.body,
query: enrichedQuery, query: enrichedQuery,
tableId, tableId,
viewId, viewId,
bookmark: searchRequest.bookmark ?? undefined,
paginate: searchRequest.paginate,
limit: searchRequest.limit,
sort: searchRequest.sort ?? undefined,
sortOrder: searchRequest.sortOrder,
sortType: searchRequest.sortType ?? undefined,
countRows: searchRequest.countRows,
version: searchRequest.version,
disableEscaping: searchRequest.disableEscaping,
fields: undefined,
indexer: undefined,
rows: undefined,
} }
ctx.status = 200 ctx.status = 200

View File

@ -15,10 +15,21 @@ import {
} from "@budibase/types" } from "@budibase/types"
import * as linkRows from "../../../db/linkedRows" import * as linkRows from "../../../db/linkedRows"
import isEqual from "lodash/isEqual" import isEqual from "lodash/isEqual"
import { cloneDeep } from "lodash/fp" import { cloneDeep, merge } from "lodash/fp"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import * as pro from "@budibase/pro" import * as pro from "@budibase/pro"
function mergeRows(row1: Row, row2: Row) {
const merged = merge(row1, row2)
// make sure any specifically undefined fields are removed
for (const key of Object.keys(row2)) {
if (row2[key] === undefined) {
delete merged[key]
}
}
return merged
}
/** /**
* This function runs through a list of enriched rows, looks at the rows which * This function runs through a list of enriched rows, looks at the rows which
* are related and then checks if they need the state of their formulas * are related and then checks if they need the state of their formulas
@ -162,9 +173,14 @@ export async function finaliseRow(
}) })
} }
const response = await db.put(row) await db.put(row)
// for response, calculate the formulas for the enriched row const retrieved = await db.tryGet<Row>(row._id)
enrichedRow._rev = response.rev if (!retrieved) {
throw new Error(`Unable to retrieve row ${row._id} after saving.`)
}
delete enrichedRow._rev
enrichedRow = mergeRows(retrieved, enrichedRow)
enrichedRow = await processFormulas(table, enrichedRow, { enrichedRow = await processFormulas(table, enrichedRow, {
dynamic: false, dynamic: false,
}) })

View File

@ -175,7 +175,7 @@ export async function enrichArrayContext(
} }
export async function enrichSearchContext( export async function enrichSearchContext(
fields: Record<string, any>, fields: Record<string, any> | undefined,
inputs = {}, inputs = {},
helpers = true helpers = true
): Promise<Record<string, any>> { ): Promise<Record<string, any>> {

View File

@ -29,19 +29,20 @@ export async function searchView(
await context.ensureSnippetContext(true) await context.ensureSnippetContext(true)
const searchOptions: RequiredKeys<SearchViewRowRequest> & const searchOptions: RequiredKeys<RowSearchParams> = {
RequiredKeys<
Pick<RowSearchParams, "tableId" | "viewId" | "query" | "fields">
> = {
tableId: view.tableId, tableId: view.tableId,
viewId: view.id, viewId: view.id,
query: body.query, query: body.query || {},
fields: viewFields, fields: viewFields,
...getSortOptions(body, view), ...getSortOptions(body, view),
limit: body.limit, limit: body.limit,
bookmark: body.bookmark, bookmark: body.bookmark ?? undefined,
paginate: body.paginate, paginate: body.paginate,
countRows: body.countRows, countRows: body.countRows,
version: undefined,
disableEscaping: undefined,
indexer: undefined,
rows: undefined,
} }
const result = await sdk.rows.search(searchOptions, { const result = await sdk.rows.search(searchOptions, {
@ -56,7 +57,7 @@ function getSortOptions(request: SearchViewRowRequest, view: ViewV2) {
return { return {
sort: request.sort, sort: request.sort,
sortOrder: request.sortOrder, sortOrder: request.sortOrder,
sortType: request.sortType, sortType: request.sortType ?? undefined,
} }
} }
if (view.sort) { if (view.sort) {

View File

@ -5,6 +5,8 @@ import { paramResource, paramSubResource } from "../../middleware/resourceId"
import { permissions } from "@budibase/backend-core" import { permissions } from "@budibase/backend-core"
import { internalSearchValidator } from "./utils/validators" import { internalSearchValidator } from "./utils/validators"
import trimViewRowInfo from "../../middleware/trimViewRowInfo" import trimViewRowInfo from "../../middleware/trimViewRowInfo"
import { validateBody } from "../../middleware/zod-validator"
import { searchRowRequestValidator } from "@budibase/types"
const { PermissionType, PermissionLevel } = permissions const { PermissionType, PermissionLevel } = permissions
@ -32,6 +34,7 @@ router
.post( .post(
"/api/:sourceId/search", "/api/:sourceId/search",
internalSearchValidator(), internalSearchValidator(),
validateBody(searchRowRequestValidator),
paramResource("sourceId"), paramResource("sourceId"),
authorized(PermissionType.TABLE, PermissionLevel.READ), authorized(PermissionType.TABLE, PermissionLevel.READ),
rowController.search rowController.search
@ -87,6 +90,7 @@ router
router.post( router.post(
"/api/v2/views/:viewId/search", "/api/v2/views/:viewId/search",
internalSearchValidator(), internalSearchValidator(),
validateBody(searchRowRequestValidator),
authorizedResource(PermissionType.VIEW, PermissionLevel.READ, "viewId"), authorizedResource(PermissionType.VIEW, PermissionLevel.READ, "viewId"),
rowController.views.searchView rowController.views.searchView
) )

View File

@ -2607,6 +2607,8 @@ if (descriptions.length) {
name: "foo", name: "foo",
description: "bar", description: "bar",
tableId, tableId,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2628,6 +2630,8 @@ if (descriptions.length) {
id: isInternal ? undefined : expect.any(Number), id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined, type: isInternal ? "row" : undefined,
[`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2650,6 +2654,8 @@ if (descriptions.length) {
_rev: expect.any(String), _rev: expect.any(String),
id: isInternal ? undefined : expect.any(Number), id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined, type: isInternal ? "row" : undefined,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2729,6 +2735,8 @@ if (descriptions.length) {
id: isInternal ? undefined : expect.any(Number), id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined, type: isInternal ? "row" : undefined,
[`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2745,15 +2753,8 @@ if (descriptions.length) {
user: null, user: null,
users: null, users: null,
}) })
expect(updatedRow).toEqual({ expect(updatedRow.user).toBeUndefined()
name: "foo", expect(updatedRow.users).toBeUndefined()
description: "bar",
tableId,
_id: row._id,
_rev: expect.any(String),
id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined,
})
}) })
it("fetch all will populate the relationships", async () => { it("fetch all will populate the relationships", async () => {

View File

@ -24,6 +24,7 @@ import {
JsonFieldSubType, JsonFieldSubType,
LogicalOperator, LogicalOperator,
RelationshipType, RelationshipType,
RequiredKeys,
Row, Row,
RowSearchParams, RowSearchParams,
SearchFilters, SearchFilters,
@ -208,9 +209,25 @@ if (descriptions.length) {
private async performSearch(): Promise<SearchResponse<Row>> { private async performSearch(): Promise<SearchResponse<Row>> {
if (isInMemory) { if (isInMemory) {
return dataFilters.search(_.cloneDeep(rows), { const inMemoryQuery: RequiredKeys<
...this.query, Omit<RowSearchParams, "tableId">
}) > = {
sort: this.query.sort ?? undefined,
query: { ...this.query.query },
paginate: this.query.paginate,
bookmark: this.query.bookmark ?? undefined,
limit: this.query.limit,
sortOrder: this.query.sortOrder,
sortType: this.query.sortType ?? undefined,
version: this.query.version,
disableEscaping: this.query.disableEscaping,
countRows: this.query.countRows,
viewId: undefined,
fields: undefined,
indexer: undefined,
rows: undefined,
}
return dataFilters.search(_.cloneDeep(rows), inMemoryQuery)
} else { } else {
return config.api.row.search(tableOrViewId, this.query) return config.api.row.search(tableOrViewId, this.query)
} }

View File

@ -152,6 +152,44 @@ describe("Loop automations", () => {
) )
}) })
it("ensure the loop stops if the max iterations are reached", async () => {
const builder = createAutomationBuilder({
name: "Test Loop max iterations",
})
const results = await builder
.appAction({ fields: {} })
.loop({
option: LoopStepType.ARRAY,
binding: ["test", "test2", "test3"],
iterations: 2,
})
.serverLog({ text: "{{loop.currentItem}}" })
.serverLog({ text: "{{steps.1.iterations}}" })
.run()
expect(results.steps[0].outputs.iterations).toBe(2)
})
it("should run an automation with loop and max iterations to ensure context correctness further down the tree", async () => {
const builder = createAutomationBuilder({
name: "Test context down tree with Loop and max iterations",
})
const results = await builder
.appAction({ fields: {} })
.loop({
option: LoopStepType.ARRAY,
binding: ["test", "test2", "test3"],
iterations: 2,
})
.serverLog({ text: "{{loop.currentItem}}" })
.serverLog({ text: "{{steps.1.iterations}}" })
.run()
expect(results.steps[1].outputs.message).toContain("- 2")
})
it("should run an automation where a loop is successfully run twice", async () => { it("should run an automation where a loop is successfully run twice", async () => {
const builder = createAutomationBuilder({ const builder = createAutomationBuilder({
name: "Test Trigger with Loop and Create Row", name: "Test Trigger with Loop and Create Row",

View File

@ -137,7 +137,6 @@ export enum InvalidColumns {
export enum AutomationErrors { export enum AutomationErrors {
INCORRECT_TYPE = "INCORRECT_TYPE", INCORRECT_TYPE = "INCORRECT_TYPE",
MAX_ITERATIONS = "MAX_ITERATIONS_REACHED",
FAILURE_CONDITION = "FAILURE_CONDITION_MET", FAILURE_CONDITION = "FAILURE_CONDITION_MET",
} }

View File

@ -102,6 +102,9 @@ function createDummyTest() {
} }
export function datasourceDescribe(opts: DatasourceDescribeOpts) { export function datasourceDescribe(opts: DatasourceDescribeOpts) {
// tests that call this need a lot longer timeouts
jest.setTimeout(120000)
if (process.env.DATASOURCE === "none") { if (process.env.DATASOURCE === "none") {
createDummyTest() createDummyTest()
} }

View File

@ -25,7 +25,7 @@ export async function getDatasource(): Promise<Datasource> {
}) })
.withWaitStrategy( .withWaitStrategy(
Wait.forLogMessage("DATABASE IS READY TO USE!").withStartupTimeout( Wait.forLogMessage("DATABASE IS READY TO USE!").withStartupTimeout(
20000 60000
) )
) )
) )

View File

@ -0,0 +1,43 @@
import { features } from "@budibase/backend-core"
import { Ctx, FeatureFlag } from "@budibase/types"
import { AnyZodObject } from "zod"
import { fromZodError } from "zod-validation-error"
function validate(schema: AnyZodObject, property: "body" | "params") {
// Return a Koa middleware function
return async (ctx: Ctx, next: any) => {
if (!(await features.flags.isEnabled(FeatureFlag.USE_ZOD_VALIDATOR))) {
return next()
}
if (!schema) {
return next()
}
let params = null
let setClean: ((data: any) => void) | undefined
if (ctx[property] != null) {
params = ctx[property]
setClean = data => (ctx[property] = data)
} else if (property === "body" && ctx.request[property] != null) {
params = ctx.request[property]
setClean = data => (ctx.request[property] = data)
} else if (property === "params") {
params = ctx.request.query
setClean = data => (ctx.request.query = data)
}
const result = schema.safeParse(params)
if (!result.success) {
ctx.throw(400, fromZodError(result.error))
} else {
setClean?.(result.data)
}
return next()
}
}
export function validateBody(schema: AnyZodObject) {
return validate(schema, "body")
}

View File

@ -9,11 +9,12 @@ import {
db as dbUtils, db as dbUtils,
} from "@budibase/backend-core" } from "@budibase/backend-core"
import { import {
QuotaUsage,
CloudAccount,
App, App,
TenantBackfillSucceededEvent, CloudAccount,
Event, Event,
Hosting,
QuotaUsage,
TenantBackfillSucceededEvent,
User, User,
} from "@budibase/types" } from "@budibase/types"
import env from "../../../environment" import env from "../../../environment"
@ -125,7 +126,7 @@ export const run = async (db: any) => {
try { try {
await events.identification.identifyTenantGroup( await events.identification.identifyTenantGroup(
tenantId, tenantId,
account, env.SELF_HOSTED ? Hosting.SELF : Hosting.CLOUD,
timestamp timestamp
) )
} catch (e) { } catch (e) {

View File

@ -392,6 +392,7 @@ class Orchestrator {
let iterationCount = 0 let iterationCount = 0
let shouldCleanup = true let shouldCleanup = true
let reachedMaxIterations = false
for (let loopStepIndex = 0; loopStepIndex < iterations; loopStepIndex++) { for (let loopStepIndex = 0; loopStepIndex < iterations; loopStepIndex++) {
try { try {
@ -419,19 +420,8 @@ class Orchestrator {
loopStepIndex === env.AUTOMATION_MAX_ITERATIONS || loopStepIndex === env.AUTOMATION_MAX_ITERATIONS ||
(loopStep.inputs.iterations && loopStepIndex === maxIterations) (loopStep.inputs.iterations && loopStepIndex === maxIterations)
) { ) {
this.updateContextAndOutput( reachedMaxIterations = true
pathStepIdx + 1, shouldCleanup = true
steps[stepToLoopIndex],
{
items: this.loopStepOutputs,
iterations: loopStepIndex,
},
{
status: AutomationErrors.MAX_ITERATIONS,
success: true,
}
)
shouldCleanup = false
break break
} }
@ -485,6 +475,10 @@ class Orchestrator {
iterations: iterationCount, iterations: iterationCount,
} }
if (reachedMaxIterations && iterations !== 0) {
tempOutput.status = AutomationStepStatus.MAX_ITERATIONS
}
// Loop Step clean up // Loop Step clean up
this.executionOutput.steps.splice(pathStepIdx, 0, { this.executionOutput.steps.splice(pathStepIdx, 0, {
id: steps[stepToLoopIndex].id, id: steps[stepToLoopIndex].id,

View File

@ -153,10 +153,10 @@ export async function processOutputBBReference(
} }
export async function processOutputBBReferences( export async function processOutputBBReferences(
value: string | null | undefined, value: string | string[] | null | undefined,
subtype: BBReferenceFieldSubType subtype: BBReferenceFieldSubType
): Promise<UserReferenceInfo[] | undefined> { ): Promise<UserReferenceInfo[] | undefined> {
if (!value) { if (!value || (Array.isArray(value) && value.length === 0)) {
return undefined return undefined
} }
const ids = const ids =

View File

@ -29,6 +29,8 @@ import {
import { isExternalTableID } from "../../integrations/utils" import { isExternalTableID } from "../../integrations/utils"
import { import {
helpers, helpers,
isExternalColumnName,
isInternalColumnName,
PROTECTED_EXTERNAL_COLUMNS, PROTECTED_EXTERNAL_COLUMNS,
PROTECTED_INTERNAL_COLUMNS, PROTECTED_INTERNAL_COLUMNS,
} from "@budibase/shared-core" } from "@budibase/shared-core"
@ -200,14 +202,17 @@ export async function inputProcessing(
const clonedRow = cloneDeep(row) const clonedRow = cloneDeep(row)
const table = await getTableFromSource(source) const table = await getTableFromSource(source)
const dontCleanseKeys = ["type", "_id", "_rev", "tableId"]
for (const [key, value] of Object.entries(clonedRow)) { for (const [key, value] of Object.entries(clonedRow)) {
const field = table.schema[key] const field = table.schema[key]
const isBuiltinColumn = isExternalTableID(table._id!)
? isExternalColumnName(key)
: isInternalColumnName(key)
// cleanse fields that aren't in the schema // cleanse fields that aren't in the schema
if (!field && !isBuiltinColumn) {
delete clonedRow[key]
}
// field isn't found - might be a built-in column, skip over it
if (!field) { if (!field) {
if (dontCleanseKeys.indexOf(key) === -1) {
delete clonedRow[key]
}
continue continue
} }
// remove any formula values, they are to be generated // remove any formula values, they are to be generated

View File

@ -12,3 +12,7 @@ export const PROTECTED_EXTERNAL_COLUMNS = ["_id", "_rev", "tableId"] as const
export function isInternalColumnName(name: string): boolean { export function isInternalColumnName(name: string): boolean {
return (PROTECTED_INTERNAL_COLUMNS as readonly string[]).includes(name) return (PROTECTED_INTERNAL_COLUMNS as readonly string[]).includes(name)
} }
export function isExternalColumnName(name: string): boolean {
return (PROTECTED_EXTERNAL_COLUMNS as readonly string[]).includes(name)
}

View File

@ -20,7 +20,8 @@
"@types/redlock": "4.0.7", "@types/redlock": "4.0.7",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"typescript": "5.5.2", "typescript": "5.5.2",
"koa-useragent": "^4.1.0" "koa-useragent": "^4.1.0",
"zod": "^3.23.8"
}, },
"dependencies": { "dependencies": {
"scim-patch": "^0.8.1" "scim-patch": "^0.8.1"

View File

@ -1,49 +0,0 @@
import { SearchFilters, RowSearchParams } from "../../../sdk"
import { Row } from "../../../documents"
import { PaginationResponse, SortOrder } from "../../../api"
import { ReadStream } from "fs"
export interface SaveRowRequest extends Row {}
export interface PatchRowRequest extends Row {
_id: string
_rev: string
tableId: string
}
export interface PatchRowResponse extends Row {}
export interface SearchRowRequest extends Omit<RowSearchParams, "tableId"> {}
export interface SearchViewRowRequest
extends Pick<
SearchRowRequest,
| "sort"
| "sortOrder"
| "sortType"
| "limit"
| "bookmark"
| "paginate"
| "query"
| "countRows"
> {}
export interface SearchRowResponse {
rows: any[]
}
export interface PaginatedSearchRowResponse
extends SearchRowResponse,
PaginationResponse {}
export interface ExportRowsRequest {
rows?: string[]
columns?: string[]
query?: SearchFilters
sort?: string
sortOrder?: SortOrder
delimiter?: string
customHeaders?: { [key: string]: string }
}
export type ExportRowsResponse = ReadStream

View File

@ -0,0 +1,28 @@
import { SearchFilters } from "../../../../sdk"
import { Row } from "../../../../documents"
import { SortOrder } from "../../../../api/web/pagination"
import { ReadStream } from "fs"
export * from "./search"
export interface SaveRowRequest extends Row {}
export interface PatchRowRequest extends Row {
_id: string
_rev: string
tableId: string
}
export interface PatchRowResponse extends Row {}
export interface ExportRowsRequest {
rows?: string[]
columns?: string[]
query?: SearchFilters
sort?: string
sortOrder?: SortOrder
delimiter?: string
customHeaders?: { [key: string]: string }
}
export type ExportRowsResponse = ReadStream

View File

@ -0,0 +1,100 @@
import {
ArrayOperator,
BasicOperator,
EmptyFilterOption,
InternalSearchFilterOperator,
LogicalOperator,
RangeOperator,
SearchFilterKey,
} from "../../../../sdk"
import { Row } from "../../../../documents"
import {
PaginationResponse,
SortOrder,
SortType,
} from "../../../../api/web/pagination"
import { z } from "zod"
const fieldKey = z
.string()
.refine(s => s !== InternalSearchFilterOperator.COMPLEX_ID_OPERATOR, {
message: `Key '${InternalSearchFilterOperator.COMPLEX_ID_OPERATOR}' is not allowed`,
})
const stringBasicFilter = z.record(fieldKey, z.string())
const basicFilter = z.record(fieldKey, z.any())
const arrayFilter = z.record(fieldKey, z.union([z.any().array(), z.string()]))
const logicFilter = z.lazy(() =>
z.object({
conditions: z.array(z.object(queryFilterValidation)),
})
)
const stringOrNumber = z.union([z.string(), z.number()])
const queryFilterValidation: Record<SearchFilterKey, z.ZodTypeAny> = {
[BasicOperator.STRING]: stringBasicFilter.optional(),
[BasicOperator.FUZZY]: stringBasicFilter.optional(),
[RangeOperator.RANGE]: z
.record(
fieldKey,
z.union([
z.object({ high: stringOrNumber, low: stringOrNumber }),
z.object({ high: stringOrNumber }),
z.object({ low: stringOrNumber }),
])
)
.optional(),
[BasicOperator.EQUAL]: basicFilter.optional(),
[BasicOperator.NOT_EQUAL]: basicFilter.optional(),
[BasicOperator.EMPTY]: basicFilter.optional(),
[BasicOperator.NOT_EMPTY]: basicFilter.optional(),
[ArrayOperator.ONE_OF]: arrayFilter.optional(),
[ArrayOperator.CONTAINS]: arrayFilter.optional(),
[ArrayOperator.NOT_CONTAINS]: arrayFilter.optional(),
[ArrayOperator.CONTAINS_ANY]: arrayFilter.optional(),
[LogicalOperator.AND]: logicFilter.optional(),
[LogicalOperator.OR]: logicFilter.optional(),
}
const searchRowRequest = z.object({
query: z
.object({
allOr: z.boolean().optional(),
onEmptyFilter: z.nativeEnum(EmptyFilterOption).optional(),
...queryFilterValidation,
})
.optional(),
paginate: z.boolean().optional(),
bookmark: z.union([z.string(), z.number()]).nullish(),
limit: z.number().optional(),
sort: z.string().nullish(),
sortOrder: z.nativeEnum(SortOrder).optional(),
sortType: z.nativeEnum(SortType).nullish(),
version: z.string().optional(),
disableEscaping: z.boolean().optional(),
countRows: z.boolean().optional(),
})
export const searchRowRequestValidator = searchRowRequest
export type SearchRowRequest = z.infer<typeof searchRowRequest>
export type SearchViewRowRequest = Pick<
SearchRowRequest,
| "sort"
| "sortOrder"
| "sortType"
| "limit"
| "bookmark"
| "paginate"
| "query"
| "countRows"
>
export interface SearchRowResponse {
rows: Row[]
}
export interface PaginatedSearchRowResponse
extends SearchRowResponse,
PaginationResponse {}

View File

@ -174,6 +174,7 @@ export enum AutomationFeature {
export enum AutomationStepStatus { export enum AutomationStepStatus {
NO_ITERATIONS = "no_iterations", NO_ITERATIONS = "no_iterations",
MAX_ITERATIONS = "max_iterations_reached",
} }
export enum AutomationStatus { export enum AutomationStatus {

View File

@ -1,11 +1,9 @@
export enum FeatureFlag { export enum FeatureFlag {
PER_CREATOR_PER_USER_PRICE = "PER_CREATOR_PER_USER_PRICE",
PER_CREATOR_PER_USER_PRICE_ALERT = "PER_CREATOR_PER_USER_PRICE_ALERT",
AUTOMATION_BRANCHING = "AUTOMATION_BRANCHING", AUTOMATION_BRANCHING = "AUTOMATION_BRANCHING",
AI_CUSTOM_CONFIGS = "AI_CUSTOM_CONFIGS", AI_CUSTOM_CONFIGS = "AI_CUSTOM_CONFIGS",
DEFAULT_VALUES = "DEFAULT_VALUES", DEFAULT_VALUES = "DEFAULT_VALUES",
BUDIBASE_AI = "BUDIBASE_AI", BUDIBASE_AI = "BUDIBASE_AI",
USE_ZOD_VALIDATOR = "USE_ZOD_VALIDATOR",
} }
export interface TenantFeatureFlags { export interface TenantFeatureFlags {

View File

@ -6,12 +6,12 @@ import {
AddSSoUserRequest, AddSSoUserRequest,
BulkUserRequest, BulkUserRequest,
BulkUserResponse, BulkUserResponse,
CloudAccount,
CreateAdminUserRequest, CreateAdminUserRequest,
CreateAdminUserResponse, CreateAdminUserResponse,
Ctx, Ctx,
DeleteInviteUserRequest, DeleteInviteUserRequest,
DeleteInviteUsersRequest, DeleteInviteUsersRequest,
Hosting,
InviteUserRequest, InviteUserRequest,
InviteUsersRequest, InviteUsersRequest,
InviteUsersResponse, InviteUsersResponse,
@ -26,7 +26,6 @@ import {
UserIdentifier, UserIdentifier,
} from "@budibase/types" } from "@budibase/types"
import { import {
accounts,
users, users,
cache, cache,
ErrorCode, ErrorCode,
@ -192,12 +191,10 @@ export const adminUser = async (
lastName: familyName, lastName: familyName,
}) })
// events await events.identification.identifyTenantGroup(
let account: CloudAccount | undefined tenantId,
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) { env.SELF_HOSTED ? Hosting.SELF : Hosting.CLOUD
account = await accounts.getAccountByTenantId(tenantId) )
}
await events.identification.identifyTenantGroup(tenantId, account)
ctx.body = { ctx.body = {
_id: finalUser._id!, _id: finalUser._id!,

154
yarn.lock
View File

@ -2319,6 +2319,7 @@
version "0.0.0" version "0.0.0"
dependencies: dependencies:
scim-patch "^0.8.1" scim-patch "^0.8.1"
zod "^3.23.8"
"@bull-board/api@5.10.2": "@bull-board/api@5.10.2":
version "5.10.2" version "5.10.2"
@ -8863,17 +8864,6 @@ cross-spawn@7.0.6:
shebang-command "^2.0.0" shebang-command "^2.0.0"
which "^2.0.1" which "^2.0.1"
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3" version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@ -10675,19 +10665,6 @@ execa@5.0.0:
signal-exit "^3.0.3" signal-exit "^3.0.3"
strip-final-newline "^2.0.0" strip-final-newline "^2.0.0"
execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
dependencies:
cross-spawn "^6.0.0"
get-stream "^4.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
execa@^5.0.0: execa@^5.0.0:
version "5.1.1" version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@ -11495,7 +11472,7 @@ get-stream@^2.2.0:
object-assign "^4.0.1" object-assign "^4.0.1"
pinkie-promise "^2.0.0" pinkie-promise "^2.0.0"
get-stream@^4.0.0, get-stream@^4.1.0: get-stream@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
@ -12591,11 +12568,6 @@ into-stream@^3.1.0:
from2 "^2.1.1" from2 "^2.1.1"
p-is-promise "^1.1.0" p-is-promise "^1.1.0"
invert-kv@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
ioredis-mock@8.9.0: ioredis-mock@8.9.0:
version "8.9.0" version "8.9.0"
resolved "https://registry.yarnpkg.com/ioredis-mock/-/ioredis-mock-8.9.0.tgz#5d694c4b81d3835e4291e0b527f947e260981779" resolved "https://registry.yarnpkg.com/ioredis-mock/-/ioredis-mock-8.9.0.tgz#5d694c4b81d3835e4291e0b527f947e260981779"
@ -14287,13 +14259,6 @@ lazystream@^1.0.0:
dependencies: dependencies:
readable-stream "^2.0.5" readable-stream "^2.0.5"
lcid@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
dependencies:
invert-kv "^2.0.0"
leaflet@^1.7.1: leaflet@^1.7.1:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.3.tgz#52ec436954964e2d3d39e0d433da4b2500d74414" resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.3.tgz#52ec436954964e2d3d39e0d433da4b2500d74414"
@ -15109,13 +15074,6 @@ makeerror@1.0.12:
dependencies: dependencies:
tmpl "1.0.5" tmpl "1.0.5"
map-age-cleaner@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
dependencies:
p-defer "^1.0.0"
map-obj@^1.0.0: map-obj@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
@ -15157,15 +15115,6 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
mem@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
dependencies:
map-age-cleaner "^0.1.1"
mimic-fn "^2.0.0"
p-is-promise "^2.0.0"
memdown@1.4.1: memdown@1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215"
@ -15276,7 +15225,7 @@ mime@^1.3.4:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mimic-fn@^2.0.0, mimic-fn@^2.1.0: mimic-fn@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
@ -15732,11 +15681,6 @@ neo-async@^2.6.2:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
nock@13.5.4, nock@^13.5.4: nock@13.5.4, nock@^13.5.4:
version "13.5.4" version "13.5.4"
resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.4.tgz#8918f0addc70a63736170fef7106a9721e0dc479" resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.4.tgz#8918f0addc70a63736170fef7106a9721e0dc479"
@ -16074,13 +16018,6 @@ npm-registry-fetch@^14.0.0, npm-registry-fetch@^14.0.3, npm-registry-fetch@^14.0
npm-package-arg "^10.0.0" npm-package-arg "^10.0.0"
proc-log "^3.0.0" proc-log "^3.0.0"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
dependencies:
path-key "^2.0.0"
npm-run-path@^4.0.1: npm-run-path@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
@ -16492,15 +16429,6 @@ oracledb@6.5.1:
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-6.5.1.tgz#814d985035acdb1a6470b1152af0ca3767569ede" resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-6.5.1.tgz#814d985035acdb1a6470b1152af0ca3767569ede"
integrity sha512-JzoSGei1wnvmqgKnAZK1W650mzHTZXx+7hClV4mwsbY/ZjUtrpnojNJMYJ2jkOhj7XG5oJPfXc4GqDKaNzkxqg== integrity sha512-JzoSGei1wnvmqgKnAZK1W650mzHTZXx+7hClV4mwsbY/ZjUtrpnojNJMYJ2jkOhj7XG5oJPfXc4GqDKaNzkxqg==
os-locale@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
dependencies:
execa "^1.0.0"
lcid "^2.0.0"
mem "^4.0.0"
os-tmpdir@~1.0.2: os-tmpdir@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
@ -16516,11 +16444,6 @@ p-cancelable@^1.0.0:
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
p-defer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==
p-event@^2.1.0: p-event@^2.1.0:
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6"
@ -16538,11 +16461,6 @@ p-is-promise@^1.1.0:
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
integrity sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg== integrity sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg==
p-is-promise@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
p-limit@^1.1.0: p-limit@^1.1.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
@ -16903,11 +16821,6 @@ path-is-absolute@1.0.1, path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
path-key@^3.0.0, path-key@^3.1.0: path-key@^3.0.0, path-key@^3.1.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
@ -18918,7 +18831,7 @@ semver-diff@^3.1.1:
dependencies: dependencies:
semver "^6.3.0" semver "^6.3.0"
"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: "semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1:
version "7.5.3" version "7.5.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e"
integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==
@ -19013,13 +18926,6 @@ shallow-clone@^3.0.0:
dependencies: dependencies:
kind-of "^6.0.2" kind-of "^6.0.2"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
dependencies:
shebang-regex "^1.0.0"
shebang-command@^2.0.0: shebang-command@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@ -19027,11 +18933,6 @@ shebang-command@^2.0.0:
dependencies: dependencies:
shebang-regex "^3.0.0" shebang-regex "^3.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
shebang-regex@^3.0.0: shebang-regex@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
@ -19746,11 +19647,6 @@ strip-dirs@^2.0.0:
dependencies: dependencies:
is-natural-number "^4.0.1" is-natural-number "^4.0.1"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
strip-final-newline@^2.0.0: strip-final-newline@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
@ -21424,7 +21320,7 @@ which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15,
gopd "^1.0.1" gopd "^1.0.1"
has-tostringtag "^1.0.2" has-tostringtag "^1.0.2"
which@^1.2.14, which@^1.2.9: which@^1.2.14:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@ -21775,7 +21671,7 @@ yargs-parser@21.1.1, yargs-parser@>=21.1.1, yargs-parser@^21.0.0, yargs-parser@^
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
yargs-parser@^13.1.0: yargs-parser@^13.1.2:
version "13.1.2" version "13.1.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
@ -21788,23 +21684,6 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.3:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs@13.2.4:
version "13.2.4"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==
dependencies:
cliui "^5.0.0"
find-up "^3.0.0"
get-caller-file "^2.0.1"
os-locale "^3.1.0"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^3.0.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^13.1.0"
yargs@16.2.0, yargs@^16.1.0, yargs@^16.2.0: yargs@16.2.0, yargs@^16.1.0, yargs@^16.2.0:
version "16.2.0" version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
@ -21818,6 +21697,22 @@ yargs@16.2.0, yargs@^16.1.0, yargs@^16.2.0:
y18n "^5.0.5" y18n "^5.0.5"
yargs-parser "^20.2.2" yargs-parser "^20.2.2"
yargs@^13.2.4:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
dependencies:
cliui "^5.0.0"
find-up "^3.0.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^3.0.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^13.1.2"
yargs@^17.3.1, yargs@^17.6.2, yargs@^17.7.2: yargs@^17.3.1, yargs@^17.6.2, yargs@^17.7.2:
version "17.7.2" version "17.7.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
@ -21925,6 +21820,11 @@ zip-stream@^6.0.1:
compress-commons "^6.0.2" compress-commons "^6.0.2"
readable-stream "^4.0.0" readable-stream "^4.0.0"
zod-validation-error@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.4.0.tgz#3a8a1f55c65579822d7faa190b51336c61bee2a6"
integrity sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==
zod@^3.23.8: zod@^3.23.8:
version "3.23.8" version "3.23.8"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"