Merge branch 'master' of github.com:Budibase/budibase into fix/cypress-fixes
This commit is contained in:
commit
1e9ce62261
66
README.md
66
README.md
|
@ -30,9 +30,6 @@
|
||||||
<a href="https://github.com/Budibase/budibase/releases">
|
<a href="https://github.com/Budibase/budibase/releases">
|
||||||
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Budibase/budibase">
|
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Budibase/budibase">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/rCYayfe">
|
|
||||||
<img alt="Discord" src="https://img.shields.io/discord/733030666647765003">
|
|
||||||
</a>
|
|
||||||
<a href="https://twitter.com/intent/follow?screen_name=budibase">
|
<a href="https://twitter.com/intent/follow?screen_name=budibase">
|
||||||
<img src="https://img.shields.io/twitter/follow/budibase?style=social" alt="Follow @budibase" />
|
<img src="https://img.shields.io/twitter/follow/budibase?style=social" alt="Follow @budibase" />
|
||||||
</a>
|
</a>
|
||||||
|
@ -52,8 +49,6 @@
|
||||||
<a href="https://github.com/Budibase/budibase/issues">Report a bug</a>
|
<a href="https://github.com/Budibase/budibase/issues">Report a bug</a>
|
||||||
<span> · </span>
|
<span> · </span>
|
||||||
Support: <a href="https://github.com/Budibase/budibase/discussions">Discussions</a>
|
Support: <a href="https://github.com/Budibase/budibase/discussions">Discussions</a>
|
||||||
<span> & </span>
|
|
||||||
<a href="https://discord.gg/rCYayfe">Discord</a>
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +56,7 @@
|
||||||
|
|
||||||
- **Build and ship real software.** Unlike other platforms, with Budibase you build and ship single page applications. Budibase applications have performance baked in and can be designed responsively, providing your users with a great experience.
|
- **Build and ship real software.** Unlike other platforms, with Budibase you build and ship single page applications. Budibase applications have performance baked in and can be designed responsively, providing your users with a great experience.
|
||||||
|
|
||||||
- **Open source and extensable.** Budibase is open-source - licensed as GPL v3. This should fill you with confidence that Budibase will always be around. You can also code against Budibase or fork it and make changes as you please, providing a developer-friendly experience.
|
- **Open source and extensible.** Budibase is open-source - licensed as GPL v3. This should fill you with confidence that Budibase will always be around. You can also code against Budibase or fork it and make changes as you please, providing a developer-friendly experience.
|
||||||
|
|
||||||
- **Load data or start from scratch.** Budibase pulls in data from multiple sources, including MongoDB, CouchDB, PostgreSQL, mySQL, Airtable, S3, DyanmoDB, or a REST API. And unlike other platforms, with Budibase you can start from scratch and create business apps with no data sources. [Request new data sources](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).
|
- **Load data or start from scratch.** Budibase pulls in data from multiple sources, including MongoDB, CouchDB, PostgreSQL, mySQL, Airtable, S3, DyanmoDB, or a REST API. And unlike other platforms, with Budibase you can start from scratch and create business apps with no data sources. [Request new data sources](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).
|
||||||
|
|
||||||
|
@ -79,28 +74,6 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
## ⌛ Status
|
|
||||||
- [x] Alpha: We are demoing Budibase to users and receiving feedback
|
|
||||||
- [x] Private Beta: We are testing Budibase with a closed set of customers
|
|
||||||
- [x] Public Beta: Anyone can [get started](https://docs.budibase.com/getting-started).
|
|
||||||
- [ ] Official Launch
|
|
||||||
|
|
||||||
Watch "releases" of this repo to get notified of major updates, and give the star button a click whilst you're there.
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://i.imgur.com/cJpgqm8.png">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
### Stargazers over time
|
|
||||||
|
|
||||||
[![Stargazers over time](https://starchart.cc/Budibase/budibase.svg)](https://starchart.cc/Budibase/budibase)
|
|
||||||
|
|
||||||
If you are having issues between updates of the builder, please use the guide [here](https://github.com/Budibase/budibase/blob/HEAD/.github/CONTRIBUTING.md#troubleshooting) to clear down your environment.
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
## 🏁 Getting Started with Budibase in 5 minutes
|
## 🏁 Getting Started with Budibase in 5 minutes
|
||||||
|
|
||||||
To get started, you must have docker and docker compose installed on your machine.
|
To get started, you must have docker and docker compose installed on your machine.
|
||||||
|
@ -141,21 +114,40 @@ Done! You are now ready to build powerful internal tools in minutes. For additio
|
||||||
|
|
||||||
The Budibase [documentation lives here](https://docs.budibase.com).
|
The Budibase [documentation lives here](https://docs.budibase.com).
|
||||||
|
|
||||||
You can also follow a quick tutorial on [how to build a CRM with Budibase](https://docs.budibase.com/tutorial/tutorial-introduction)
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⌛ Status
|
||||||
|
- [x] Alpha: We are demoing Budibase to users and receiving feedback
|
||||||
|
- [x] Private Beta: We are testing Budibase with a closed set of customers
|
||||||
|
- [x] Public Beta: Anyone can [get started](https://docs.budibase.com/getting-started).
|
||||||
|
- [ ] Official Launch
|
||||||
|
|
||||||
|
Watch "releases" of this repo to get notified of major updates, and give the star button a click whilst you're there.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://i.imgur.com/cJpgqm8.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stargazers over time
|
||||||
|
|
||||||
|
[![Stargazers over time](https://starchart.cc/Budibase/budibase.svg)](https://starchart.cc/Budibase/budibase)
|
||||||
|
|
||||||
|
If you are having issues between updates of the builder, please use the guide [here](https://github.com/Budibase/budibase/blob/HEAD/.github/CONTRIBUTING.md#troubleshooting) to clear down your environment.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
Checkout our [Public Roadmap](https://github.com/Budibase/budibase/projects/10). If you would like to discuss some of the items on the roadmap, please feel to reach out on [Discord](https://discord.gg/rCYayfe), or via [Github discussions](https://github.com/Budibase/budibase/discussions)
|
|
||||||
|
|
||||||
|
|
||||||
## ❗ Code of Conduct
|
## ❗ Code of Conduct
|
||||||
|
|
||||||
Budibase is dedicated to providing a welcoming, diverse, and harrassment-free experience for everyone. We expect everyone in the Budibase community to abide by our [**Code of Conduct**](https://github.com/Budibase/budibase/blob/HEAD/.github/CODE_OF_CONDUCT.md). Please read it.
|
Budibase is dedicated to providing a welcoming, diverse, and harrassment-free experience for everyone. We expect everyone in the Budibase community to abide by our [**Code of Conduct**](https://github.com/Budibase/budibase/blob/HEAD/.github/CODE_OF_CONDUCT.md). Please read it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 🙌 Contributing to Budibase
|
## 🙌 Contributing to Budibase
|
||||||
|
|
||||||
From opening a bug report to creating a pull request: every contribution is appreciated and welcomed. If you're planning to implement a new feature or change the API please create an issue first. This way we can ensure your work is not in vain.
|
From opening a bug report to creating a pull request: every contribution is appreciated and welcomed. If you're planning to implement a new feature or change the API please create an issue first. This way we can ensure your work is not in vain.
|
||||||
|
@ -188,11 +180,7 @@ Budibase is open-source. The builder is licensed [AGPL v3](https://www.gnu.org/l
|
||||||
|
|
||||||
## 💬 Get in touch
|
## 💬 Get in touch
|
||||||
|
|
||||||
If you have a question or would like to talk with other Budibase users, please hop over to [Github discussions](https://github.com/Budibase/budibase/discussions) or join our Discord server:
|
If you have a question or would like to talk with other Budibase users and join our community, please hop over to [Github discussions](https://github.com/Budibase/budibase/discussions)
|
||||||
|
|
||||||
[Discord chatroom](https://discord.gg/rCYayfe)
|
|
||||||
|
|
||||||
![Discord Shield](https://discordapp.com/api/guilds/733030666647765003/widget.png?style=shield)
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -24,6 +24,8 @@ services:
|
||||||
ENABLE_ANALYTICS: "true"
|
ENABLE_ANALYTICS: "true"
|
||||||
REDIS_URL: redis-service:6379
|
REDIS_URL: redis-service:6379
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ./logs:/logs
|
||||||
depends_on:
|
depends_on:
|
||||||
- worker-service
|
- worker-service
|
||||||
|
|
||||||
|
@ -46,6 +48,8 @@ services:
|
||||||
INTERNAL_API_KEY: ${INTERNAL_API_KEY}
|
INTERNAL_API_KEY: ${INTERNAL_API_KEY}
|
||||||
REDIS_URL: redis-service:6379
|
REDIS_URL: redis-service:6379
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ./logs:/logs
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis-service
|
- redis-service
|
||||||
- minio-service
|
- minio-service
|
||||||
|
@ -109,6 +113,21 @@ services:
|
||||||
- "${REDIS_PORT}:6379"
|
- "${REDIS_PORT}:6379"
|
||||||
volumes:
|
volumes:
|
||||||
- redis_data:/data
|
- redis_data:/data
|
||||||
|
|
||||||
|
watchtower-service:
|
||||||
|
image: containrrr/watchtower
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
command: --debug --http-api-update budibase/apps budibase/worker
|
||||||
|
environment:
|
||||||
|
- WATCHTOWER_HTTP_API=true
|
||||||
|
- WATCHTOWER_HTTP_API_TOKEN=budibase
|
||||||
|
- WATCHTOWER_CLEANUP=true
|
||||||
|
labels:
|
||||||
|
- "com.centurylinklabs.watchtower.enable=false"
|
||||||
|
ports:
|
||||||
|
- 6161:8080
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
couchdb3_data:
|
couchdb3_data:
|
||||||
|
|
|
@ -133,4 +133,3 @@ static_resources:
|
||||||
socket_address:
|
socket_address:
|
||||||
address: {{ address }}
|
address: {{ address }}
|
||||||
port_value: 4002
|
port_value: 4002
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,10 @@ static_resources:
|
||||||
cluster: app-service
|
cluster: app-service
|
||||||
prefix_rewrite: "/"
|
prefix_rewrite: "/"
|
||||||
|
|
||||||
|
- match: { path: "/v1/update" }
|
||||||
|
route:
|
||||||
|
cluster: watchtower-service
|
||||||
|
|
||||||
- match: { prefix: "/builder/" }
|
- match: { prefix: "/builder/" }
|
||||||
route:
|
route:
|
||||||
cluster: app-service
|
cluster: app-service
|
||||||
|
@ -123,3 +127,17 @@ static_resources:
|
||||||
address: couchdb-service
|
address: couchdb-service
|
||||||
port_value: 5984
|
port_value: 5984
|
||||||
|
|
||||||
|
- name: watchtower-service
|
||||||
|
connect_timeout: 0.25s
|
||||||
|
type: strict_dns
|
||||||
|
lb_policy: round_robin
|
||||||
|
load_assignment:
|
||||||
|
cluster_name: watchtower-service
|
||||||
|
endpoints:
|
||||||
|
- lb_endpoints:
|
||||||
|
- endpoint:
|
||||||
|
address:
|
||||||
|
socket_address:
|
||||||
|
address: watchtower-service
|
||||||
|
port_value: 6161
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/auth",
|
"name": "@budibase/auth",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"description": "Authentication middlewares for budibase builder and apps",
|
"description": "Authentication middlewares for budibase builder and apps",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
|
|
|
@ -2,7 +2,7 @@ const passport = require("koa-passport")
|
||||||
const LocalStrategy = require("passport-local").Strategy
|
const LocalStrategy = require("passport-local").Strategy
|
||||||
const JwtStrategy = require("passport-jwt").Strategy
|
const JwtStrategy = require("passport-jwt").Strategy
|
||||||
const { StaticDatabases } = require("./db/utils")
|
const { StaticDatabases } = require("./db/utils")
|
||||||
const { jwt, local, authenticated, google } = require("./middleware")
|
const { jwt, local, authenticated, google, auditLog } = require("./middleware")
|
||||||
const { setDB, getDB } = require("./db")
|
const { setDB, getDB } = require("./db")
|
||||||
|
|
||||||
// Strategies
|
// Strategies
|
||||||
|
@ -45,6 +45,7 @@ module.exports = {
|
||||||
passport,
|
passport,
|
||||||
google,
|
google,
|
||||||
jwt: require("jsonwebtoken"),
|
jwt: require("jsonwebtoken"),
|
||||||
|
auditLog,
|
||||||
},
|
},
|
||||||
StaticDatabases,
|
StaticDatabases,
|
||||||
constants: require("./constants"),
|
constants: require("./constants"),
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = async (ctx, next) => {
|
||||||
|
// Placeholder for audit log middleware
|
||||||
|
return next()
|
||||||
|
}
|
|
@ -2,10 +2,12 @@ const jwt = require("./passport/jwt")
|
||||||
const local = require("./passport/local")
|
const local = require("./passport/local")
|
||||||
const google = require("./passport/google")
|
const google = require("./passport/google")
|
||||||
const authenticated = require("./authenticated")
|
const authenticated = require("./authenticated")
|
||||||
|
const auditLog = require("./auditLog")
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
google,
|
google,
|
||||||
jwt,
|
jwt,
|
||||||
local,
|
local,
|
||||||
authenticated,
|
authenticated,
|
||||||
|
auditLog,
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ exports.upload = async ({
|
||||||
* Similar to the upload function but can be used to send a file stream
|
* Similar to the upload function but can be used to send a file stream
|
||||||
* through to the object store.
|
* through to the object store.
|
||||||
*/
|
*/
|
||||||
exports.streamUpload = async (bucketName, filename, stream) => {
|
exports.streamUpload = async (bucketName, filename, stream, extra = {}) => {
|
||||||
const objectStore = exports.ObjectStore(bucketName)
|
const objectStore = exports.ObjectStore(bucketName)
|
||||||
await exports.makeSureBucketExists(objectStore, bucketName)
|
await exports.makeSureBucketExists(objectStore, bucketName)
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ exports.streamUpload = async (bucketName, filename, stream) => {
|
||||||
Bucket: sanitizeBucket(bucketName),
|
Bucket: sanitizeBucket(bucketName),
|
||||||
Key: sanitizeKey(filename),
|
Key: sanitizeKey(filename),
|
||||||
Body: stream,
|
Body: stream,
|
||||||
|
...extra,
|
||||||
}
|
}
|
||||||
return objectStore.upload(params).promise()
|
return objectStore.upload(params).promise()
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ const BUILTIN_IDS = {
|
||||||
POWER: "POWER",
|
POWER: "POWER",
|
||||||
BASIC: "BASIC",
|
BASIC: "BASIC",
|
||||||
PUBLIC: "PUBLIC",
|
PUBLIC: "PUBLIC",
|
||||||
BUILDER: "BUILDER",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// exclude internal roles like builder
|
// exclude internal roles like builder
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"description": "A UI solution used in the different Budibase projects.",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
|
|
@ -37,3 +37,9 @@
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.spectrum-Radio-input {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^0.9.21",
|
"@budibase/bbui": "^0.9.27",
|
||||||
"@budibase/client": "^0.9.21",
|
"@budibase/client": "^0.9.27",
|
||||||
"@budibase/colorpicker": "1.1.2",
|
"@budibase/colorpicker": "1.1.2",
|
||||||
"@budibase/string-templates": "^0.9.21",
|
"@budibase/string-templates": "^0.9.27",
|
||||||
"@sentry/browser": "5.19.1",
|
"@sentry/browser": "5.19.1",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
|
|
|
@ -136,7 +136,7 @@ const getContextBindings = (asset, componentId) => {
|
||||||
if (!datasource) {
|
if (!datasource) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const info = getSchemaForDatasource(datasource)
|
const info = getSchemaForDatasource(asset, datasource)
|
||||||
schema = info.schema
|
schema = info.schema
|
||||||
readablePrefix = info.table?.name
|
readablePrefix = info.table?.name
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ const getContextBindings = (asset, componentId) => {
|
||||||
*/
|
*/
|
||||||
const getUserBindings = () => {
|
const getUserBindings = () => {
|
||||||
let bindings = []
|
let bindings = []
|
||||||
const { schema } = getSchemaForDatasource({
|
const { schema } = getSchemaForDatasource(null, {
|
||||||
type: "table",
|
type: "table",
|
||||||
tableId: TableNames.USERS,
|
tableId: TableNames.USERS,
|
||||||
})
|
})
|
||||||
|
@ -244,11 +244,15 @@ const getUrlBindings = asset => {
|
||||||
/**
|
/**
|
||||||
* Gets a schema for a datasource object.
|
* Gets a schema for a datasource object.
|
||||||
*/
|
*/
|
||||||
export const getSchemaForDatasource = (datasource, isForm = false) => {
|
export const getSchemaForDatasource = (asset, datasource, isForm = false) => {
|
||||||
let schema, table
|
let schema, table
|
||||||
if (datasource) {
|
if (datasource) {
|
||||||
const { type } = datasource
|
const { type } = datasource
|
||||||
if (type === "query") {
|
if (type === "provider") {
|
||||||
|
const component = findComponent(asset.props, datasource.providerId)
|
||||||
|
const source = getDatasourceForProvider(asset, component)
|
||||||
|
return getSchemaForDatasource(asset, source, isForm)
|
||||||
|
} else if (type === "query") {
|
||||||
const queries = get(queriesStores).list
|
const queries = get(queriesStores).list
|
||||||
table = queries.find(query => query._id === datasource._id)
|
table = queries.find(query => query._id === datasource._id)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -174,7 +174,7 @@ const fieldTypeToComponentMap = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeDatasourceFormComponents(datasource) {
|
export function makeDatasourceFormComponents(datasource) {
|
||||||
const { schema } = getSchemaForDatasource(datasource, true)
|
const { schema } = getSchemaForDatasource(null, datasource, true)
|
||||||
let components = []
|
let components = []
|
||||||
let fields = Object.keys(schema || {})
|
let fields = Object.keys(schema || {})
|
||||||
fields.forEach(field => {
|
fields.forEach(field => {
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
let originalName = field.name
|
let originalName = field.name
|
||||||
|
const linkEditDisabled = originalName != null
|
||||||
let primaryDisplay =
|
let primaryDisplay =
|
||||||
$tables.selected.primaryDisplay == null ||
|
$tables.selected.primaryDisplay == null ||
|
||||||
$tables.selected.primaryDisplay === field.name
|
$tables.selected.primaryDisplay === field.name
|
||||||
|
@ -198,7 +199,7 @@
|
||||||
<Input
|
<Input
|
||||||
label="Name"
|
label="Name"
|
||||||
bind:value={field.name}
|
bind:value={field.name}
|
||||||
disabled={uneditable || field.type === LINK_TYPE}
|
disabled={uneditable || (linkEditDisabled && field.type === LINK_TYPE)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
|
@ -285,6 +286,7 @@
|
||||||
{:else if field.type === "link"}
|
{:else if field.type === "link"}
|
||||||
<Select
|
<Select
|
||||||
label="Table"
|
label="Table"
|
||||||
|
disabled={linkEditDisabled}
|
||||||
bind:value={field.tableId}
|
bind:value={field.tableId}
|
||||||
options={tableOptions}
|
options={tableOptions}
|
||||||
getOptionLabel={table => table.name}
|
getOptionLabel={table => table.name}
|
||||||
|
@ -292,7 +294,7 @@
|
||||||
/>
|
/>
|
||||||
{#if relationshipOptions && relationshipOptions.length > 0}
|
{#if relationshipOptions && relationshipOptions.length > 0}
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
disabled={originalName != null}
|
disabled={linkEditDisabled}
|
||||||
label="Define the relationship"
|
label="Define the relationship"
|
||||||
bind:value={field.relationshipType}
|
bind:value={field.relationshipType}
|
||||||
options={relationshipOptions}
|
options={relationshipOptions}
|
||||||
|
@ -300,7 +302,11 @@
|
||||||
getOptionValue={option => option.value}
|
getOptionValue={option => option.value}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<Input label={`Column name in other table`} bind:value={field.fieldName} />
|
<Input
|
||||||
|
disabled={linkEditDisabled}
|
||||||
|
label={`Column name in other table`}
|
||||||
|
bind:value={field.fieldName}
|
||||||
|
/>
|
||||||
{:else if field.type === FORMULA_TYPE}
|
{:else if field.type === FORMULA_TYPE}
|
||||||
<ModalBindableInput
|
<ModalBindableInput
|
||||||
title="Handlebars Formula"
|
title="Handlebars Formula"
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
"longformfield",
|
"longformfield",
|
||||||
"datetimefield",
|
"datetimefield",
|
||||||
"attachmentfield",
|
"attachmentfield",
|
||||||
"relationshipfield"
|
"relationshipfield",
|
||||||
|
"daterangepicker"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import { getBindableProperties } from "builderStore/dataBinding"
|
import {
|
||||||
|
getBindableProperties,
|
||||||
|
getDataProviderComponents,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Popover,
|
Popover,
|
||||||
|
@ -61,6 +64,17 @@
|
||||||
$currentAsset,
|
$currentAsset,
|
||||||
$store.selectedComponentId
|
$store.selectedComponentId
|
||||||
)
|
)
|
||||||
|
$: dataProviders = getDataProviderComponents(
|
||||||
|
$currentAsset,
|
||||||
|
$store.selectedComponentId
|
||||||
|
).map(provider => ({
|
||||||
|
label: provider._instanceName,
|
||||||
|
name: provider._instanceName,
|
||||||
|
providerId: provider._id,
|
||||||
|
value: `{{ literal [${provider._id}] }}`,
|
||||||
|
type: "provider",
|
||||||
|
schema: provider.schema,
|
||||||
|
}))
|
||||||
$: queryBindableProperties = bindableProperties.map(property => ({
|
$: queryBindableProperties = bindableProperties.map(property => ({
|
||||||
...property,
|
...property,
|
||||||
category: property.type === "instance" ? "Component" : "Table",
|
category: property.type === "instance" ? "Component" : "Table",
|
||||||
|
@ -182,7 +196,20 @@
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
<Divider size="S" />
|
||||||
|
<div class="title">
|
||||||
|
<Heading size="XS">Data Providers</Heading>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
{#each dataProviders as provider}
|
||||||
|
<li
|
||||||
|
class:selected={value === provider}
|
||||||
|
on:click={() => handleSelected(provider)}
|
||||||
|
>
|
||||||
|
{provider.label}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
{#if otherSources?.length}
|
{#if otherSources?.length}
|
||||||
<Divider size="S" />
|
<Divider size="S" />
|
||||||
<div class="title">
|
<div class="title">
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
$currentAsset,
|
$currentAsset,
|
||||||
$store.selectedComponentId
|
$store.selectedComponentId
|
||||||
)
|
)
|
||||||
$: schemaFields = getSchemaFields(parameters?.tableId)
|
$: schemaFields = getSchemaFields($currentAsset, parameters?.tableId)
|
||||||
$: tableOptions = $tables.list || []
|
$: tableOptions = $tables.list || []
|
||||||
|
|
||||||
const getSchemaFields = tableId => {
|
const getSchemaFields = (asset, tableId) => {
|
||||||
const { schema } = getSchemaForDatasource({ type: "table", tableId })
|
const { schema } = getSchemaForDatasource(asset, { type: "table", tableId })
|
||||||
return Object.values(schema || {})
|
return Object.values(schema || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ import ExecuteQuery from "./ExecuteQuery.svelte"
|
||||||
import TriggerAutomation from "./TriggerAutomation.svelte"
|
import TriggerAutomation from "./TriggerAutomation.svelte"
|
||||||
import ValidateForm from "./ValidateForm.svelte"
|
import ValidateForm from "./ValidateForm.svelte"
|
||||||
|
|
||||||
// defines what actions are available, when adding a new one
|
// Defines which actions are available to configure in the front end.
|
||||||
// the component is the setup panel for the action
|
// Unfortunately the "name" property is used as the identifier so please don't
|
||||||
// NOTE that the "name" is used by the client library,
|
// change them.
|
||||||
// so if you want to change it, you must change it client lib too
|
// The client library removes any spaces when processing actions, so they can
|
||||||
|
// be considered as camel case too.
|
||||||
|
// There is technical debt here to sanitize all these and standardise them
|
||||||
|
// across the packages but it's a breaking change to existing apps.
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
name: "Save Row",
|
name: "Save Row",
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
|
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
|
||||||
$: schema = getSchemaForDatasource(datasource).schema
|
$: schema = getSchemaForDatasource($currentAsset, datasource).schema
|
||||||
$: options = Object.keys(schema || {})
|
$: options = Object.keys(schema || {})
|
||||||
$: boundValue = getValidValue(value, options)
|
$: boundValue = getValidValue(value, options)
|
||||||
|
|
||||||
|
|
|
@ -27,19 +27,16 @@
|
||||||
? tempValue.length
|
? tempValue.length
|
||||||
: Object.keys(tempValue || {}).length
|
: Object.keys(tempValue || {}).length
|
||||||
$: dataSource = getDatasourceForProvider($currentAsset, componentInstance)
|
$: dataSource = getDatasourceForProvider($currentAsset, componentInstance)
|
||||||
$: schema = getSchemaForDatasource(dataSource)?.schema
|
$: schema = getSchemaForDatasource($currentAsset, dataSource)?.schema
|
||||||
$: schemaFields = Object.values(schema || {})
|
$: schemaFields = Object.values(schema || {})
|
||||||
$: internalTable = dataSource?.type === "table"
|
$: internalTable = dataSource?.type === "table"
|
||||||
|
|
||||||
// Reset value if value is wrong type for the datasource.
|
// Reset value if value is wrong type for the datasource.
|
||||||
// Lucene editor needs an array, and simple editor needs an object.
|
// Lucene editor needs an array, and simple editor needs an object.
|
||||||
$: {
|
$: {
|
||||||
if (internalTable && !Array.isArray(value)) {
|
if (!Array.isArray(value)) {
|
||||||
tempValue = []
|
tempValue = []
|
||||||
dispatch("change", [])
|
dispatch("change", [])
|
||||||
} else if (!internalTable && Array.isArray(value)) {
|
|
||||||
tempValue = {}
|
|
||||||
dispatch("change", {})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,28 +60,7 @@
|
||||||
constaints.
|
constaints.
|
||||||
{/if}
|
{/if}
|
||||||
</Body>
|
</Body>
|
||||||
{#if internalTable}
|
<LuceneFilterBuilder bind:value={tempValue} {schemaFields} />
|
||||||
<LuceneFilterBuilder bind:value={tempValue} {schemaFields} />
|
|
||||||
{:else}
|
|
||||||
<div class="fields">
|
|
||||||
<SaveFields
|
|
||||||
parameterFields={Array.isArray(value) ? {} : value}
|
|
||||||
{schemaFields}
|
|
||||||
valueLabel="Equals"
|
|
||||||
on:change={e => (tempValue = e.detail)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</Layout>
|
</Layout>
|
||||||
</DrawerContent>
|
</DrawerContent>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|
||||||
<style>
|
|
||||||
.fields {
|
|
||||||
display: grid;
|
|
||||||
column-gap: var(--spacing-l);
|
|
||||||
row-gap: var(--spacing-s);
|
|
||||||
align-items: center;
|
|
||||||
grid-template-columns: auto 1fr auto 1fr auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
component => component._component === "@budibase/standard-components/form"
|
component => component._component === "@budibase/standard-components/form"
|
||||||
)
|
)
|
||||||
$: datasource = getDatasourceForProvider($currentAsset, form)
|
$: datasource = getDatasourceForProvider($currentAsset, form)
|
||||||
$: schema = getSchemaForDatasource(datasource, true).schema
|
$: schema = getSchemaForDatasource($currentAsset, datasource, true).schema
|
||||||
$: options = getOptions(schema, type)
|
$: options = getOptions(schema, type)
|
||||||
|
|
||||||
const getOptions = (schema, fieldType) => {
|
const getOptions = (schema, fieldType) => {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
|
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
|
||||||
$: schema = getSchemaForDatasource(datasource).schema
|
$: schema = getSchemaForDatasource($currentAsset, datasource).schema
|
||||||
$: options = Object.keys(schema || {})
|
$: options = Object.keys(schema || {})
|
||||||
$: boundValue = getValidOptions(value, options)
|
$: boundValue = getValidOptions(value, options)
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,10 @@
|
||||||
title: "Theming",
|
title: "Theming",
|
||||||
href: "/builder/portal/settings/theming",
|
href: "/builder/portal/settings/theming",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Updates",
|
||||||
|
href: "/builder/portal/settings/update",
|
||||||
|
},
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
menu = menu.concat([
|
menu = menu.concat([
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
notifications,
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { auth, organisation } from "stores/portal"
|
import { auth, organisation } from "stores/portal"
|
||||||
import { post } from "builderStore/api"
|
import { post, get } from "builderStore/api"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { redirect } from "@roxi/routify"
|
import { redirect } from "@roxi/routify"
|
||||||
|
@ -130,10 +130,10 @@
|
||||||
<Toggle text="" bind:value={$values.analytics} />
|
<Toggle text="" bind:value={$values.analytics} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button disabled={loading} on:click={saveConfig} cta>Save</Button>
|
||||||
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
<div>
|
|
||||||
<Button disabled={loading} on:click={saveConfig} cta>Save</Button>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
Layout,
|
||||||
|
Heading,
|
||||||
|
Body,
|
||||||
|
Button,
|
||||||
|
Divider,
|
||||||
|
Label,
|
||||||
|
Input,
|
||||||
|
Toggle,
|
||||||
|
Dropzone,
|
||||||
|
notifications,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { auth, organisation } from "stores/portal"
|
||||||
|
import { post, get } from "builderStore/api"
|
||||||
|
import analytics from "analytics"
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import { redirect } from "@roxi/routify"
|
||||||
|
|
||||||
|
// Only admins allowed here
|
||||||
|
$: {
|
||||||
|
if (!$auth.isAdmin) {
|
||||||
|
$redirect("../../portal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateBudibase() {
|
||||||
|
try {
|
||||||
|
notifications.info("Updating budibase..")
|
||||||
|
const response = await fetch("/v1/update", {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer budibase",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
notifications.success("Your budibase installation is up to date.")
|
||||||
|
} catch (err) {
|
||||||
|
notifications.error(`Error installing budibase update ${err}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $auth.isAdmin}
|
||||||
|
<Layout>
|
||||||
|
<Layout gap="XS" noPadding>
|
||||||
|
<Heading size="M">Update</Heading>
|
||||||
|
<Body>
|
||||||
|
Keep your budibase installation up to date to take advantage of the
|
||||||
|
latest features, security updates and much more.
|
||||||
|
</Body>
|
||||||
|
</Layout>
|
||||||
|
<Divider size="S" />
|
||||||
|
<div class="fields">
|
||||||
|
<div class="field">
|
||||||
|
<Button cta on:click={updateBudibase}>Check For Updates</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.fields {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: var(--spacing-m);
|
||||||
|
}
|
||||||
|
.field {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 33% 1fr;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.js",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
|
@ -18,13 +18,13 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/string-templates": "^0.9.21",
|
"@budibase/string-templates": "^0.9.27",
|
||||||
"regexparam": "^1.3.0",
|
"regexparam": "^1.3.0",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
"svelte-spa-router": "^3.0.5"
|
"svelte-spa-router": "^3.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@budibase/standard-components": "^0.9.21",
|
"@budibase/standard-components": "^0.9.27",
|
||||||
"@rollup/plugin-commonjs": "^18.0.0",
|
"@rollup/plugin-commonjs": "^18.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
|
|
|
@ -55,13 +55,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enriches any string component props using handlebars
|
// Enriches any string component props using handlebars
|
||||||
const updateComponentProps = async (definition, context) => {
|
const updateComponentProps = (definition, context) => {
|
||||||
// Record the timestamp so we can reference it after enrichment
|
// Record the timestamp so we can reference it after enrichment
|
||||||
latestUpdateTime = Date.now()
|
latestUpdateTime = Date.now()
|
||||||
const enrichmentTime = latestUpdateTime
|
const enrichmentTime = latestUpdateTime
|
||||||
|
|
||||||
// Enrich props with context
|
// Enrich props with context
|
||||||
const enrichedProps = await enrichProps(definition, context)
|
const enrichedProps = enrichProps(definition, context)
|
||||||
|
|
||||||
// Abandon this update if a newer update has started
|
// Abandon this update if a newer update has started
|
||||||
if (enrichmentTime !== latestUpdateTime) {
|
if (enrichmentTime !== latestUpdateTime) {
|
||||||
|
|
|
@ -5,4 +5,5 @@ export const TableNames = {
|
||||||
export const ActionTypes = {
|
export const ActionTypes = {
|
||||||
ValidateForm: "ValidateForm",
|
ValidateForm: "ValidateForm",
|
||||||
RefreshDatasource: "RefreshDatasource",
|
RefreshDatasource: "RefreshDatasource",
|
||||||
|
SetDataProviderQuery: "SetDataProviderQuery",
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import { styleable } from "./utils/styleable"
|
import { styleable } from "./utils/styleable"
|
||||||
import transition from "./utils/transition"
|
import transition from "./utils/transition"
|
||||||
import { linkable } from "./utils/linkable"
|
import { linkable } from "./utils/linkable"
|
||||||
|
import { getAction } from "./utils/getAction"
|
||||||
import Provider from "./components/Provider.svelte"
|
import Provider from "./components/Provider.svelte"
|
||||||
import { ActionTypes } from "./constants"
|
import { ActionTypes } from "./constants"
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ export default {
|
||||||
styleable,
|
styleable,
|
||||||
transition,
|
transition,
|
||||||
linkable,
|
linkable,
|
||||||
|
getAction,
|
||||||
Provider,
|
Provider,
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const propsAreSame = (a, b) => {
|
||||||
* Enriches component props.
|
* Enriches component props.
|
||||||
* Data bindings are enriched, and button actions are enriched.
|
* Data bindings are enriched, and button actions are enriched.
|
||||||
*/
|
*/
|
||||||
export const enrichProps = async (props, context) => {
|
export const enrichProps = (props, context) => {
|
||||||
// Exclude all private props that start with an underscore
|
// Exclude all private props that start with an underscore
|
||||||
let validProps = {}
|
let validProps = {}
|
||||||
Object.entries(props)
|
Object.entries(props)
|
||||||
|
@ -41,7 +41,7 @@ export const enrichProps = async (props, context) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enrich all data bindings in top level props
|
// Enrich all data bindings in top level props
|
||||||
let enrichedProps = await enrichDataBindings(validProps, totalContext)
|
let enrichedProps = enrichDataBindings(validProps, totalContext)
|
||||||
|
|
||||||
// Enrich click actions if they exist
|
// Enrich click actions if they exist
|
||||||
if (enrichedProps.onClick) {
|
if (enrichedProps.onClick) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { processString, processObject } from "@budibase/string-templates"
|
import { processString, processObjectSync } from "@budibase/string-templates"
|
||||||
|
|
||||||
// Regex to test inputs with to see if they are likely candidates for template strings
|
// Regex to test inputs with to see if they are likely candidates for template strings
|
||||||
const looksLikeTemplate = /{{.*}}/
|
const looksLikeTemplate = /{{.*}}/
|
||||||
|
@ -23,6 +23,6 @@ export const enrichDataBinding = async (input, context) => {
|
||||||
* Recursively enriches all props in a props object and returns the new props.
|
* Recursively enriches all props in a props object and returns the new props.
|
||||||
* Props are deeply cloned so that no mutation is done to the source object.
|
* Props are deeply cloned so that no mutation is done to the source object.
|
||||||
*/
|
*/
|
||||||
export const enrichDataBindings = async (props, context) => {
|
export const enrichDataBindings = (props, context) => {
|
||||||
return await processObject(cloneDeep(props), context)
|
return processObjectSync(cloneDeep(props), context)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a component action.
|
||||||
|
* @param id The component ID that provides the action
|
||||||
|
* @param type The action type to get
|
||||||
|
* @returns {null|*} The action function
|
||||||
|
*/
|
||||||
|
export const getAction = (id, type) => {
|
||||||
|
if (!id || !type) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const context = getContext("context")
|
||||||
|
if (!context) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return get(context)?.[`${id}_${type}`]
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/electron.js",
|
"main": "src/electron.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -55,9 +55,9 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/auth": "^0.9.21",
|
"@budibase/auth": "^0.9.27",
|
||||||
"@budibase/client": "^0.9.21",
|
"@budibase/client": "^0.9.27",
|
||||||
"@budibase/string-templates": "^0.9.21",
|
"@budibase/string-templates": "^0.9.27",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
"@koa/router": "8.0.0",
|
"@koa/router": "8.0.0",
|
||||||
"@sendgrid/mail": "7.1.1",
|
"@sendgrid/mail": "7.1.1",
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.14.3",
|
"@babel/core": "^7.14.3",
|
||||||
"@babel/preset-env": "^7.14.4",
|
"@babel/preset-env": "^7.14.4",
|
||||||
"@budibase/standard-components": "^0.9.21",
|
"@budibase/standard-components": "^0.9.27",
|
||||||
"@jest/test-sequencer": "^24.8.0",
|
"@jest/test-sequencer": "^24.8.0",
|
||||||
"babel-jest": "^27.0.2",
|
"babel-jest": "^27.0.2",
|
||||||
"docker-compose": "^0.23.6",
|
"docker-compose": "^0.23.6",
|
||||||
|
|
|
@ -99,12 +99,18 @@ async function createInstance(template) {
|
||||||
// replicate the template data to the instance DB
|
// replicate the template data to the instance DB
|
||||||
// this is currently very hard to test, downloading and importing template files
|
// this is currently very hard to test, downloading and importing template files
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
|
let _rev
|
||||||
if (template && template.useTemplate === "true") {
|
if (template && template.useTemplate === "true") {
|
||||||
const { ok } = await db.load(await getTemplateStream(template))
|
const { ok } = await db.load(await getTemplateStream(template))
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw "Error loading database dump from template."
|
throw "Error loading database dump from template."
|
||||||
}
|
}
|
||||||
var { _rev } = await db.get(DocumentTypes.APP_METADATA)
|
try {
|
||||||
|
const response = await db.get(DocumentTypes.APP_METADATA)
|
||||||
|
_rev = response._rev
|
||||||
|
} catch (err) {
|
||||||
|
_rev = null
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// create the users table
|
// create the users table
|
||||||
await db.put(USERS_TABLE_SCHEMA)
|
await db.put(USERS_TABLE_SCHEMA)
|
||||||
|
|
|
@ -5,7 +5,7 @@ const { getFullUser } = require("../../utilities/users")
|
||||||
|
|
||||||
exports.fetchSelf = async ctx => {
|
exports.fetchSelf = async ctx => {
|
||||||
const appId = ctx.appId
|
const appId = ctx.appId
|
||||||
const { userId } = ctx.user
|
let userId = ctx.user.userId || ctx.user._id
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
ctx.body = {}
|
ctx.body = {}
|
||||||
|
|
|
@ -63,10 +63,6 @@ exports.fetch = async ctx => {
|
||||||
exports.clientFetch = async ctx => {
|
exports.clientFetch = async ctx => {
|
||||||
const routing = await getRoutingStructure(ctx.appId)
|
const routing = await getRoutingStructure(ctx.appId)
|
||||||
let roleId = ctx.user.role._id
|
let roleId = ctx.user.role._id
|
||||||
// builder is a special case, always return the full routing structure
|
|
||||||
if (roleId === BUILTIN_ROLE_IDS.BUILDER) {
|
|
||||||
roleId = BUILTIN_ROLE_IDS.ADMIN
|
|
||||||
}
|
|
||||||
const roleIds = await getUserRoleHierarchy(ctx.appId, roleId)
|
const roleIds = await getUserRoleHierarchy(ctx.appId, roleId)
|
||||||
for (let topLevel of Object.values(routing.routes)) {
|
for (let topLevel of Object.values(routing.routes)) {
|
||||||
for (let subpathKey of Object.keys(topLevel.subpaths)) {
|
for (let subpathKey of Object.keys(topLevel.subpaths)) {
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*:before,
|
*:before,
|
||||||
*:after {
|
*:after {
|
||||||
|
@ -41,9 +40,9 @@
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<body id="app">
|
<body id="app">
|
||||||
<script src={clientLibPath}>
|
<script type="application/javascript" src={clientLibPath}>
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script type="application/javascript">
|
||||||
loadBudibase()
|
loadBudibase()
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -4,7 +4,6 @@ const {
|
||||||
getUserMetadataParams,
|
getUserMetadataParams,
|
||||||
} = require("../../db/utils")
|
} = require("../../db/utils")
|
||||||
const { InternalTables } = require("../../db/utils")
|
const { InternalTables } = require("../../db/utils")
|
||||||
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
|
||||||
const {
|
const {
|
||||||
getGlobalUsers,
|
getGlobalUsers,
|
||||||
addAppRoleToUser,
|
addAppRoleToUser,
|
||||||
|
@ -47,10 +46,6 @@ exports.fetchMetadata = async function (ctx) {
|
||||||
exports.updateSelfMetadata = async function (ctx) {
|
exports.updateSelfMetadata = async function (ctx) {
|
||||||
// overwrite the ID with current users
|
// overwrite the ID with current users
|
||||||
ctx.request.body._id = ctx.user._id
|
ctx.request.body._id = ctx.user._id
|
||||||
if (ctx.user.builder && ctx.user.builder.global) {
|
|
||||||
// specific case, update self role in global user
|
|
||||||
await addAppRoleToUser(ctx, ctx.appId, BUILTIN_ROLE_IDS.ADMIN)
|
|
||||||
}
|
|
||||||
// make sure no stale rev
|
// make sure no stale rev
|
||||||
delete ctx.request.body._rev
|
delete ctx.request.body._rev
|
||||||
await exports.updateMetadata(ctx)
|
await exports.updateMetadata(ctx)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const Router = require("@koa/router")
|
const Router = require("@koa/router")
|
||||||
const { buildAuthMiddleware } = require("@budibase/auth").auth
|
const { buildAuthMiddleware, auditLog } = require("@budibase/auth").auth
|
||||||
const currentApp = require("../middleware/currentapp")
|
const currentApp = require("../middleware/currentapp")
|
||||||
const compress = require("koa-compress")
|
const compress = require("koa-compress")
|
||||||
const zlib = require("zlib")
|
const zlib = require("zlib")
|
||||||
|
@ -37,6 +37,7 @@ router
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.use(currentApp)
|
.use(currentApp)
|
||||||
|
.use(auditLog)
|
||||||
|
|
||||||
// error handling middleware
|
// error handling middleware
|
||||||
router.use(async (ctx, next) => {
|
router.use(async (ctx, next) => {
|
||||||
|
|
|
@ -28,9 +28,7 @@ describe("/routing", () => {
|
||||||
it("returns the correct routing for basic user", async () => {
|
it("returns the correct routing for basic user", async () => {
|
||||||
workerRequests.getGlobalUsers.mockImplementationOnce((ctx, appId) => {
|
workerRequests.getGlobalUsers.mockImplementationOnce((ctx, appId) => {
|
||||||
return {
|
return {
|
||||||
roles: {
|
roleId: BUILTIN_ROLE_IDS.BASIC,
|
||||||
[appId]: BUILTIN_ROLE_IDS.BASIC,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const res = await request
|
const res = await request
|
||||||
|
|
|
@ -2,6 +2,7 @@ const rowController = require("../../../controllers/row")
|
||||||
const appController = require("../../../controllers/application")
|
const appController = require("../../../controllers/application")
|
||||||
const CouchDB = require("../../../../db")
|
const CouchDB = require("../../../../db")
|
||||||
const { AppStatus } = require("../../../../db/utils")
|
const { AppStatus } = require("../../../../db/utils")
|
||||||
|
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
||||||
|
|
||||||
function Request(appId, params) {
|
function Request(appId, params) {
|
||||||
this.appId = appId
|
this.appId = appId
|
||||||
|
@ -77,11 +78,17 @@ exports.checkPermissionsEndpoint = async ({
|
||||||
.set(passHeader)
|
.set(passHeader)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
user = await config.createUser("fail@budibase.com", password, failRole)
|
let failHeader
|
||||||
const failHeader = await config.login("fail@budibase.com", password, {
|
if (failRole === BUILTIN_ROLE_IDS.PUBLIC) {
|
||||||
roleId: failRole,
|
failHeader = config.publicHeaders()
|
||||||
userId: user.globalId,
|
} else {
|
||||||
})
|
user = await config.createUser("fail@budibase.com", password, failRole)
|
||||||
|
failHeader = await config.login("fail@budibase.com", password, {
|
||||||
|
roleId: failRole,
|
||||||
|
userId: user.globalId,
|
||||||
|
builder: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
await exports
|
await exports
|
||||||
.createRequest(config.request, method, url, body)
|
.createRequest(config.request, method, url, body)
|
||||||
|
|
|
@ -5,7 +5,7 @@ require("@budibase/auth").init(CouchDB)
|
||||||
const Koa = require("koa")
|
const Koa = require("koa")
|
||||||
const destroyable = require("server-destroy")
|
const destroyable = require("server-destroy")
|
||||||
const koaBody = require("koa-body")
|
const koaBody = require("koa-body")
|
||||||
const logger = require("koa-pino-logger")
|
const pino = require("koa-pino-logger")
|
||||||
const http = require("http")
|
const http = require("http")
|
||||||
const api = require("./api")
|
const api = require("./api")
|
||||||
const eventEmitter = require("./events")
|
const eventEmitter = require("./events")
|
||||||
|
@ -29,7 +29,7 @@ app.use(
|
||||||
)
|
)
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
logger({
|
pino({
|
||||||
prettyPrint: {
|
prettyPrint: {
|
||||||
levelFirst: true,
|
levelFirst: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@ const createRow = require("./steps/createRow")
|
||||||
const updateRow = require("./steps/updateRow")
|
const updateRow = require("./steps/updateRow")
|
||||||
const deleteRow = require("./steps/deleteRow")
|
const deleteRow = require("./steps/deleteRow")
|
||||||
const executeScript = require("./steps/executeScript")
|
const executeScript = require("./steps/executeScript")
|
||||||
|
const bash = require("./steps/bash")
|
||||||
const executeQuery = require("./steps/executeQuery")
|
const executeQuery = require("./steps/executeQuery")
|
||||||
const outgoingWebhook = require("./steps/outgoingWebhook")
|
const outgoingWebhook = require("./steps/outgoingWebhook")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
|
@ -21,6 +22,7 @@ const BUILTIN_ACTIONS = {
|
||||||
DELETE_ROW: deleteRow.run,
|
DELETE_ROW: deleteRow.run,
|
||||||
OUTGOING_WEBHOOK: outgoingWebhook.run,
|
OUTGOING_WEBHOOK: outgoingWebhook.run,
|
||||||
EXECUTE_SCRIPT: executeScript.run,
|
EXECUTE_SCRIPT: executeScript.run,
|
||||||
|
EXECUTE_BASH: bash.run,
|
||||||
EXECUTE_QUERY: executeQuery.run,
|
EXECUTE_QUERY: executeQuery.run,
|
||||||
}
|
}
|
||||||
const BUILTIN_DEFINITIONS = {
|
const BUILTIN_DEFINITIONS = {
|
||||||
|
@ -32,6 +34,7 @@ const BUILTIN_DEFINITIONS = {
|
||||||
OUTGOING_WEBHOOK: outgoingWebhook.definition,
|
OUTGOING_WEBHOOK: outgoingWebhook.definition,
|
||||||
EXECUTE_SCRIPT: executeScript.definition,
|
EXECUTE_SCRIPT: executeScript.definition,
|
||||||
EXECUTE_QUERY: executeQuery.definition,
|
EXECUTE_QUERY: executeQuery.definition,
|
||||||
|
EXECUTE_BASH: bash.definition,
|
||||||
}
|
}
|
||||||
|
|
||||||
let MANIFEST = null
|
let MANIFEST = null
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
const { execSync } = require("child_process")
|
||||||
|
const { processStringSync } = require("@budibase/string-templates")
|
||||||
|
|
||||||
|
module.exports.definition = {
|
||||||
|
name: "Bash Scripting",
|
||||||
|
tagline: "Execute a bash command",
|
||||||
|
icon: "ri-terminal-box-line",
|
||||||
|
description: "Run a bash script",
|
||||||
|
type: "ACTION",
|
||||||
|
stepId: "EXECUTE_BASH",
|
||||||
|
inputs: {},
|
||||||
|
schema: {
|
||||||
|
inputs: {
|
||||||
|
properties: {
|
||||||
|
code: {
|
||||||
|
type: "string",
|
||||||
|
customType: "code",
|
||||||
|
title: "Code",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["code"],
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
properties: {
|
||||||
|
stdout: {
|
||||||
|
type: "string",
|
||||||
|
description: "Standard output of your bash command or script.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["stdout"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.run = async function ({ inputs, context }) {
|
||||||
|
if (inputs.code == null) {
|
||||||
|
return {
|
||||||
|
stdout: "Budibase bash automation failed: Invalid inputs",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const command = processStringSync(inputs.code, context)
|
||||||
|
|
||||||
|
let stdout
|
||||||
|
try {
|
||||||
|
stdout = execSync(command, { timeout: 500 })
|
||||||
|
} catch (err) {
|
||||||
|
stdout = err.message
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
stdout,
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
response: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
const scriptController = require("../../api/controllers/script")
|
const scriptController = require("../../api/controllers/script")
|
||||||
|
|
||||||
module.exports.definition = {
|
module.exports.definition = {
|
||||||
name: "Scripting",
|
name: "JS Scripting",
|
||||||
tagline: "Execute JavaScript Code",
|
tagline: "Execute JavaScript Code",
|
||||||
icon: "ri-terminal-box-line",
|
icon: "ri-terminal-box-line",
|
||||||
description: "Run a piece of JavaScript code in your automation",
|
description: "Run a piece of JavaScript code in your automation",
|
||||||
|
|
|
@ -33,7 +33,7 @@ module.exports = async (ctx, next) => {
|
||||||
updateCookie = true
|
updateCookie = true
|
||||||
appId = requestAppId
|
appId = requestAppId
|
||||||
// retrieving global user gets the right role
|
// retrieving global user gets the right role
|
||||||
roleId = globalUser.roleId
|
roleId = globalUser.roleId || BUILTIN_ROLE_IDS.PUBLIC
|
||||||
} else if (appCookie != null) {
|
} else if (appCookie != null) {
|
||||||
appId = appCookie.appId
|
appId = appCookie.appId
|
||||||
roleId = appCookie.roleId || BUILTIN_ROLE_IDS.PUBLIC
|
roleId = appCookie.roleId || BUILTIN_ROLE_IDS.PUBLIC
|
||||||
|
|
|
@ -101,7 +101,7 @@ class TestConfiguration {
|
||||||
userId: GLOBAL_USER_ID,
|
userId: GLOBAL_USER_ID,
|
||||||
}
|
}
|
||||||
const app = {
|
const app = {
|
||||||
roleId: BUILTIN_ROLE_IDS.BUILDER,
|
roleId: BUILTIN_ROLE_IDS.ADMIN,
|
||||||
appId: this.appId,
|
appId: this.appId,
|
||||||
}
|
}
|
||||||
const authToken = jwt.sign(auth, env.JWT_SECRET)
|
const authToken = jwt.sign(auth, env.JWT_SECRET)
|
||||||
|
@ -306,12 +306,9 @@ class TestConfiguration {
|
||||||
return await this._req(config, null, controllers.layout.save)
|
return await this._req(config, null, controllers.layout.save)
|
||||||
}
|
}
|
||||||
|
|
||||||
async createUser(roleId = BUILTIN_ROLE_IDS.POWER) {
|
async createUser() {
|
||||||
const globalId = `us_${Math.random()}`
|
const globalId = `us_${Math.random()}`
|
||||||
const resp = await this.globalUser(
|
const resp = await this.globalUser(globalId)
|
||||||
globalId,
|
|
||||||
roleId === BUILTIN_ROLE_IDS.BUILDER
|
|
||||||
)
|
|
||||||
return {
|
return {
|
||||||
...resp,
|
...resp,
|
||||||
globalId,
|
globalId,
|
||||||
|
@ -319,7 +316,6 @@ class TestConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
async login(email, password, { roleId, userId, builder } = {}) {
|
async login(email, password, { roleId, userId, builder } = {}) {
|
||||||
roleId = !roleId ? BUILTIN_ROLE_IDS.BUILDER : roleId
|
|
||||||
userId = !userId ? `us_uuid1` : userId
|
userId = !userId ? `us_uuid1` : userId
|
||||||
if (!this.request) {
|
if (!this.request) {
|
||||||
throw "Server has not been opened, cannot login."
|
throw "Server has not been opened, cannot login."
|
||||||
|
|
|
@ -30,5 +30,7 @@ exports.uploadClientLibrary = async appId => {
|
||||||
const sourcepath = require.resolve("@budibase/client")
|
const sourcepath = require.resolve("@budibase/client")
|
||||||
const destPath = join(appId, "budibase-client.js")
|
const destPath = join(appId, "budibase-client.js")
|
||||||
|
|
||||||
await streamUpload(BUCKET_NAME, destPath, fs.createReadStream(sourcepath))
|
await streamUpload(BUCKET_NAME, destPath, fs.createReadStream(sourcepath), {
|
||||||
|
ContentType: "application/javascript",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,8 @@ exports.init = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.shutdown = async () => {
|
exports.shutdown = async () => {
|
||||||
if (devAppClient != null) {
|
if (devAppClient) await devAppClient.finish()
|
||||||
await devAppClient.finish()
|
if (debounceClient) await debounceClient.finish()
|
||||||
}
|
|
||||||
if (debounceClient != null) {
|
|
||||||
await debounceClient.finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.doesUserHaveLock = async (devAppId, user) => {
|
exports.doesUserHaveLock = async (devAppId, user) => {
|
||||||
|
|
|
@ -169,9 +169,14 @@ exports.inputProcessing = (user = {}, table, row) => {
|
||||||
let clonedRow = cloneDeep(row)
|
let clonedRow = cloneDeep(row)
|
||||||
// need to copy the table so it can be differenced on way out
|
// need to copy the table so it can be differenced on way out
|
||||||
const copiedTable = cloneDeep(table)
|
const copiedTable = cloneDeep(table)
|
||||||
|
const dontCleanseKeys = ["type", "_id", "_rev", "tableId"]
|
||||||
for (let [key, value] of Object.entries(clonedRow)) {
|
for (let [key, value] of Object.entries(clonedRow)) {
|
||||||
const field = table.schema[key]
|
const field = table.schema[key]
|
||||||
|
// cleanse fields that aren't in the schema
|
||||||
if (!field) {
|
if (!field) {
|
||||||
|
if (dontCleanseKeys.indexOf(key) === -1) {
|
||||||
|
delete clonedRow[key]
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
clonedRow[key] = exports.coerce(value, field.type)
|
clonedRow[key] = exports.coerce(value, field.type)
|
||||||
|
|
|
@ -9,19 +9,26 @@ function getAppRole(appId, user) {
|
||||||
if (!user.roles) {
|
if (!user.roles) {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
// always use the deployed app
|
if (user.builder && user.builder.global) {
|
||||||
user.roleId = user.roles[getDeployedAppID(appId)]
|
user.roleId = BUILTIN_ROLE_IDS.ADMIN
|
||||||
if (!user.roleId) {
|
} else {
|
||||||
user.roleId = BUILTIN_ROLE_IDS.PUBLIC
|
// always use the deployed app
|
||||||
|
user.roleId = user.roles[getDeployedAppID(appId)]
|
||||||
|
if (!user.roleId) {
|
||||||
|
user.roleId = BUILTIN_ROLE_IDS.PUBLIC
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete user.roles
|
delete user.roles
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
function request(ctx, request) {
|
function request(ctx, request, noApiKey) {
|
||||||
if (!request.headers) {
|
if (!request.headers) {
|
||||||
request.headers = {}
|
request.headers = {}
|
||||||
}
|
}
|
||||||
|
if (!noApiKey) {
|
||||||
|
request.headers["x-budibase-api-key"] = env.INTERNAL_API_KEY
|
||||||
|
}
|
||||||
if (request.body && Object.keys(request.body).length > 0) {
|
if (request.body && Object.keys(request.body).length > 0) {
|
||||||
request.headers["Content-Type"] = "application/json"
|
request.headers["Content-Type"] = "application/json"
|
||||||
request.body =
|
request.body =
|
||||||
|
@ -44,9 +51,6 @@ exports.sendSmtpEmail = async (to, from, subject, contents) => {
|
||||||
checkSlashesInUrl(env.WORKER_URL + `/api/admin/email/send`),
|
checkSlashesInUrl(env.WORKER_URL + `/api/admin/email/send`),
|
||||||
request(null, {
|
request(null, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
|
||||||
"x-budibase-api-key": env.INTERNAL_API_KEY,
|
|
||||||
},
|
|
||||||
body: {
|
body: {
|
||||||
email: to,
|
email: to,
|
||||||
from,
|
from,
|
||||||
|
@ -86,16 +90,6 @@ exports.getDeployedApps = async ctx => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteGlobalUser = async (ctx, globalId) => {
|
|
||||||
const endpoint = `/api/admin/users/${globalId}`
|
|
||||||
const reqCfg = { method: "DELETE" }
|
|
||||||
const response = await fetch(
|
|
||||||
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
|
||||||
request(ctx, reqCfg)
|
|
||||||
)
|
|
||||||
return response.json()
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getGlobalUsers = async (ctx, appId = null, globalId = null) => {
|
exports.getGlobalUsers = async (ctx, appId = null, globalId = null) => {
|
||||||
const endpoint = globalId
|
const endpoint = globalId
|
||||||
? `/api/admin/users/${globalId}`
|
? `/api/admin/users/${globalId}`
|
||||||
|
@ -121,7 +115,8 @@ exports.getGlobalSelf = async (ctx, appId = null) => {
|
||||||
const endpoint = `/api/admin/users/self`
|
const endpoint = `/api/admin/users/self`
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
||||||
request(ctx, { method: "GET" })
|
// we don't want to use API key when getting self
|
||||||
|
request(ctx, { method: "GET" }, true)
|
||||||
)
|
)
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
ctx.throw(400, "Unable to get self globally.")
|
ctx.throw(400, "Unable to get self globally.")
|
||||||
|
@ -172,9 +167,6 @@ exports.removeAppFromUserRoles = async appId => {
|
||||||
checkSlashesInUrl(env.WORKER_URL + `/api/admin/roles/${deployedAppId}`),
|
checkSlashesInUrl(env.WORKER_URL + `/api/admin/roles/${deployedAppId}`),
|
||||||
request(null, {
|
request(null, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
|
||||||
"x-budibase-api-key": env.INTERNAL_API_KEY,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
|
|
|
@ -1505,5 +1505,38 @@
|
||||||
"context": {
|
"context": {
|
||||||
"type": "schema"
|
"type": "schema"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"daterangepicker": {
|
||||||
|
"name": "Date Range",
|
||||||
|
"icon": "Date",
|
||||||
|
"styleable": true,
|
||||||
|
"hasChildren": false,
|
||||||
|
"info": "Your data provider will be automatically filtered to the given date range.",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "dataProvider",
|
||||||
|
"label": "Provider",
|
||||||
|
"key": "dataProvider"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "field",
|
||||||
|
"label": "Date field",
|
||||||
|
"key": "field"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "select",
|
||||||
|
"label": "Default range",
|
||||||
|
"key": "defaultValue",
|
||||||
|
"options": [
|
||||||
|
"Last 1 day",
|
||||||
|
"Last 7 days",
|
||||||
|
"Last 30 days",
|
||||||
|
"Last 3 months",
|
||||||
|
"Last 6 months",
|
||||||
|
"Last 1 year"
|
||||||
|
],
|
||||||
|
"defaultValue": "Last 30 days"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,14 +29,15 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"svelte"
|
"svelte"
|
||||||
],
|
],
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
|
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^0.9.21",
|
"@budibase/bbui": "^0.9.27",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
"apexcharts": "^3.22.1",
|
"apexcharts": "^3.22.1",
|
||||||
|
"dayjs": "^1.10.5",
|
||||||
"svelte-apexcharts": "^1.0.2",
|
"svelte-apexcharts": "^1.0.2",
|
||||||
"svelte-flatpickr": "^3.1.0"
|
"svelte-flatpickr": "^3.1.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import { ProgressCircle, Pagination } from "@budibase/bbui"
|
import { ProgressCircle, Pagination } from "@budibase/bbui"
|
||||||
|
import {
|
||||||
|
buildLuceneQuery,
|
||||||
|
luceneQuery,
|
||||||
|
luceneSort,
|
||||||
|
luceneLimit,
|
||||||
|
} from "./lucene"
|
||||||
|
|
||||||
export let dataSource
|
export let dataSource
|
||||||
export let filter
|
export let filter
|
||||||
|
@ -25,9 +31,11 @@
|
||||||
let schema = {}
|
let schema = {}
|
||||||
let bookmarks = [null]
|
let bookmarks = [null]
|
||||||
let pageNumber = 0
|
let pageNumber = 0
|
||||||
|
let query = null
|
||||||
|
|
||||||
|
$: query = buildLuceneQuery(filter)
|
||||||
$: internalTable = dataSource?.type === "table"
|
$: internalTable = dataSource?.type === "table"
|
||||||
$: query = internalTable ? buildLuceneQuery(filter) : null
|
$: nestedProvider = dataSource?.type === "provider"
|
||||||
$: hasNextPage = bookmarks[pageNumber + 1] != null
|
$: hasNextPage = bookmarks[pageNumber + 1] != null
|
||||||
$: hasPrevPage = pageNumber > 0
|
$: hasPrevPage = pageNumber > 0
|
||||||
$: getSchema(dataSource)
|
$: getSchema(dataSource)
|
||||||
|
@ -48,22 +56,38 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$: {
|
$: {
|
||||||
// Sort and limit rows in memory when we aren't searching internal tables
|
|
||||||
if (internalTable) {
|
if (internalTable) {
|
||||||
|
// Internal tables are already processed server-side
|
||||||
rows = allRows
|
rows = allRows
|
||||||
} else {
|
} else {
|
||||||
const sortedRows = sortRows(allRows, sortColumn, sortOrder)
|
// For anything else we use client-side implementations to filter, sort
|
||||||
rows = limitRows(sortedRows, limit)
|
// and limit
|
||||||
|
const filtered = luceneQuery(allRows, query)
|
||||||
|
const sorted = luceneSort(filtered, sortColumn, sortOrder, sortType)
|
||||||
|
rows = luceneLimit(sorted, limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$: actions = [
|
$: actions = [
|
||||||
{
|
{
|
||||||
type: ActionTypes.RefreshDatasource,
|
type: ActionTypes.RefreshDatasource,
|
||||||
callback: () => fetchData(dataSource),
|
callback: () => refresh(),
|
||||||
metadata: { dataSource },
|
metadata: { dataSource },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: ActionTypes.SetDataProviderQuery,
|
||||||
|
callback: newQuery => (query = newQuery),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
$: dataContext = { rows, schema, rowsLength: rows.length }
|
$: dataContext = {
|
||||||
|
rows,
|
||||||
|
schema,
|
||||||
|
rowsLength: rows.length,
|
||||||
|
|
||||||
|
// Undocumented properties. These aren't supposed to be used in builder
|
||||||
|
// bindings, but are used internally by other components
|
||||||
|
id: $component?.id,
|
||||||
|
state: { query },
|
||||||
|
}
|
||||||
|
|
||||||
const getSortType = (schema, sortColumn) => {
|
const getSortType = (schema, sortColumn) => {
|
||||||
if (!schema || !sortColumn || !schema[sortColumn]) {
|
if (!schema || !sortColumn || !schema[sortColumn]) {
|
||||||
|
@ -73,36 +97,18 @@
|
||||||
return type === "number" ? "number" : "string"
|
return type === "number" ? "number" : "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildLuceneQuery = filter => {
|
const refresh = async () => {
|
||||||
let query = {
|
if (schemaLoaded && !nestedProvider) {
|
||||||
string: {},
|
fetchData(
|
||||||
fuzzy: {},
|
dataSource,
|
||||||
range: {},
|
query,
|
||||||
equal: {},
|
limit,
|
||||||
notEqual: {},
|
sortColumn,
|
||||||
empty: {},
|
sortOrder,
|
||||||
notEmpty: {},
|
sortType,
|
||||||
|
paginate
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (Array.isArray(filter)) {
|
|
||||||
filter.forEach(({ operator, field, type, value }) => {
|
|
||||||
if (operator.startsWith("range")) {
|
|
||||||
if (!query.range[field]) {
|
|
||||||
query.range[field] = {
|
|
||||||
low: type === "number" ? Number.MIN_SAFE_INTEGER : "0000",
|
|
||||||
high: type === "number" ? Number.MAX_SAFE_INTEGER : "9999",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (operator === "rangeLow") {
|
|
||||||
query.range[field].low = value
|
|
||||||
} else if (operator === "rangeHigh") {
|
|
||||||
query.range[field].high = value
|
|
||||||
}
|
|
||||||
} else if (query[operator]) {
|
|
||||||
query[operator][field] = value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchData = async (
|
const fetchData = async (
|
||||||
|
@ -116,6 +122,7 @@
|
||||||
) => {
|
) => {
|
||||||
loading = true
|
loading = true
|
||||||
if (dataSource?.type === "table") {
|
if (dataSource?.type === "table") {
|
||||||
|
// For internal tables we use server-side processing
|
||||||
const res = await API.searchTable({
|
const res = await API.searchTable({
|
||||||
tableId: dataSource.tableId,
|
tableId: dataSource.tableId,
|
||||||
query,
|
query,
|
||||||
|
@ -132,55 +139,27 @@
|
||||||
} else {
|
} else {
|
||||||
bookmarks = [null]
|
bookmarks = [null]
|
||||||
}
|
}
|
||||||
|
} else if (dataSource?.type === "provider") {
|
||||||
|
// For providers referencing another provider, just use the rows it
|
||||||
|
// provides
|
||||||
|
allRows = dataSource?.value?.rows ?? []
|
||||||
} else {
|
} else {
|
||||||
const rows = await API.fetchDatasource(dataSource)
|
// For other data sources like queries or views, fetch all rows from the
|
||||||
allRows = inMemoryFilterRows(rows, filter)
|
// server
|
||||||
|
allRows = await API.fetchDatasource(dataSource)
|
||||||
}
|
}
|
||||||
loading = false
|
loading = false
|
||||||
loaded = true
|
loaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const inMemoryFilterRows = (rows, filter) => {
|
|
||||||
let filteredData = [...rows]
|
|
||||||
Object.entries(filter || {}).forEach(([field, value]) => {
|
|
||||||
if (value != null && value !== "") {
|
|
||||||
filteredData = filteredData.filter(row => {
|
|
||||||
return row[field] === value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return filteredData
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortRows = (rows, sortColumn, sortOrder) => {
|
|
||||||
if (!sortColumn || !sortOrder) {
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
return rows.slice().sort((a, b) => {
|
|
||||||
const colA = a[sortColumn]
|
|
||||||
const colB = b[sortColumn]
|
|
||||||
if (sortOrder === "Descending") {
|
|
||||||
return colA > colB ? -1 : 1
|
|
||||||
} else {
|
|
||||||
return colA > colB ? 1 : -1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const limitRows = (rows, limit) => {
|
|
||||||
const numLimit = parseFloat(limit)
|
|
||||||
if (isNaN(numLimit)) {
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
return rows.slice(0, numLimit)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSchema = async dataSource => {
|
const getSchema = async dataSource => {
|
||||||
if (dataSource?.schema) {
|
if (dataSource?.schema) {
|
||||||
schema = dataSource.schema
|
schema = dataSource.schema
|
||||||
} else if (dataSource?.tableId) {
|
} else if (dataSource?.tableId) {
|
||||||
const definition = await API.fetchTableDefinition(dataSource.tableId)
|
const definition = await API.fetchTableDefinition(dataSource.tableId)
|
||||||
schema = definition?.schema ?? {}
|
schema = definition?.schema ?? {}
|
||||||
|
} else if (dataSource?.type === "provider") {
|
||||||
|
schema = dataSource.value?.schema ?? {}
|
||||||
} else {
|
} else {
|
||||||
schema = {}
|
schema = {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
<script>
|
||||||
|
import { Select } from "@budibase/bbui"
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import dayjs from "dayjs"
|
||||||
|
import utc from "dayjs/plugin/utc"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
dayjs.extend(utc)
|
||||||
|
|
||||||
|
export let dataProvider
|
||||||
|
export let field
|
||||||
|
export let defaultValue
|
||||||
|
|
||||||
|
const dataContext = getContext("context")
|
||||||
|
const component = getContext("component")
|
||||||
|
const { styleable, builderStore, ActionTypes, getAction } = getContext("sdk")
|
||||||
|
|
||||||
|
const setQuery = getAction(dataProvider?.id, ActionTypes.SetDataProviderQuery)
|
||||||
|
const options = [
|
||||||
|
"Last 1 day",
|
||||||
|
"Last 7 days",
|
||||||
|
"Last 30 days",
|
||||||
|
"Last 3 months",
|
||||||
|
"Last 6 months",
|
||||||
|
"Last 1 year",
|
||||||
|
]
|
||||||
|
let value = options.includes(defaultValue) ? defaultValue : "Last 30 days"
|
||||||
|
|
||||||
|
const updateDateRange = option => {
|
||||||
|
const query = dataProvider?.state?.query
|
||||||
|
if (!query || !setQuery) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
value = option
|
||||||
|
let low = dayjs.utc().subtract(1, "year")
|
||||||
|
let high = dayjs.utc().add(1, "day")
|
||||||
|
|
||||||
|
if (option === "Last 1 day") {
|
||||||
|
low = dayjs.utc().subtract(1, "day")
|
||||||
|
} else if (option === "Last 7 days") {
|
||||||
|
low = dayjs.utc().subtract(7, "days")
|
||||||
|
} else if (option === "Last 30 days") {
|
||||||
|
low = dayjs.utc().subtract(30, "days")
|
||||||
|
} else if (option === "Last 3 months") {
|
||||||
|
low = dayjs.utc().subtract(3, "months")
|
||||||
|
} else if (option === "Last 6 months") {
|
||||||
|
low = dayjs.utc().subtract(6, "months")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update data provider query with the new filter
|
||||||
|
setQuery({
|
||||||
|
...query,
|
||||||
|
range: {
|
||||||
|
...query.range,
|
||||||
|
[field]: {
|
||||||
|
high: high.format(),
|
||||||
|
low: low.format(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the range on mount to the initial value
|
||||||
|
onMount(() => {
|
||||||
|
updateDateRange(value)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div use:styleable={$component.styles}>
|
||||||
|
<Select
|
||||||
|
placeholder={null}
|
||||||
|
{options}
|
||||||
|
{value}
|
||||||
|
on:change={e => updateDateRange(e.detail)}
|
||||||
|
/>
|
||||||
|
</div>
|
|
@ -22,6 +22,7 @@
|
||||||
>
|
>
|
||||||
{#if fieldState}
|
{#if fieldState}
|
||||||
<CoreTextField
|
<CoreTextField
|
||||||
|
updateOnChange={false}
|
||||||
value={$fieldState.value}
|
value={$fieldState.value}
|
||||||
on:change={e => fieldApi.setValue(e.detail)}
|
on:change={e => fieldApi.setValue(e.detail)}
|
||||||
disabled={$fieldState.disabled}
|
disabled={$fieldState.disabled}
|
||||||
|
|
|
@ -27,6 +27,7 @@ export { default as cardhorizontal } from "./CardHorizontal.svelte"
|
||||||
export { default as cardstat } from "./CardStat.svelte"
|
export { default as cardstat } from "./CardStat.svelte"
|
||||||
export { default as icon } from "./Icon.svelte"
|
export { default as icon } from "./Icon.svelte"
|
||||||
export { default as backgroundimage } from "./BackgroundImage.svelte"
|
export { default as backgroundimage } from "./BackgroundImage.svelte"
|
||||||
|
export { default as daterangepicker } from "./DateRangePicker.svelte"
|
||||||
export * from "./charts"
|
export * from "./charts"
|
||||||
export * from "./forms"
|
export * from "./forms"
|
||||||
export * from "./table"
|
export * from "./table"
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/**
|
||||||
|
* Builds a lucene JSON query from the filter structure generated in the builder
|
||||||
|
* @param filter the builder filter structure
|
||||||
|
*/
|
||||||
|
export const buildLuceneQuery = filter => {
|
||||||
|
let query = {
|
||||||
|
string: {},
|
||||||
|
fuzzy: {},
|
||||||
|
range: {},
|
||||||
|
equal: {},
|
||||||
|
notEqual: {},
|
||||||
|
empty: {},
|
||||||
|
notEmpty: {},
|
||||||
|
}
|
||||||
|
if (Array.isArray(filter)) {
|
||||||
|
filter.forEach(({ operator, field, type, value }) => {
|
||||||
|
if (operator.startsWith("range")) {
|
||||||
|
if (!query.range[field]) {
|
||||||
|
query.range[field] = {
|
||||||
|
low:
|
||||||
|
type === "number"
|
||||||
|
? Number.MIN_SAFE_INTEGER
|
||||||
|
: "0000-00-00T00:00:00.000Z",
|
||||||
|
high:
|
||||||
|
type === "number"
|
||||||
|
? Number.MAX_SAFE_INTEGER
|
||||||
|
: "9999-00-00T00:00:00.000Z",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (operator === "rangeLow" && value != null && value !== "") {
|
||||||
|
query.range[field].low = value
|
||||||
|
} else if (operator === "rangeHigh" && value != null && value !== "") {
|
||||||
|
query.range[field].high = value
|
||||||
|
}
|
||||||
|
} else if (query[operator]) {
|
||||||
|
query[operator][field] = value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a client-side lucene search on an array of data
|
||||||
|
* @param docs the data
|
||||||
|
* @param query the JSON lucene query
|
||||||
|
*/
|
||||||
|
export const luceneQuery = (docs, query) => {
|
||||||
|
if (!query) {
|
||||||
|
return docs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterates over a set of filters and evaluates a fail function against a doc
|
||||||
|
const match = (type, failFn) => doc => {
|
||||||
|
const filters = Object.entries(query[type] || {})
|
||||||
|
for (let i = 0; i < filters.length; i++) {
|
||||||
|
if (failFn(filters[i][0], filters[i][1], doc)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process a string match (fails if the value does not start with the string)
|
||||||
|
const stringMatch = match("string", (key, value, doc) => {
|
||||||
|
return !doc[key] || !doc[key].startsWith(value)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Process a range match
|
||||||
|
const rangeMatch = match("range", (key, value, doc) => {
|
||||||
|
return !doc[key] || doc[key] < value.low || doc[key] > value.high
|
||||||
|
})
|
||||||
|
|
||||||
|
// Process an equal match (fails if the value is different)
|
||||||
|
const equalMatch = match("equal", (key, value, doc) => {
|
||||||
|
return doc[key] !== value
|
||||||
|
})
|
||||||
|
|
||||||
|
// Process a not-equal match (fails if the value is the same)
|
||||||
|
const notEqualMatch = match("notEqual", (key, value, doc) => {
|
||||||
|
return doc[key] === value
|
||||||
|
})
|
||||||
|
|
||||||
|
// Process an empty match (fails if the value is not empty)
|
||||||
|
const emptyMatch = match("empty", (key, value, doc) => {
|
||||||
|
return doc[key] != null && doc[key] !== ""
|
||||||
|
})
|
||||||
|
|
||||||
|
// Process a not-empty match (fails is the value is empty)
|
||||||
|
const notEmptyMatch = match("notEmpty", (key, value, doc) => {
|
||||||
|
return doc[key] == null || doc[key] === ""
|
||||||
|
})
|
||||||
|
|
||||||
|
// Match a document against all criteria
|
||||||
|
const docMatch = doc => {
|
||||||
|
return (
|
||||||
|
stringMatch(doc) &&
|
||||||
|
rangeMatch(doc) &&
|
||||||
|
equalMatch(doc) &&
|
||||||
|
notEqualMatch(doc) &&
|
||||||
|
emptyMatch(doc) &&
|
||||||
|
notEmptyMatch(doc)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all docs
|
||||||
|
return docs.filter(docMatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a client-side sort from the equivalent server-side lucene sort
|
||||||
|
* parameters.
|
||||||
|
* @param docs the data
|
||||||
|
* @param sort the sort column
|
||||||
|
* @param sortOrder the sort order ("ascending" or "descending")
|
||||||
|
* @param sortType the type of sort ("string" or "number")
|
||||||
|
*/
|
||||||
|
export const luceneSort = (docs, sort, sortOrder, sortType = "string") => {
|
||||||
|
if (!sort || !sortOrder || !sortType) {
|
||||||
|
return docs
|
||||||
|
}
|
||||||
|
const parse = sortType === "string" ? x => `${x}` : x => parseFloat(x)
|
||||||
|
return docs.slice().sort((a, b) => {
|
||||||
|
const colA = parse(a[sort])
|
||||||
|
const colB = parse(b[sort])
|
||||||
|
if (sortOrder === "Descending") {
|
||||||
|
return colA > colB ? -1 : 1
|
||||||
|
} else {
|
||||||
|
return colA > colB ? 1 : -1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limits the specified docs to the specified number of rows from the equivalent
|
||||||
|
* server-side lucene limit parameters.
|
||||||
|
* @param docs the data
|
||||||
|
* @param limit the number of docs to limit to
|
||||||
|
*/
|
||||||
|
export const luceneLimit = (docs, limit) => {
|
||||||
|
const numLimit = parseFloat(limit)
|
||||||
|
if (isNaN(numLimit)) {
|
||||||
|
return docs
|
||||||
|
}
|
||||||
|
return docs.slice(0, numLimit)
|
||||||
|
}
|
|
@ -2,6 +2,59 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@adobe/spectrum-css-workflow-icons@^1.2.1":
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@adobe/spectrum-css-workflow-icons/-/spectrum-css-workflow-icons-1.2.1.tgz#7e2cb3fcfb5c8b12d7275afafbb6ec44913551b4"
|
||||||
|
integrity sha512-uVgekyBXnOVkxp+CUssjN/gefARtudZC8duEn1vm0lBQFwGRZFlDEzU1QC+aIRWCrD1Z8OgRpmBYlSZ7QS003w==
|
||||||
|
|
||||||
|
"@budibase/bbui@^0.9.12":
|
||||||
|
version "0.9.16"
|
||||||
|
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.16.tgz#6cf454790d3e8d776d4d642379958a56260b0840"
|
||||||
|
integrity sha512-8hV4Vj3h3clzLclNTvVxPdOK9f02xTIcXA/lW1QPD9HZLOUxDogphujpDpb+E0/NevPlPYMHaX68kVtefNL5Jw==
|
||||||
|
dependencies:
|
||||||
|
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||||
|
"@spectrum-css/actionbutton" "^1.0.1"
|
||||||
|
"@spectrum-css/actiongroup" "^1.0.1"
|
||||||
|
"@spectrum-css/avatar" "^3.0.2"
|
||||||
|
"@spectrum-css/button" "^3.0.1"
|
||||||
|
"@spectrum-css/buttongroup" "^3.0.2"
|
||||||
|
"@spectrum-css/checkbox" "^3.0.2"
|
||||||
|
"@spectrum-css/dialog" "^3.0.1"
|
||||||
|
"@spectrum-css/divider" "^1.0.1"
|
||||||
|
"@spectrum-css/dropzone" "^3.0.2"
|
||||||
|
"@spectrum-css/fieldgroup" "^3.0.2"
|
||||||
|
"@spectrum-css/fieldlabel" "^3.0.1"
|
||||||
|
"@spectrum-css/icon" "^3.0.1"
|
||||||
|
"@spectrum-css/illustratedmessage" "^3.0.2"
|
||||||
|
"@spectrum-css/inputgroup" "^3.0.2"
|
||||||
|
"@spectrum-css/label" "^2.0.10"
|
||||||
|
"@spectrum-css/link" "^3.1.1"
|
||||||
|
"@spectrum-css/menu" "^3.0.1"
|
||||||
|
"@spectrum-css/modal" "^3.0.1"
|
||||||
|
"@spectrum-css/pagination" "^3.0.3"
|
||||||
|
"@spectrum-css/picker" "^1.0.1"
|
||||||
|
"@spectrum-css/popover" "^3.0.1"
|
||||||
|
"@spectrum-css/progressbar" "^1.0.2"
|
||||||
|
"@spectrum-css/progresscircle" "^1.0.2"
|
||||||
|
"@spectrum-css/radio" "^3.0.2"
|
||||||
|
"@spectrum-css/search" "^3.0.2"
|
||||||
|
"@spectrum-css/sidenav" "^3.0.2"
|
||||||
|
"@spectrum-css/statuslight" "^3.0.2"
|
||||||
|
"@spectrum-css/switch" "^1.0.2"
|
||||||
|
"@spectrum-css/table" "^3.0.1"
|
||||||
|
"@spectrum-css/tabs" "^3.0.1"
|
||||||
|
"@spectrum-css/tags" "^3.0.2"
|
||||||
|
"@spectrum-css/textfield" "^3.0.1"
|
||||||
|
"@spectrum-css/toast" "^3.0.1"
|
||||||
|
"@spectrum-css/tooltip" "^3.0.3"
|
||||||
|
"@spectrum-css/treeview" "^3.0.2"
|
||||||
|
"@spectrum-css/typography" "^3.0.1"
|
||||||
|
"@spectrum-css/underlay" "^2.0.9"
|
||||||
|
"@spectrum-css/vars" "^3.0.1"
|
||||||
|
dayjs "^1.10.4"
|
||||||
|
svelte-flatpickr "^3.1.0"
|
||||||
|
svelte-portal "^1.0.0"
|
||||||
|
|
||||||
"@rollup/pluginutils@^4.1.0":
|
"@rollup/pluginutils@^4.1.0":
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.0.tgz#0dcc61c780e39257554feb7f77207dceca13c838"
|
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.0.tgz#0dcc61c780e39257554feb7f77207dceca13c838"
|
||||||
|
@ -10,6 +63,98 @@
|
||||||
estree-walker "^2.0.1"
|
estree-walker "^2.0.1"
|
||||||
picomatch "^2.2.2"
|
picomatch "^2.2.2"
|
||||||
|
|
||||||
|
"@spectrum-css/actionbutton@^1.0.1":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.0.3.tgz#8f7342a69b303c5acdcfa0a59f5e9267b9f3cb30"
|
||||||
|
integrity sha512-P9qoCPSiZ1SB6ZYqK5hub0vGty00YYqonQE0KTjtb1i+T1nYR/87vWqVPERx9j63uhgZncjwFYaThTvRqye7eQ==
|
||||||
|
|
||||||
|
"@spectrum-css/actiongroup@^1.0.1":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/actiongroup/-/actiongroup-1.0.3.tgz#4713ce65e6f5c72c404a7b638fbc3b4fd7e3874f"
|
||||||
|
integrity sha512-NlB9Q4ZlWixXxymoPIYG6g2hkwAGKFodHWPFfxHD8ddkjXWRB9G2akUP7cfsJ4DcYn4VisUORCOYQwqDiSmboQ==
|
||||||
|
|
||||||
|
"@spectrum-css/avatar@^3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/avatar/-/avatar-3.0.2.tgz#4f1826223eae330e64b6d3cc899e9bc2e98dac95"
|
||||||
|
integrity sha512-wEczvSqxttTWSiL3cOvXV/RmGRwSkw2w6+slcHhnf0kb7ovymMM+9oz8vvEpEsSeo5u598bc+7ktrKFpAd6soQ==
|
||||||
|
|
||||||
|
"@spectrum-css/button@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/button/-/button-3.0.3.tgz#2df1efaab6c7e0b3b06cb4b59e1eae59c7f1fc84"
|
||||||
|
integrity sha512-6CnLPqqtaU/PcSSIGeGRi0iFIIxIUByYLKFO6zn5NEUc12KQ28dJ4PLwB6WBa0L8vRoAGlnWWH2ZZweTijbXgg==
|
||||||
|
|
||||||
|
"@spectrum-css/buttongroup@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/buttongroup/-/buttongroup-3.0.3.tgz#719d868845ac9d2c4f939c1b9f6044507902d5aa"
|
||||||
|
integrity sha512-eXl8U4QWMWXqyTu654FdQdEGnmczgOYlpIFSHyCMVjhtPqZp2xwnLFiGh6LKw+bLio6eeOZ0L+vpk1GcoYqgkw==
|
||||||
|
|
||||||
|
"@spectrum-css/checkbox@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/checkbox/-/checkbox-3.0.3.tgz#8577067fc8b97e4609f92bd242364937a533a7bb"
|
||||||
|
integrity sha512-QVG9uMHq+lh70Dh6mDNnY+vEvNz2p7VC6xgLfDYfijp2qeiqYPq72fQK6p/SiyqPk96ZACzNRwgeROU6Xf6Wgg==
|
||||||
|
|
||||||
|
"@spectrum-css/dialog@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/dialog/-/dialog-3.0.3.tgz#7715a4ea435e753afb623d99ca5917ed1bcd6f34"
|
||||||
|
integrity sha512-AhmKgfRIVyTe3ABiJ8lLUQL34VB/H6fN16na2LlbDRJvyRMzkdN1Xf2i6U3f4OMd3qQ8Gm5xat4BvMxIQPBAUQ==
|
||||||
|
|
||||||
|
"@spectrum-css/divider@^1.0.1":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/divider/-/divider-1.0.3.tgz#639e2ebaa0834efa40f42397668bbd5c153ea385"
|
||||||
|
integrity sha512-Zy4Rn40w8UtzMh3wx/U9+CepSCpm1aOCGftHgWDub0XZuVTzh0c1WwyzTuLCx2Hf21z5VRGNiDh8bGEEzSbtNA==
|
||||||
|
dependencies:
|
||||||
|
"@spectrum-css/vars" "^3.0.2"
|
||||||
|
|
||||||
|
"@spectrum-css/dropzone@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/dropzone/-/dropzone-3.0.3.tgz#aee71697a2c195947599d7541b858c3c198741dc"
|
||||||
|
integrity sha512-ujrswdtB6bHigklyHsm6zomFd6rUnKJ3xVVRjroVF4+ouK4DxK5tX0iVd0EW6AOfOjx4Cc28uyFot3fpxp+MQw==
|
||||||
|
|
||||||
|
"@spectrum-css/fieldgroup@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/fieldgroup/-/fieldgroup-3.0.3.tgz#85d85da048d08200f25ceab378026dd2b11e0bb2"
|
||||||
|
integrity sha512-wXUXTXN1CPnR7M4Ltd+3uh7BfcNGUV1+Xe0/h0tCpq/j+S2Sd4xo7/pUMdU19sIDrAAtpEFp1tt+nouHcU5HGQ==
|
||||||
|
|
||||||
|
"@spectrum-css/fieldlabel@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/fieldlabel/-/fieldlabel-3.0.3.tgz#f73c04d20734d4718ffb620dc46458904685b449"
|
||||||
|
integrity sha512-nEvIkEXCD5n4fW67Unq6Iu7VXoauEd/JGpfTY02VsC5p4FJLnwKfPDbJUuUsqClAxqw7nAsmXVKtn4zQFf5yPQ==
|
||||||
|
|
||||||
|
"@spectrum-css/icon@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/icon/-/icon-3.0.3.tgz#5c612822380927087aebd526855d82ed2c3e2cba"
|
||||||
|
integrity sha512-hyloKOejPCXhP3MBNsm3SjR9j8xT1R1S19p32KW/0Qhj+VMUtfyEPmevyFptpn7wcovQccdl/vZVIVDuML/imw==
|
||||||
|
|
||||||
|
"@spectrum-css/illustratedmessage@^3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/illustratedmessage/-/illustratedmessage-3.0.2.tgz#6a480be98b027e050b086e7899e40d87adb0a8c0"
|
||||||
|
integrity sha512-dqnE8X27bGcO0HN8+dYx8O4o0dNNIAqeivOzDHhe2El+V4dTzMrNIerF6G0NLm3GjVf6XliwmitsZK+K6FmbtA==
|
||||||
|
|
||||||
|
"@spectrum-css/inputgroup@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/inputgroup/-/inputgroup-3.0.3.tgz#00c9a370ddc2c55cf0f37dd6069faa9501fd7eb5"
|
||||||
|
integrity sha512-FqRJTiLL7jiGfzDVXWUGVLqHryJjCcqQIrqAi+Tq0oenapzsBe2qc/zIrKgh2wtMI+NTIBLXTECvij3L1HlqAg==
|
||||||
|
|
||||||
|
"@spectrum-css/label@^2.0.10":
|
||||||
|
version "2.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/label/-/label-2.0.10.tgz#2368651d7636a19385b5d300cdf6272db1916001"
|
||||||
|
integrity sha512-xCbtEiQkZIlLdWFikuw7ifDCC21DOC/KMgVrrVJHXFc4KRQe9LTZSqmGF3tovm+CSq1adE59mYoTbojVQ9YuEQ==
|
||||||
|
|
||||||
|
"@spectrum-css/link@^3.1.1":
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/link/-/link-3.1.3.tgz#b0e560a7e0acdb4a2b329b6669696aa3438f5993"
|
||||||
|
integrity sha512-8Pmy5d73MwKcATTPaj+fSrZYnIw7GmfX40AvpC1xx5LauOxsbUb4AVNp1kn2H8rrOBmxF7czyhoBBhEiv66QUg==
|
||||||
|
|
||||||
|
"@spectrum-css/menu@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/menu/-/menu-3.0.3.tgz#46a9b221bb5f470a2f8a934bdfd512d84d2fdc4d"
|
||||||
|
integrity sha512-qKA9J/MrikNKIpCEHsAazG2vY3im5tjGCmo6p9Pdnu8/aQMsiuZDHZayukeCttJUZkrb9guDVL9OIHlK5RZvcQ==
|
||||||
|
|
||||||
|
"@spectrum-css/modal@^3.0.1":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/modal/-/modal-3.0.2.tgz#58b6621cab65f90788d310374f40df1f7090473f"
|
||||||
|
integrity sha512-YnIivJhoaao7Otu+HV7sgebPyFbO6sd/oMvTN/Rb2wwgnaMnIIuIRdGandSrcgotN2uNgs+P0knG6mv/xA1/dg==
|
||||||
|
|
||||||
"@spectrum-css/page@^3.0.1":
|
"@spectrum-css/page@^3.0.1":
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@spectrum-css/page/-/page-3.0.1.tgz#5e1c3dd5b1a1ee591f9d636b75f03665f542d846"
|
resolved "https://registry.yarnpkg.com/@spectrum-css/page/-/page-3.0.1.tgz#5e1c3dd5b1a1ee591f9d636b75f03665f542d846"
|
||||||
|
@ -17,11 +162,111 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@spectrum-css/vars" "^3.0.1"
|
"@spectrum-css/vars" "^3.0.1"
|
||||||
|
|
||||||
|
"@spectrum-css/pagination@^3.0.3":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/pagination/-/pagination-3.0.3.tgz#b204c3ada384c4af751a354bc428346d82eeea65"
|
||||||
|
integrity sha512-OJ/v9GeNXJOZ9Yr9LDBYPrR2NCiLOWP9wANT/a5sqFuugRnQbn/HYMnRp9TBxwpDY6ihaPo0T/wi7kLiAJFdDw==
|
||||||
|
|
||||||
|
"@spectrum-css/picker@^1.0.1":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/picker/-/picker-1.0.3.tgz#21379bcf8ae94277deeb6ad65dcd9e2bbfacb487"
|
||||||
|
integrity sha512-oHLGxBx5BwVCSGo7/T1C9PTHX1+/5AmVjyLiTJ4UoIdSJmOERw9YcRZbcGZgBJNWbxcjr4TyGtwj1EcSjEy97w==
|
||||||
|
|
||||||
|
"@spectrum-css/popover@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/popover/-/popover-3.0.3.tgz#6fb69873474fb968afb738eacb9e121f93e83a09"
|
||||||
|
integrity sha512-KvmXv4TV19FBx39KfmgVlDYtvtBqv/8RRK7RRLDDHGViTxZtShjVsVpwIgfkfgn4iJztCnXpWzFqRXWUu2XCpQ==
|
||||||
|
|
||||||
|
"@spectrum-css/progressbar@^1.0.2":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/progressbar/-/progressbar-1.0.3.tgz#f70bcc38a2a21cff2f422ec825724ebbb9455e67"
|
||||||
|
integrity sha512-vJHplefUuy8+NjCw1X7fLbqHVGNVBpvGFXNAeaIj4SFf4ygxiUq/5c9iRhhsCQixEsJlfD/b7BnGXU7BUDkr6Q==
|
||||||
|
|
||||||
|
"@spectrum-css/progresscircle@^1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/progresscircle/-/progresscircle-1.0.2.tgz#258ea9170fb70f795edda03e38a61d93bef4487c"
|
||||||
|
integrity sha512-JLULpyzjIY95lzlWR1yE1gv4l1K6p+scQ+edmuZZUHBzwM3pUtkvHJmUlA9TYdResUYW6Uka60VRdY6lZ8gnFQ==
|
||||||
|
|
||||||
|
"@spectrum-css/radio@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/radio/-/radio-3.0.3.tgz#25c3bc5e9c30a8a8ae728717b7c7fb736cdae640"
|
||||||
|
integrity sha512-LaLGfz/eGNR2iyqouXYILIA+pKRqF769iPdwM0REm5RpWvMQDD7rPZ/kWlg18owjaFsyllEp25gEjmhRJIIVOw==
|
||||||
|
|
||||||
|
"@spectrum-css/search@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/search/-/search-3.0.3.tgz#3415dc106aca0d5dd996e87084a1b47c2b95a882"
|
||||||
|
integrity sha512-kdLpKTt0obljuhS1q1tukujRlvSs8sBwij76D4Qp8KpMzwePfZyvv1kYzuWPNZfTeISxWsmyZ6Wxd1uvzjn+UA==
|
||||||
|
|
||||||
|
"@spectrum-css/sidenav@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/sidenav/-/sidenav-3.0.3.tgz#132141fbd2500a927c312fa4e1d712c438b3d597"
|
||||||
|
integrity sha512-cQ+CgwjxGftrcc79i1XnGd66QTl7H7zopSU0UTV4Qq7hvqfrjjWxfZ6b+3tezrrhNlDope1ff9o8sm67PsPXtg==
|
||||||
|
|
||||||
|
"@spectrum-css/statuslight@^3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/statuslight/-/statuslight-3.0.2.tgz#dc54b6cd113413dcdb909c486b5d7bae60db65c5"
|
||||||
|
integrity sha512-xodB8g8vGJH20XmUj9ZsPlM1jHrGeRbvmVXkz0q7YvQrYAhim8pP3W+XKKZAletPFAuu8cmUOc6SWn6i4X4z6w==
|
||||||
|
|
||||||
|
"@spectrum-css/switch@^1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/switch/-/switch-1.0.2.tgz#f0b4c69271964573e02b08e90998096e49e1de44"
|
||||||
|
integrity sha512-zqmHpgWPNg1gEwdUNFYV3CBX5JaeALfIqcJIxE0FLZqr9d1C4+oLE0ItIFzt1bwr4bFAOmkEpvtiY+amluzGxQ==
|
||||||
|
|
||||||
|
"@spectrum-css/table@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/table/-/table-3.0.3.tgz#7f7f19905ef3275cbf907ce3a5818e63c30b2caf"
|
||||||
|
integrity sha512-nxwzVjLPsXoY/v4sdxOVYLcC+cEbGgJyLcLclT5LT9MGSbngFeUMJzzVR4EvehzuN4dH7hrATG7Mbuq29Mf0Hg==
|
||||||
|
|
||||||
|
"@spectrum-css/tabs@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/tabs/-/tabs-3.0.3.tgz#51dd6f168c897b0fdc3a7e9f901df7bd2288b4fc"
|
||||||
|
integrity sha512-iLP1I72bJWz9APdQB1jiw+pOv5a7N+hYOCJvRoc56Us/hJKVzowkyGRe3uH+8v36nCG9bHxiAQNLoU8eXisVrg==
|
||||||
|
|
||||||
|
"@spectrum-css/tags@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/tags/-/tags-3.0.3.tgz#fc76d2735cdc442de91b7eb3bee49a928c0767ac"
|
||||||
|
integrity sha512-SL8vPxVDfWcY5VdIuyl0TImEXcOU1I7yCyXkk7MudMwfnYs81FaIyY32hFV9OHj0Tz/36UzRzc7AVMSuRQ53pw==
|
||||||
|
|
||||||
|
"@spectrum-css/textfield@^3.0.1":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/textfield/-/textfield-3.0.2.tgz#907f62d2dc82852dd6236a820be99e252b531631"
|
||||||
|
integrity sha512-nkFgAb0cP4jUodkUBErMNfyF78jJLtgL1Mrr9/rvGpGobo10IAbb8zZY4CkZ64o8XmMy/85+wZTKcx+KHatqpg==
|
||||||
|
|
||||||
|
"@spectrum-css/toast@^3.0.1":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/toast/-/toast-3.0.3.tgz#97c1527384707600832ecda35643ed304615250f"
|
||||||
|
integrity sha512-CjLeaMs+cjUXojCCRtbj0YkD2BoZW16kjj2o5omkEpUTjA34IJ8xJ1a+CCtDILWekhXvN0MBN4sbumcnwcnx8w==
|
||||||
|
|
||||||
|
"@spectrum-css/tooltip@^3.0.3":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/tooltip/-/tooltip-3.0.3.tgz#26b8ca3b3d30e29630244d85eb4fc11d0c841281"
|
||||||
|
integrity sha512-ztRF7WW1FzyNavXBRc+80z67UoOrY9wl3cMYsVD3MpDnyxdzP8cjza1pCcolKBaFqRTcQKkxKw3GWtGICRKR5A==
|
||||||
|
|
||||||
|
"@spectrum-css/treeview@^3.0.2":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/treeview/-/treeview-3.0.3.tgz#aeda5175158b9f8d7529cb2b394428eb2a428046"
|
||||||
|
integrity sha512-D5gGzZC/KtRArdx86Mesc9+99W9nTbUOeyYGqoJoAfJSOttoT6Tk5CrDvlCmAqjKf5rajemAkGri1ChqvUIwkw==
|
||||||
|
|
||||||
|
"@spectrum-css/typography@^3.0.1":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/typography/-/typography-3.0.2.tgz#ea3ca0a60e18064527819d48c8c4364cab4fcd38"
|
||||||
|
integrity sha512-5ZOLmQe0edzsDMyhghUd4hBb5uxGsFrxzf+WasfcUw9klSfTsRZ09n1BsaaWbgrLjlMQ+EEHS46v5VNo0Ms2CA==
|
||||||
|
|
||||||
|
"@spectrum-css/underlay@^2.0.9":
|
||||||
|
version "2.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/underlay/-/underlay-2.0.10.tgz#8b75b646605a311850f6620caa18d4996cd64ed7"
|
||||||
|
integrity sha512-PmsmkzeGD/rY4pp3ILXHt9w8BW7uaEqXe08hQRS7rGki7wqCpG4mE0/8N3yEcA3QxWQclmG9gdkg5uz6wMmYzA==
|
||||||
|
|
||||||
"@spectrum-css/vars@^3.0.1":
|
"@spectrum-css/vars@^3.0.1":
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.1.tgz#561fd69098f896a647242dd8d6108af603bfa31e"
|
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.1.tgz#561fd69098f896a647242dd8d6108af603bfa31e"
|
||||||
integrity sha512-l4oRcCOqInChYXZN6OQhpe3isk6l4OE6Ys8cgdlsiKp53suNoQxyyd9p/eGRbCjZgH3xQ8nK0t4DHa7QYC0S6w==
|
integrity sha512-l4oRcCOqInChYXZN6OQhpe3isk6l4OE6Ys8cgdlsiKp53suNoQxyyd9p/eGRbCjZgH3xQ8nK0t4DHa7QYC0S6w==
|
||||||
|
|
||||||
|
"@spectrum-css/vars@^3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.2.tgz#ea9062c3c98dfc6ba59e5df14a03025ad8969999"
|
||||||
|
integrity sha512-vzS9KqYXot4J3AEER/u618MXWAS+IoMvYMNrOoscKiLLKYQWenaueakUWulFonToPd/9vIpqtdbwxznqrK5qDw==
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte@^1.0.0-next.5":
|
"@sveltejs/vite-plugin-svelte@^1.0.0-next.5":
|
||||||
version "1.0.0-next.5"
|
version "1.0.0-next.5"
|
||||||
resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.5.tgz#8cf608f7a3c33dfa5b648397aae1ba90e6a4883f"
|
resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.5.tgz#8cf608f7a3c33dfa5b648397aae1ba90e6a4883f"
|
||||||
|
@ -80,6 +325,11 @@ colorette@^1.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
||||||
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
||||||
|
|
||||||
|
dayjs@^1.10.4, dayjs@^1.10.5:
|
||||||
|
version "1.10.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.5.tgz#5600df4548fc2453b3f163ebb2abbe965ccfb986"
|
||||||
|
integrity sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==
|
||||||
|
|
||||||
debug@^4.3.2:
|
debug@^4.3.2:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||||
|
@ -226,6 +476,11 @@ svelte-hmr@^0.13.3:
|
||||||
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.13.3.tgz#fba5739b477ea44caf70e542a24a4352bee2b897"
|
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.13.3.tgz#fba5739b477ea44caf70e542a24a4352bee2b897"
|
||||||
integrity sha512-gagW62pLQ2lULmvNA3pIZu9pBCYOaGu3rQikUOv6Nokz5VxUgT9/mQLfMxj9phDEKHCg/lgr3i6PkqZDbO9P2Q==
|
integrity sha512-gagW62pLQ2lULmvNA3pIZu9pBCYOaGu3rQikUOv6Nokz5VxUgT9/mQLfMxj9phDEKHCg/lgr3i6PkqZDbO9P2Q==
|
||||||
|
|
||||||
|
svelte-portal@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/svelte-portal/-/svelte-portal-1.0.0.tgz#36a47c5578b1a4d9b4dc60fa32a904640ec4cdd3"
|
||||||
|
integrity sha512-nHf+DS/jZ6jjnZSleBMSaZua9JlG5rZv9lOGKgJuaZStfevtjIlUJrkLc3vbV8QdBvPPVmvcjTlazAzfKu0v3Q==
|
||||||
|
|
||||||
svelte@^3.38.2:
|
svelte@^3.38.2:
|
||||||
version "3.38.2"
|
version "3.38.2"
|
||||||
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.38.2.tgz#55e5c681f793ae349b5cc2fe58e5782af4275ef5"
|
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.38.2.tgz#55e5c681f793ae349b5cc2fe58e5782af4275ef5"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"description": "Handlebars wrapper for Budibase templating.",
|
"description": "Handlebars wrapper for Budibase templating.",
|
||||||
"main": "src/index.cjs",
|
"main": "src/index.cjs",
|
||||||
"module": "dist/bundle.mjs",
|
"module": "dist/bundle.mjs",
|
||||||
|
|
|
@ -33,7 +33,7 @@ function testObject(object) {
|
||||||
*/
|
*/
|
||||||
module.exports.processObject = async (object, context) => {
|
module.exports.processObject = async (object, context) => {
|
||||||
testObject(object)
|
testObject(object)
|
||||||
for (let key of Object.keys(object)) {
|
for (let key of Object.keys(object || {})) {
|
||||||
if (object[key] != null) {
|
if (object[key] != null) {
|
||||||
let val = object[key]
|
let val = object[key]
|
||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
|
@ -68,7 +68,7 @@ module.exports.processString = async (string, context) => {
|
||||||
*/
|
*/
|
||||||
module.exports.processObjectSync = (object, context) => {
|
module.exports.processObjectSync = (object, context) => {
|
||||||
testObject(object)
|
testObject(object)
|
||||||
for (let key of Object.keys(object)) {
|
for (let key of Object.keys(object || {})) {
|
||||||
let val = object[key]
|
let val = object[key]
|
||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
object[key] = module.exports.processStringSync(object[key], context)
|
object[key] = module.exports.processStringSync(object[key], context)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.9.21",
|
"version": "0.9.27",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -21,8 +21,8 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/auth": "^0.9.21",
|
"@budibase/auth": "^0.9.27",
|
||||||
"@budibase/string-templates": "^0.9.21",
|
"@budibase/string-templates": "^0.9.27",
|
||||||
"@koa/router": "^8.0.0",
|
"@koa/router": "^8.0.0",
|
||||||
"aws-sdk": "^2.811.0",
|
"aws-sdk": "^2.811.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
|
|
@ -2,7 +2,7 @@ const Router = require("@koa/router")
|
||||||
const compress = require("koa-compress")
|
const compress = require("koa-compress")
|
||||||
const zlib = require("zlib")
|
const zlib = require("zlib")
|
||||||
const { routes } = require("./routes")
|
const { routes } = require("./routes")
|
||||||
const { buildAuthMiddleware } = require("@budibase/auth").auth
|
const { buildAuthMiddleware, auditLog } = require("@budibase/auth").auth
|
||||||
|
|
||||||
const PUBLIC_ENDPOINTS = [
|
const PUBLIC_ENDPOINTS = [
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,7 @@ router
|
||||||
}
|
}
|
||||||
return next()
|
return next()
|
||||||
})
|
})
|
||||||
|
.use(auditLog)
|
||||||
|
|
||||||
// error handling middleware
|
// error handling middleware
|
||||||
router.use(async (ctx, next) => {
|
router.use(async (ctx, next) => {
|
||||||
|
|
|
@ -51,12 +51,8 @@ exports.init = async () => {
|
||||||
* make sure redis connection is closed.
|
* make sure redis connection is closed.
|
||||||
*/
|
*/
|
||||||
exports.shutdown = async () => {
|
exports.shutdown = async () => {
|
||||||
if (pwResetClient != null) {
|
if (pwResetClient) await pwResetClient.finish()
|
||||||
await pwResetClient.finish()
|
if (invitationClient) await invitationClient.finish()
|
||||||
}
|
|
||||||
if (invitationClient != null) {
|
|
||||||
await invitationClient.finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -910,7 +910,7 @@ array-unique@^0.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
||||||
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
|
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
|
||||||
|
|
||||||
asn1@~0.2.3:
|
asn1@~0.2.0, asn1@~0.2.3:
|
||||||
version "0.2.4"
|
version "0.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||||
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||||
|
@ -1076,7 +1076,7 @@ base@^0.11.1:
|
||||||
mixin-deep "^1.2.0"
|
mixin-deep "^1.2.0"
|
||||||
pascalcase "^0.1.1"
|
pascalcase "^0.1.1"
|
||||||
|
|
||||||
bcrypt-pbkdf@^1.0.0:
|
bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||||
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||||
|
@ -1093,6 +1093,15 @@ binary-extensions@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||||
|
|
||||||
|
bl@^4.0.3:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||||
|
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
|
||||||
|
dependencies:
|
||||||
|
buffer "^5.5.0"
|
||||||
|
inherits "^2.0.4"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
boxen@^4.2.0:
|
boxen@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
|
resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
|
||||||
|
@ -1337,6 +1346,11 @@ chokidar@^3.2.2:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.1"
|
fsevents "~2.3.1"
|
||||||
|
|
||||||
|
chownr@^1.1.1:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||||
|
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||||
|
|
||||||
ci-info@^2.0.0:
|
ci-info@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
||||||
|
@ -1773,6 +1787,24 @@ diff-sequences@^26.6.2:
|
||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
|
||||||
integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==
|
integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==
|
||||||
|
|
||||||
|
docker-modem@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.0.tgz#cb912ad8daed42f858269fb3be6944df281ec12d"
|
||||||
|
integrity sha512-WwFajJ8I5geZ/dDZ5FDMDA6TBkWa76xWwGIGw8uzUjNUGCN0to83wJ8Oi1AxrJTC0JBn+7fvIxUctnawtlwXeg==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.1.1"
|
||||||
|
readable-stream "^3.5.0"
|
||||||
|
split-ca "^1.0.1"
|
||||||
|
ssh2 "^0.8.7"
|
||||||
|
|
||||||
|
dockerode@^3.3.0:
|
||||||
|
version "3.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.0.tgz#bedaf48ef9fa9124275a54a9881a92374c51008e"
|
||||||
|
integrity sha512-St08lfOjpYCOXEM8XA0VLu3B3hRjtddODphNW5GFoA0AS3JHgoPQKOz0Qmdzg3P+hUPxhb02g1o1Cu1G+U3lRg==
|
||||||
|
dependencies:
|
||||||
|
docker-modem "^3.0.0"
|
||||||
|
tar-fs "~2.0.1"
|
||||||
|
|
||||||
domexception@^2.0.1:
|
domexception@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
|
resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
|
||||||
|
@ -1857,7 +1889,7 @@ encoding-down@^6.3.0:
|
||||||
level-codec "^9.0.0"
|
level-codec "^9.0.0"
|
||||||
level-errors "^2.0.0"
|
level-errors "^2.0.0"
|
||||||
|
|
||||||
end-of-stream@^1.1.0:
|
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||||
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||||
|
@ -2238,6 +2270,11 @@ fresh@~0.5.2:
|
||||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||||
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
||||||
|
|
||||||
|
fs-constants@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||||
|
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
|
@ -3998,6 +4035,11 @@ mixin-deep@^1.2.0:
|
||||||
for-in "^1.0.2"
|
for-in "^1.0.2"
|
||||||
is-extendable "^1.0.1"
|
is-extendable "^1.0.1"
|
||||||
|
|
||||||
|
mkdirp-classic@^0.5.2:
|
||||||
|
version "0.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||||
|
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||||
|
|
||||||
mkdirp@^0.5.0:
|
mkdirp@^0.5.0:
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||||
|
@ -4829,7 +4871,7 @@ readable-stream@1.1.14:
|
||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
string_decoder "~0.10.x"
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
|
@ -5326,6 +5368,11 @@ spdx-license-ids@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
|
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
|
||||||
integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
|
integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
|
||||||
|
|
||||||
|
split-ca@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6"
|
||||||
|
integrity sha1-bIOv82kvphJW4M0ZfgXp3hV2kaY=
|
||||||
|
|
||||||
split-string@^3.0.1, split-string@^3.0.2:
|
split-string@^3.0.1, split-string@^3.0.2:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
|
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
|
||||||
|
@ -5345,6 +5392,22 @@ sprintf-js@~1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||||
|
|
||||||
|
ssh2-streams@~0.4.10:
|
||||||
|
version "0.4.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.10.tgz#48ef7e8a0e39d8f2921c30521d56dacb31d23a34"
|
||||||
|
integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==
|
||||||
|
dependencies:
|
||||||
|
asn1 "~0.2.0"
|
||||||
|
bcrypt-pbkdf "^1.0.2"
|
||||||
|
streamsearch "~0.1.2"
|
||||||
|
|
||||||
|
ssh2@^0.8.7:
|
||||||
|
version "0.8.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3"
|
||||||
|
integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==
|
||||||
|
dependencies:
|
||||||
|
ssh2-streams "~0.4.10"
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.16.1"
|
version "1.16.1"
|
||||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||||
|
@ -5390,6 +5453,11 @@ stealthy-require@^1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
|
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
|
||||||
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
|
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
|
||||||
|
|
||||||
|
streamsearch@~0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||||
|
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
||||||
|
|
||||||
string-length@^4.0.1:
|
string-length@^4.0.1:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
|
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
|
||||||
|
@ -5529,6 +5597,27 @@ symbol-tree@^3.2.4:
|
||||||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||||
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
||||||
|
|
||||||
|
tar-fs@~2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2"
|
||||||
|
integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==
|
||||||
|
dependencies:
|
||||||
|
chownr "^1.1.1"
|
||||||
|
mkdirp-classic "^0.5.2"
|
||||||
|
pump "^3.0.0"
|
||||||
|
tar-stream "^2.0.0"
|
||||||
|
|
||||||
|
tar-stream@^2.0.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
|
||||||
|
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
|
||||||
|
dependencies:
|
||||||
|
bl "^4.0.3"
|
||||||
|
end-of-stream "^1.4.1"
|
||||||
|
fs-constants "^1.0.0"
|
||||||
|
inherits "^2.0.3"
|
||||||
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
term-size@^2.1.0:
|
term-size@^2.1.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
|
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
|
||||||
|
|
Loading…
Reference in New Issue