Merge branch 'develop' of github.com:Budibase/budibase into views-v2-frontend
This commit is contained in:
commit
c4e4b5c979
|
@ -1,4 +1,4 @@
|
|||
name: Deploy Budibase Single Container Image to DockerHub
|
||||
name: release-singleimage
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
@ -8,8 +8,8 @@ env:
|
|||
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
REGISTRY_URL: registry.hub.docker.com
|
||||
jobs:
|
||||
build:
|
||||
name: "build"
|
||||
build-amd64:
|
||||
name: "build-amd64"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -27,14 +27,12 @@ jobs:
|
|||
submodules: true
|
||||
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fail if tag is not in master
|
||||
run: |
|
||||
if ! git merge-base --is-ancestor ${{ github.sha }} origin/master; then
|
||||
echo "Tag is not in master. This pipeline can only execute tags that are present on the master branch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
|
@ -70,9 +68,139 @@ jobs:
|
|||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: budibase/budibase,budibase/budibase:${{ env.RELEASE_VERSION }}
|
||||
platforms: linux/amd64
|
||||
tags: budibase/budibase,budibase/budibase:v${{ env.RELEASE_VERSION }}
|
||||
file: ./hosting/single/Dockerfile
|
||||
|
||||
- name: Tag and release Budibase Azure App Service docker image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
build-args: TARGETBUILD=aas
|
||||
tags: budibase/budibase-aas,budibase/budibase-aas:v${{ env.RELEASE_VERSION }}
|
||||
file: ./hosting/single/Dockerfile
|
||||
|
||||
build-arm64:
|
||||
name: "build-arm64"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- name: Fail if not a tag
|
||||
run: |
|
||||
if [[ $GITHUB_REF != refs/tags/* ]]; then
|
||||
echo "Workflow Dispatch can only be run on tags"
|
||||
exit 1
|
||||
fi
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
fetch-depth: 0
|
||||
- name: Fail if tag is not in master
|
||||
run: |
|
||||
if ! git merge-base --is-ancestor ${{ github.sha }} origin/master; then
|
||||
echo "Tag is not in master. This pipeline can only execute tags that are present on the master branch"
|
||||
exit 1
|
||||
fi
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Run Yarn
|
||||
run: yarn
|
||||
- name: Update versions
|
||||
run: ./scripts/updateVersions.sh
|
||||
- name: Runt Yarn Lint
|
||||
run: yarn lint
|
||||
- name: Update versions
|
||||
run: ./scripts/updateVersions.sh
|
||||
- name: Run Yarn Build
|
||||
run: yarn build:docker:pre
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_API_KEY }}
|
||||
- name: Get the latest release version
|
||||
id: version
|
||||
run: |
|
||||
release_version=$(cat lerna.json | jq -r '.version')
|
||||
echo $release_version
|
||||
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||
- name: Tag and release Budibase service docker image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/arm64
|
||||
tags: budibase/budibase,budibase/budibase:v${{ env.RELEASE_VERSION }}
|
||||
file: ./hosting/single/Dockerfile
|
||||
|
||||
build-aas:
|
||||
name: "build-aas"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- name: Fail if not a tag
|
||||
run: |
|
||||
if [[ $GITHUB_REF != refs/tags/* ]]; then
|
||||
echo "Workflow Dispatch can only be run on tags"
|
||||
exit 1
|
||||
fi
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
fetch-depth: 0
|
||||
- name: Fail if tag is not in master
|
||||
run: |
|
||||
if ! git merge-base --is-ancestor ${{ github.sha }} origin/master; then
|
||||
echo "Tag is not in master. This pipeline can only execute tags that are present on the master branch"
|
||||
exit 1
|
||||
fi
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Run Yarn
|
||||
run: yarn
|
||||
- name: Update versions
|
||||
run: ./scripts/updateVersions.sh
|
||||
- name: Runt Yarn Lint
|
||||
run: yarn lint
|
||||
- name: Update versions
|
||||
run: ./scripts/updateVersions.sh
|
||||
- name: Run Yarn Build
|
||||
run: yarn build:docker:pre
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_API_KEY }}
|
||||
- name: Get the latest release version
|
||||
id: version
|
||||
run: |
|
||||
release_version=$(cat lerna.json | jq -r '.version')
|
||||
echo $release_version
|
||||
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||
- name: Tag and release Budibase Azure App Service docker image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.8.22-alpha.4",
|
||||
"version": "2.8.28-alpha.0",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
10
package.json
10
package.json
|
@ -6,8 +6,8 @@
|
|||
"@nx/js": "16.4.3",
|
||||
"@rollup/plugin-json": "^4.0.2",
|
||||
"@typescript-eslint/parser": "5.45.0",
|
||||
"esbuild": "^0.17.18",
|
||||
"esbuild-node-externals": "^1.7.0",
|
||||
"esbuild": "^0.18.17",
|
||||
"esbuild-node-externals": "^1.8.0",
|
||||
"eslint": "^8.44.0",
|
||||
"eslint-plugin-cypress": "^2.11.3",
|
||||
"husky": "^8.0.3",
|
||||
|
@ -51,9 +51,9 @@
|
|||
"kill-builder": "kill-port 3000",
|
||||
"kill-server": "kill-port 4001 4002",
|
||||
"kill-all": "yarn run kill-builder && yarn run kill-server",
|
||||
"dev": "yarn run kill-all && lerna run --stream dev:builder --stream",
|
||||
"dev:noserver": "yarn run kill-builder && lerna run --stream dev:stack:up && lerna run --stream dev:builder --ignore @budibase/backend-core --ignore @budibase/server --ignore @budibase/worker",
|
||||
"dev:server": "yarn run kill-server && lerna run --stream dev:builder --scope @budibase/worker --scope @budibase/server",
|
||||
"dev": "yarn run kill-all && yarn nx run-many --target=dev:builder",
|
||||
"dev:noserver": "yarn run kill-builder && lerna run --stream dev:stack:up && yarn nx run-many --target=dev:builder --exclude=@budibase/backend-core,@budibase/server,@budibase/worker",
|
||||
"dev:server": "yarn run kill-server && yarn nx run-many --target=dev:builder --projects=@budibase/worker,@budibase/server",
|
||||
"dev:built": "yarn run kill-all && cd packages/server && yarn dev:stack:up && cd ../../ && lerna run --stream dev:built",
|
||||
"dev:docker": "yarn build:docker:pre && docker-compose -f hosting/docker-compose.build.yaml -f hosting/docker-compose.dev.yaml --env-file hosting/.env up --build --scale proxy-service=0",
|
||||
"test": "lerna run --stream test --stream",
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
export const CONSTANT_INTERNAL_ROW_COLS = [
|
||||
"_id",
|
||||
"_rev",
|
||||
"type",
|
||||
"createdAt",
|
||||
"updatedAt",
|
||||
"tableId",
|
||||
] as const
|
||||
|
||||
export const CONSTANT_EXTERNAL_ROW_COLS = ["_id", "_rev", "tableId"] as const
|
|
@ -2,3 +2,4 @@ export * from "./connections"
|
|||
export * from "./DatabaseImpl"
|
||||
export * from "./utils"
|
||||
export { init, getPouch, getPouchDB, closePouchDB } from "./pouchDB"
|
||||
export * from "../constants"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { db } from "../../../src"
|
||||
|
||||
export function expectFunctionWasCalledTimesWith(
|
||||
jestFunction: any,
|
||||
times: number,
|
||||
|
@ -7,3 +9,22 @@ export function expectFunctionWasCalledTimesWith(
|
|||
jestFunction.mock.calls.filter((call: any) => call[0] === argument).length
|
||||
).toBe(times)
|
||||
}
|
||||
|
||||
export const expectAnyInternalColsAttributes: {
|
||||
[K in (typeof db.CONSTANT_INTERNAL_ROW_COLS)[number]]: any
|
||||
} = {
|
||||
tableId: expect.anything(),
|
||||
type: expect.anything(),
|
||||
_id: expect.anything(),
|
||||
_rev: expect.anything(),
|
||||
createdAt: expect.anything(),
|
||||
updatedAt: expect.anything(),
|
||||
}
|
||||
|
||||
export const expectAnyExternalColsAttributes: {
|
||||
[K in (typeof db.CONSTANT_EXTERNAL_ROW_COLS)[number]]: any
|
||||
} = {
|
||||
tableId: expect.anything(),
|
||||
_id: expect.anything(),
|
||||
_rev: expect.anything(),
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ export default function positionDropdown(element, opts) {
|
|||
|
||||
// Apply styles
|
||||
Object.entries(styles).forEach(([style, value]) => {
|
||||
if (value) {
|
||||
if (value != null) {
|
||||
element.style[style] = `${value.toFixed(0)}px`
|
||||
} else {
|
||||
element.style[style] = null
|
||||
|
|
|
@ -491,6 +491,7 @@ const getSelectedRowsBindings = asset => {
|
|||
readableBinding: `${table._instanceName}.Selected rows`,
|
||||
category: "Selected rows",
|
||||
icon: "ViewRow",
|
||||
display: { name: table._instanceName },
|
||||
}))
|
||||
)
|
||||
|
||||
|
@ -506,6 +507,7 @@ const getSelectedRowsBindings = asset => {
|
|||
)}.${makePropSafe("selectedRows")}`,
|
||||
readableBinding: `${block._instanceName}.Selected rows`,
|
||||
category: "Selected rows",
|
||||
display: { name: block._instanceName },
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { datasources, tables } from "stores/backend"
|
||||
import { datasources, tables, integrations } from "stores/backend"
|
||||
import EditRolesButton from "./buttons/EditRolesButton.svelte"
|
||||
import { TableNames } from "constants"
|
||||
import { Grid } from "@budibase/frontend-core"
|
||||
|
@ -31,6 +31,17 @@
|
|||
tableId: id,
|
||||
}
|
||||
|
||||
$: datasource = $datasources.list.find(datasource => {
|
||||
return datasource._id === $tables.selected?.sourceId
|
||||
})
|
||||
|
||||
$: relationshipsEnabled = relationshipSupport(datasource)
|
||||
|
||||
const relationshipSupport = datasource => {
|
||||
const integration = $integrations[datasource?.source]
|
||||
return !isInternal && integration?.relationships !== false
|
||||
}
|
||||
|
||||
const handleGridTableUpdate = async e => {
|
||||
tables.replaceTable(id, e.detail)
|
||||
|
||||
|
@ -62,7 +73,7 @@
|
|||
<GridCreateViewButton />
|
||||
{/if}
|
||||
<GridManageAccessButton />
|
||||
{#if !isInternal}
|
||||
{#if relationshipsEnabled}
|
||||
<GridRelationshipButton />
|
||||
{/if}
|
||||
{#if isUsersTable}
|
||||
|
|
|
@ -341,7 +341,7 @@
|
|||
</Tab>
|
||||
{/if}
|
||||
<div class="drawer-actions">
|
||||
{#if typeof drawerActions.hide === "function" && drawerActions.headless}
|
||||
{#if typeof drawerActions?.hide === "function" && drawerActions?.headless}
|
||||
<Button
|
||||
secondary
|
||||
quiet
|
||||
|
@ -352,7 +352,7 @@
|
|||
Cancel
|
||||
</Button>
|
||||
{/if}
|
||||
{#if typeof bindingDrawerActions?.save === "function" && drawerActions.headless}
|
||||
{#if typeof bindingDrawerActions?.save === "function" && drawerActions?.headless}
|
||||
<Button
|
||||
cta
|
||||
disabled={!valid}
|
||||
|
|
|
@ -206,6 +206,11 @@
|
|||
|
||||
return allBindings
|
||||
}
|
||||
|
||||
const toDisplay = eventKey => {
|
||||
const type = actionTypes.find(action => action.name == eventKey)
|
||||
return type?.displayName || type?.name
|
||||
}
|
||||
</script>
|
||||
|
||||
<DrawerContent>
|
||||
|
@ -231,7 +236,9 @@
|
|||
<ul>
|
||||
{#each category as actionType}
|
||||
<li on:click={onAddAction(actionType)}>
|
||||
<span class="action-name">{actionType.name}</span>
|
||||
<span class="action-name">
|
||||
{actionType.displayName || actionType.name}
|
||||
</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
@ -262,7 +269,7 @@
|
|||
>
|
||||
<Icon name="DragHandle" size="XL" />
|
||||
<div class="action-header">
|
||||
{index + 1}. {action[EVENT_TYPE_KEY]}
|
||||
{index + 1}. {toDisplay(action[EVENT_TYPE_KEY])}
|
||||
</div>
|
||||
<Icon
|
||||
name="Close"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Select, Label, Checkbox, Input } from "@budibase/bbui"
|
||||
import { Select, Label, Checkbox, Input, Body } from "@budibase/bbui"
|
||||
import { tables } from "stores/backend"
|
||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||
|
||||
|
@ -10,47 +10,59 @@
|
|||
</script>
|
||||
|
||||
<div class="root">
|
||||
<Label>Table</Label>
|
||||
<Select
|
||||
bind:value={parameters.tableId}
|
||||
options={tableOptions}
|
||||
getOptionLabel={table => table.name}
|
||||
getOptionValue={table => table._id}
|
||||
/>
|
||||
|
||||
<Label small>Row ID</Label>
|
||||
<DrawerBindableInput
|
||||
{bindings}
|
||||
title="Row ID to delete"
|
||||
value={parameters.rowId}
|
||||
on:change={value => (parameters.rowId = value.detail)}
|
||||
/>
|
||||
|
||||
<Label small />
|
||||
<Checkbox
|
||||
text="Do not display default notification"
|
||||
bind:value={parameters.notificationOverride}
|
||||
/>
|
||||
<br />
|
||||
<Checkbox text="Require confirmation" bind:value={parameters.confirm} />
|
||||
|
||||
{#if parameters.confirm}
|
||||
<Label small>Confirm text</Label>
|
||||
<Input
|
||||
placeholder="Are you sure you want to delete this row?"
|
||||
bind:value={parameters.confirmText}
|
||||
<Body size="small">Please specify one or more rows to delete.</Body>
|
||||
<div class="params">
|
||||
<Label>Table</Label>
|
||||
<Select
|
||||
bind:value={parameters.tableId}
|
||||
options={tableOptions}
|
||||
getOptionLabel={table => table.name}
|
||||
getOptionValue={table => table._id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<Label small>Row IDs</Label>
|
||||
<DrawerBindableInput
|
||||
{bindings}
|
||||
title="Rows to delete"
|
||||
value={parameters.rowId}
|
||||
on:change={value => (parameters.rowId = value.detail)}
|
||||
/>
|
||||
|
||||
<Label small />
|
||||
<Checkbox
|
||||
text="Do not display default notification"
|
||||
bind:value={parameters.notificationOverride}
|
||||
/>
|
||||
<br />
|
||||
<Checkbox text="Require confirmation" bind:value={parameters.confirm} />
|
||||
|
||||
{#if parameters.confirm}
|
||||
<Label small>Confirm text</Label>
|
||||
<Input
|
||||
placeholder="Are you sure you want to delete?"
|
||||
bind:value={parameters.confirmText}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.params {
|
||||
display: grid;
|
||||
column-gap: var(--spacing-l);
|
||||
row-gap: var(--spacing-s);
|
||||
grid-template-columns: 60px 1fr;
|
||||
align-items: center;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -73,9 +73,12 @@
|
|||
{#if query?.parameters?.length > 0}
|
||||
<div class="params">
|
||||
<BindingBuilder
|
||||
bind:customParams={parameters.queryParams}
|
||||
customParams={parameters.queryParams}
|
||||
queryBindings={query.parameters}
|
||||
bind:bindings
|
||||
on:change={v => {
|
||||
parameters.queryParams = { ...v.detail }
|
||||
}}
|
||||
/>
|
||||
<IntegrationQueryEditor
|
||||
height={200}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Delete Row",
|
||||
"displayName": "Delete Rows",
|
||||
"type": "data",
|
||||
"component": "DeleteRow"
|
||||
},
|
||||
|
|
|
@ -143,13 +143,12 @@
|
|||
}
|
||||
|
||||
const openQueryParamsDrawer = () => {
|
||||
tmpQueryParams = value.queryParams
|
||||
tmpQueryParams = { ...value.queryParams }
|
||||
drawer.show()
|
||||
}
|
||||
|
||||
const getQueryValue = queries => {
|
||||
value = queries.find(q => q._id === value._id) || value
|
||||
return value
|
||||
return queries.find(q => q._id === value._id) || value
|
||||
}
|
||||
|
||||
const saveQueryParams = () => {
|
||||
|
@ -176,7 +175,10 @@
|
|||
<Layout noPadding gap="XS">
|
||||
{#if getQueryParams(value).length > 0}
|
||||
<BindingBuilder
|
||||
bind:customParams={tmpQueryParams}
|
||||
customParams={tmpQueryParams}
|
||||
on:change={v => {
|
||||
tmpQueryParams = { ...v.detail }
|
||||
}}
|
||||
queryBindings={getQueryParams(value)}
|
||||
bind:bindings
|
||||
/>
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
runtimeToReadableBinding,
|
||||
} from "builderStore/dataBinding"
|
||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let bindable = true
|
||||
export let queryBindings = []
|
||||
|
@ -20,7 +23,10 @@
|
|||
// The readable binding in the UI gets converted to a UUID value that the client understands
|
||||
// for parsing, then converted back so we can display it the readable form in the UI
|
||||
function onBindingChange(param, valueToParse) {
|
||||
customParams[param] = readableToRuntimeBinding(bindings, valueToParse)
|
||||
dispatch("change", {
|
||||
...customParams,
|
||||
[param]: readableToRuntimeBinding(bindings, valueToParse),
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
Tab,
|
||||
Modal,
|
||||
ModalContent,
|
||||
notifications,
|
||||
Divider,
|
||||
} from "@budibase/bbui"
|
||||
import { notifications, Divider } from "@budibase/bbui"
|
||||
import ExtraQueryConfig from "./ExtraQueryConfig.svelte"
|
||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||
import ExternalDataSourceTable from "components/backend/DataTable/ExternalDataSourceTable.svelte"
|
||||
|
@ -28,6 +29,7 @@
|
|||
import KeyValueBuilder from "./KeyValueBuilder.svelte"
|
||||
import { fieldsToSchema, schemaToFields } from "helpers/data/utils"
|
||||
import AccessLevelSelect from "./AccessLevelSelect.svelte"
|
||||
import { ValidQueryNameRegex } from "@budibase/shared-core"
|
||||
|
||||
export let query
|
||||
|
||||
|
@ -47,6 +49,7 @@
|
|||
let saveModal
|
||||
let override = false
|
||||
let navigateTo = null
|
||||
let nameError = null
|
||||
|
||||
// seed the transformer
|
||||
if (query && !query.transformer) {
|
||||
|
@ -77,7 +80,7 @@
|
|||
$: queryConfig = integrationInfo?.query
|
||||
$: shouldShowQueryConfig = queryConfig && query.queryVerb
|
||||
$: readQuery = query.queryVerb === "read" || query.readable
|
||||
$: queryInvalid = !query.name || (readQuery && data.length === 0)
|
||||
$: queryInvalid = !query.name || nameError || (readQuery && data.length === 0)
|
||||
|
||||
//Cast field in query preview response to number if specified by schema
|
||||
$: {
|
||||
|
@ -139,9 +142,10 @@
|
|||
queryStr = JSON.stringify(query)
|
||||
}
|
||||
|
||||
notifications.success("Query saved successfully")
|
||||
return response
|
||||
} catch (error) {
|
||||
notifications.error("Error saving query")
|
||||
notifications.error(error.message || "Error saving query")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -183,8 +187,14 @@
|
|||
value={query.name}
|
||||
on:input={e => {
|
||||
let newValue = e.target.value || ""
|
||||
query.name = newValue.trim()
|
||||
if (newValue.match(ValidQueryNameRegex)) {
|
||||
query.name = newValue.trim()
|
||||
nameError = null
|
||||
} else {
|
||||
nameError = "Invalid query name"
|
||||
}
|
||||
}}
|
||||
error={nameError}
|
||||
/>
|
||||
</div>
|
||||
{#if queryConfig}
|
||||
|
@ -250,9 +260,9 @@
|
|||
size="L"
|
||||
/>
|
||||
</div>
|
||||
<Body size="S"
|
||||
>Add a JavaScript function to transform the query result.</Body
|
||||
>
|
||||
<Body size="S">
|
||||
Add a JavaScript function to transform the query result.
|
||||
</Body>
|
||||
<CodeMirrorEditor
|
||||
height={200}
|
||||
label="Transformer"
|
||||
|
@ -264,13 +274,12 @@
|
|||
</div>
|
||||
<div class="viewer-controls">
|
||||
<Heading size="S">Results</Heading>
|
||||
<ButtonGroup gap="XS">
|
||||
<ButtonGroup gap="S">
|
||||
<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}`)
|
||||
|
|
|
@ -47,6 +47,14 @@
|
|||
)
|
||||
}
|
||||
|
||||
// If the data changes, double check that the selected elements are still present.
|
||||
$: if (data) {
|
||||
let rowIds = data.map(row => row._id)
|
||||
if (rowIds.length) {
|
||||
selectedRows = selectedRows.filter(row => rowIds.includes(row._id))
|
||||
}
|
||||
}
|
||||
|
||||
const getFields = (schema, customColumns, showAutoColumns) => {
|
||||
// Check for an invalid column selection
|
||||
let invalid = false
|
||||
|
|
|
@ -102,12 +102,46 @@ const fetchRowHandler = async action => {
|
|||
}
|
||||
|
||||
const deleteRowHandler = async action => {
|
||||
const { tableId, revId, rowId, notificationOverride } = action.parameters
|
||||
if (tableId && rowId) {
|
||||
const { tableId, rowId: rowConfig, notificationOverride } = action.parameters
|
||||
|
||||
if (tableId && rowConfig) {
|
||||
try {
|
||||
await API.deleteRow({ tableId, rowId, revId })
|
||||
let requestConfig
|
||||
|
||||
let parsedRowConfig = []
|
||||
if (typeof rowConfig === "string") {
|
||||
try {
|
||||
parsedRowConfig = JSON.parse(rowConfig)
|
||||
} catch (e) {
|
||||
parsedRowConfig = rowConfig
|
||||
.split(",")
|
||||
.map(id => id.trim())
|
||||
.filter(id => id)
|
||||
}
|
||||
} else {
|
||||
parsedRowConfig = rowConfig
|
||||
}
|
||||
|
||||
if (
|
||||
typeof parsedRowConfig === "object" &&
|
||||
parsedRowConfig.constructor === Object
|
||||
) {
|
||||
requestConfig = [parsedRowConfig]
|
||||
} else if (Array.isArray(parsedRowConfig)) {
|
||||
requestConfig = parsedRowConfig
|
||||
}
|
||||
|
||||
if (!requestConfig.length) {
|
||||
notificationStore.actions.warning("No valid rows were supplied")
|
||||
return false
|
||||
}
|
||||
|
||||
const resp = await API.deleteRows({ tableId, rows: requestConfig })
|
||||
|
||||
if (!notificationOverride) {
|
||||
notificationStore.actions.success("Row deleted")
|
||||
notificationStore.actions.success(
|
||||
resp?.length == 1 ? "Row deleted" : `${resp.length} Rows deleted`
|
||||
)
|
||||
}
|
||||
|
||||
// Refresh related datasources
|
||||
|
@ -115,8 +149,10 @@ const deleteRowHandler = async action => {
|
|||
invalidateRelationships: true,
|
||||
})
|
||||
} catch (error) {
|
||||
// Abort next actions
|
||||
return false
|
||||
console.error(error)
|
||||
notificationStore.actions.error(
|
||||
"An error occurred while executing the query"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 347ee5326812c01ef07f0e744f691ab4823e185a
|
||||
Subproject commit a60183319f410d05aaa1c2f2718b772978b54d64
|
|
@ -183,6 +183,16 @@
|
|||
},
|
||||
"nx": {
|
||||
"targets": {
|
||||
"dev:builder": {
|
||||
"dependsOn": [
|
||||
{
|
||||
"projects": [
|
||||
"@budibase/backend-core"
|
||||
],
|
||||
"target": "build"
|
||||
}
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": [
|
||||
{
|
||||
|
|
|
@ -43,6 +43,12 @@ CREATE TABLE test.table1 (
|
|||
id SERIAL PRIMARY KEY,
|
||||
Name varchar(255)
|
||||
);
|
||||
CREATE TABLE CompositeTable (
|
||||
KeyPartOne varchar(128),
|
||||
KeyPartTwo varchar(128),
|
||||
Name varchar(255),
|
||||
PRIMARY KEY (KeyPartOne, KeyPartTwo)
|
||||
);
|
||||
INSERT INTO Persons (FirstName, LastName, Address, City, Type) VALUES ('Mike', 'Hughes', '123 Fake Street', 'Belfast', 'qa');
|
||||
INSERT INTO Persons (FirstName, LastName, Address, City, Type) VALUES ('John', 'Smith', '64 Updown Road', 'Dublin', 'programmer');
|
||||
INSERT INTO Tasks (ExecutorID, QaID, TaskName, Completed) VALUES (1, 2, 'assembling', TRUE);
|
||||
|
@ -55,3 +61,6 @@ INSERT INTO Products_Tasks (ProductID, TaskID) VALUES (2, 1);
|
|||
INSERT INTO Products_Tasks (ProductID, TaskID) VALUES (3, 1);
|
||||
INSERT INTO Products_Tasks (ProductID, TaskID) VALUES (1, 2);
|
||||
INSERT INTO test.table1 (Name) VALUES ('Test');
|
||||
INSERT INTO CompositeTable (KeyPartOne, KeyPartTwo, Name) VALUES ('aaa', 'bbb', 'Michael');
|
||||
INSERT INTO CompositeTable (KeyPartOne, KeyPartTwo, Name) VALUES ('bbb', 'ccc', 'Andrew');
|
||||
INSERT INTO CompositeTable (KeyPartOne, KeyPartTwo, Name) VALUES ('ddd', '', 'OneKey');
|
||||
|
|
|
@ -5,7 +5,7 @@ import { convertBookmark } from "../../../utilities"
|
|||
|
||||
// makes sure that the user doesn't need to pass in the type, tableId or _id params for
|
||||
// the call to be correct
|
||||
function fixRow(row: Row, params: any) {
|
||||
export function fixRow(row: Row, params: any) {
|
||||
if (!params || !row) {
|
||||
return row
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import { events, context, utils, constants } from "@budibase/backend-core"
|
|||
import sdk from "../../../sdk"
|
||||
import { QueryEvent } from "../../../threads/definitions"
|
||||
import { Query } from "@budibase/types"
|
||||
import { ValidQueryNameRegex } from "@budibase/shared-core"
|
||||
|
||||
const Runner = new Thread(ThreadType.QUERY, {
|
||||
timeoutMs: env.QUERY_THREAD_TIMEOUT || 10000,
|
||||
|
@ -76,6 +77,11 @@ export async function save(ctx: any) {
|
|||
const db = context.getAppDB()
|
||||
const query = ctx.request.body
|
||||
|
||||
// Validate query name
|
||||
if (!query?.name.match(ValidQueryNameRegex)) {
|
||||
ctx.throw(400, "Invalid query name")
|
||||
}
|
||||
|
||||
const datasource = await sdk.datasources.get(query.datasourceId)
|
||||
|
||||
let eventFn
|
||||
|
|
|
@ -163,7 +163,7 @@ function generateIdForRow(
|
|||
fieldName: field,
|
||||
isLinked,
|
||||
})
|
||||
if (fieldValue) {
|
||||
if (fieldValue != null) {
|
||||
idParts.push(fieldValue)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@ import * as external from "./external"
|
|||
import { isExternalTable } from "../../../integrations/utils"
|
||||
import {
|
||||
Ctx,
|
||||
UserCtx,
|
||||
DeleteRowRequest,
|
||||
DeleteRow,
|
||||
DeleteRows,
|
||||
Row,
|
||||
SearchResponse,
|
||||
SortOrder,
|
||||
SortType,
|
||||
|
@ -11,6 +16,8 @@ import {
|
|||
} from "@budibase/types"
|
||||
import * as utils from "./utils"
|
||||
import { gridSocket } from "../../../websockets"
|
||||
import { addRev } from "../public/utils"
|
||||
import { fixRow } from "../public/rows"
|
||||
import sdk from "../../../sdk"
|
||||
import * as exporters from "../view/exporters"
|
||||
import { apiFileReturn } from "../../../utilities/fileSystem"
|
||||
|
@ -104,35 +111,83 @@ export async function find(ctx: any) {
|
|||
})
|
||||
}
|
||||
|
||||
export async function destroy(ctx: any) {
|
||||
const appId = ctx.appId
|
||||
const inputs = ctx.request.body
|
||||
function isDeleteRows(input: any): input is DeleteRows {
|
||||
return input.rows !== undefined && Array.isArray(input.rows)
|
||||
}
|
||||
|
||||
function isDeleteRow(input: any): input is DeleteRow {
|
||||
return input._id !== undefined
|
||||
}
|
||||
|
||||
async function processDeleteRowsRequest(ctx: UserCtx<DeleteRowRequest>) {
|
||||
let request = ctx.request.body as DeleteRows
|
||||
const tableId = utils.getTableId(ctx)
|
||||
let response, row
|
||||
if (inputs.rows) {
|
||||
let { rows } = await quotas.addQuery<any>(
|
||||
() => pickApi(tableId).bulkDestroy(ctx),
|
||||
{
|
||||
datasourceId: tableId,
|
||||
}
|
||||
)
|
||||
await quotas.removeRows(rows.length)
|
||||
response = rows
|
||||
for (let row of rows) {
|
||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
||||
gridSocket?.emitRowDeletion(ctx, row._id!)
|
||||
}
|
||||
} else {
|
||||
let resp = await quotas.addQuery<any>(() => pickApi(tableId).destroy(ctx), {
|
||||
|
||||
const processedRows = request.rows.map(row => {
|
||||
let processedRow: Row = typeof row == "string" ? { _id: row } : row
|
||||
return !processedRow._rev
|
||||
? addRev(fixRow(processedRow, ctx.params), tableId)
|
||||
: fixRow(processedRow, ctx.params)
|
||||
})
|
||||
|
||||
return await Promise.all(processedRows)
|
||||
}
|
||||
|
||||
async function deleteRows(ctx: UserCtx<DeleteRowRequest>) {
|
||||
const tableId = utils.getTableId(ctx)
|
||||
const appId = ctx.appId
|
||||
|
||||
let deleteRequest = ctx.request.body as DeleteRows
|
||||
|
||||
const rowDeletes: Row[] = await processDeleteRowsRequest(ctx)
|
||||
deleteRequest.rows = rowDeletes
|
||||
|
||||
let { rows } = await quotas.addQuery<any>(
|
||||
() => pickApi(tableId).bulkDestroy(ctx),
|
||||
{
|
||||
datasourceId: tableId,
|
||||
})
|
||||
await quotas.removeRow()
|
||||
response = resp.response
|
||||
row = resp.row
|
||||
}
|
||||
)
|
||||
await quotas.removeRows(rows.length)
|
||||
|
||||
for (let row of rows) {
|
||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
||||
gridSocket?.emitRowDeletion(ctx, row._id!)
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
async function deleteRow(ctx: UserCtx<DeleteRowRequest>) {
|
||||
const appId = ctx.appId
|
||||
const tableId = utils.getTableId(ctx)
|
||||
|
||||
let resp = await quotas.addQuery<any>(() => pickApi(tableId).destroy(ctx), {
|
||||
datasourceId: tableId,
|
||||
})
|
||||
await quotas.removeRow()
|
||||
|
||||
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, resp.row)
|
||||
gridSocket?.emitRowDeletion(ctx, resp.row._id)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
export async function destroy(ctx: UserCtx<DeleteRowRequest>) {
|
||||
let response, row
|
||||
ctx.status = 200
|
||||
|
||||
if (isDeleteRows(ctx.request.body)) {
|
||||
response = await deleteRows(ctx)
|
||||
} else if (isDeleteRow(ctx.request.body)) {
|
||||
const deleteResp = await deleteRow(ctx)
|
||||
response = deleteResp.response
|
||||
row = deleteResp.row
|
||||
} else {
|
||||
ctx.status = 400
|
||||
response = { message: "Invalid delete rows request" }
|
||||
}
|
||||
|
||||
// for automations include the row that was deleted
|
||||
ctx.row = row || {}
|
||||
ctx.body = response
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import sdk from "../../../sdk"
|
||||
import { CreateViewRequest, Ctx, ViewResponse } from "@budibase/types"
|
||||
import {
|
||||
CreateViewRequest,
|
||||
Ctx,
|
||||
UpdateViewRequest,
|
||||
ViewResponse,
|
||||
} from "@budibase/types"
|
||||
|
||||
export async function create(ctx: Ctx<CreateViewRequest, ViewResponse>) {
|
||||
const view = ctx.request.body
|
||||
|
@ -12,6 +17,25 @@ export async function create(ctx: Ctx<CreateViewRequest, ViewResponse>) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function update(ctx: Ctx<UpdateViewRequest, ViewResponse>) {
|
||||
const view = ctx.request.body
|
||||
|
||||
if (view.version !== 2) {
|
||||
ctx.throw(400, "Only views V2 can be updated")
|
||||
}
|
||||
|
||||
if (ctx.params.viewId !== view.id) {
|
||||
ctx.throw(400, "View id does not match between the body and the uri path")
|
||||
}
|
||||
|
||||
const { tableId } = view
|
||||
|
||||
const result = await sdk.views.update(tableId, view)
|
||||
ctx.body = {
|
||||
data: result,
|
||||
}
|
||||
}
|
||||
|
||||
export async function remove(ctx: Ctx) {
|
||||
const { viewId } = ctx.params
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ tk.freeze(timestamp)
|
|||
import { outputProcessing } from "../../../utilities/rowProcessor"
|
||||
import * as setup from "./utilities"
|
||||
const { basicRow } = setup.structures
|
||||
import { context, tenancy } from "@budibase/backend-core"
|
||||
import { context, db, tenancy } from "@budibase/backend-core"
|
||||
import { quotas } from "@budibase/pro"
|
||||
import {
|
||||
QuotaUsageType,
|
||||
|
@ -17,7 +17,11 @@ import {
|
|||
SortType,
|
||||
SortOrder,
|
||||
} from "@budibase/types"
|
||||
import { generator, structures } from "@budibase/backend-core/tests"
|
||||
import {
|
||||
expectAnyInternalColsAttributes,
|
||||
generator,
|
||||
structures,
|
||||
} from "@budibase/backend-core/tests"
|
||||
|
||||
describe("/rows", () => {
|
||||
let request = setup.getRequest()
|
||||
|
@ -519,6 +523,81 @@ describe("/rows", () => {
|
|||
await assertRowUsage(rowUsage - 2)
|
||||
await assertQueryUsage(queryUsage + 1)
|
||||
})
|
||||
|
||||
it("should be able to delete a variety of row set types", async () => {
|
||||
const row1 = await config.createRow()
|
||||
const row2 = await config.createRow()
|
||||
const row3 = await config.createRow()
|
||||
const rowUsage = await getRowUsage()
|
||||
const queryUsage = await getQueryUsage()
|
||||
|
||||
const res = await request
|
||||
.delete(`/api/${table._id}/rows`)
|
||||
.send({
|
||||
rows: [row1, row2._id, { _id: row3._id }],
|
||||
})
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
|
||||
expect(res.body.length).toEqual(3)
|
||||
await loadRow(row1._id!, table._id!, 404)
|
||||
await assertRowUsage(rowUsage - 3)
|
||||
await assertQueryUsage(queryUsage + 1)
|
||||
})
|
||||
|
||||
it("should accept a valid row object and delete the row", async () => {
|
||||
const row1 = await config.createRow()
|
||||
const rowUsage = await getRowUsage()
|
||||
const queryUsage = await getQueryUsage()
|
||||
|
||||
const res = await request
|
||||
.delete(`/api/${table._id}/rows`)
|
||||
.send(row1)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
|
||||
expect(res.body.id).toEqual(row1._id)
|
||||
await loadRow(row1._id!, table._id!, 404)
|
||||
await assertRowUsage(rowUsage - 1)
|
||||
await assertQueryUsage(queryUsage + 1)
|
||||
})
|
||||
|
||||
it("Should ignore malformed/invalid delete requests", async () => {
|
||||
const rowUsage = await getRowUsage()
|
||||
const queryUsage = await getQueryUsage()
|
||||
|
||||
const res = await request
|
||||
.delete(`/api/${table._id}/rows`)
|
||||
.send({ not: "valid" })
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(400)
|
||||
|
||||
expect(res.body.message).toEqual("Invalid delete rows request")
|
||||
|
||||
const res2 = await request
|
||||
.delete(`/api/${table._id}/rows`)
|
||||
.send({ rows: 123 })
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(400)
|
||||
|
||||
expect(res2.body.message).toEqual("Invalid delete rows request")
|
||||
|
||||
const res3 = await request
|
||||
.delete(`/api/${table._id}/rows`)
|
||||
.send("invalid")
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(400)
|
||||
|
||||
expect(res3.body.message).toEqual("Invalid delete rows request")
|
||||
|
||||
await assertRowUsage(rowUsage)
|
||||
await assertQueryUsage(queryUsage)
|
||||
})
|
||||
})
|
||||
|
||||
describe("fetchView", () => {
|
||||
|
@ -894,7 +973,7 @@ describe("/rows", () => {
|
|||
}
|
||||
)
|
||||
|
||||
it("when schema is defined, no other columns are returned", async () => {
|
||||
it("when schema is defined, defined columns and row attributes are returned", async () => {
|
||||
const table = await config.createTable(userTable())
|
||||
const rows = []
|
||||
for (let i = 0; i < 10; i++) {
|
||||
|
@ -914,7 +993,12 @@ describe("/rows", () => {
|
|||
|
||||
expect(response.body.rows).toHaveLength(10)
|
||||
expect(response.body.rows).toEqual(
|
||||
expect.arrayContaining(rows.map(r => ({ name: r.name })))
|
||||
expect.arrayContaining(
|
||||
rows.map(r => ({
|
||||
...expectAnyInternalColsAttributes,
|
||||
name: r.name,
|
||||
}))
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
@ -86,6 +86,124 @@ describe("/v2/views", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
let view: ViewV2
|
||||
|
||||
beforeEach(async () => {
|
||||
await config.createTable(priceTable())
|
||||
view = await config.api.viewV2.create({ name: "View A" })
|
||||
})
|
||||
|
||||
it("can update an existing view data", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update({
|
||||
...view,
|
||||
query: { equal: { newField: "thatValue" } },
|
||||
})
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual({
|
||||
...config.table,
|
||||
views: {
|
||||
[view.name]: {
|
||||
...view,
|
||||
query: { equal: { newField: "thatValue" } },
|
||||
schema: expect.anything(),
|
||||
},
|
||||
},
|
||||
_rev: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
})
|
||||
})
|
||||
|
||||
it("can update an existing view name", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update({ ...view, name: "View B" })
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual(
|
||||
expect.objectContaining({
|
||||
views: {
|
||||
"View B": { ...view, name: "View B", schema: expect.anything() },
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update an unexisting views nor edit ids", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update(
|
||||
{ ...view, id: generator.guid() },
|
||||
{ expectStatus: 404 }
|
||||
)
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual(
|
||||
expect.objectContaining({
|
||||
views: {
|
||||
[view.name]: {
|
||||
...view,
|
||||
schema: expect.anything(),
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update views with the wrong tableId", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update(
|
||||
{
|
||||
...view,
|
||||
tableId: generator.guid(),
|
||||
query: { equal: { newField: "thatValue" } },
|
||||
},
|
||||
{ expectStatus: 404 }
|
||||
)
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual(
|
||||
expect.objectContaining({
|
||||
views: {
|
||||
[view.name]: {
|
||||
...view,
|
||||
schema: expect.anything(),
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update views v1", async () => {
|
||||
const viewV1 = await config.createView()
|
||||
await config.api.viewV2.update(
|
||||
{
|
||||
...viewV1,
|
||||
},
|
||||
{
|
||||
expectStatus: 400,
|
||||
handleResponse: r => {
|
||||
expect(r.body).toEqual({
|
||||
message: "Only views V2 can be updated",
|
||||
status: 400,
|
||||
})
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update the a view with unmatching ids between url and body", async () => {
|
||||
const anotherView = await config.api.viewV2.create()
|
||||
const result = await config
|
||||
.request!.put(`/api/v2/views/${anotherView.id}`)
|
||||
.send(view)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(400)
|
||||
|
||||
expect(result.body).toEqual({
|
||||
message: "View id does not match between the body and the uri path",
|
||||
status: 400,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
let view: ViewV2
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@ router
|
|||
authorized(permissions.BUILDER),
|
||||
viewController.v2.create
|
||||
)
|
||||
.put(
|
||||
`/api/v2/views/:viewId`,
|
||||
authorized(permissions.BUILDER),
|
||||
viewController.v2.update
|
||||
)
|
||||
.delete(
|
||||
`/api/v2/views/:viewId`,
|
||||
authorized(permissions.BUILDER),
|
||||
|
|
|
@ -3,7 +3,6 @@ import { isExternalTable } from "../../../integrations/utils"
|
|||
import * as internal from "./search/internal"
|
||||
import * as external from "./search/external"
|
||||
import { Format } from "../../../api/controllers/view/exporters"
|
||||
import _ from "lodash"
|
||||
|
||||
export interface SearchParams {
|
||||
tableId: string
|
||||
|
@ -37,12 +36,7 @@ export async function search(options: SearchParams): Promise<{
|
|||
hasNextPage?: boolean
|
||||
bookmark?: number | null
|
||||
}> {
|
||||
const result = await pickApi(options.tableId).search(options)
|
||||
|
||||
if (options.fields) {
|
||||
result.rows = result.rows.map((r: any) => _.pick(r, options.fields!))
|
||||
}
|
||||
return result
|
||||
return pickApi(options.tableId).search(options)
|
||||
}
|
||||
|
||||
export interface ExportRowsParams {
|
||||
|
|
|
@ -14,7 +14,8 @@ import { breakExternalTableId } from "../../../../integrations/utils"
|
|||
import { cleanExportRows } from "../utils"
|
||||
import { utils } from "@budibase/shared-core"
|
||||
import { ExportRowsParams, ExportRowsResult, SearchParams } from "../search"
|
||||
import { HTTPError } from "@budibase/backend-core"
|
||||
import { HTTPError, db } from "@budibase/backend-core"
|
||||
import pick from "lodash/pick"
|
||||
|
||||
export async function search(options: SearchParams) {
|
||||
const { tableId } = options
|
||||
|
@ -48,7 +49,7 @@ export async function search(options: SearchParams) {
|
|||
}
|
||||
}
|
||||
try {
|
||||
const rows = (await handleRequest(Operation.READ, tableId, {
|
||||
let rows = (await handleRequest(Operation.READ, tableId, {
|
||||
filters: query,
|
||||
sort,
|
||||
paginate: paginateObj as PaginationJson,
|
||||
|
@ -67,6 +68,12 @@ export async function search(options: SearchParams) {
|
|||
})) as Row[]
|
||||
hasNextPage = nextRows.length > 0
|
||||
}
|
||||
|
||||
if (options.fields) {
|
||||
const fields = [...options.fields, ...db.CONSTANT_EXTERNAL_ROW_COLS]
|
||||
rows = rows.map((r: any) => pick(r, fields))
|
||||
}
|
||||
|
||||
// need wrapper object for bookmarks etc when paginating
|
||||
return { rows, hasNextPage, bookmark: bookmark && bookmark + 1 }
|
||||
} catch (err: any) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
context,
|
||||
db,
|
||||
SearchParams as InternalSearchParams,
|
||||
} from "@budibase/backend-core"
|
||||
import env from "../../../../environment"
|
||||
|
@ -28,6 +29,7 @@ import {
|
|||
} from "../../../../api/controllers/view/utils"
|
||||
import sdk from "../../../../sdk"
|
||||
import { ExportRowsParams, ExportRowsResult, SearchParams } from "../search"
|
||||
import pick from "lodash/pick"
|
||||
|
||||
export async function search(options: SearchParams) {
|
||||
const { tableId } = options
|
||||
|
@ -72,6 +74,12 @@ export async function search(options: SearchParams) {
|
|||
response.rows = await getGlobalUsersFromMetadata(response.rows)
|
||||
}
|
||||
table = table || (await sdk.tables.getTable(tableId))
|
||||
|
||||
if (options.fields) {
|
||||
const fields = [...options.fields, ...db.CONSTANT_INTERNAL_ROW_COLS]
|
||||
response.rows = response.rows.map((r: any) => pick(r, fields))
|
||||
}
|
||||
|
||||
response.rows = await outputProcessing(table, response.rows)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
import { GenericContainer } from "testcontainers"
|
||||
|
||||
import { Datasource, FieldType, Row, SourceName, Table } from "@budibase/types"
|
||||
import TestConfiguration from "../../../../../tests/utilities/TestConfiguration"
|
||||
import { SearchParams } from "../../search"
|
||||
import { search } from "../external"
|
||||
import {
|
||||
expectAnyExternalColsAttributes,
|
||||
generator,
|
||||
} from "@budibase/backend-core/tests"
|
||||
|
||||
jest.unmock("mysql2/promise")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("external", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
let externalDatasource: Datasource
|
||||
|
||||
const tableData: Table = {
|
||||
name: generator.word(),
|
||||
type: "external",
|
||||
primary: ["id"],
|
||||
schema: {
|
||||
id: {
|
||||
name: "id",
|
||||
type: FieldType.AUTO,
|
||||
autocolumn: true,
|
||||
},
|
||||
name: {
|
||||
name: "name",
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
surname: {
|
||||
name: "surname",
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
age: {
|
||||
name: "age",
|
||||
type: FieldType.NUMBER,
|
||||
},
|
||||
address: {
|
||||
name: "address",
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
const container = await new GenericContainer("mysql")
|
||||
.withExposedPorts(3306)
|
||||
.withEnv("MYSQL_ROOT_PASSWORD", "admin")
|
||||
.withEnv("MYSQL_DATABASE", "db")
|
||||
.withEnv("MYSQL_USER", "user")
|
||||
.withEnv("MYSQL_PASSWORD", "password")
|
||||
.start()
|
||||
|
||||
const host = container.getContainerIpAddress()
|
||||
const port = container.getMappedPort(3306)
|
||||
|
||||
await config.init()
|
||||
|
||||
externalDatasource = await config.createDatasource({
|
||||
datasource: {
|
||||
type: "datasource",
|
||||
name: "Test",
|
||||
source: SourceName.MYSQL,
|
||||
plus: true,
|
||||
config: {
|
||||
host,
|
||||
port,
|
||||
user: "user",
|
||||
database: "db",
|
||||
password: "password",
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe("search", () => {
|
||||
const rows: Row[] = []
|
||||
beforeAll(async () => {
|
||||
const table = await config.createTable({
|
||||
...tableData,
|
||||
sourceId: externalDatasource._id,
|
||||
})
|
||||
for (let i = 0; i < 10; i++) {
|
||||
rows.push(
|
||||
await config.createRow({
|
||||
tableId: table._id,
|
||||
name: generator.first(),
|
||||
surname: generator.last(),
|
||||
age: generator.age(),
|
||||
address: generator.address(),
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("default search returns all the data", async () => {
|
||||
await config.doInContext(config.appId, async () => {
|
||||
const tableId = config.table!._id!
|
||||
|
||||
const searchParams: SearchParams = {
|
||||
tableId,
|
||||
query: {},
|
||||
}
|
||||
const result = await search(searchParams)
|
||||
|
||||
expect(result.rows).toHaveLength(10)
|
||||
expect(result.rows).toEqual(
|
||||
expect.arrayContaining(rows.map(r => expect.objectContaining(r)))
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("querying by fields will always return data attribute columns", async () => {
|
||||
await config.doInContext(config.appId, async () => {
|
||||
const tableId = config.table!._id!
|
||||
|
||||
const searchParams: SearchParams = {
|
||||
tableId,
|
||||
query: {},
|
||||
fields: ["name", "age"],
|
||||
}
|
||||
const result = await search(searchParams)
|
||||
|
||||
expect(result.rows).toHaveLength(10)
|
||||
expect(result.rows).toEqual(
|
||||
expect.arrayContaining(
|
||||
rows.map(r => ({
|
||||
...expectAnyExternalColsAttributes,
|
||||
name: r.name,
|
||||
age: r.age,
|
||||
}))
|
||||
)
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,109 @@
|
|||
import { FieldType, Row, Table } from "@budibase/types"
|
||||
import TestConfiguration from "../../../../../tests/utilities/TestConfiguration"
|
||||
import { SearchParams } from "../../search"
|
||||
import { search } from "../internal"
|
||||
import {
|
||||
expectAnyInternalColsAttributes,
|
||||
generator,
|
||||
} from "@budibase/backend-core/tests"
|
||||
|
||||
describe("internal", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
const tableData: Table = {
|
||||
name: generator.word(),
|
||||
type: "table",
|
||||
schema: {
|
||||
name: {
|
||||
name: "name",
|
||||
type: FieldType.STRING,
|
||||
constraints: {
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
},
|
||||
surname: {
|
||||
name: "surname",
|
||||
type: FieldType.STRING,
|
||||
constraints: {
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
},
|
||||
age: {
|
||||
name: "age",
|
||||
type: FieldType.NUMBER,
|
||||
constraints: {
|
||||
type: FieldType.NUMBER,
|
||||
},
|
||||
},
|
||||
address: {
|
||||
name: "address",
|
||||
type: FieldType.STRING,
|
||||
constraints: {
|
||||
type: FieldType.STRING,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.init()
|
||||
})
|
||||
|
||||
describe("search", () => {
|
||||
const rows: Row[] = []
|
||||
beforeAll(async () => {
|
||||
await config.createTable(tableData)
|
||||
for (let i = 0; i < 10; i++) {
|
||||
rows.push(
|
||||
await config.createRow({
|
||||
name: generator.first(),
|
||||
surname: generator.last(),
|
||||
age: generator.age(),
|
||||
address: generator.address(),
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("default search returns all the data", async () => {
|
||||
await config.doInContext(config.appId, async () => {
|
||||
const tableId = config.table!._id!
|
||||
|
||||
const searchParams: SearchParams = {
|
||||
tableId,
|
||||
query: {},
|
||||
}
|
||||
const result = await search(searchParams)
|
||||
|
||||
expect(result.rows).toHaveLength(10)
|
||||
expect(result.rows).toEqual(
|
||||
expect.arrayContaining(rows.map(r => expect.objectContaining(r)))
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("querying by fields will always return data attribute columns", async () => {
|
||||
await config.doInContext(config.appId, async () => {
|
||||
const tableId = config.table!._id!
|
||||
|
||||
const searchParams: SearchParams = {
|
||||
tableId,
|
||||
query: {},
|
||||
fields: ["name", "age"],
|
||||
}
|
||||
const result = await search(searchParams)
|
||||
|
||||
expect(result.rows).toHaveLength(10)
|
||||
expect(result.rows).toEqual(
|
||||
expect.arrayContaining(
|
||||
rows.map(r => ({
|
||||
...expectAnyInternalColsAttributes,
|
||||
name: r.name,
|
||||
age: r.age,
|
||||
}))
|
||||
)
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -33,6 +33,24 @@ export async function create(
|
|||
return view
|
||||
}
|
||||
|
||||
export async function update(tableId: string, view: ViewV2): Promise<ViewV2> {
|
||||
const db = context.getAppDB()
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
table.views ??= {}
|
||||
|
||||
const existingView = Object.values(table.views).find(
|
||||
v => isV2(v) && v.id === view.id
|
||||
)
|
||||
if (!existingView) {
|
||||
throw new HTTPError(`View ${view.id} not found in table ${tableId}`, 404)
|
||||
}
|
||||
|
||||
delete table.views[existingView.name]
|
||||
table.views[view.name] = view
|
||||
await db.put(table)
|
||||
return view
|
||||
}
|
||||
|
||||
export function isV2(view: View | ViewV2): view is ViewV2 {
|
||||
return (view as ViewV2).version === 2
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { SortOrder, SortType, ViewV2 } from "@budibase/types"
|
||||
import { CreateViewRequest, SortOrder, SortType, ViewV2 } from "@budibase/types"
|
||||
import TestConfiguration from "../TestConfiguration"
|
||||
import { TestAPI } from "./base"
|
||||
import { generator } from "@budibase/backend-core/tests"
|
||||
import { Response } from "superagent"
|
||||
|
||||
export class ViewV2API extends TestAPI {
|
||||
constructor(config: TestConfiguration) {
|
||||
|
@ -9,7 +10,7 @@ export class ViewV2API extends TestAPI {
|
|||
}
|
||||
|
||||
create = async (
|
||||
viewData?: Partial<ViewV2>,
|
||||
viewData?: Partial<CreateViewRequest>,
|
||||
{ expectStatus } = { expectStatus: 201 }
|
||||
): Promise<ViewV2> => {
|
||||
let tableId = viewData?.tableId
|
||||
|
@ -31,6 +32,29 @@ export class ViewV2API extends TestAPI {
|
|||
return result.body.data as ViewV2
|
||||
}
|
||||
|
||||
update = async (
|
||||
view: ViewV2,
|
||||
{
|
||||
expectStatus,
|
||||
handleResponse,
|
||||
}: {
|
||||
expectStatus: number
|
||||
handleResponse?: (response: Response) => void
|
||||
} = { expectStatus: 200 }
|
||||
): Promise<ViewV2> => {
|
||||
const result = await this.request
|
||||
.put(`/api/v2/views/${view.id}`)
|
||||
.send(view)
|
||||
.set(this.config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(expectStatus)
|
||||
|
||||
if (handleResponse) {
|
||||
handleResponse(result)
|
||||
}
|
||||
return result.body.data as ViewV2
|
||||
}
|
||||
|
||||
delete = async (viewId: string, { expectStatus } = { expectStatus: 204 }) => {
|
||||
return this.request
|
||||
.delete(`/api/v2/views/${viewId}`)
|
||||
|
|
|
@ -94,4 +94,5 @@ export enum BuilderSocketEvent {
|
|||
}
|
||||
|
||||
export const SocketSessionTTL = 60
|
||||
export const ValidQueryNameRegex = /^[^()]*$/
|
||||
export const ValidColumnNameRegex = /^[_a-zA-Z0-9\s]*$/g
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export * from "./backup"
|
||||
export * from "./datasource"
|
||||
export * from "./row"
|
||||
export * from "./view"
|
||||
export * from "./rows"
|
||||
export * from "./table"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { Row } from "../../../documents/app/row"
|
||||
|
||||
export interface DeleteRows {
|
||||
rows: (Row | string)[]
|
||||
}
|
||||
|
||||
export interface DeleteRow {
|
||||
_id: string
|
||||
}
|
||||
|
||||
export type DeleteRowRequest = DeleteRows | DeleteRow
|
|
@ -5,3 +5,5 @@ export interface ViewResponse {
|
|||
}
|
||||
|
||||
export type CreateViewRequest = Omit<ViewV2, "version" | "id">
|
||||
|
||||
export type UpdateViewRequest = ViewV2
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
const actual = jest.requireActual("@budibase/pro")
|
||||
const pro = {
|
||||
...actual,
|
||||
features: {
|
||||
...actual.features,
|
||||
isSSOEnforced: jest.fn(),
|
||||
},
|
||||
licensing: {
|
||||
keys: {
|
||||
activateLicenseKey: jest.fn(),
|
||||
|
|
|
@ -104,5 +104,19 @@
|
|||
"typescript": "4.7.3",
|
||||
"update-dotenv": "1.1.1"
|
||||
},
|
||||
"nx": {
|
||||
"targets": {
|
||||
"dev:builder": {
|
||||
"dependsOn": [
|
||||
{
|
||||
"projects": [
|
||||
"@budibase/backend-core"
|
||||
],
|
||||
"target": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc"
|
||||
}
|
||||
|
|
|
@ -277,6 +277,7 @@ describe("configs", () => {
|
|||
describe("GET /api/global/configs/public", () => {
|
||||
it("should return the expected public settings", async () => {
|
||||
await saveSettingsConfig()
|
||||
mocks.pro.features.isSSOEnforced.mockResolvedValue(false)
|
||||
|
||||
const res = await config.api.configs.getPublicSettings()
|
||||
const body = res.body as GetPublicSettingsResponse
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
import { structures } from "../../../tests"
|
||||
import { mocks } from "@budibase/backend-core/tests"
|
||||
import { structures, mocks } from "../../../tests"
|
||||
import { env, context } from "@budibase/backend-core"
|
||||
import * as users from "../users"
|
||||
import { CloudAccount } from "@budibase/types"
|
||||
import { isPreventPasswordActions } from "../users"
|
||||
|
||||
jest.mock("@budibase/pro")
|
||||
import * as _pro from "@budibase/pro"
|
||||
const pro = jest.mocked(_pro, true)
|
||||
|
||||
describe("users", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
|
@ -56,7 +51,7 @@ describe("users", () => {
|
|||
it("returns true for all users when sso is enforced", async () => {
|
||||
await context.doInTenant(structures.tenant.id(), async () => {
|
||||
const user = structures.users.user()
|
||||
pro.features.isSSOEnforced.mockResolvedValueOnce(true)
|
||||
mocks.pro.features.isSSOEnforced.mockResolvedValueOnce(true)
|
||||
const result = await users.isPreventPasswordActions(user)
|
||||
expect(result).toBe(true)
|
||||
})
|
||||
|
|
|
@ -18,6 +18,20 @@ var argv = require("minimist")(process.argv.slice(2))
|
|||
function runBuild(entry, outfile) {
|
||||
const isDev = process.env.NODE_ENV !== "production"
|
||||
const tsconfig = argv["p"] || `tsconfig.build.json`
|
||||
const tsconfigPathPluginContent = JSON.parse(
|
||||
fs.readFileSync(tsconfig, "utf-8")
|
||||
)
|
||||
|
||||
if (!fs.existsSync("../pro/src")) {
|
||||
// If we don't have pro, we cannot bundle backend-core.
|
||||
// Otherwise, the main context will not be shared between libraries
|
||||
delete tsconfigPathPluginContent.compilerOptions.paths[
|
||||
"@budibase/backend-core"
|
||||
]
|
||||
delete tsconfigPathPluginContent.compilerOptions.paths[
|
||||
"@budibase/backend-core/*"
|
||||
]
|
||||
}
|
||||
|
||||
const sharedConfig = {
|
||||
entryPoints: [entry],
|
||||
|
@ -25,7 +39,10 @@ function runBuild(entry, outfile) {
|
|||
minify: !isDev,
|
||||
sourcemap: isDev,
|
||||
tsconfig,
|
||||
plugins: [TsconfigPathsPlugin({ tsconfig }), nodeExternalsPlugin()],
|
||||
plugins: [
|
||||
TsconfigPathsPlugin({ tsconfig: tsconfigPathPluginContent }),
|
||||
nodeExternalsPlugin(),
|
||||
],
|
||||
target: "node14",
|
||||
preserveSymlinks: true,
|
||||
loader: {
|
||||
|
|
240
yarn.lock
240
yarn.lock
|
@ -2977,10 +2977,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz#164b054d58551f8856285f386e1a8f45d9ba3a31"
|
||||
integrity sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==
|
||||
|
||||
"@esbuild/android-arm64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz#4aa8d8afcffb4458736ca9b32baa97d7cb5861ea"
|
||||
integrity sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==
|
||||
"@esbuild/android-arm64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz#9e00eb6865ed5f2dbe71a1e96f2c52254cd92903"
|
||||
integrity sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==
|
||||
|
||||
"@esbuild/android-arm@0.15.18":
|
||||
version "0.15.18"
|
||||
|
@ -2997,10 +2997,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.17.tgz#1b3b5a702a69b88deef342a7a80df4c894e4f065"
|
||||
integrity sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==
|
||||
|
||||
"@esbuild/android-arm@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.18.tgz#74a7e95af4ee212ebc9db9baa87c06a594f2a427"
|
||||
integrity sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==
|
||||
"@esbuild/android-arm@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.17.tgz#1aa013b65524f4e9f794946b415b32ae963a4618"
|
||||
integrity sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==
|
||||
|
||||
"@esbuild/android-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3012,10 +3012,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.17.tgz#6781527e3c4ea4de532b149d18a2167f06783e7f"
|
||||
integrity sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==
|
||||
|
||||
"@esbuild/android-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.18.tgz#1dcd13f201997c9fe0b204189d3a0da4eb4eb9b6"
|
||||
integrity sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==
|
||||
"@esbuild/android-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.17.tgz#c2bd0469b04ded352de011fae34a7a1d4dcecb79"
|
||||
integrity sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==
|
||||
|
||||
"@esbuild/darwin-arm64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3027,10 +3027,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz#c5961ef4d3c1cc80dafe905cc145b5a71d2ac196"
|
||||
integrity sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==
|
||||
|
||||
"@esbuild/darwin-arm64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz#444f3b961d4da7a89eb9bd35cfa4415141537c2a"
|
||||
integrity sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==
|
||||
"@esbuild/darwin-arm64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz#0c21a59cb5bd7a2cec66c7a42431dca42aefeddd"
|
||||
integrity sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==
|
||||
|
||||
"@esbuild/darwin-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3042,10 +3042,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz#b81f3259cc349691f67ae30f7b333a53899b3c20"
|
||||
integrity sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==
|
||||
|
||||
"@esbuild/darwin-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz#a6da308d0ac8a498c54d62e0b2bfb7119b22d315"
|
||||
integrity sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==
|
||||
"@esbuild/darwin-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz#92f8763ff6f97dff1c28a584da7b51b585e87a7b"
|
||||
integrity sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3057,10 +3057,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz#db846ad16cf916fd3acdda79b85ea867cb100e87"
|
||||
integrity sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz#b83122bb468889399d0d63475d5aea8d6829c2c2"
|
||||
integrity sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==
|
||||
"@esbuild/freebsd-arm64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz#934f74bdf4022e143ba2f21d421b50fd0fead8f8"
|
||||
integrity sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==
|
||||
|
||||
"@esbuild/freebsd-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3072,10 +3072,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz#4dd99acbaaba00949d509e7c144b1b6ef9e1815b"
|
||||
integrity sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==
|
||||
|
||||
"@esbuild/freebsd-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz#af59e0e03fcf7f221b34d4c5ab14094862c9c864"
|
||||
integrity sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==
|
||||
"@esbuild/freebsd-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz#16b6e90ba26ecc865eab71c56696258ec7f5d8bf"
|
||||
integrity sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==
|
||||
|
||||
"@esbuild/linux-arm64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3087,10 +3087,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz#7f9274140b2bb9f4230dbbfdf5dc2761215e30f6"
|
||||
integrity sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==
|
||||
|
||||
"@esbuild/linux-arm64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz#8551d72ba540c5bce4bab274a81c14ed01eafdcf"
|
||||
integrity sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==
|
||||
"@esbuild/linux-arm64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz#179a58e8d4c72116eb068563629349f8f4b48072"
|
||||
integrity sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==
|
||||
|
||||
"@esbuild/linux-arm@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3102,10 +3102,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz#5c8e44c2af056bb2147cf9ad13840220bcb8948b"
|
||||
integrity sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==
|
||||
|
||||
"@esbuild/linux-arm@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz#e09e76e526df4f665d4d2720d28ff87d15cdf639"
|
||||
integrity sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==
|
||||
"@esbuild/linux-arm@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz#9d78cf87a310ae9ed985c3915d5126578665c7b5"
|
||||
integrity sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==
|
||||
|
||||
"@esbuild/linux-ia32@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3117,10 +3117,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz#18a6b3798658be7f46e9873fa0c8d4bec54c9212"
|
||||
integrity sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==
|
||||
|
||||
"@esbuild/linux-ia32@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz#47878860ce4fe73a36fd8627f5647bcbbef38ba4"
|
||||
integrity sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==
|
||||
"@esbuild/linux-ia32@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz#6fed202602d37361bca376c9d113266a722a908c"
|
||||
integrity sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==
|
||||
|
||||
"@esbuild/linux-loong64@0.15.18":
|
||||
version "0.15.18"
|
||||
|
@ -3137,10 +3137,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz#a8d93514a47f7b4232716c9f02aeb630bae24c40"
|
||||
integrity sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==
|
||||
|
||||
"@esbuild/linux-loong64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz#3f8fbf5267556fc387d20b2e708ce115de5c967a"
|
||||
integrity sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==
|
||||
"@esbuild/linux-loong64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz#cdc60304830be1e74560c704bfd72cab8a02fa06"
|
||||
integrity sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3152,10 +3152,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz#4784efb1c3f0eac8133695fa89253d558149ee1b"
|
||||
integrity sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==
|
||||
|
||||
"@esbuild/linux-mips64el@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz#9d896d8f3c75f6c226cbeb840127462e37738226"
|
||||
integrity sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==
|
||||
"@esbuild/linux-mips64el@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz#c367b2855bb0902f5576291a2049812af2088086"
|
||||
integrity sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==
|
||||
|
||||
"@esbuild/linux-ppc64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3167,10 +3167,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz#ef6558ec5e5dd9dc16886343e0ccdb0699d70d3c"
|
||||
integrity sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==
|
||||
|
||||
"@esbuild/linux-ppc64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz#3d9deb60b2d32c9985bdc3e3be090d30b7472783"
|
||||
integrity sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==
|
||||
"@esbuild/linux-ppc64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz#7fdc0083d42d64a4651711ee0a7964f489242f45"
|
||||
integrity sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3182,10 +3182,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz#13a87fdbcb462c46809c9d16bcf79817ecf9ce6f"
|
||||
integrity sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==
|
||||
|
||||
"@esbuild/linux-riscv64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz#8a943cf13fd24ff7ed58aefb940ef178f93386bc"
|
||||
integrity sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==
|
||||
"@esbuild/linux-riscv64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz#5198a417f3f5b86b10c95647b8bc032e5b6b2b1c"
|
||||
integrity sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==
|
||||
|
||||
"@esbuild/linux-s390x@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3197,10 +3197,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz#83cb16d1d3ac0dca803b3f031ba3dc13f1ec7ade"
|
||||
integrity sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz#66cb01f4a06423e5496facabdce4f7cae7cb80e5"
|
||||
integrity sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==
|
||||
"@esbuild/linux-s390x@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz#7459c2fecdee2d582f0697fb76a4041f4ad1dd1e"
|
||||
integrity sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==
|
||||
|
||||
"@esbuild/linux-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3212,10 +3212,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz#7bc400568690b688e20a0c94b2faabdd89ae1a79"
|
||||
integrity sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==
|
||||
|
||||
"@esbuild/linux-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz#23c26050c6c5d1359c7b774823adc32b3883b6c9"
|
||||
integrity sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==
|
||||
"@esbuild/linux-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz#948cdbf46d81c81ebd7225a7633009bc56a4488c"
|
||||
integrity sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==
|
||||
|
||||
"@esbuild/netbsd-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3227,10 +3227,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz#1b5dcfbc4bfba80e67a11e9148de836af5b58b6c"
|
||||
integrity sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==
|
||||
|
||||
"@esbuild/netbsd-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz#789a203d3115a52633ff6504f8cbf757f15e703b"
|
||||
integrity sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==
|
||||
"@esbuild/netbsd-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz#6bb89668c0e093c5a575ded08e1d308bd7fd63e7"
|
||||
integrity sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==
|
||||
|
||||
"@esbuild/openbsd-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3242,10 +3242,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz#e275098902291149a5dcd012c9ea0796d6b7adff"
|
||||
integrity sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==
|
||||
|
||||
"@esbuild/openbsd-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz#d7b998a30878f8da40617a10af423f56f12a5e90"
|
||||
integrity sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==
|
||||
"@esbuild/openbsd-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz#abac2ae75fef820ef6c2c48da4666d092584c79d"
|
||||
integrity sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==
|
||||
|
||||
"@esbuild/sunos-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3257,10 +3257,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz#10603474866f64986c0370a2d4fe5a2bb7fee4f5"
|
||||
integrity sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==
|
||||
|
||||
"@esbuild/sunos-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz#ecad0736aa7dae07901ba273db9ef3d3e93df31f"
|
||||
integrity sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==
|
||||
"@esbuild/sunos-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz#74a45fe1db8ea96898f1a9bb401dcf1dadfc8371"
|
||||
integrity sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==
|
||||
|
||||
"@esbuild/win32-arm64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3272,10 +3272,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz#521a6d97ee0f96b7c435930353cc4e93078f0b54"
|
||||
integrity sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==
|
||||
|
||||
"@esbuild/win32-arm64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz#58dfc177da30acf956252d7c8ae9e54e424887c4"
|
||||
integrity sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==
|
||||
"@esbuild/win32-arm64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz#fd95ffd217995589058a4ed8ac17ee72a3d7f615"
|
||||
integrity sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==
|
||||
|
||||
"@esbuild/win32-ia32@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3287,10 +3287,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz#56f88462ebe82dad829dc2303175c0e0ccd8e38e"
|
||||
integrity sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz#340f6163172b5272b5ae60ec12c312485f69232b"
|
||||
integrity sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==
|
||||
"@esbuild/win32-ia32@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz#9b7ef5d0df97593a80f946b482e34fcba3fa4aaf"
|
||||
integrity sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==
|
||||
|
||||
"@esbuild/win32-x64@0.16.17":
|
||||
version "0.16.17"
|
||||
|
@ -3302,10 +3302,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz#2b577b976e6844106715bbe0cdc57cd1528063f9"
|
||||
integrity sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==
|
||||
|
||||
"@esbuild/win32-x64@0.17.18":
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz#3a8e57153905308db357fd02f57c180ee3a0a1fa"
|
||||
integrity sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==
|
||||
"@esbuild/win32-x64@0.18.17":
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz#bcb2e042631b3c15792058e189ed879a22b2968b"
|
||||
integrity sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.4.0"
|
||||
|
@ -11810,10 +11810,10 @@ esbuild-netbsd-64@0.15.18:
|
|||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz#ae75682f60d08560b1fe9482bfe0173e5110b998"
|
||||
integrity sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==
|
||||
|
||||
esbuild-node-externals@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-node-externals/-/esbuild-node-externals-1.7.0.tgz#f6d755c577aec1ffa8548b0a648f13df27551805"
|
||||
integrity sha512-nfY3hxtO2anCTZ87LgfzCTfBuyG6de+NyiCNMF1mgrBufS0NgoYlBwF77HHuOInsJLxsAJf0BfLeV6ekZ3hRuA==
|
||||
esbuild-node-externals@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-node-externals/-/esbuild-node-externals-1.8.0.tgz#878fbe458d4e58337753c2eacfd7200dc1077bd1"
|
||||
integrity sha512-pYslmT8Bl383UnfxzHQQRpCgBNIOwAzDaYheuIeI4CODxelsN/eQroVn5STDow5QOpRalMgWUR+R8LfSgUROcw==
|
||||
dependencies:
|
||||
find-up "^5.0.0"
|
||||
tslib "^2.4.1"
|
||||
|
@ -11899,34 +11899,6 @@ esbuild@^0.16.17:
|
|||
"@esbuild/win32-ia32" "0.16.17"
|
||||
"@esbuild/win32-x64" "0.16.17"
|
||||
|
||||
esbuild@^0.17.18:
|
||||
version "0.17.18"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.18.tgz#f4f8eb6d77384d68cd71c53eb6601c7efe05e746"
|
||||
integrity sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.17.18"
|
||||
"@esbuild/android-arm64" "0.17.18"
|
||||
"@esbuild/android-x64" "0.17.18"
|
||||
"@esbuild/darwin-arm64" "0.17.18"
|
||||
"@esbuild/darwin-x64" "0.17.18"
|
||||
"@esbuild/freebsd-arm64" "0.17.18"
|
||||
"@esbuild/freebsd-x64" "0.17.18"
|
||||
"@esbuild/linux-arm" "0.17.18"
|
||||
"@esbuild/linux-arm64" "0.17.18"
|
||||
"@esbuild/linux-ia32" "0.17.18"
|
||||
"@esbuild/linux-loong64" "0.17.18"
|
||||
"@esbuild/linux-mips64el" "0.17.18"
|
||||
"@esbuild/linux-ppc64" "0.17.18"
|
||||
"@esbuild/linux-riscv64" "0.17.18"
|
||||
"@esbuild/linux-s390x" "0.17.18"
|
||||
"@esbuild/linux-x64" "0.17.18"
|
||||
"@esbuild/netbsd-x64" "0.17.18"
|
||||
"@esbuild/openbsd-x64" "0.17.18"
|
||||
"@esbuild/sunos-x64" "0.17.18"
|
||||
"@esbuild/win32-arm64" "0.17.18"
|
||||
"@esbuild/win32-ia32" "0.17.18"
|
||||
"@esbuild/win32-x64" "0.17.18"
|
||||
|
||||
esbuild@^0.17.5:
|
||||
version "0.17.17"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.17.tgz#fa906ab11b11d2ed4700f494f4f764229b25c916"
|
||||
|
@ -11955,6 +11927,34 @@ esbuild@^0.17.5:
|
|||
"@esbuild/win32-ia32" "0.17.17"
|
||||
"@esbuild/win32-x64" "0.17.17"
|
||||
|
||||
esbuild@^0.18.17:
|
||||
version "0.18.17"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.17.tgz#2aaf6bc6759b0c605777fdc435fea3969e091cad"
|
||||
integrity sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.18.17"
|
||||
"@esbuild/android-arm64" "0.18.17"
|
||||
"@esbuild/android-x64" "0.18.17"
|
||||
"@esbuild/darwin-arm64" "0.18.17"
|
||||
"@esbuild/darwin-x64" "0.18.17"
|
||||
"@esbuild/freebsd-arm64" "0.18.17"
|
||||
"@esbuild/freebsd-x64" "0.18.17"
|
||||
"@esbuild/linux-arm" "0.18.17"
|
||||
"@esbuild/linux-arm64" "0.18.17"
|
||||
"@esbuild/linux-ia32" "0.18.17"
|
||||
"@esbuild/linux-loong64" "0.18.17"
|
||||
"@esbuild/linux-mips64el" "0.18.17"
|
||||
"@esbuild/linux-ppc64" "0.18.17"
|
||||
"@esbuild/linux-riscv64" "0.18.17"
|
||||
"@esbuild/linux-s390x" "0.18.17"
|
||||
"@esbuild/linux-x64" "0.18.17"
|
||||
"@esbuild/netbsd-x64" "0.18.17"
|
||||
"@esbuild/openbsd-x64" "0.18.17"
|
||||
"@esbuild/sunos-x64" "0.18.17"
|
||||
"@esbuild/win32-arm64" "0.18.17"
|
||||
"@esbuild/win32-ia32" "0.18.17"
|
||||
"@esbuild/win32-x64" "0.18.17"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
|
|
Loading…
Reference in New Issue