1
0
Fork 0
mirror of synced 2024-07-06 15:00:49 +12:00

Merge branch 'develop' of github.com:Budibase/budibase into websocket-redis-integration

This commit is contained in:
Andrew Kingston 2023-05-31 16:28:14 +01:00
commit 8a2d4b7052
34 changed files with 583 additions and 259 deletions

View file

@ -1,5 +1,7 @@
name: Budibase Prerelease
concurrency: release-prerelease
concurrency:
group: release-prerelease
cancel-in-progress: false
on:
push:

View file

@ -1,5 +1,7 @@
name: Budibase Release
concurrency: release
concurrency:
group: release
cancel-in-progress: false
on:
push:

View file

@ -1,5 +1,7 @@
name: Tag prerelease
concurrency: release-prerelease
concurrency:
group: tag-prerelease
cancel-in-progress: false
on:
push:

View file

@ -1,5 +1,7 @@
name: Tag release
concurrency: release-prerelease
concurrency:
group: tag-release
cancel-in-progress: false
on:
push:

View file

@ -1,5 +1,5 @@
{
"version": "2.6.19-alpha.30",
"version": "2.6.19-alpha.37",
"npmClient": "yarn",
"packages": [
"packages/backend-core",

View file

@ -72,16 +72,12 @@ describe("writethrough", () => {
writethrough.put({ ...current, value: 4 }),
])
// with a lock, this will work
const newRev = responses.map(x => x.rev).find(x => x !== current._rev)
expect(newRev).toBeDefined()
expect(responses.map(x => x.rev)).toEqual(
expect.arrayContaining([current._rev, current._rev, newRev])
)
expectFunctionWasCalledTimesWith(
mocks.alerts.logWarn,
2,
"Ignoring redlock conflict in write-through cache"
)
const output = await db.get(current._id)
expect(output.value).toBe(4)

View file

@ -96,6 +96,7 @@ if (!env.DISABLE_PINO_LOGGER) {
const mergingObject: any = {
err: error,
pid: process.pid,
...contextObject,
}

View file

@ -4,10 +4,10 @@ import { LockOptions, LockType } from "@budibase/types"
import * as context from "../context"
import env from "../environment"
const getClient = async (
async function getClient(
type: LockType,
opts?: Redlock.Options
): Promise<Redlock> => {
): Promise<Redlock> {
if (type === LockType.CUSTOM) {
return newRedlock(opts)
}
@ -18,6 +18,9 @@ const getClient = async (
case LockType.TRY_ONCE: {
return newRedlock(OPTIONS.TRY_ONCE)
}
case LockType.TRY_TWICE: {
return newRedlock(OPTIONS.TRY_TWICE)
}
case LockType.DEFAULT: {
return newRedlock(OPTIONS.DEFAULT)
}
@ -35,6 +38,9 @@ const OPTIONS = {
// immediately throws an error if the lock is already held
retryCount: 0,
},
TRY_TWICE: {
retryCount: 1,
},
TEST: {
// higher retry count in unit tests
// due to high contention.
@ -62,7 +68,7 @@ const OPTIONS = {
},
}
const newRedlock = async (opts: Redlock.Options = {}) => {
export async function newRedlock(opts: Redlock.Options = {}) {
let options = { ...OPTIONS.DEFAULT, ...opts }
const redisWrapper = await getLockClient()
const client = redisWrapper.getClient()
@ -81,22 +87,26 @@ type RedlockExecution<T> =
| SuccessfulRedlockExecution<T>
| UnsuccessfulRedlockExecution
export const doWithLock = async <T>(
function getLockName(opts: LockOptions) {
// determine lock name
// by default use the tenantId for uniqueness, unless using a system lock
const prefix = opts.systemLock ? "system" : context.getTenantId()
let name: string = `lock:${prefix}_${opts.name}`
// add additional unique name if required
if (opts.resource) {
name = name + `_${opts.resource}`
}
return name
}
export async function doWithLock<T>(
opts: LockOptions,
task: () => Promise<T>
): Promise<RedlockExecution<T>> => {
): Promise<RedlockExecution<T>> {
const redlock = await getClient(opts.type, opts.customOptions)
let lock
try {
// determine lock name
// by default use the tenantId for uniqueness, unless using a system lock
const prefix = opts.systemLock ? "system" : context.getTenantId()
let name: string = `lock:${prefix}_${opts.name}`
// add additional unique name if required
if (opts.resource) {
name = name + `_${opts.resource}`
}
const name = getLockName(opts)
// create the lock
lock = await redlock.lock(name, opts.ttl)
@ -112,7 +122,6 @@ export const doWithLock = async <T>(
if (opts.type === LockType.TRY_ONCE) {
// don't throw for try-once locks, they will always error
// due to retry count (0) exceeded
console.warn(e)
return { executed: false }
} else {
console.error(e)

View file

@ -165,7 +165,7 @@
{/if}
{#if !disabled}
<div class="delete-button" on:click={removeFile}>
<Icon name="Close" />
<Icon name="Delete" />
</div>
{/if}
</div>
@ -209,7 +209,7 @@
{/if}
{#if !disabled}
<div class="delete-button" on:click={removeFile}>
<Icon name="Close" />
<Icon name="Delete" />
</div>
{/if}
</div>

View file

@ -3,6 +3,7 @@
export let query = {}
export let data = []
export let editRows = false
let loading = false
let error = false
@ -12,7 +13,14 @@
{#if error}
<div class="errors">{error}</div>
{/if}
<Table schema={query.schema} {data} {loading} {type} rowCount={5} />
<Table
schema={query.schema}
{data}
{loading}
{type}
rowCount={5}
allowEditing={editRows}
/>
<style>
.errors {

View file

@ -22,8 +22,8 @@
export let rowCount
export let disableSorting = false
export let customPlaceholder = false
export let allowClickRows
export let allowEditing = true
export let allowClickRows
const dispatch = createEventDispatcher()

View file

@ -9,6 +9,8 @@
import { store } from "builderStore"
import { API } from "api"
export let disabled = false
let revertModal
let appName
@ -34,6 +36,7 @@
size="M"
tooltip="Revert changes"
on:click={revertModal.show}
{disabled}
/>
<Modal bind:this={revertModal}>

View file

@ -58,6 +58,7 @@
justify-content: flex-start;
align-items: stretch;
transition: width 130ms ease-out;
overflow: hidden;
}
.panel.borderLeft {
border-left: var(--border-light);

View file

@ -1,5 +1,5 @@
<script>
import { goto } from "@roxi/routify"
import { goto, beforeUrlChange } from "@roxi/routify"
import {
Icon,
Select,
@ -12,6 +12,8 @@
Heading,
Tabs,
Tab,
Modal,
ModalContent,
} from "@budibase/bbui"
import { notifications, Divider } from "@budibase/bbui"
import ExtraQueryConfig from "./ExtraQueryConfig.svelte"
@ -29,6 +31,12 @@
export let query
const resumeNavigation = () => {
if (typeof navigateTo == "string") {
$goto(typeof navigateTo == "string" ? `${navigateTo}` : navigateTo)
}
}
const transformerDocs = "https://docs.budibase.com/docs/transformers"
let fields = query?.schema ? schemaToFields(query.schema) : []
@ -36,6 +44,31 @@
let data = []
let saveId
let currentTab = "JSON"
let saveModal
let override = false
let navigateTo = null
// seed the transformer
if (query && !query.transformer) {
query.transformer = "return data"
}
// initialise a new empty schema
if (query && !query.schema) {
query.schema = {}
}
let queryStr = JSON.stringify(query)
$beforeUrlChange(event => {
const updated = JSON.stringify(query)
if (updated !== queryStr && !override) {
navigateTo = event.type == "pushstate" ? event.url : null
saveModal.show()
return false
} else return true
})
$: datasource = $datasources.list.find(ds => ds._id === query.datasourceId)
$: query.schema = fieldsToSchema(fields)
@ -60,11 +93,6 @@
}
}
// seed the transformer
if (query && !query.transformer) {
query.transformer = "return data"
}
function resetDependentFields() {
if (query.fields.extra) {
query.fields.extra = {}
@ -101,22 +129,48 @@
}
}
// return the query.
async function saveQuery() {
try {
const { _id } = await queries.save(query.datasourceId, query)
saveId = _id
notifications.success(`Query saved successfully`)
const response = await queries.save(query.datasourceId, query)
saveId = response._id
// Go to the correct URL if we just created a new query
if (!query._rev) {
$goto(`../../${_id}`)
if (response?._rev) {
queryStr = JSON.stringify(query)
}
return response
} catch (error) {
notifications.error("Error saving query")
}
}
</script>
<Modal
bind:this={saveModal}
on:hide={() => {
navigateTo = null
}}
>
<ModalContent
title="You have unsaved changes"
confirmText="Save and Continue"
cancelText="Discard Changes"
size="L"
onConfirm={async () => {
await saveQuery()
override = true
resumeNavigation()
}}
onCancel={async () => {
override = true
resumeNavigation()
}}
>
<Body>Leaving this section will mean losing and changes to your query</Body>
</ModalContent>
</Modal>
<div class="wrapper">
<Layout gap="S" noPadding>
<Heading size="M">Query {integrationInfo?.friendlyName}</Heading>
@ -125,7 +179,13 @@
<div class="config">
<div class="config-field">
<Label>Query Name</Label>
<Input bind:value={query.name} />
<Input
value={query.name}
on:input={e => {
let newValue = e.target.value || ""
query.name = newValue.trim()
}}
/>
</div>
{#if queryConfig}
<div class="config-field">
@ -149,18 +209,20 @@
/>
{/if}
{#key query.parameters}
<BindingBuilder
queryBindings={query.parameters}
bindable={false}
on:change={e => {
query.parameters = e.detail.map(binding => {
return {
name: binding.name,
default: binding.value,
}
})
}}
/>
<div class="binding-wrap">
<BindingBuilder
queryBindings={query.parameters}
bindable={false}
on:change={e => {
query.parameters = e.detail.map(binding => {
return {
name: binding.name,
default: binding.value,
}
})
}}
/>
</div>
{/key}
{/if}
</div>
@ -203,7 +265,18 @@
<div class="viewer-controls">
<Heading size="S">Results</Heading>
<ButtonGroup gap="XS">
<Button cta disabled={queryInvalid} on:click={saveQuery}>
<Button
cta
disabled={queryInvalid}
on:click={async () => {
await saveQuery()
notifications.success(`Query saved successfully`)
// Go to the correct URL if we just created a new query
if (!query._rev) {
$goto(`../../${query._id}`)
}
}}
>
Save Query
</Button>
<Button secondary on:click={previewQuery}>Run Query</Button>
@ -274,4 +347,9 @@
min-width: 150px;
align-items: center;
}
.binding-wrap :global(div.container) {
padding-left: 0px;
padding-right: 0px;
}
</style>

View file

@ -3,8 +3,10 @@
import QueryViewer from "components/integration/QueryViewer.svelte"
import RestQueryViewer from "components/integration/RestQueryViewer.svelte"
import { IntegrationTypes } from "constants/backend"
import { cloneDeep } from "lodash/fp"
$: query = $queries.selected
$: editableQuery = cloneDeep(query)
$: datasource = $datasources.list.find(ds => ds._id === query?.datasourceId)
$: isRestQuery = datasource?.source === IntegrationTypes.REST
</script>
@ -13,6 +15,6 @@
{#if isRestQuery}
<RestQueryViewer queryId={$queries.selectedQueryId} />
{:else}
<QueryViewer {query} />
<QueryViewer query={editableQuery} />
{/if}
{/if}

View file

@ -51,6 +51,26 @@
return groups.actions.getGroupAppIds(group).includes(prodAppId)
})
const updateDeploymentString = () => {
return deployments?.length
? processStringSync(
"Last published {{ duration time 'millisecond' }} ago",
{
time:
new Date().getTime() -
new Date(deployments[0].updatedAt).getTime(),
}
)
: ""
}
// App is updating in the layout asynchronously
$: if ($store.appId?.length) {
fetchDeployments().then(resp => {
deployments = resp
})
}
$: deploymentString = updateDeploymentString(deployments)
async function fetchAppEditor(editorId) {
appEditor = await users.get(editorId)
}
@ -107,19 +127,11 @@
</div>
<div class="status-text">
{#if deployments?.length}
{processStringSync(
"Last published {{ duration time 'millisecond' }} ago",
{
time:
new Date().getTime() -
new Date(deployments[0].updatedAt).getTime(),
}
)}
{#if isPublished}
- <Link on:click={unpublishModal.show}>Unpublish</Link>
{/if}
{#if isPublished}
{deploymentString}
- <Link on:click={unpublishModal.show}>Unpublish</Link>
{/if}
{#if !deployments?.length}
-
{/if}

@ -1 +1 @@
Subproject commit 2adc101c1ede13f861f282d702f45b94ab91fd41
Subproject commit 86c32b80e08d2f19b57dcc2a3159667ac5a86c21

View file

@ -100,6 +100,7 @@
"mssql": "6.2.3",
"mysql2": "2.3.3",
"node-fetch": "2.6.7",
"object-sizeof": "2.6.1",
"open": "8.4.0",
"openai": "^3.2.1",
"pg": "8.10.0",

View file

@ -104,6 +104,7 @@ export async function fetchDeployments(ctx: any) {
}
ctx.body = Object.values(deployments.history).reverse()
} catch (err) {
console.error(err)
ctx.body = []
}
}

View file

@ -2,6 +2,23 @@ import env from "../../environment"
import { AutomationResults, Automation, App } from "@budibase/types"
import { automations } from "@budibase/pro"
import { db as dbUtils } from "@budibase/backend-core"
import sizeof from "object-sizeof"
const MAX_LOG_SIZE_MB = 5
const MB_IN_BYTES = 1024 * 1024
function sanitiseResults(results: AutomationResults) {
const message = `[removed] - max results size of ${MAX_LOG_SIZE_MB}MB exceeded`
for (let step of results.steps) {
step.inputs = {
message,
}
step.outputs = {
message,
success: step.outputs.success,
}
}
}
export async function storeLog(
automation: Automation,
@ -11,6 +28,10 @@ export async function storeLog(
if (env.DISABLE_AUTOMATION_LOGS) {
return
}
const bytes = sizeof(results)
if (bytes / MB_IN_BYTES > MAX_LOG_SIZE_MB) {
sanitiseResults(results)
}
await automations.logs.storeLog(automation, results)
}

View file

@ -80,6 +80,7 @@ const environment = {
ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
SELF_HOSTED: process.env.SELF_HOSTED,
HTTP_MB_LIMIT: process.env.HTTP_MB_LIMIT,
FORKED_PROCESS_NAME: process.env.FORKED_PROCESS_NAME || "main",
// old
CLIENT_ID: process.env.CLIENT_ID,
_set(key: string, value: any) {

View file

@ -9,8 +9,8 @@ import {
checkDebounce,
setDebounce,
} from "../utilities/redis"
import { db as dbCore, cache, permissions } from "@budibase/backend-core"
import { BBContext, Database } from "@budibase/types"
import { db as dbCore, cache } from "@budibase/backend-core"
import { UserCtx, Database } from "@budibase/types"
const DEBOUNCE_TIME_SEC = 30
@ -23,7 +23,7 @@ const DEBOUNCE_TIME_SEC = 30
* through the authorized middleware *
****************************************************/
async function checkDevAppLocks(ctx: BBContext) {
async function checkDevAppLocks(ctx: UserCtx) {
const appId = ctx.appId
// if any public usage, don't proceed
@ -42,7 +42,7 @@ async function checkDevAppLocks(ctx: BBContext) {
}
}
async function updateAppUpdatedAt(ctx: BBContext) {
async function updateAppUpdatedAt(ctx: UserCtx) {
const appId = ctx.appId
// if debouncing skip this update
// get methods also aren't updating
@ -50,20 +50,29 @@ async function updateAppUpdatedAt(ctx: BBContext) {
return
}
await dbCore.doWithDB(appId, async (db: Database) => {
const metadata = await db.get(DocumentType.APP_METADATA)
metadata.updatedAt = new Date().toISOString()
try {
const metadata = await db.get(DocumentType.APP_METADATA)
metadata.updatedAt = new Date().toISOString()
metadata.updatedBy = getGlobalIDFromUserMetadataID(ctx.user?.userId!)
metadata.updatedBy = getGlobalIDFromUserMetadataID(ctx.user?.userId!)
const response = await db.put(metadata)
metadata._rev = response.rev
await cache.app.invalidateAppMetadata(appId, metadata)
// set a new debounce record with a short TTL
await setDebounce(appId, DEBOUNCE_TIME_SEC)
const response = await db.put(metadata)
metadata._rev = response.rev
await cache.app.invalidateAppMetadata(appId, metadata)
// set a new debounce record with a short TTL
await setDebounce(appId, DEBOUNCE_TIME_SEC)
} catch (err: any) {
// if a 409 occurs, then multiple clients connected at the same time - ignore
if (err?.status === 409) {
return
} else {
throw err
}
}
})
}
export default async function builder(ctx: BBContext) {
export default async function builder(ctx: UserCtx) {
const appId = ctx.appId
// this only functions within an app context
if (!appId) {

View file

@ -19,6 +19,7 @@ import {
AutomationStatus,
AutomationMetadata,
AutomationJob,
AutomationData,
} from "@budibase/types"
import {
LoopStep,
@ -30,6 +31,7 @@ import { WorkerCallback } from "./definitions"
import { context, logging } from "@budibase/backend-core"
import { processObject } from "@budibase/string-templates"
import { cloneDeep } from "lodash/fp"
import { performance } from "perf_hooks"
import * as sdkUtils from "../sdk/utils"
import env from "../environment"
const FILTER_STEP_ID = actions.BUILTIN_ACTION_DEFINITIONS.FILTER.stepId
@ -37,8 +39,8 @@ const LOOP_STEP_ID = actions.BUILTIN_ACTION_DEFINITIONS.LOOP.stepId
const CRON_STEP_ID = triggerDefs.CRON.stepId
const STOPPED_STATUS = { success: true, status: AutomationStatus.STOPPED }
function getLoopIterations(loopStep: LoopStep, input: LoopInput) {
const binding = automationUtils.typecastForLooping(loopStep, input)
function getLoopIterations(loopStep: LoopStep) {
let binding = loopStep.inputs.binding
if (!binding) {
return 0
}
@ -68,7 +70,6 @@ class Orchestrator {
constructor(job: AutomationJob) {
let automation = job.data.automation
let triggerOutput = job.data.event
let timeout = job.data.event.timeout
const metadata = triggerOutput.metadata
this._chainCount = metadata ? metadata.automationChainCount! : 0
this._appId = triggerOutput.appId as string
@ -252,7 +253,7 @@ class Orchestrator {
return
}
}
const start = performance.now()
for (let step of automation.definition.steps) {
if (timeoutFlag) {
break
@ -277,22 +278,17 @@ class Orchestrator {
if (loopStep) {
input = await processObject(loopStep.inputs, this._context)
iterations = getLoopIterations(loopStep as LoopStep, input)
iterations = getLoopIterations(loopStep as LoopStep)
}
for (let index = 0; index < iterations; index++) {
let originalStepInput = cloneDeep(step.inputs)
// Handle if the user has set a max iteration count or if it reaches the max limit set by us
if (loopStep && input.binding) {
let newInput: any = await processObject(
loopStep.inputs,
cloneDeep(this._context)
)
let tempOutput = { items: loopSteps, iterations: iterationCount }
try {
newInput.binding = automationUtils.typecastForLooping(
loopStep.inputs.binding = automationUtils.typecastForLooping(
loopStep as LoopStep,
newInput
loopStep.inputs as LoopInput
)
} catch (err) {
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
@ -303,13 +299,12 @@ class Orchestrator {
loopStep = undefined
break
}
let item = []
if (
typeof loopStep.inputs.binding === "string" &&
loopStep.inputs.option === "String"
) {
item = automationUtils.stringSplit(newInput.binding)
item = automationUtils.stringSplit(loopStep.inputs.binding)
} else if (Array.isArray(loopStep.inputs.binding)) {
item = loopStep.inputs.binding
}
@ -351,6 +346,7 @@ class Orchestrator {
}
}
}
if (
index === env.AUTOMATION_MAX_ITERATIONS ||
index === parseInt(loopStep.inputs.iterations)
@ -479,8 +475,25 @@ class Orchestrator {
}
}
const end = performance.now()
const executionTime = end - start
console.info(`Execution time: ${executionTime} milliseconds`, {
_logKey: "automation",
executionTime,
})
// store the logs for the automation run
await storeLog(this._automation, this.executionOutput)
try {
await storeLog(this._automation, this.executionOutput)
} catch (e: any) {
if (e.status === 413 && e.request?.data) {
// if content is too large we shouldn't log it
delete e.request.data
e.request.data = { message: "removed due to large size" }
}
logging.logAlert("Error writing automation log", e)
}
if (isProdAppID(this._appId) && isRecurring(automation) && metadata) {
await this.updateMetadata(metadata)
}
@ -488,23 +501,31 @@ class Orchestrator {
}
}
export function execute(job: Job, callback: WorkerCallback) {
export function execute(job: Job<AutomationData>, callback: WorkerCallback) {
const appId = job.data.event.appId
const automationId = job.data.automation._id
if (!appId) {
throw new Error("Unable to execute, event doesn't contain app ID.")
}
return context.doInAppContext(appId, async () => {
const envVars = await sdkUtils.getEnvironmentVariables()
// put into automation thread for whole context
await context.doInEnvironmentContext(envVars, async () => {
const automationOrchestrator = new Orchestrator(job)
try {
const response = await automationOrchestrator.execute()
callback(null, response)
} catch (err) {
callback(err)
}
})
if (!automationId) {
throw new Error("Unable to execute, event doesn't contain automation ID.")
}
return context.doInAutomationContext({
appId,
automationId,
task: async () => {
const envVars = await sdkUtils.getEnvironmentVariables()
// put into automation thread for whole context
await context.doInEnvironmentContext(envVars, async () => {
const automationOrchestrator = new Orchestrator(job)
try {
const response = await automationOrchestrator.execute()
callback(null, response)
} catch (err) {
callback(err)
}
})
},
})
}

View file

@ -38,6 +38,9 @@ export class Thread {
this.count = opts.count ? opts.count : 1
this.disableThreading = this.shouldDisableThreading()
if (!this.disableThreading) {
console.debug(
`[${env.FORKED_PROCESS_NAME}] initialising worker farm type=${type}`
)
const workerOpts: any = {
autoStart: true,
maxConcurrentWorkers: this.count,
@ -45,6 +48,7 @@ export class Thread {
env: {
...process.env,
FORKED_PROCESS: "1",
FORKED_PROCESS_NAME: type,
},
},
}
@ -54,6 +58,10 @@ export class Thread {
}
this.workers = workerFarm(workerOpts, typeToFile(type), ["execute"])
Thread.workerRefs.push(this.workers)
} else {
console.debug(
`[${env.FORKED_PROCESS_NAME}] skipping worker farm type=${type}`
)
}
}
@ -72,9 +80,7 @@ export class Thread {
function fire(worker: any) {
worker.execute(job, (err: any, response: any) => {
if (err && err.type === "TimeoutError") {
reject(
new Error(`Query response time exceeded ${timeout}ms timeout.`)
)
reject(new Error(`Thread timeout exceeded ${timeout}ms timeout.`))
} else if (err) {
reject(err)
} else {

View file

@ -26,8 +26,10 @@ function makeVariableKey(queryId: string, variable: string) {
export function threadSetup() {
// don't run this if not threading
if (env.isTest() || env.DISABLE_THREADING || !env.isInThread()) {
console.debug(`[${env.FORKED_PROCESS_NAME}] thread setup skipped`)
return
}
console.debug(`[${env.FORKED_PROCESS_NAME}] thread setup running`)
db.init()
}

View file

@ -35,10 +35,20 @@ export const getComponentLibraryManifest = async (library: string) => {
const filename = "manifest.json"
if (env.isDev() || env.isTest()) {
const path = join(TOP_LEVEL_PATH, "packages/client", filename)
// always load from new so that updates are refreshed
delete require.cache[require.resolve(path)]
return require(path)
const paths = [
join(TOP_LEVEL_PATH, "packages/client", filename),
join(process.cwd(), "client", filename),
]
for (let path of paths) {
if (fs.existsSync(path)) {
// always load from new so that updates are refreshed
delete require.cache[require.resolve(path)]
return require(path)
}
}
throw new Error(
`Unable to find ${filename} in development environment (may need to build).`
)
}
if (!appId) {

View file

@ -6,6 +6,7 @@ export enum LockType {
* No retries will take place and no error will be thrown.
*/
TRY_ONCE = "try_once",
TRY_TWICE = "try_twice",
DEFAULT = "default",
DELAY_500 = "delay_500",
CUSTOM = "custom",

View file

@ -58,4 +58,10 @@ export default class AccountAPI {
}
return [response, json]
}
async delete(accountID: string) {
const [response, json] = await this.client.del(`/api/accounts/${accountID}`)
expect(response).toHaveStatusCode(200)
return response
}
}

View file

@ -1,4 +1,7 @@
import { Datasource } from "@budibase/types"
import { DatasourceRequest } from "../../types"
import { generator } from "../../shared"
// Add information about the data source to the fixtures file from 1password
export const mongoDB = (): DatasourceRequest => {
return {
@ -70,3 +73,50 @@ export const restAPI = (): DatasourceRequest => {
fetchSchema: false,
}
}
export const generateRelationshipForMySQL = (
updatedDataSourceJson: any
): Datasource => {
const entities = updatedDataSourceJson!.datasource!.entities!
const datasourceId = updatedDataSourceJson!.datasource!._id!
const relationShipBody = {
...updatedDataSourceJson.datasource,
entities: {
...updatedDataSourceJson.datasource.entities,
employees: {
...entities.employees,
schema: {
...entities.employees.schema,
salaries: {
tableId: `${datasourceId}__salaries`,
name: "salaries",
relationshipType: "many-to-one",
fieldName: "salary",
type: "link",
main: true,
_id: generator.string(),
foreignKey: "emp_no",
},
},
},
titles: {
...entities.titles,
schema: {
...entities.titles.schema,
employees: {
tableId: `${datasourceId}__employees`,
name: "employees",
relationshipType: "one-to-many",
fieldName: "emp_no",
type: "link",
main: true,
_id: generator.string(),
foreignKey: "emp_no",
},
},
},
},
}
return relationShipBody
}

View file

@ -66,4 +66,41 @@ describe("Internal API - Data Sources: MariaDB", () => {
updatedDataSourceJson.datasource._rev!
)
})
it("Create a relationship", async () => {
// Create app
await config.createApp()
// Get all integrations
await config.api.integrations.getAll()
// Add data source
const [dataSourceResponse, dataSourceJson] =
await config.api.datasources.add(fixtures.datasources.mariaDB())
// Update data source
const newDataSourceInfo = {
...dataSourceJson.datasource,
name: "MariaDB2",
}
const [updatedDataSourceResponse, updatedDataSourceJson] =
await config.api.datasources.update(newDataSourceInfo)
// Query data source
const [queryResponse, queryJson] = await config.api.queries.preview(
fixtures.queries.mariaDB(updatedDataSourceJson.datasource._id!)
)
expect(queryJson.rows.length).toBeGreaterThan(9)
expect(queryJson.schemaFields).toEqual(
fixtures.queries.expectedSchemaFields.mariaDB
)
// Add relationship
const relationShipBody = fixtures.datasources.generateRelationshipForMySQL(
updatedDataSourceJson
)
const [relationshipResponse, relationshipJson] =
await config.api.datasources.update(relationShipBody)
})
})

View file

@ -37,7 +37,7 @@ describe("Internal API - Data Sources: PostgresSQL", () => {
fixtures.queries.postgres(updatedDataSourceJson.datasource._id!)
)
expect(queryJson.rows.length).toEqual(91)
expect(queryJson.rows.length).toBeGreaterThan(10)
expect(queryJson.schemaFields).toEqual(
fixtures.queries.expectedSchemaFields.postgres
)

View file

@ -2,7 +2,7 @@ import { DEFAULT_TENANT_ID, logging } from "@budibase/backend-core"
import { AccountInternalAPI } from "../account-api"
import * as fixtures from "../internal-api/fixtures"
import { BudibaseInternalAPI } from "../internal-api"
import { CreateAccountRequest, Feature } from "@budibase/types"
import { Account, CreateAccountRequest, Feature } from "@budibase/types"
import env from "../environment"
import { APIRequestOpts } from "../types"
@ -18,13 +18,13 @@ const API_OPTS: APIRequestOpts = { doExpect: false }
// @ts-ignore
global.qa = {}
async function createAccount() {
async function createAccount(): Promise<[CreateAccountRequest, Account]> {
const account = fixtures.accounts.generateAccount()
await accountsApi.accounts.validateEmail(account.email, API_OPTS)
await accountsApi.accounts.validateTenantId(account.tenantId, API_OPTS)
const [res, newAccount] = await accountsApi.accounts.create(account, API_OPTS)
await updateLicense(newAccount.accountId)
return account
return [account, newAccount]
}
const UNLIMITED = { value: -1 }
@ -85,9 +85,11 @@ async function setup() {
console.log(`Environment: ${JSON.stringify(env)}`)
if (env.multiTenancy) {
const account = await createAccount()
const [account, newAccount] = await createAccount()
// @ts-ignore
global.qa.tenantId = account.tenantId
// @ts-ignore
global.qa.accountId = newAccount.accountId
await loginAsAccount(account)
} else {
// @ts-ignore

View file

@ -1,7 +1,24 @@
import { AccountInternalAPI } from "../account-api"
import { BudibaseInternalAPI } from "../internal-api"
import { APIRequestOpts } from "../types"
const accountsApi = new AccountInternalAPI({})
const internalApi = new BudibaseInternalAPI({})
const API_OPTS: APIRequestOpts = { doExpect: false }
async function deleteAccount() {
// @ts-ignore
const accountID = global.qa.accountId
await accountsApi.accounts.delete(accountID)
}
async function teardown() {
console.log("\nGLOBAL TEARDOWN STARTING")
// TODO: Delete account and apps after test run
const env = await internalApi.environment.getEnvironment(API_OPTS)
if (env.multiTenancy) {
await deleteAccount()
}
console.log("GLOBAL TEARDOWN COMPLETE")
}

291
yarn.lock
View file

@ -3470,7 +3470,7 @@
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
version "0.3.17"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==
@ -5471,11 +5471,6 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/estree@^0.0.51":
version "0.0.51"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40"
integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==
"@types/express-serve-static-core@^4.17.33":
version "4.17.33"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543"
@ -6315,125 +6310,125 @@
loupe "^2.3.6"
pretty-format "^27.5.1"
"@webassemblyjs/ast@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
dependencies:
"@webassemblyjs/helper-numbers" "1.11.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
"@webassemblyjs/helper-numbers" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/floating-point-hex-parser@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f"
integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==
"@webassemblyjs/floating-point-hex-parser@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
"@webassemblyjs/helper-api-error@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16"
integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==
"@webassemblyjs/helper-api-error@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
"@webassemblyjs/helper-buffer@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5"
integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==
"@webassemblyjs/helper-buffer@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
"@webassemblyjs/helper-numbers@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae"
integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==
"@webassemblyjs/helper-numbers@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
dependencies:
"@webassemblyjs/floating-point-hex-parser" "1.11.1"
"@webassemblyjs/helper-api-error" "1.11.1"
"@webassemblyjs/floating-point-hex-parser" "1.11.6"
"@webassemblyjs/helper-api-error" "1.11.6"
"@xtuc/long" "4.2.2"
"@webassemblyjs/helper-wasm-bytecode@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1"
integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==
"@webassemblyjs/helper-wasm-bytecode@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
"@webassemblyjs/helper-wasm-section@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a"
integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==
"@webassemblyjs/helper-wasm-section@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
dependencies:
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/helper-buffer" "1.11.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
"@webassemblyjs/wasm-gen" "1.11.1"
"@webassemblyjs/ast" "1.11.6"
"@webassemblyjs/helper-buffer" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/wasm-gen" "1.11.6"
"@webassemblyjs/ieee754@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614"
integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==
"@webassemblyjs/ieee754@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
dependencies:
"@xtuc/ieee754" "^1.2.0"
"@webassemblyjs/leb128@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5"
integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==
"@webassemblyjs/leb128@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
dependencies:
"@xtuc/long" "4.2.2"
"@webassemblyjs/utf8@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff"
integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==
"@webassemblyjs/utf8@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
"@webassemblyjs/wasm-edit@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6"
integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==
"@webassemblyjs/wasm-edit@^1.11.5":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
dependencies:
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/helper-buffer" "1.11.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
"@webassemblyjs/helper-wasm-section" "1.11.1"
"@webassemblyjs/wasm-gen" "1.11.1"
"@webassemblyjs/wasm-opt" "1.11.1"
"@webassemblyjs/wasm-parser" "1.11.1"
"@webassemblyjs/wast-printer" "1.11.1"
"@webassemblyjs/ast" "1.11.6"
"@webassemblyjs/helper-buffer" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/helper-wasm-section" "1.11.6"
"@webassemblyjs/wasm-gen" "1.11.6"
"@webassemblyjs/wasm-opt" "1.11.6"
"@webassemblyjs/wasm-parser" "1.11.6"
"@webassemblyjs/wast-printer" "1.11.6"
"@webassemblyjs/wasm-gen@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76"
integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==
"@webassemblyjs/wasm-gen@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
dependencies:
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
"@webassemblyjs/ieee754" "1.11.1"
"@webassemblyjs/leb128" "1.11.1"
"@webassemblyjs/utf8" "1.11.1"
"@webassemblyjs/ast" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/ieee754" "1.11.6"
"@webassemblyjs/leb128" "1.11.6"
"@webassemblyjs/utf8" "1.11.6"
"@webassemblyjs/wasm-opt@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2"
integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==
"@webassemblyjs/wasm-opt@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
dependencies:
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/helper-buffer" "1.11.1"
"@webassemblyjs/wasm-gen" "1.11.1"
"@webassemblyjs/wasm-parser" "1.11.1"
"@webassemblyjs/ast" "1.11.6"
"@webassemblyjs/helper-buffer" "1.11.6"
"@webassemblyjs/wasm-gen" "1.11.6"
"@webassemblyjs/wasm-parser" "1.11.6"
"@webassemblyjs/wasm-parser@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199"
integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==
"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
dependencies:
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/helper-api-error" "1.11.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.1"
"@webassemblyjs/ieee754" "1.11.1"
"@webassemblyjs/leb128" "1.11.1"
"@webassemblyjs/utf8" "1.11.1"
"@webassemblyjs/ast" "1.11.6"
"@webassemblyjs/helper-api-error" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/ieee754" "1.11.6"
"@webassemblyjs/leb128" "1.11.6"
"@webassemblyjs/utf8" "1.11.6"
"@webassemblyjs/wast-printer@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0"
integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==
"@webassemblyjs/wast-printer@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
dependencies:
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/ast" "1.11.6"
"@xtuc/long" "4.2.2"
"@webpack-cli/configtest@^1.2.0":
@ -6588,10 +6583,10 @@ acorn-globals@^7.0.0:
acorn "^8.1.0"
acorn-walk "^8.0.2"
acorn-import-assertions@^1.7.6:
version "1.8.0"
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==
acorn-import-assertions@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
acorn-jsx@^5.2.0, acorn-jsx@^5.3.1:
version "5.3.2"
@ -10582,10 +10577,10 @@ engine.io@~6.4.1:
engine.io-parser "~5.0.3"
ws "~8.11.0"
enhanced-resolve@^5.10.0:
version "5.12.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634"
integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==
enhanced-resolve@^5.14.1:
version "5.14.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz#de684b6803724477a4af5d74ccae5de52c25f6b3"
integrity sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==
dependencies:
graceful-fs "^4.2.4"
tapable "^2.2.0"
@ -10754,10 +10749,10 @@ es-get-iterator@^1.1.2:
isarray "^2.0.5"
stop-iteration-iterator "^1.0.0"
es-module-lexer@^0.9.0:
version "0.9.3"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19"
integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==
es-module-lexer@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.2.1.tgz#ba303831f63e6a394983fde2f97ad77b22324527"
integrity sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==
es-set-tostringtag@^2.0.1:
version "2.0.1"
@ -19043,6 +19038,13 @@ object-keys@~0.4.0:
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==
object-sizeof@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/object-sizeof/-/object-sizeof-2.6.1.tgz#1e2b6a01d182c268dbb07ee3403f539de45f63d3"
integrity sha512-a7VJ1Zx7ZuHceKwjgfsSqzV/X0PVGvpZz7ho3Dn4Cs0LLcR5e5WuV+gsbizmplD8s0nAXMJmckKB2rkSiPm/Gg==
dependencies:
buffer "^6.0.3"
object-visit@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
@ -22419,7 +22421,7 @@ saxes@^6.0.0:
dependencies:
xmlchars "^2.2.0"
schema-utils@^3.1.0, schema-utils@^3.1.1:
schema-utils@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
@ -22428,6 +22430,15 @@ schema-utils@^3.1.0, schema-utils@^3.1.1:
ajv "^6.12.5"
ajv-keywords "^3.5.2"
schema-utils@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99"
integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==
dependencies:
"@types/json-schema" "^7.0.8"
ajv "^6.12.5"
ajv-keywords "^3.5.2"
scim-patch@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/scim-patch/-/scim-patch-0.7.0.tgz#3f6d94256c07be415a74a49c0ff48dc91e4e0219"
@ -22580,7 +22591,7 @@ serialize-javascript@^4.0.0:
dependencies:
randombytes "^2.1.0"
serialize-javascript@^6.0.0:
serialize-javascript@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c"
integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==
@ -22943,9 +22954,9 @@ socket.io-client@^4.6.1:
socket.io-parser "~4.2.1"
socket.io-parser@~4.2.1:
version "4.2.2"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.2.tgz#1dd384019e25b7a3d374877f492ab34f2ad0d206"
integrity sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==
version "4.2.3"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.3.tgz#926bcc6658e2ae0883dc9dee69acbdc76e4e3667"
integrity sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
@ -24102,18 +24113,18 @@ terminal-link@^2.0.0:
ansi-escapes "^4.2.1"
supports-hyperlinks "^2.0.0"
terser-webpack-plugin@^5.1.3:
version "5.3.6"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c"
integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==
terser-webpack-plugin@^5.3.7:
version "5.3.9"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1"
integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==
dependencies:
"@jridgewell/trace-mapping" "^0.3.14"
"@jridgewell/trace-mapping" "^0.3.17"
jest-worker "^27.4.5"
schema-utils "^3.1.1"
serialize-javascript "^6.0.0"
terser "^5.14.1"
serialize-javascript "^6.0.1"
terser "^5.16.8"
terser@^5.0.0, terser@^5.14.1:
terser@^5.0.0:
version "5.16.5"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.5.tgz#1c285ca0655f467f92af1bbab46ab72d1cb08e5a"
integrity sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==
@ -24123,6 +24134,16 @@ terser@^5.0.0, terser@^5.14.1:
commander "^2.20.0"
source-map-support "~0.5.20"
terser@^5.16.8:
version "5.17.6"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.6.tgz#d810e75e1bb3350c799cd90ebefe19c9412c12de"
integrity sha512-V8QHcs8YuyLkLHsJO5ucyff1ykrLVsR4dNnS//L5Y3NiSXpbK1J+WMVUs67eI0KTxs9JtHhgEQpXQVHlHI92DQ==
dependencies:
"@jridgewell/source-map" "^0.3.2"
acorn "^8.5.0"
commander "^2.20.0"
source-map-support "~0.5.20"
test-console@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/test-console/-/test-console-2.0.0.tgz#a279f7e2e148815224d8446ffa5208f0077d68fb"
@ -25499,21 +25520,21 @@ webpack-sources@^3.2.3:
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
webpack@^5.64.2:
version "5.75.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152"
integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==
version "5.84.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.84.0.tgz#011115617668744aece87a9eb68534487d84de1a"
integrity sha512-XezNK3kwJq6IyeoZmZ1uEqQs+42nTqIi4jYM/YjLwaJedUC1N3bwnCC0+UcnHJPfqWX0kGrQnMIvZZyWYaIZrA==
dependencies:
"@types/eslint-scope" "^3.7.3"
"@types/estree" "^0.0.51"
"@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/wasm-edit" "1.11.1"
"@webassemblyjs/wasm-parser" "1.11.1"
"@types/estree" "^1.0.0"
"@webassemblyjs/ast" "^1.11.5"
"@webassemblyjs/wasm-edit" "^1.11.5"
"@webassemblyjs/wasm-parser" "^1.11.5"
acorn "^8.7.1"
acorn-import-assertions "^1.7.6"
acorn-import-assertions "^1.9.0"
browserslist "^4.14.5"
chrome-trace-event "^1.0.2"
enhanced-resolve "^5.10.0"
es-module-lexer "^0.9.0"
enhanced-resolve "^5.14.1"
es-module-lexer "^1.2.1"
eslint-scope "5.1.1"
events "^3.2.0"
glob-to-regexp "^0.4.1"
@ -25522,9 +25543,9 @@ webpack@^5.64.2:
loader-runner "^4.2.0"
mime-types "^2.1.27"
neo-async "^2.6.2"
schema-utils "^3.1.0"
schema-utils "^3.1.2"
tapable "^2.1.1"
terser-webpack-plugin "^5.1.3"
terser-webpack-plugin "^5.3.7"
watchpack "^2.4.0"
webpack-sources "^3.2.3"