Merge remote-tracking branch 'origin/develop' into feature/dependencies-image
This commit is contained in:
commit
2edb48e47b
|
@ -0,0 +1 @@
|
||||||
|
3.11.1
|
|
@ -0,0 +1,2 @@
|
||||||
|
nodejs 14.19.3
|
||||||
|
python 3.11.1
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"svelte.svelte-vscode"
|
||||||
|
]
|
||||||
|
}
|
|
@ -3,12 +3,12 @@
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll": true
|
"source.fixAll": true
|
||||||
},
|
},
|
||||||
"editor.defaultFormatter": "svelte.svelte-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"[json]": {
|
"[json]": {
|
||||||
"editor.defaultFormatter": "vscode.json-language-features"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[javascript]": {
|
"[javascript]": {
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"debug.javascript.terminalOptions": {
|
"debug.javascript.terminalOptions": {
|
||||||
"skipFiles": [
|
"skipFiles": [
|
||||||
|
@ -19,4 +19,10 @@
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
|
"[dockercompose]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[svelte]": {
|
||||||
|
"editor.defaultFormatter": "svelte.svelte-vscode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ From opening a bug report to creating a pull request: every contribution is appr
|
||||||
- [Glossary of Terms](#glossary-of-terms)
|
- [Glossary of Terms](#glossary-of-terms)
|
||||||
- [Contributing to Budibase](#contributing-to-budibase)
|
- [Contributing to Budibase](#contributing-to-budibase)
|
||||||
|
|
||||||
|
|
||||||
## Not Sure Where to Start?
|
## Not Sure Where to Start?
|
||||||
|
|
||||||
Budibase is a low-code web application builder that creates svelte-based web applications.
|
Budibase is a low-code web application builder that creates svelte-based web applications.
|
||||||
|
@ -77,24 +76,51 @@ Component libraries are collections of components as well as the definition of t
|
||||||
|
|
||||||
## Contributing to Budibase
|
## Contributing to Budibase
|
||||||
|
|
||||||
* Please maintain the existing code style.
|
- Please maintain the existing code style.
|
||||||
|
|
||||||
* Please try to keep your commits small and focused.
|
- Please try to keep your commits small and focused.
|
||||||
|
|
||||||
* Please write tests.
|
- Please write tests.
|
||||||
|
|
||||||
* If the project diverges from your branch, please rebase instead of merging. This makes the commit graph easier to read.
|
- If the project diverges from your branch, please rebase instead of merging. This makes the commit graph easier to read.
|
||||||
|
|
||||||
* Once your work is completed, please raise a PR against the `develop` branch with some information about what has changed and why.
|
- Once your work is completed, please raise a PR against the `develop` branch with some information about what has changed and why.
|
||||||
|
|
||||||
### Getting Started For Contributors
|
### Getting Started For Contributors
|
||||||
|
|
||||||
#### 1. Prerequisites
|
#### 1. Prerequisites
|
||||||
|
|
||||||
NodeJS Version `14.x.x`
|
- NodeJS version `14.x.x`
|
||||||
|
- Python version `3.x`
|
||||||
|
|
||||||
*yarn -* `npm install -g yarn`
|
### Using asdf (recommended)
|
||||||
|
|
||||||
*jest* - `npm install -g jest`
|
Asdf is a package manager that allows managing multiple dependencies.
|
||||||
|
|
||||||
|
You can install them following any of the steps described below:
|
||||||
|
|
||||||
|
- Install using script (only for mac users):
|
||||||
|
|
||||||
|
`./scripts/install-contributor-dependencies.sh`
|
||||||
|
|
||||||
|
- Or, manually:
|
||||||
|
|
||||||
|
- Installation steps: https://asdf-vm.com/guide/getting-started.html
|
||||||
|
- asdf plugin add nodejs
|
||||||
|
- asdf plugin add python
|
||||||
|
- npm install -g yarn
|
||||||
|
|
||||||
|
### Using NVM and pyenv
|
||||||
|
|
||||||
|
- NVM:
|
||||||
|
- Install: https://github.com/nvm-sh/nvm#installing-and-updating
|
||||||
|
- Setup: `nvm use`
|
||||||
|
- Pyenv:
|
||||||
|
|
||||||
|
- Install: https://github.com/pyenv/pyenv#installation
|
||||||
|
- Setup: `pyenv install -v 3.7.2`
|
||||||
|
|
||||||
|
- _yarn -_ `npm install -g yarn`
|
||||||
|
|
||||||
#### 2. Clone this repository
|
#### 2. Clone this repository
|
||||||
|
|
||||||
|
@ -172,29 +198,37 @@ A combination of environment variables controls the mode budibase runs in.
|
||||||
Yarn commands can be used to mimic the different modes as described in the sections below:
|
Yarn commands can be used to mimic the different modes as described in the sections below:
|
||||||
|
|
||||||
#### Self Hosted
|
#### Self Hosted
|
||||||
|
|
||||||
The default mode. A single tenant installation with no usage restrictions.
|
The default mode. A single tenant installation with no usage restrictions.
|
||||||
|
|
||||||
To enable this mode, use:
|
To enable this mode, use:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn mode:self
|
yarn mode:self
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Cloud
|
#### Cloud
|
||||||
|
|
||||||
The cloud mode, with account portal turned off.
|
The cloud mode, with account portal turned off.
|
||||||
|
|
||||||
To enable this mode, use:
|
To enable this mode, use:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn mode:cloud
|
yarn mode:cloud
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Cloud & Account
|
#### Cloud & Account
|
||||||
|
|
||||||
The cloud mode, with account portal turned on. This is a replica of the mode that runs at https://budibase.app
|
The cloud mode, with account portal turned on. This is a replica of the mode that runs at https://budibase.app
|
||||||
|
|
||||||
|
|
||||||
To enable this mode, use:
|
To enable this mode, use:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn mode:account
|
yarn mode:account
|
||||||
```
|
```
|
||||||
|
|
||||||
### CI
|
### CI
|
||||||
|
|
||||||
An overview of the CI pipelines can be found [here](../.github/workflows/README.md)
|
An overview of the CI pipelines can be found [here](../.github/workflows/README.md)
|
||||||
|
|
||||||
### Pro
|
### Pro
|
||||||
|
@ -214,6 +248,7 @@ The `yarn bootstrap` command can be used to replace the NPM supplied dependency
|
||||||
### Troubleshooting
|
### Troubleshooting
|
||||||
|
|
||||||
Sometimes, things go wrong. This can be due to incompatible updates on the budibase platform. To clear down your development environment and start again follow **Step 6. Cleanup**, then proceed from **Step 3. Install and Build** in the setup guide above to create a fresh Budibase installation.
|
Sometimes, things go wrong. This can be due to incompatible updates on the budibase platform. To clear down your development environment and start again follow **Step 6. Cleanup**, then proceed from **Step 3. Install and Build** in the setup guide above to create a fresh Budibase installation.
|
||||||
|
|
||||||
### Running tests
|
### Running tests
|
||||||
|
|
||||||
#### End-to-end Tests
|
#### End-to-end Tests
|
||||||
|
@ -226,12 +261,11 @@ yarn test:e2e
|
||||||
|
|
||||||
Or if you are in the builder you can run `yarn cy:test`.
|
Or if you are in the builder you can run `yarn cy:test`.
|
||||||
|
|
||||||
|
|
||||||
### Other Useful Information
|
### Other Useful Information
|
||||||
|
|
||||||
* The contributors are listed in [AUTHORS.md](https://github.com/Budibase/budibase/blob/master/.github/AUTHORS.md) (add yourself).
|
- The contributors are listed in [AUTHORS.md](https://github.com/Budibase/budibase/blob/master/.github/AUTHORS.md) (add yourself).
|
||||||
|
|
||||||
* This project uses a modified version of the MPLv2 license, see [LICENSE](https://github.com/budibase/server/blob/master/LICENSE).
|
- This project uses a modified version of the MPLv2 license, see [LICENSE](https://github.com/budibase/server/blob/master/LICENSE).
|
||||||
|
|
||||||
* We use the [C4 (Collective Code Construction Contract)](https://rfc.zeromq.org/spec:42/C4/) process for contributions.
|
- We use the [C4 (Collective Code Construction Contract)](https://rfc.zeromq.org/spec:42/C4/) process for contributions.
|
||||||
Please read this if you are unfamiliar with it.
|
Please read this if you are unfamiliar with it.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
"types": "dist/src/index.d.ts",
|
"types": "dist/src/index.d.ts",
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/nano": "10.1.1",
|
"@budibase/nano": "10.1.1",
|
||||||
"@budibase/types": "2.2.12-alpha.68",
|
"@budibase/types": "2.2.12-alpha.70",
|
||||||
"@shopify/jest-koa-mocks": "5.0.1",
|
"@shopify/jest-koa-mocks": "5.0.1",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
"aws-cloudfront-sign": "2.2.0",
|
"aws-cloudfront-sign": "2.2.0",
|
||||||
|
|
|
@ -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": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.68",
|
"@budibase/string-templates": "2.2.12-alpha.70",
|
||||||
"@spectrum-css/accordion": "3.0.24",
|
"@spectrum-css/accordion": "3.0.24",
|
||||||
"@spectrum-css/actionbutton": "1.0.1",
|
"@spectrum-css/actionbutton": "1.0.1",
|
||||||
"@spectrum-css/actiongroup": "1.0.1",
|
"@spectrum-css/actiongroup": "1.0.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -58,10 +58,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.2.12-alpha.68",
|
"@budibase/bbui": "2.2.12-alpha.70",
|
||||||
"@budibase/client": "2.2.12-alpha.68",
|
"@budibase/client": "2.2.12-alpha.70",
|
||||||
"@budibase/frontend-core": "2.2.12-alpha.68",
|
"@budibase/frontend-core": "2.2.12-alpha.70",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.68",
|
"@budibase/string-templates": "2.2.12-alpha.70",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
|
|
||||||
let displayString
|
let displayString
|
||||||
if (throughTableName) {
|
if (throughTableName) {
|
||||||
displayString = `${fromTableName} through ${throughTableName} → ${toTableName}`
|
displayString = `${fromTableName} ↔ ${toTableName}`
|
||||||
} else {
|
} else {
|
||||||
displayString = `${fromTableName} → ${toTableName}`
|
displayString = `${fromTableName} → ${toTableName}`
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,17 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import { Helpers } from "@budibase/bbui"
|
import { Helpers } from "@budibase/bbui"
|
||||||
|
import { RelationshipErrorChecker } from "./relationshipErrors"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
export let save
|
export let save
|
||||||
export let datasource
|
export let datasource
|
||||||
export let plusTables = []
|
export let plusTables = []
|
||||||
export let fromRelationship = {}
|
export let fromRelationship = {}
|
||||||
export let toRelationship = {}
|
export let toRelationship = {}
|
||||||
|
export let selectedFromTable
|
||||||
export let close
|
export let close
|
||||||
|
|
||||||
const colNotSet = "Please specify a column name"
|
|
||||||
const relationshipAlreadyExists =
|
|
||||||
"A relationship between these tables already exists."
|
|
||||||
const relationshipTypes = [
|
const relationshipTypes = [
|
||||||
{
|
{
|
||||||
label: "One to Many",
|
label: "One to Many",
|
||||||
|
@ -42,63 +42,28 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
let tableOptions
|
let tableOptions
|
||||||
|
let errorChecker = new RelationshipErrorChecker(
|
||||||
|
invalidThroughTable,
|
||||||
|
relationshipExists
|
||||||
|
)
|
||||||
let errors = {}
|
let errors = {}
|
||||||
let hasClickedSave = !!fromRelationship.relationshipType
|
let fromPrimary, fromForeign, fromColumn, toColumn
|
||||||
let fromPrimary,
|
|
||||||
fromForeign,
|
|
||||||
fromTable,
|
|
||||||
toTable,
|
|
||||||
throughTable,
|
|
||||||
fromColumn,
|
|
||||||
toColumn
|
|
||||||
let fromId, toId, throughId, throughToKey, throughFromKey
|
let fromId, toId, throughId, throughToKey, throughFromKey
|
||||||
let isManyToMany, isManyToOne, relationshipType
|
let isManyToMany, isManyToOne, relationshipType
|
||||||
|
let hasValidated = false
|
||||||
$: {
|
|
||||||
if (!fromPrimary) {
|
|
||||||
fromPrimary = fromRelationship.foreignKey
|
|
||||||
fromForeign = toRelationship.foreignKey
|
|
||||||
}
|
|
||||||
if (!fromColumn && !errors.fromColumn) {
|
|
||||||
fromColumn = toRelationship.name
|
|
||||||
}
|
|
||||||
if (!toColumn && !errors.toColumn) {
|
|
||||||
toColumn = fromRelationship.name
|
|
||||||
}
|
|
||||||
if (!fromId) {
|
|
||||||
fromId = toRelationship.tableId
|
|
||||||
}
|
|
||||||
if (!toId) {
|
|
||||||
toId = fromRelationship.tableId
|
|
||||||
}
|
|
||||||
if (!throughId) {
|
|
||||||
throughId = fromRelationship.through
|
|
||||||
throughFromKey = fromRelationship.throughFrom
|
|
||||||
throughToKey = fromRelationship.throughTo
|
|
||||||
}
|
|
||||||
if (!relationshipType) {
|
|
||||||
relationshipType = fromRelationship.relationshipType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$: tableOptions = plusTables.map(table => ({
|
$: tableOptions = plusTables.map(table => ({
|
||||||
label: table.name,
|
label: table.name,
|
||||||
value: table._id,
|
value: table._id,
|
||||||
}))
|
}))
|
||||||
$: valid = getErrorCount(errors) === 0 || !hasClickedSave
|
$: valid = getErrorCount(errors) === 0 && allRequiredAttributesSet()
|
||||||
|
|
||||||
$: isManyToMany = relationshipType === RelationshipTypes.MANY_TO_MANY
|
$: isManyToMany = relationshipType === RelationshipTypes.MANY_TO_MANY
|
||||||
$: isManyToOne = relationshipType === RelationshipTypes.MANY_TO_ONE
|
$: isManyToOne = relationshipType === RelationshipTypes.MANY_TO_ONE
|
||||||
$: fromTable = plusTables.find(table => table._id === fromId)
|
|
||||||
$: toTable = plusTables.find(table => table._id === toId)
|
|
||||||
$: throughTable = plusTables.find(table => table._id === throughId)
|
|
||||||
|
|
||||||
$: toRelationship.relationshipType = fromRelationship?.relationshipType
|
$: toRelationship.relationshipType = fromRelationship?.relationshipType
|
||||||
|
|
||||||
const getErrorCount = errors =>
|
function getTable(id) {
|
||||||
Object.entries(errors)
|
return plusTables.find(table => table._id === id)
|
||||||
.filter(entry => !!entry[1])
|
}
|
||||||
.map(entry => entry[0]).length
|
|
||||||
|
|
||||||
function invalidThroughTable() {
|
function invalidThroughTable() {
|
||||||
// need to know the foreign key columns to check error
|
// need to know the foreign key columns to check error
|
||||||
|
@ -116,93 +81,103 @@
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
function relationshipExists() {
|
||||||
function validate() {
|
|
||||||
const isMany = relationshipType === RelationshipTypes.MANY_TO_MANY
|
|
||||||
const tableNotSet = "Please specify a table"
|
|
||||||
const foreignKeyNotSet = "Please pick a foreign key"
|
|
||||||
const errObj = {}
|
|
||||||
if (!relationshipType) {
|
|
||||||
errObj.relationshipType = "Please specify a relationship type"
|
|
||||||
}
|
|
||||||
if (!fromTable) {
|
|
||||||
errObj.fromTable = tableNotSet
|
|
||||||
}
|
|
||||||
if (!toTable) {
|
|
||||||
errObj.toTable = tableNotSet
|
|
||||||
}
|
|
||||||
if (isMany && !throughTable) {
|
|
||||||
errObj.throughTable = tableNotSet
|
|
||||||
}
|
|
||||||
if (isMany && !throughFromKey) {
|
|
||||||
errObj.throughFromKey = foreignKeyNotSet
|
|
||||||
}
|
|
||||||
if (isMany && !throughToKey) {
|
|
||||||
errObj.throughToKey = foreignKeyNotSet
|
|
||||||
}
|
|
||||||
if (invalidThroughTable()) {
|
|
||||||
errObj.throughTable =
|
|
||||||
"Ensure non-key columns are nullable or auto-generated"
|
|
||||||
}
|
|
||||||
if (!isMany && !fromForeign) {
|
|
||||||
errObj.fromForeign = foreignKeyNotSet
|
|
||||||
}
|
|
||||||
if (!fromColumn) {
|
|
||||||
errObj.fromColumn = colNotSet
|
|
||||||
}
|
|
||||||
if (!toColumn) {
|
|
||||||
errObj.toColumn = colNotSet
|
|
||||||
}
|
|
||||||
if (!isMany && !fromPrimary) {
|
|
||||||
errObj.fromPrimary = "Please pick the primary key"
|
|
||||||
}
|
|
||||||
if (isMany && relationshipExists()) {
|
|
||||||
errObj.fromTable = relationshipAlreadyExists
|
|
||||||
errObj.toTable = relationshipAlreadyExists
|
|
||||||
}
|
|
||||||
|
|
||||||
// currently don't support relationships back onto the table itself, needs to relate out
|
|
||||||
const tableError = "From/to/through tables must be different"
|
|
||||||
if (fromTable && (fromTable === toTable || fromTable === throughTable)) {
|
|
||||||
errObj.fromTable = tableError
|
|
||||||
}
|
|
||||||
if (toTable && (toTable === fromTable || toTable === throughTable)) {
|
|
||||||
errObj.toTable = tableError
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
throughTable &&
|
originalFromTable &&
|
||||||
(throughTable === fromTable || throughTable === toTable)
|
originalToTable &&
|
||||||
|
originalFromTable === getTable(fromId) &&
|
||||||
|
originalToTable === getTable(toId)
|
||||||
) {
|
) {
|
||||||
errObj.throughTable = tableError
|
|
||||||
}
|
|
||||||
const colError = "Column name cannot be an existing column"
|
|
||||||
if (isColumnNameBeingUsed(toTable, fromColumn, originalFromColumnName)) {
|
|
||||||
errObj.fromColumn = colError
|
|
||||||
}
|
|
||||||
if (isColumnNameBeingUsed(fromTable, toColumn, originalToColumnName)) {
|
|
||||||
errObj.toColumn = colError
|
|
||||||
}
|
|
||||||
|
|
||||||
let fromType, toType
|
|
||||||
if (fromPrimary && fromForeign) {
|
|
||||||
fromType = fromTable?.schema[fromPrimary]?.type
|
|
||||||
toType = toTable?.schema[fromForeign]?.type
|
|
||||||
}
|
|
||||||
if (fromType && toType && fromType !== toType) {
|
|
||||||
errObj.fromForeign =
|
|
||||||
"Column type of the foreign key must match the primary key"
|
|
||||||
}
|
|
||||||
|
|
||||||
errors = errObj
|
|
||||||
return getErrorCount(errors) === 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function isColumnNameBeingUsed(table, columnName, originalName) {
|
|
||||||
if (!table || !columnName || columnName === originalName) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const keys = Object.keys(table.schema).map(key => key.toLowerCase())
|
let fromThroughLinks = Object.values(
|
||||||
return keys.indexOf(columnName.toLowerCase()) !== -1
|
datasource.entities[getTable(fromId).name].schema
|
||||||
|
).filter(value => value.through)
|
||||||
|
let toThroughLinks = Object.values(
|
||||||
|
datasource.entities[getTable(toId).name].schema
|
||||||
|
).filter(value => value.through)
|
||||||
|
|
||||||
|
const matchAgainstUserInput = (fromTableId, toTableId) =>
|
||||||
|
(fromTableId === fromId && toTableId === toId) ||
|
||||||
|
(fromTableId === toId && toTableId === fromId)
|
||||||
|
|
||||||
|
return !!fromThroughLinks.find(from =>
|
||||||
|
toThroughLinks.find(
|
||||||
|
to =>
|
||||||
|
from.through === to.through &&
|
||||||
|
matchAgainstUserInput(from.tableId, to.tableId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getErrorCount(errors) {
|
||||||
|
return Object.entries(errors).filter(entry => !!entry[1]).length
|
||||||
|
}
|
||||||
|
|
||||||
|
function allRequiredAttributesSet() {
|
||||||
|
const base = getTable(fromId) && getTable(toId) && fromColumn && toColumn
|
||||||
|
if (relationshipType === RelationshipTypes.MANY_TO_ONE) {
|
||||||
|
return base && fromPrimary && fromForeign
|
||||||
|
} else {
|
||||||
|
return base && getTable(throughId) && throughFromKey && throughToKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
if (!allRequiredAttributesSet() && !hasValidated) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hasValidated = true
|
||||||
|
errorChecker.setType(relationshipType)
|
||||||
|
const fromTable = getTable(fromId),
|
||||||
|
toTable = getTable(toId),
|
||||||
|
throughTable = getTable(throughId)
|
||||||
|
errors = {
|
||||||
|
relationshipType: errorChecker.relationshipTypeSet(relationshipType),
|
||||||
|
fromTable:
|
||||||
|
errorChecker.tableSet(fromTable) ||
|
||||||
|
errorChecker.doesRelationshipExists() ||
|
||||||
|
errorChecker.differentTables(fromId, toId, throughId),
|
||||||
|
toTable:
|
||||||
|
errorChecker.tableSet(toTable) ||
|
||||||
|
errorChecker.doesRelationshipExists() ||
|
||||||
|
errorChecker.differentTables(toId, fromId, throughId),
|
||||||
|
throughTable:
|
||||||
|
errorChecker.throughTableSet(throughTable) ||
|
||||||
|
errorChecker.throughIsNullable() ||
|
||||||
|
errorChecker.differentTables(throughId, fromId, toId),
|
||||||
|
throughFromKey:
|
||||||
|
errorChecker.manyForeignKeySet(throughFromKey) ||
|
||||||
|
errorChecker.manyTypeMismatch(
|
||||||
|
fromTable,
|
||||||
|
throughTable,
|
||||||
|
fromTable.primary[0],
|
||||||
|
throughFromKey
|
||||||
|
),
|
||||||
|
throughToKey:
|
||||||
|
errorChecker.manyForeignKeySet(throughToKey) ||
|
||||||
|
errorChecker.manyTypeMismatch(
|
||||||
|
toTable,
|
||||||
|
throughTable,
|
||||||
|
toTable.primary[0],
|
||||||
|
throughToKey
|
||||||
|
),
|
||||||
|
fromForeign:
|
||||||
|
errorChecker.foreignKeySet(fromForeign) ||
|
||||||
|
errorChecker.typeMismatch(fromTable, toTable, fromPrimary, fromForeign),
|
||||||
|
fromPrimary: errorChecker.primaryKeySet(fromPrimary),
|
||||||
|
fromColumn: errorChecker.columnBeingUsed(
|
||||||
|
toTable,
|
||||||
|
fromColumn,
|
||||||
|
originalFromColumnName
|
||||||
|
),
|
||||||
|
toColumn: errorChecker.columnBeingUsed(
|
||||||
|
fromTable,
|
||||||
|
toColumn,
|
||||||
|
originalToColumnName
|
||||||
|
),
|
||||||
|
}
|
||||||
|
return getErrorCount(errors) === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildRelationships() {
|
function buildRelationships() {
|
||||||
|
@ -243,13 +218,13 @@
|
||||||
if (manyToMany) {
|
if (manyToMany) {
|
||||||
relateFrom = {
|
relateFrom = {
|
||||||
...relateFrom,
|
...relateFrom,
|
||||||
through: throughTable._id,
|
through: getTable(throughId)._id,
|
||||||
fieldName: toTable.primary[0],
|
fieldName: getTable(toId).primary[0],
|
||||||
}
|
}
|
||||||
relateTo = {
|
relateTo = {
|
||||||
...relateTo,
|
...relateTo,
|
||||||
through: throughTable._id,
|
through: getTable(throughId)._id,
|
||||||
fieldName: fromTable.primary[0],
|
fieldName: getTable(fromId).primary[0],
|
||||||
throughFrom: relateFrom.throughTo,
|
throughFrom: relateFrom.throughTo,
|
||||||
throughTo: relateFrom.throughFrom,
|
throughTo: relateFrom.throughFrom,
|
||||||
}
|
}
|
||||||
|
@ -277,35 +252,6 @@
|
||||||
toRelationship = relateTo
|
toRelationship = relateTo
|
||||||
}
|
}
|
||||||
|
|
||||||
function relationshipExists() {
|
|
||||||
if (
|
|
||||||
originalFromTable &&
|
|
||||||
originalToTable &&
|
|
||||||
originalFromTable === fromTable &&
|
|
||||||
originalToTable === toTable
|
|
||||||
) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
let fromThroughLinks = Object.values(
|
|
||||||
datasource.entities[fromTable.name].schema
|
|
||||||
).filter(value => value.through)
|
|
||||||
let toThroughLinks = Object.values(
|
|
||||||
datasource.entities[toTable.name].schema
|
|
||||||
).filter(value => value.through)
|
|
||||||
|
|
||||||
const matchAgainstUserInput = (fromTableId, toTableId) =>
|
|
||||||
(fromTableId === fromId && toTableId === toId) ||
|
|
||||||
(fromTableId === toId && toTableId === fromId)
|
|
||||||
|
|
||||||
return !!fromThroughLinks.find(from =>
|
|
||||||
toThroughLinks.find(
|
|
||||||
to =>
|
|
||||||
from.through === to.through &&
|
|
||||||
matchAgainstUserInput(from.tableId, to.tableId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeExistingRelationship() {
|
function removeExistingRelationship() {
|
||||||
if (originalFromTable && originalFromColumnName) {
|
if (originalFromTable && originalFromColumnName) {
|
||||||
delete datasource.entities[originalFromTable.name].schema[
|
delete datasource.entities[originalFromTable.name].schema[
|
||||||
|
@ -320,7 +266,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveRelationship() {
|
async function saveRelationship() {
|
||||||
hasClickedSave = true
|
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -328,10 +273,10 @@
|
||||||
removeExistingRelationship()
|
removeExistingRelationship()
|
||||||
|
|
||||||
// source of relationship
|
// source of relationship
|
||||||
datasource.entities[fromTable.name].schema[fromRelationship.name] =
|
datasource.entities[getTable(fromId).name].schema[fromRelationship.name] =
|
||||||
fromRelationship
|
fromRelationship
|
||||||
// save other side of relationship in the other schema
|
// save other side of relationship in the other schema
|
||||||
datasource.entities[toTable.name].schema[toRelationship.name] =
|
datasource.entities[getTable(toId).name].schema[toRelationship.name] =
|
||||||
toRelationship
|
toRelationship
|
||||||
|
|
||||||
await save()
|
await save()
|
||||||
|
@ -342,6 +287,36 @@
|
||||||
await tables.fetch()
|
await tables.fetch()
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changed(fn) {
|
||||||
|
if (typeof fn === "function") {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (fromRelationship) {
|
||||||
|
fromPrimary = fromRelationship.foreignKey
|
||||||
|
toId = fromRelationship.tableId
|
||||||
|
throughId = fromRelationship.through
|
||||||
|
throughFromKey = fromRelationship.throughFrom
|
||||||
|
throughToKey = fromRelationship.throughTo
|
||||||
|
toColumn = fromRelationship.name
|
||||||
|
}
|
||||||
|
if (toRelationship) {
|
||||||
|
fromForeign = toRelationship.foreignKey
|
||||||
|
fromId = toRelationship.tableId
|
||||||
|
fromColumn = toRelationship.name
|
||||||
|
}
|
||||||
|
relationshipType =
|
||||||
|
fromRelationship.relationshipType || RelationshipTypes.MANY_TO_ONE
|
||||||
|
if (selectedFromTable) {
|
||||||
|
fromId = selectedFromTable._id
|
||||||
|
fromColumn = selectedFromTable.name
|
||||||
|
fromPrimary = selectedFromTable?.primary[0] || null
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent
|
<ModalContent
|
||||||
|
@ -355,34 +330,35 @@
|
||||||
options={relationshipTypes}
|
options={relationshipTypes}
|
||||||
bind:value={relationshipType}
|
bind:value={relationshipType}
|
||||||
bind:error={errors.relationshipType}
|
bind:error={errors.relationshipType}
|
||||||
on:change={() => (errors.relationshipType = null)}
|
on:change={() =>
|
||||||
|
changed(() => {
|
||||||
|
hasValidated = false
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
<div class="headings">
|
<div class="headings">
|
||||||
<Detail>Tables</Detail>
|
<Detail>Tables</Detail>
|
||||||
</div>
|
</div>
|
||||||
|
{#if !selectedFromTable}
|
||||||
<Select
|
<Select
|
||||||
label="Select from table"
|
label="Select from table"
|
||||||
options={tableOptions}
|
options={tableOptions}
|
||||||
bind:value={fromId}
|
bind:value={fromId}
|
||||||
bind:error={errors.fromTable}
|
bind:error={errors.fromTable}
|
||||||
on:change={e => {
|
on:change={e =>
|
||||||
fromColumn = tableOptions.find(opt => opt.value === e.detail)?.label || ""
|
changed(() => {
|
||||||
if (errors.fromTable === relationshipAlreadyExists) {
|
const table = plusTables.find(tbl => tbl._id === e.detail)
|
||||||
errors.toColumn = null
|
fromColumn = table?.name || ""
|
||||||
}
|
fromPrimary = table?.primary?.[0]
|
||||||
errors.fromTable = null
|
})}
|
||||||
errors.fromColumn = null
|
|
||||||
errors.toTable = null
|
|
||||||
errors.throughTable = null
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{#if isManyToOne && fromTable}
|
{/if}
|
||||||
|
{#if isManyToOne && fromId}
|
||||||
<Select
|
<Select
|
||||||
label={`Primary Key (${fromTable.name})`}
|
label={`Primary Key (${getTable(fromId).name})`}
|
||||||
options={Object.keys(fromTable.schema)}
|
options={Object.keys(getTable(fromId).schema)}
|
||||||
bind:value={fromPrimary}
|
bind:value={fromPrimary}
|
||||||
bind:error={errors.fromPrimary}
|
bind:error={errors.fromPrimary}
|
||||||
on:change={() => (errors.fromPrimary = null)}
|
on:change={changed}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<Select
|
<Select
|
||||||
|
@ -390,16 +366,12 @@
|
||||||
options={tableOptions}
|
options={tableOptions}
|
||||||
bind:value={toId}
|
bind:value={toId}
|
||||||
bind:error={errors.toTable}
|
bind:error={errors.toTable}
|
||||||
on:change={e => {
|
on:change={e =>
|
||||||
toColumn = tableOptions.find(opt => opt.value === e.detail)?.label || ""
|
changed(() => {
|
||||||
if (errors.toTable === relationshipAlreadyExists) {
|
const table = plusTables.find(tbl => tbl._id === e.detail)
|
||||||
errors.fromColumn = null
|
toColumn = table.name || ""
|
||||||
}
|
fromForeign = null
|
||||||
errors.toTable = null
|
})}
|
||||||
errors.toColumn = null
|
|
||||||
errors.fromTable = null
|
|
||||||
errors.throughTable = null
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{#if isManyToMany}
|
{#if isManyToMany}
|
||||||
<Select
|
<Select
|
||||||
|
@ -407,45 +379,45 @@
|
||||||
options={tableOptions}
|
options={tableOptions}
|
||||||
bind:value={throughId}
|
bind:value={throughId}
|
||||||
bind:error={errors.throughTable}
|
bind:error={errors.throughTable}
|
||||||
on:change={() => {
|
on:change={() =>
|
||||||
errors.fromTable = null
|
changed(() => {
|
||||||
errors.toTable = null
|
throughToKey = null
|
||||||
errors.throughTable = null
|
throughFromKey = null
|
||||||
}}
|
})}
|
||||||
/>
|
/>
|
||||||
{#if fromTable && toTable && throughTable}
|
{#if fromId && toId && throughId}
|
||||||
<Select
|
<Select
|
||||||
label={`Foreign Key (${fromTable?.name})`}
|
label={`Foreign Key (${getTable(fromId)?.name})`}
|
||||||
options={Object.keys(throughTable?.schema)}
|
options={Object.keys(getTable(throughId)?.schema)}
|
||||||
bind:value={throughToKey}
|
bind:value={throughToKey}
|
||||||
bind:error={errors.throughToKey}
|
bind:error={errors.throughToKey}
|
||||||
on:change={e => {
|
on:change={e =>
|
||||||
|
changed(() => {
|
||||||
if (throughFromKey === e.detail) {
|
if (throughFromKey === e.detail) {
|
||||||
throughFromKey = null
|
throughFromKey = null
|
||||||
}
|
}
|
||||||
errors.throughToKey = null
|
})}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
label={`Foreign Key (${toTable?.name})`}
|
label={`Foreign Key (${getTable(toId)?.name})`}
|
||||||
options={Object.keys(throughTable?.schema)}
|
options={Object.keys(getTable(throughId)?.schema)}
|
||||||
bind:value={throughFromKey}
|
bind:value={throughFromKey}
|
||||||
bind:error={errors.throughFromKey}
|
bind:error={errors.throughFromKey}
|
||||||
on:change={e => {
|
on:change={e =>
|
||||||
|
changed(() => {
|
||||||
if (throughToKey === e.detail) {
|
if (throughToKey === e.detail) {
|
||||||
throughToKey = null
|
throughToKey = null
|
||||||
}
|
}
|
||||||
errors.throughFromKey = null
|
})}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{:else if isManyToOne && toTable}
|
{:else if isManyToOne && toId}
|
||||||
<Select
|
<Select
|
||||||
label={`Foreign Key (${toTable?.name})`}
|
label={`Foreign Key (${getTable(toId)?.name})`}
|
||||||
options={Object.keys(toTable?.schema)}
|
options={Object.keys(getTable(toId)?.schema)}
|
||||||
bind:value={fromForeign}
|
bind:value={fromForeign}
|
||||||
bind:error={errors.fromForeign}
|
bind:error={errors.fromForeign}
|
||||||
on:change={() => (errors.fromForeign = null)}
|
on:change={changed}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="headings">
|
<div class="headings">
|
||||||
|
@ -459,15 +431,13 @@
|
||||||
label="From table column"
|
label="From table column"
|
||||||
bind:value={fromColumn}
|
bind:value={fromColumn}
|
||||||
bind:error={errors.fromColumn}
|
bind:error={errors.fromColumn}
|
||||||
on:change={e => {
|
on:change={changed}
|
||||||
errors.fromColumn = e.detail?.length > 0 ? null : colNotSet
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
label="To table column"
|
label="To table column"
|
||||||
bind:value={toColumn}
|
bind:value={toColumn}
|
||||||
bind:error={errors.toColumn}
|
bind:error={errors.toColumn}
|
||||||
on:change={e => (errors.toColumn = e.detail?.length > 0 ? null : colNotSet)}
|
on:change={changed}
|
||||||
/>
|
/>
|
||||||
<div slot="footer">
|
<div slot="footer">
|
||||||
{#if originalFromColumnName != null}
|
{#if originalFromColumnName != null}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
import { RelationshipTypes } from "constants/backend"
|
||||||
|
|
||||||
|
const typeMismatch = "Column type of the foreign key must match the primary key"
|
||||||
|
const columnBeingUsed = "Column name cannot be an existing column"
|
||||||
|
const mustBeDifferentTables = "From/to/through tables must be different"
|
||||||
|
const primaryKeyNotSet = "Please pick the primary key"
|
||||||
|
const throughNotNullable =
|
||||||
|
"Ensure non-key columns are nullable or auto-generated"
|
||||||
|
const noRelationshipType = "Please specify a relationship type"
|
||||||
|
const tableNotSet = "Please specify a table"
|
||||||
|
const foreignKeyNotSet = "Please pick a foreign key"
|
||||||
|
const relationshipAlreadyExists =
|
||||||
|
"A relationship between these tables already exists"
|
||||||
|
|
||||||
|
function isColumnNameBeingUsed(table, columnName, originalName) {
|
||||||
|
if (!table || !columnName || columnName === originalName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const keys = Object.keys(table.schema).map(key => key.toLowerCase())
|
||||||
|
return keys.indexOf(columnName.toLowerCase()) !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeMismatchCheck(fromTable, toTable, primary, foreign) {
|
||||||
|
let fromType, toType
|
||||||
|
if (primary && foreign) {
|
||||||
|
fromType = fromTable?.schema[primary]?.type
|
||||||
|
toType = toTable?.schema[foreign]?.type
|
||||||
|
}
|
||||||
|
return fromType && toType && fromType !== toType ? typeMismatch : null
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RelationshipErrorChecker {
|
||||||
|
constructor(invalidThroughTableFn, relationshipExistsFn) {
|
||||||
|
this.invalidThroughTable = invalidThroughTableFn
|
||||||
|
this.relationshipExists = relationshipExistsFn
|
||||||
|
}
|
||||||
|
|
||||||
|
setType(type) {
|
||||||
|
this.type = type
|
||||||
|
}
|
||||||
|
|
||||||
|
isMany() {
|
||||||
|
return this.type === RelationshipTypes.MANY_TO_MANY
|
||||||
|
}
|
||||||
|
|
||||||
|
relationshipTypeSet(type) {
|
||||||
|
return !type ? noRelationshipType : null
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSet(table) {
|
||||||
|
return !table ? tableNotSet : null
|
||||||
|
}
|
||||||
|
|
||||||
|
throughTableSet(table) {
|
||||||
|
return this.isMany() && !table ? tableNotSet : null
|
||||||
|
}
|
||||||
|
|
||||||
|
manyForeignKeySet(key) {
|
||||||
|
return this.isMany() && !key ? foreignKeyNotSet : null
|
||||||
|
}
|
||||||
|
|
||||||
|
foreignKeySet(key) {
|
||||||
|
return !this.isMany() && !key ? foreignKeyNotSet : null
|
||||||
|
}
|
||||||
|
|
||||||
|
primaryKeySet(key) {
|
||||||
|
return !this.isMany() && !key ? primaryKeyNotSet : null
|
||||||
|
}
|
||||||
|
|
||||||
|
throughIsNullable() {
|
||||||
|
return this.invalidThroughTable() ? throughNotNullable : null
|
||||||
|
}
|
||||||
|
|
||||||
|
doesRelationshipExists() {
|
||||||
|
return this.isMany() && this.relationshipExists()
|
||||||
|
? relationshipAlreadyExists
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
differentTables(table1, table2, table3) {
|
||||||
|
// currently don't support relationships back onto the table itself, needs to relate out
|
||||||
|
const error = table1 && (table1 === table2 || (table3 && table1 === table3))
|
||||||
|
return error ? mustBeDifferentTables : null
|
||||||
|
}
|
||||||
|
|
||||||
|
columnBeingUsed(table, column, ogName) {
|
||||||
|
return isColumnNameBeingUsed(table, column, ogName) ? columnBeingUsed : null
|
||||||
|
}
|
||||||
|
|
||||||
|
typeMismatch(fromTable, toTable, primary, foreign) {
|
||||||
|
if (this.isMany()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return typeMismatchCheck(fromTable, toTable, primary, foreign)
|
||||||
|
}
|
||||||
|
|
||||||
|
manyTypeMismatch(table, throughTable, primary, foreign) {
|
||||||
|
if (!this.isMany()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return typeMismatchCheck(table, throughTable, primary, foreign)
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ const componentMap = {
|
||||||
"field/link": FormFieldSelect,
|
"field/link": FormFieldSelect,
|
||||||
"field/array": FormFieldSelect,
|
"field/array": FormFieldSelect,
|
||||||
"field/json": FormFieldSelect,
|
"field/json": FormFieldSelect,
|
||||||
"field/barcode/qr": FormFieldSelect,
|
"field/barcodeqr": FormFieldSelect,
|
||||||
// Some validation types are the same as others, so not all types are
|
// Some validation types are the same as others, so not all types are
|
||||||
// explicitly listed here. e.g. options uses string validation
|
// explicitly listed here. e.g. options uses string validation
|
||||||
"validation/string": ValidationEditor,
|
"validation/string": ValidationEditor,
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
const getOptions = (schema, type) => {
|
const getOptions = (schema, type) => {
|
||||||
let entries = Object.entries(schema ?? {})
|
let entries = Object.entries(schema ?? {})
|
||||||
let types = []
|
let types = []
|
||||||
if (type === "field/options" || type === "field/barcode/qr") {
|
if (type === "field/options") {
|
||||||
// allow options to be used on both options and string fields
|
// allow options to be used on both options and string fields
|
||||||
types = [type, "field/string"]
|
types = [type, "field/string"]
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,6 +35,7 @@
|
||||||
types = types.map(type => type.slice(type.indexOf("/") + 1))
|
types = types.map(type => type.slice(type.indexOf("/") + 1))
|
||||||
|
|
||||||
entries = entries.filter(entry => types.includes(entry[1].type))
|
entries = entries.filter(entry => types.includes(entry[1].type))
|
||||||
|
|
||||||
return entries.map(entry => entry[0])
|
return entries.map(entry => entry[0])
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"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": {
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
"outputPath": "build"
|
"outputPath": "build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "2.2.12-alpha.68",
|
"@budibase/backend-core": "2.2.12-alpha.70",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.68",
|
"@budibase/string-templates": "2.2.12-alpha.70",
|
||||||
"@budibase/types": "2.2.12-alpha.68",
|
"@budibase/types": "2.2.12-alpha.70",
|
||||||
"axios": "0.21.2",
|
"axios": "0.21.2",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
"cli-progress": "3.11.2",
|
"cli-progress": "3.11.2",
|
||||||
|
|
|
@ -3241,7 +3241,7 @@
|
||||||
},
|
},
|
||||||
"settings": [
|
"settings": [
|
||||||
{
|
{
|
||||||
"type": "field/barcode/qr",
|
"type": "field/barcodeqr",
|
||||||
"label": "Field",
|
"label": "Field",
|
||||||
"key": "field",
|
"key": "field",
|
||||||
"required": true
|
"required": true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"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",
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.2.12-alpha.68",
|
"@budibase/bbui": "2.2.12-alpha.70",
|
||||||
"@budibase/frontend-core": "2.2.12-alpha.68",
|
"@budibase/frontend-core": "2.2.12-alpha.70",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.68",
|
"@budibase/string-templates": "2.2.12-alpha.70",
|
||||||
"@spectrum-css/button": "^3.0.3",
|
"@spectrum-css/button": "^3.0.3",
|
||||||
"@spectrum-css/card": "^3.0.3",
|
"@spectrum-css/card": "^3.0.3",
|
||||||
"@spectrum-css/divider": "^1.0.3",
|
"@spectrum-css/divider": "^1.0.3",
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"description": "Budibase frontend core libraries used in builder and client",
|
"description": "Budibase frontend core libraries used in builder and client",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.2.12-alpha.68",
|
"@budibase/bbui": "2.2.12-alpha.70",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/sdk",
|
"name": "@budibase/sdk",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"description": "Budibase Public API SDK",
|
"description": "Budibase Public API SDK",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -43,11 +43,11 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "10.0.3",
|
"@apidevtools/swagger-parser": "10.0.3",
|
||||||
"@budibase/backend-core": "2.2.12-alpha.68",
|
"@budibase/backend-core": "2.2.12-alpha.70",
|
||||||
"@budibase/client": "2.2.12-alpha.68",
|
"@budibase/client": "2.2.12-alpha.70",
|
||||||
"@budibase/pro": "2.2.12-alpha.68",
|
"@budibase/pro": "2.2.12-alpha.70",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.68",
|
"@budibase/string-templates": "2.2.12-alpha.70",
|
||||||
"@budibase/types": "2.2.12-alpha.68",
|
"@budibase/types": "2.2.12-alpha.70",
|
||||||
"@bull-board/api": "3.7.0",
|
"@bull-board/api": "3.7.0",
|
||||||
"@bull-board/koa": "3.9.4",
|
"@bull-board/koa": "3.9.4",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
|
|
@ -1278,13 +1278,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@2.2.12-alpha.68":
|
"@budibase/backend-core@2.2.12-alpha.70":
|
||||||
version "2.2.12-alpha.68"
|
version "2.2.12-alpha.70"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.68.tgz#9efda78dfa35d3c431da188b4e3a0011b734c6b2"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.70.tgz#9894e8d676cfa25f8eb163c623eda003a43a2016"
|
||||||
integrity sha512-k+Edcvz3XcddlJv9YR+TuoYs7e583lpf9nRCu6WOO889s9e8QS+zzfkC9++Vx8aH16JTizibPDY9oNeRrMQALw==
|
integrity sha512-1nZzkZ6kQyrfL9IvNp09JUrdpCzxtE59CAW26SbXNwId5qEJLSa7zVvZCTNo2K644XNM6qCJzA5LwCwW67AL3A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/nano" "10.1.1"
|
"@budibase/nano" "10.1.1"
|
||||||
"@budibase/types" "2.2.12-alpha.68"
|
"@budibase/types" "2.2.12-alpha.70"
|
||||||
"@shopify/jest-koa-mocks" "5.0.1"
|
"@shopify/jest-koa-mocks" "5.0.1"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-cloudfront-sign "2.2.0"
|
aws-cloudfront-sign "2.2.0"
|
||||||
|
@ -1379,13 +1379,13 @@
|
||||||
qs "^6.11.0"
|
qs "^6.11.0"
|
||||||
tough-cookie "^4.1.2"
|
tough-cookie "^4.1.2"
|
||||||
|
|
||||||
"@budibase/pro@2.2.12-alpha.68":
|
"@budibase/pro@2.2.12-alpha.70":
|
||||||
version "2.2.12-alpha.68"
|
version "2.2.12-alpha.70"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.68.tgz#ee992a6451ecaabdb71b5c4d5f9a269710524529"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.70.tgz#067fce5e023817ead1452f21b7abe0ab3585d1d3"
|
||||||
integrity sha512-jp+gYg03Q39kc9PIEREC/3QikTzW9mavGrpnWQNcaFyELwmmRbI5tDZkxRmK38TNuW/1ArqKricd9uCVRb3UGA==
|
integrity sha512-V3EwQd4r/wztKPzbeLbTHJGWvYUqDELbx0HPTSbI24ee9ZFwF/Wjaapg1I6VHyku1rWgzny4/Y0+H4GvwzzEeg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "2.2.12-alpha.68"
|
"@budibase/backend-core" "2.2.12-alpha.70"
|
||||||
"@budibase/types" "2.2.12-alpha.68"
|
"@budibase/types" "2.2.12-alpha.70"
|
||||||
"@koa/router" "8.0.8"
|
"@koa/router" "8.0.8"
|
||||||
bull "4.10.1"
|
bull "4.10.1"
|
||||||
joi "17.6.0"
|
joi "17.6.0"
|
||||||
|
@ -1411,10 +1411,10 @@
|
||||||
svelte-apexcharts "^1.0.2"
|
svelte-apexcharts "^1.0.2"
|
||||||
svelte-flatpickr "^3.1.0"
|
svelte-flatpickr "^3.1.0"
|
||||||
|
|
||||||
"@budibase/types@2.2.12-alpha.68":
|
"@budibase/types@2.2.12-alpha.70":
|
||||||
version "2.2.12-alpha.68"
|
version "2.2.12-alpha.70"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.68.tgz#6284f083aceca49a8de52ebc15c9da8c8416586e"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.70.tgz#c86f43b953d3b15c6f286903ac94091ba9c6cef3"
|
||||||
integrity sha512-xNl/L6M8X+qcVytBgdPSWNM7CYk7Rr2I+ubx5+3u4Z8tF3IWoqk6pj7hMMCORAYAGK7ZdjG7xx+tvXiKK8v1NQ==
|
integrity sha512-+6f3uc6fCviRCeDNoKftcg8iuXksj2F+teCPXVmGNAs+tfwqYjX/32s5DB9EjdE3qHC70XAX+lvTWIrrNchDDA==
|
||||||
|
|
||||||
"@bull-board/api@3.7.0":
|
"@bull-board/api@3.7.0":
|
||||||
version "3.7.0"
|
version "3.7.0"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"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",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/types",
|
"name": "@budibase/types",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"description": "Budibase types",
|
"description": "Budibase types",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "2.2.12-alpha.68",
|
"version": "2.2.12-alpha.70",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -36,10 +36,10 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "2.2.12-alpha.68",
|
"@budibase/backend-core": "2.2.12-alpha.70",
|
||||||
"@budibase/pro": "2.2.12-alpha.68",
|
"@budibase/pro": "2.2.12-alpha.70",
|
||||||
"@budibase/string-templates": "2.2.12-alpha.68",
|
"@budibase/string-templates": "2.2.12-alpha.70",
|
||||||
"@budibase/types": "2.2.12-alpha.68",
|
"@budibase/types": "2.2.12-alpha.70",
|
||||||
"@koa/router": "8.0.8",
|
"@koa/router": "8.0.8",
|
||||||
"@sentry/node": "6.17.7",
|
"@sentry/node": "6.17.7",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
|
|
|
@ -475,13 +475,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@2.2.12-alpha.68":
|
"@budibase/backend-core@2.2.12-alpha.70":
|
||||||
version "2.2.12-alpha.68"
|
version "2.2.12-alpha.70"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.68.tgz#9efda78dfa35d3c431da188b4e3a0011b734c6b2"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.70.tgz#9894e8d676cfa25f8eb163c623eda003a43a2016"
|
||||||
integrity sha512-k+Edcvz3XcddlJv9YR+TuoYs7e583lpf9nRCu6WOO889s9e8QS+zzfkC9++Vx8aH16JTizibPDY9oNeRrMQALw==
|
integrity sha512-1nZzkZ6kQyrfL9IvNp09JUrdpCzxtE59CAW26SbXNwId5qEJLSa7zVvZCTNo2K644XNM6qCJzA5LwCwW67AL3A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/nano" "10.1.1"
|
"@budibase/nano" "10.1.1"
|
||||||
"@budibase/types" "2.2.12-alpha.68"
|
"@budibase/types" "2.2.12-alpha.70"
|
||||||
"@shopify/jest-koa-mocks" "5.0.1"
|
"@shopify/jest-koa-mocks" "5.0.1"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-cloudfront-sign "2.2.0"
|
aws-cloudfront-sign "2.2.0"
|
||||||
|
@ -526,13 +526,13 @@
|
||||||
qs "^6.11.0"
|
qs "^6.11.0"
|
||||||
tough-cookie "^4.1.2"
|
tough-cookie "^4.1.2"
|
||||||
|
|
||||||
"@budibase/pro@2.2.12-alpha.68":
|
"@budibase/pro@2.2.12-alpha.70":
|
||||||
version "2.2.12-alpha.68"
|
version "2.2.12-alpha.70"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.68.tgz#ee992a6451ecaabdb71b5c4d5f9a269710524529"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.70.tgz#067fce5e023817ead1452f21b7abe0ab3585d1d3"
|
||||||
integrity sha512-jp+gYg03Q39kc9PIEREC/3QikTzW9mavGrpnWQNcaFyELwmmRbI5tDZkxRmK38TNuW/1ArqKricd9uCVRb3UGA==
|
integrity sha512-V3EwQd4r/wztKPzbeLbTHJGWvYUqDELbx0HPTSbI24ee9ZFwF/Wjaapg1I6VHyku1rWgzny4/Y0+H4GvwzzEeg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "2.2.12-alpha.68"
|
"@budibase/backend-core" "2.2.12-alpha.70"
|
||||||
"@budibase/types" "2.2.12-alpha.68"
|
"@budibase/types" "2.2.12-alpha.70"
|
||||||
"@koa/router" "8.0.8"
|
"@koa/router" "8.0.8"
|
||||||
bull "4.10.1"
|
bull "4.10.1"
|
||||||
joi "17.6.0"
|
joi "17.6.0"
|
||||||
|
@ -540,10 +540,10 @@
|
||||||
lru-cache "^7.14.1"
|
lru-cache "^7.14.1"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@budibase/types@2.2.12-alpha.68":
|
"@budibase/types@2.2.12-alpha.70":
|
||||||
version "2.2.12-alpha.68"
|
version "2.2.12-alpha.70"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.68.tgz#6284f083aceca49a8de52ebc15c9da8c8416586e"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.70.tgz#c86f43b953d3b15c6f286903ac94091ba9c6cef3"
|
||||||
integrity sha512-xNl/L6M8X+qcVytBgdPSWNM7CYk7Rr2I+ubx5+3u4Z8tF3IWoqk6pj7hMMCORAYAGK7ZdjG7xx+tvXiKK8v1NQ==
|
integrity sha512-+6f3uc6fCviRCeDNoKftcg8iuXksj2F+teCPXVmGNAs+tfwqYjX/32s5DB9EjdE3qHC70XAX+lvTWIrrNchDDA==
|
||||||
|
|
||||||
"@cspotcode/source-map-support@^0.8.0":
|
"@cspotcode/source-map-support@^0.8.0":
|
||||||
version "0.8.1"
|
version "0.8.1"
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
function getDistro {
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
# freedesktop.org and systemd
|
||||||
|
. /etc/os-release
|
||||||
|
OS=$NAME
|
||||||
|
VER=$VERSION_ID
|
||||||
|
elif type lsb_release >/dev/null 2>&1; then
|
||||||
|
# linuxbase.org
|
||||||
|
OS=$(lsb_release -si)
|
||||||
|
VER=$(lsb_release -sr)
|
||||||
|
elif [ -f /etc/lsb-release ]; then
|
||||||
|
# For some versions of Debian/Ubuntu without lsb_release command
|
||||||
|
. /etc/lsb-release
|
||||||
|
OS=$DISTRIB_ID
|
||||||
|
VER=$DISTRIB_RELEASE
|
||||||
|
elif [ -f /etc/debian_version ]; then
|
||||||
|
# Older Debian/Ubuntu/etc.
|
||||||
|
OS=Debian
|
||||||
|
VER=$(cat /etc/debian_version)
|
||||||
|
elif [ -f /etc/SuSe-release ]; then
|
||||||
|
# Older SuSE/etc.
|
||||||
|
:
|
||||||
|
elif [ -f /etc/redhat-release ]; then
|
||||||
|
# Older Red Hat, CentOS, etc.
|
||||||
|
VER=$( cat /etc/redhat-release | cut -d" " -f3 | cut -d "." -f1)
|
||||||
|
d=$( cat /etc/redhat-release | cut -d" " -f1 | cut -d "." -f1)
|
||||||
|
if [[ $d == "CentOS" ]]; then
|
||||||
|
OS="CentOS Linux"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
|
||||||
|
OS=$(uname -s)
|
||||||
|
VER=$(uname -r)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getDistro
|
||||||
|
|
||||||
|
if [[ $OS == "Darwin" ]];
|
||||||
|
then
|
||||||
|
echo "This script is not setup for your machine type:" $OS
|
||||||
|
echo "Please use the manual steps described in https://github.com/Budibase/budibase/blob/develop/docs/CONTRIBUTING.md#getting-started-for-contributors"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Install brew
|
||||||
|
if ! command -v brew &> /dev/null
|
||||||
|
then
|
||||||
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install and setup asdf
|
||||||
|
if ! command -v asdf &> /dev/null
|
||||||
|
then
|
||||||
|
brew install asdf
|
||||||
|
|
||||||
|
if test -f ~/.bashrc; then
|
||||||
|
echo -e "\n. $(brew --prefix asdf)/asdf.sh" >> ~/.bashrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f ~/.zshrc; then
|
||||||
|
echo -e "\n. $(brew --prefix asdf)/asdf.sh" >> ~/.zshrc
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install ASDF Plugins
|
||||||
|
asdf plugin add nodejs
|
||||||
|
asdf plugin add python
|
||||||
|
|
||||||
|
asdf install
|
||||||
|
|
||||||
|
npm install -g yarn
|
Loading…
Reference in New Issue