Merge branch 'develop' of github.com:Budibase/budibase into default-field-values
This commit is contained in:
commit
50247bd066
|
@ -5,7 +5,7 @@ version: "3"
|
|||
services:
|
||||
app-service:
|
||||
restart: always
|
||||
image: budibase/apps
|
||||
image: budibase.docker.scarf.sh/budibase/apps
|
||||
container_name: bbapps
|
||||
ports:
|
||||
- "${APP_PORT}:4002"
|
||||
|
@ -33,7 +33,7 @@ services:
|
|||
|
||||
worker-service:
|
||||
restart: always
|
||||
image: budibase/worker
|
||||
image: budibase.docker.scarf.sh/budibase/worker
|
||||
container_name: bbworker
|
||||
ports:
|
||||
- "${WORKER_PORT}:4003"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
"test:e2e": "lerna run cy:test",
|
||||
"test:e2e:ci": "lerna run cy:ci",
|
||||
"build:docker": "lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh && cd -",
|
||||
"build:docker:develop": "lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -",
|
||||
"build:docker:develop": "node scripts/pinVersions && lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -",
|
||||
"multi:enable": "lerna run multi:enable",
|
||||
"multi:disable": "lerna run multi:disable"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/auth",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"description": "Authentication middlewares for budibase builder and apps",
|
||||
"main": "src/index.js",
|
||||
"author": "Budibase",
|
||||
|
|
|
@ -4,6 +4,8 @@ const { DEFAULT_TENANT_ID } = require("../constants")
|
|||
const env = require("../environment")
|
||||
const { StaticDatabases, SEPARATOR } = require("./constants")
|
||||
const { getTenantId } = require("../tenancy")
|
||||
const fetch = require("node-fetch")
|
||||
const { getCouch } = require("./index")
|
||||
|
||||
const UNICODE_MAX = "\ufff0"
|
||||
|
||||
|
@ -156,6 +158,23 @@ exports.getDeployedAppID = appId => {
|
|||
return appId
|
||||
}
|
||||
|
||||
/**
|
||||
* if in production this will use the CouchDB _all_dbs call to retrieve a list of databases. If testing
|
||||
* when using Pouch it will use the pouchdb-all-dbs package.
|
||||
*/
|
||||
exports.getAllDbs = async () => {
|
||||
// specifically for testing we use the pouch package for this
|
||||
if (env.isTest()) {
|
||||
return getCouch().allDbs()
|
||||
}
|
||||
const response = await fetch(`${env.COUCH_DB_URL}/_all_dbs`)
|
||||
if (response.status === 200) {
|
||||
return response.json()
|
||||
} else {
|
||||
throw "Cannot connect to CouchDB instance"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lots of different points in the system need to find the full list of apps, this will
|
||||
* enumerate the entire CouchDB cluster and get the list of databases (every app).
|
||||
|
@ -163,13 +182,13 @@ exports.getDeployedAppID = appId => {
|
|||
* different users/companies apps as there is no security around it - all apps are returned.
|
||||
* @return {Promise<object[]>} returns the app information document stored in each app database.
|
||||
*/
|
||||
exports.getAllApps = async (CouchDB, { dev, all } = {}) => {
|
||||
exports.getAllApps = async (CouchDB, { dev, all, idsOnly } = {}) => {
|
||||
let tenantId = getTenantId()
|
||||
if (!env.MULTI_TENANCY && !tenantId) {
|
||||
tenantId = DEFAULT_TENANT_ID
|
||||
}
|
||||
let allDbs = await CouchDB.allDbs()
|
||||
const appDbNames = allDbs.filter(dbName => {
|
||||
let dbs = await exports.getAllDbs()
|
||||
const appDbNames = dbs.filter(dbName => {
|
||||
const split = dbName.split(SEPARATOR)
|
||||
// it is an app, check the tenantId
|
||||
if (split[0] === DocumentTypes.APP) {
|
||||
|
@ -183,6 +202,9 @@ exports.getAllApps = async (CouchDB, { dev, all } = {}) => {
|
|||
}
|
||||
return false
|
||||
})
|
||||
if (idsOnly) {
|
||||
return appDbNames
|
||||
}
|
||||
const appPromises = appDbNames.map(db =>
|
||||
// skip setup otherwise databases could be re-created
|
||||
new CouchDB(db, { skip_setup: true }).get(DocumentTypes.APP_METADATA)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const PouchDB = require("pouchdb")
|
||||
const allDbs = require("pouchdb-all-dbs")
|
||||
const env = require("../../../../environment")
|
||||
|
||||
let POUCH_DB_DEFAULTS
|
||||
|
@ -15,6 +14,4 @@ if (env.isTest()) {
|
|||
|
||||
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
|
||||
|
||||
allDbs(Pouch)
|
||||
|
||||
module.exports = Pouch
|
||||
|
|
|
@ -6,6 +6,7 @@ const { newid } = require("../../hashing")
|
|||
const { createASession } = require("../../security/sessions")
|
||||
const { getGlobalUserByEmail } = require("../../utils")
|
||||
const { getGlobalDB, getTenantId } = require("../../tenancy")
|
||||
const fetch = require("node-fetch")
|
||||
|
||||
/**
|
||||
* Common authentication logic for third parties. e.g. OAuth, OIDC.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/bbui",
|
||||
"description": "A UI solution used in the different Budibase projects.",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"license": "AGPL-3.0",
|
||||
"svelte": "src/index.js",
|
||||
"module": "dist/bbui.es.js",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
export let text = null
|
||||
export let disabled = false
|
||||
export let error = null
|
||||
export let size = "M"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = e => {
|
||||
|
@ -18,5 +19,5 @@
|
|||
</script>
|
||||
|
||||
<Field {label} {labelPosition} {error}>
|
||||
<Checkbox {error} {disabled} {text} {value} on:change={onChange} />
|
||||
<Checkbox {error} {disabled} {text} {value} {size} on:change={onChange} />
|
||||
</Field>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
export let id = null
|
||||
export let text = null
|
||||
export let disabled = false
|
||||
export let size = null
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = event => {
|
||||
|
@ -16,7 +17,7 @@
|
|||
</script>
|
||||
|
||||
<label
|
||||
class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-Checkbox--emphasized"
|
||||
class="spectrum-Checkbox spectrum-Checkbox--size{size} spectrum-Checkbox--emphasized"
|
||||
class:is-invalid={!!error}
|
||||
>
|
||||
<input
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
on:click={onClick}
|
||||
class:is-selected={$selected.title === title}
|
||||
class="spectrum-Tabs-item"
|
||||
class:emphasized={$selected.title === title && $selected.emphasized}
|
||||
tabindex="0"
|
||||
>
|
||||
{#if icon}
|
||||
|
@ -49,3 +50,9 @@
|
|||
<slot />
|
||||
</Portal>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.emphasized {
|
||||
color: var(--spectrum-global-color-blue-600);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
export let selected
|
||||
export let vertical = false
|
||||
export let noPadding = false
|
||||
export let quiet = false
|
||||
export let emphasized = false
|
||||
|
||||
let _id = id()
|
||||
const tab = writable({ title: selected, id: _id })
|
||||
const tab = writable({ title: selected, id: _id, emphasized })
|
||||
setContext("tab", tab)
|
||||
|
||||
let container
|
||||
|
@ -56,7 +58,9 @@
|
|||
|
||||
<div
|
||||
bind:this={container}
|
||||
class="selected-border spectrum-Tabs spectrum-Tabs--{vertical
|
||||
class:quiet
|
||||
class="selected-border spectrum-Tabs {quiet &&
|
||||
'spectrum-Tabs--quiet'} spectrum-Tabs--{vertical
|
||||
? 'vertical'
|
||||
: 'horizontal'}"
|
||||
>
|
||||
|
@ -64,7 +68,8 @@
|
|||
{#if $tab.info}
|
||||
<div
|
||||
class="spectrum-Tabs-selectionIndicator indicator-transition"
|
||||
style="width: {width}; height: {height}; left: {left}; top: {top};"
|
||||
style="{emphasized &&
|
||||
'background-color: var(--spectrum-global-color-blue-400)'}; width: {width}; height: {height}; left: {left}; top: {top};"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -75,6 +80,10 @@
|
|||
/>
|
||||
|
||||
<style>
|
||||
.quiet {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.spectrum-Tabs {
|
||||
padding-left: var(--spacing-xl);
|
||||
padding-right: var(--spacing-xl);
|
||||
|
|
|
@ -7,5 +7,15 @@ context("Screen Tests", () => {
|
|||
|
||||
it("Should successfully create a screen", () => {
|
||||
cy.createScreen("Test Screen", "/test")
|
||||
cy.get(".nav-items-container").within(() => {
|
||||
cy.contains("/test").should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
it("Should update the url", () => {
|
||||
cy.createScreen("Test Screen", "test with spaces")
|
||||
cy.get(".nav-items-container").within(() => {
|
||||
cy.contains("/test-with-spaces").should("exist")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -160,7 +160,4 @@ Cypress.Commands.add("createScreen", (screenName, route) => {
|
|||
cy.get("input").eq(1).type(route)
|
||||
cy.get(".spectrum-Button--cta").click()
|
||||
})
|
||||
cy.get(".nav-items-container").within(() => {
|
||||
cy.contains(route).should("exist")
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/builder",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"license": "AGPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -65,10 +65,10 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^0.9.97-alpha.0",
|
||||
"@budibase/client": "^0.9.97-alpha.0",
|
||||
"@budibase/bbui": "^0.9.105-alpha.3",
|
||||
"@budibase/client": "^0.9.105-alpha.3",
|
||||
"@budibase/colorpicker": "1.1.2",
|
||||
"@budibase/string-templates": "^0.9.97-alpha.0",
|
||||
"@budibase/string-templates": "^0.9.105-alpha.3",
|
||||
"@sentry/browser": "5.19.1",
|
||||
"@spectrum-css/page": "^3.0.1",
|
||||
"@spectrum-css/vars": "^3.0.1",
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import { Select, Label, notifications, ModalContent } from "@budibase/bbui"
|
||||
import { tables, views } from "stores/backend"
|
||||
import analytics from "analytics"
|
||||
import { FIELDS } from "constants/backend"
|
||||
|
||||
const CALCULATIONS = [
|
||||
{
|
||||
|
@ -25,13 +26,16 @@
|
|||
)
|
||||
$: fields =
|
||||
viewTable &&
|
||||
Object.keys(viewTable.schema).filter(
|
||||
field =>
|
||||
view.calculation === "count" ||
|
||||
// don't want to perform calculations based on auto ID
|
||||
(viewTable.schema[field].type === "number" &&
|
||||
!viewTable.schema[field].autocolumn)
|
||||
)
|
||||
Object.keys(viewTable.schema).filter(fieldName => {
|
||||
const field = viewTable.schema[fieldName]
|
||||
return (
|
||||
field.type !== FIELDS.FORMULA.type &&
|
||||
field.type !== FIELDS.LINK.type &&
|
||||
(view.calculation === "count" ||
|
||||
// don't want to perform calculations based on auto ID
|
||||
(field.type === "number" && !field.autocolumn))
|
||||
)
|
||||
})
|
||||
|
||||
function saveView() {
|
||||
views.save(view)
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
let exportFormat = FORMATS[0].key
|
||||
|
||||
async function exportView() {
|
||||
const filename = `export.${exportFormat}`
|
||||
download(
|
||||
`/api/views/export?view=${encodeURIComponent(
|
||||
view
|
||||
)}&format=${exportFormat}`
|
||||
)}&format=${exportFormat}`,
|
||||
filename
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
$: fields =
|
||||
viewTable &&
|
||||
Object.entries(viewTable.schema)
|
||||
.filter(entry => entry[1].type !== FIELDS.LINK.type)
|
||||
.filter(
|
||||
entry =>
|
||||
entry[1].type !== FIELDS.LINK.type &&
|
||||
entry[1].type !== FIELDS.FORMULA.type
|
||||
)
|
||||
.map(([key]) => key)
|
||||
|
||||
function saveView() {
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
if (!event.detail.startsWith("/")) {
|
||||
route = "/" + event.detail
|
||||
}
|
||||
route = route.replaceAll(" ", "-")
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
export let componentInstance
|
||||
export let bindings
|
||||
|
||||
function setAssetProps(name, value) {
|
||||
function setAssetProps(name, value, parser) {
|
||||
if (parser && typeof parser === "function") {
|
||||
value = parser(value)
|
||||
}
|
||||
|
||||
const selectedAsset = get(currentAsset)
|
||||
store.update(state => {
|
||||
if (
|
||||
|
@ -29,7 +33,12 @@
|
|||
|
||||
const screenSettings = [
|
||||
// { key: "description", label: "Description", control: Input },
|
||||
{ key: "routing.route", label: "Route", control: Input },
|
||||
{
|
||||
key: "routing.route",
|
||||
label: "Route",
|
||||
control: Input,
|
||||
parser: val => val.replaceAll(" ", "-"),
|
||||
},
|
||||
{ key: "routing.roleId", label: "Access", control: RoleSelect },
|
||||
{ key: "layoutId", label: "Layout", control: LayoutSelect },
|
||||
]
|
||||
|
@ -44,7 +53,7 @@
|
|||
label={def.label}
|
||||
key={def.key}
|
||||
value={deepGet($currentAsset, def.key)}
|
||||
onChange={val => setAssetProps(def.key, val)}
|
||||
on:change={event => setAssetProps(def.key, event.detail, def.parser)}
|
||||
{bindings}
|
||||
/>
|
||||
{/each}
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
// Data to send off
|
||||
let rating
|
||||
let improvements
|
||||
let comment
|
||||
let improvements = ""
|
||||
let comment = ""
|
||||
|
||||
function selectNumber(n) {
|
||||
rating = n
|
||||
|
@ -106,11 +106,7 @@
|
|||
<Detail size="S">STEP 2 OF 3</Detail>
|
||||
<ButtonGroup>
|
||||
<Button secondary on:click={() => (step -= 1)}>Previous</Button>
|
||||
<Button
|
||||
disabled={!improvements}
|
||||
primary
|
||||
on:click={() => (step += 1)}>Next</Button
|
||||
>
|
||||
<Button primary on:click={() => (step += 1)}>Next</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{:else}
|
||||
|
@ -121,9 +117,7 @@
|
|||
<Detail size="S">STEP 3 OF 3</Detail>
|
||||
<ButtonGroup>
|
||||
<Button secondary on:click={() => (step -= 1)}>Previous</Button>
|
||||
<Button disabled={!comment} cta on:click={submitFeedback}
|
||||
>Complete</Button
|
||||
>
|
||||
<Button cta on:click={submitFeedback}>Complete</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
Checkbox,
|
||||
} from "@budibase/bbui"
|
||||
import { store, automationStore, hostingStore } from "builderStore"
|
||||
import { admin } from "stores/portal"
|
||||
import { string, mixed, object } from "yup"
|
||||
import api, { get, post } from "builderStore/api"
|
||||
import analytics from "analytics"
|
||||
|
@ -102,6 +103,8 @@
|
|||
if (applicationPkg.ok) {
|
||||
await store.actions.initialise(pkg)
|
||||
await automationStore.actions.fetch()
|
||||
// update checklist - incase first app
|
||||
await admin.init()
|
||||
} else {
|
||||
throw new Error(pkg)
|
||||
}
|
||||
|
|
|
@ -199,6 +199,9 @@
|
|||
delete datasource.entities[toTable.name].schema[originalToName]
|
||||
}
|
||||
|
||||
// store the original names so it won't cause an error
|
||||
originalToName = toRelationship.name
|
||||
originalFromName = fromRelationship.name
|
||||
await save()
|
||||
await tables.fetch()
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import OktaLogo from "assets/okta-logo.png"
|
||||
import OneLoginLogo from "assets/onelogin-logo.png"
|
||||
|
||||
import { oidc, organisation } from "stores/portal"
|
||||
import { oidc, organisation, auth } from "stores/portal"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
$: show = $organisation.oidc
|
||||
|
@ -31,7 +31,10 @@
|
|||
{#if show}
|
||||
<ActionButton
|
||||
on:click={() =>
|
||||
window.open(`/api/global/auth/oidc/configs/${$oidc.uuid}`, "_blank")}
|
||||
window.open(
|
||||
`/api/global/auth/${$auth.tenantId}/oidc/configs/${$oidc.uuid}`,
|
||||
"_blank"
|
||||
)}
|
||||
>
|
||||
<div class="inner">
|
||||
<img {src} alt="oidc icon" />
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import api, { del } from "builderStore/api"
|
||||
import analytics from "analytics"
|
||||
import { onMount } from "svelte"
|
||||
import { apps, auth } from "stores/portal"
|
||||
import { apps, auth, admin } from "stores/portal"
|
||||
import download from "downloadjs"
|
||||
import { goto } from "@roxi/routify"
|
||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||
|
@ -159,6 +159,8 @@
|
|||
throw json.message
|
||||
}
|
||||
await apps.load()
|
||||
// get checklist, just in case that was the last app
|
||||
await admin.init()
|
||||
notifications.success("App deleted successfully")
|
||||
} catch (err) {
|
||||
notifications.error(`Error deleting app: ${err}`)
|
||||
|
|
|
@ -187,7 +187,6 @@
|
|||
`Please fill in all required ${ConfigTypes.Google} fields`
|
||||
)
|
||||
} else {
|
||||
delete element.config.callbackURL
|
||||
calls.push(api.post(`/api/global/configs`, element))
|
||||
googleSaveButtonDisabled = true
|
||||
originalGoogleDoc = cloneDeep(providers.google)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/cli",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||
"main": "src/index.js",
|
||||
"bin": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/client",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"license": "MPL-2.0",
|
||||
"module": "dist/budibase-client.js",
|
||||
"main": "dist/budibase-client.js",
|
||||
|
@ -18,9 +18,9 @@
|
|||
"dev:builder": "rollup -cw"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^0.9.97-alpha.0",
|
||||
"@budibase/standard-components": "^0.9.97-alpha.0",
|
||||
"@budibase/string-templates": "^0.9.97-alpha.0",
|
||||
"@budibase/bbui": "^0.9.105-alpha.3",
|
||||
"@budibase/standard-components": "^0.9.105-alpha.3",
|
||||
"@budibase/string-templates": "^0.9.105-alpha.3",
|
||||
"regexparam": "^1.3.0",
|
||||
"shortid": "^2.2.15",
|
||||
"svelte-spa-router": "^3.0.5"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/server",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"description": "Budibase Web Server",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
|
@ -62,9 +62,9 @@
|
|||
"author": "Budibase",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@budibase/auth": "^0.9.97-alpha.0",
|
||||
"@budibase/client": "^0.9.97-alpha.0",
|
||||
"@budibase/string-templates": "^0.9.97-alpha.0",
|
||||
"@budibase/auth": "^0.9.105-alpha.3",
|
||||
"@budibase/client": "^0.9.105-alpha.3",
|
||||
"@budibase/string-templates": "^0.9.105-alpha.3",
|
||||
"@elastic/elasticsearch": "7.10.0",
|
||||
"@koa/router": "8.0.0",
|
||||
"@sendgrid/mail": "7.1.1",
|
||||
|
@ -117,7 +117,7 @@
|
|||
"devDependencies": {
|
||||
"@babel/core": "^7.14.3",
|
||||
"@babel/preset-env": "^7.14.4",
|
||||
"@budibase/standard-components": "^0.9.97-alpha.0",
|
||||
"@budibase/standard-components": "^0.9.105-alpha.3",
|
||||
"@jest/test-sequencer": "^24.8.0",
|
||||
"@types/bull": "^3.15.1",
|
||||
"@types/jest": "^26.0.23",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
const CouchDB = require("../src/db")
|
||||
const { DocumentTypes } = require("../src/db/utils")
|
||||
const { getAllDbs } = require("@budibase/auth/db")
|
||||
|
||||
const appName = process.argv[2].toLowerCase()
|
||||
const remoteUrl = process.argv[3]
|
||||
|
@ -14,8 +15,8 @@ const remoteUrl = process.argv[3]
|
|||
console.log(`Replicating from ${appName} to ${remoteUrl}/${appName}`)
|
||||
|
||||
const run = async () => {
|
||||
const allDbs = await CouchDB.allDbs()
|
||||
const appDbNames = allDbs.filter(dbName => dbName.startsWith("inst_app"))
|
||||
const dbs = await getAllDbs()
|
||||
const appDbNames = dbs.filter(dbName => dbName.startsWith("inst_app"))
|
||||
let apps = []
|
||||
for (let dbName of appDbNames) {
|
||||
const db = new CouchDB(dbName)
|
||||
|
|
|
@ -25,10 +25,10 @@ interface ManyRelationship {
|
|||
|
||||
interface RunConfig {
|
||||
id: string
|
||||
row: Row
|
||||
filters: SearchFilters
|
||||
sort: SortJson
|
||||
paginate: PaginationJson
|
||||
row: Row
|
||||
}
|
||||
|
||||
module External {
|
||||
|
@ -89,8 +89,9 @@ module External {
|
|||
// build id array
|
||||
let idParts = []
|
||||
for (let field of primary) {
|
||||
if (row[field]) {
|
||||
idParts.push(row[field])
|
||||
const fieldValue = row[`${table.name}.${field}`]
|
||||
if (fieldValue) {
|
||||
idParts.push(fieldValue)
|
||||
}
|
||||
}
|
||||
if (idParts.length === 0) {
|
||||
|
@ -115,7 +116,11 @@ module External {
|
|||
const thisRow: { [key: string]: any } = {}
|
||||
// filter the row down to what is actually the row (not joined)
|
||||
for (let fieldName of Object.keys(table.schema)) {
|
||||
thisRow[fieldName] = row[fieldName]
|
||||
const value = row[`${table.name}.${fieldName}`]
|
||||
// all responses include "select col as table.col" so that overlaps are handled
|
||||
if (value) {
|
||||
thisRow[fieldName] = value
|
||||
}
|
||||
}
|
||||
thisRow._id = generateIdForRow(row, table)
|
||||
thisRow.tableId = table._id
|
||||
|
@ -191,7 +196,7 @@ module External {
|
|||
const isUpdate = !field.through
|
||||
const thisKey: string = isUpdate ? "id" : linkTablePrimary
|
||||
// @ts-ignore
|
||||
const otherKey: string = isUpdate ? field.foreignKey : tablePrimary
|
||||
const otherKey: string = isUpdate ? field.fieldName : tablePrimary
|
||||
row[key].map((relationship: any) => {
|
||||
// we don't really support composite keys for relationships, this is why [0] is used
|
||||
manyRelationships.push({
|
||||
|
@ -359,7 +364,7 @@ module External {
|
|||
}
|
||||
}
|
||||
if (cache[fullKey] == null) {
|
||||
cache[fullKey] = await makeExternalQuery(this.appId, {
|
||||
const response = await makeExternalQuery(this.appId, {
|
||||
endpoint: getEndpoint(tableId, DataSourceOperation.READ),
|
||||
filters: {
|
||||
equal: {
|
||||
|
@ -367,8 +372,12 @@ module External {
|
|||
},
|
||||
},
|
||||
})
|
||||
// this is the response from knex if no rows found
|
||||
if (!response[0].read) {
|
||||
cache[fullKey] = response
|
||||
}
|
||||
}
|
||||
return { rows: cache[fullKey], table }
|
||||
return { rows: cache[fullKey] || [], table }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -418,12 +427,16 @@ module External {
|
|||
const { tableName } = breakExternalTableId(tableId)
|
||||
const table = this.tables[tableName]
|
||||
for (let row of rows) {
|
||||
promises.push(
|
||||
makeExternalQuery(this.appId, {
|
||||
endpoint: getEndpoint(tableId, DataSourceOperation.DELETE),
|
||||
filters: buildFilters(generateIdForRow(row, table), {}, table),
|
||||
})
|
||||
)
|
||||
const filters = buildFilters(generateIdForRow(row, table), {}, table)
|
||||
// safety check, if there are no filters on deletion bad things happen
|
||||
if (Object.keys(filters).length !== 0) {
|
||||
promises.push(
|
||||
makeExternalQuery(this.appId, {
|
||||
endpoint: getEndpoint(tableId, DataSourceOperation.DELETE),
|
||||
filters,
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
await Promise.all(promises)
|
||||
|
@ -442,7 +455,7 @@ module External {
|
|||
.filter(
|
||||
column =>
|
||||
column[1].type !== FieldTypes.LINK &&
|
||||
!existing.find((field: string) => field.includes(column[0]))
|
||||
!existing.find((field: string) => field === column[0])
|
||||
)
|
||||
.map(column => `${table.name}.${column[0]}`)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@ exports.csv = function (headers, rows) {
|
|||
|
||||
for (let row of rows) {
|
||||
csv = `${csv}\n${headers
|
||||
.map(header => `"${row[header]}"`.trim())
|
||||
.map(header => {
|
||||
let val = row[header]
|
||||
val = typeof val === "object" ? JSON.stringify(val) : val
|
||||
return `"${val}"`.trim()
|
||||
})
|
||||
.join(",")}`
|
||||
}
|
||||
return csv
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../controllers/hosting")
|
||||
const authorized = require("../../middleware/authorized")
|
||||
const selfhost = require("../../middleware/selfhost")
|
||||
const { BUILDER } = require("@budibase/auth/permissions")
|
||||
|
||||
const router = Router()
|
||||
|
@ -9,6 +8,6 @@ const router = Router()
|
|||
router
|
||||
.get("/api/hosting/urls", authorized(BUILDER), controller.fetchUrls)
|
||||
// this isn't risky, doesn't return anything about apps other than names and URLs
|
||||
.get("/api/hosting/apps", selfhost, controller.getDeployedApps)
|
||||
.get("/api/hosting/apps", controller.getDeployedApps)
|
||||
|
||||
module.exports = router
|
||||
|
|
|
@ -82,7 +82,7 @@ describe("/datasources", () => {
|
|||
entityId: "users",
|
||||
},
|
||||
resource: {
|
||||
fields: ["name", "age"],
|
||||
fields: ["users.name", "users.age"],
|
||||
},
|
||||
filters: {
|
||||
string: {
|
||||
|
@ -94,7 +94,7 @@ describe("/datasources", () => {
|
|||
.expect(200)
|
||||
// this is mock data, can't test it
|
||||
expect(res.body).toBeDefined()
|
||||
expect(pg.queryMock).toHaveBeenCalledWith(`select "name", "age" from "users" where "users"."name" like $1 limit $2`, ["John%", 5000])
|
||||
expect(pg.queryMock).toHaveBeenCalledWith(`select "users"."name" as "users.name", "users"."age" as "users.age" from "users" where "users"."name" like $1 limit $2`, ["John%", 5000])
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ module.exports.definition = {
|
|||
requestMethod: "POST",
|
||||
url: "http://",
|
||||
requestBody: "{}",
|
||||
headers: "{}",
|
||||
},
|
||||
schema: {
|
||||
inputs: {
|
||||
|
@ -45,6 +46,11 @@ module.exports.definition = {
|
|||
title: "JSON Body",
|
||||
customType: "wide",
|
||||
},
|
||||
headers: {
|
||||
type: "string",
|
||||
title: "Headers",
|
||||
customType: "wide",
|
||||
},
|
||||
},
|
||||
required: ["requestMethod", "url"],
|
||||
},
|
||||
|
@ -65,7 +71,7 @@ module.exports.definition = {
|
|||
}
|
||||
|
||||
module.exports.run = async function ({ inputs }) {
|
||||
let { requestMethod, url, requestBody } = inputs
|
||||
let { requestMethod, url, requestBody, headers } = inputs
|
||||
if (!url.startsWith("http")) {
|
||||
url = `http://${url}`
|
||||
}
|
||||
|
@ -84,6 +90,15 @@ module.exports.run = async function ({ inputs }) {
|
|||
request.headers = {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
if (headers && headers.length !== 0) {
|
||||
try {
|
||||
const customHeaders = JSON.parse(headers)
|
||||
request.headers = { ...request.headers, ...customHeaders }
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -24,21 +24,7 @@ if (env.isTest()) {
|
|||
|
||||
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
|
||||
|
||||
// have to still have pouch alldbs for testing
|
||||
allDbs(Pouch)
|
||||
|
||||
// replicate your local levelDB pouch to a running HTTP compliant couch or pouchdb server.
|
||||
/* istanbul ignore next */
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function replicateLocal() {
|
||||
Pouch.allDbs().then(dbs => {
|
||||
for (let db of dbs) {
|
||||
new Pouch(db).sync(
|
||||
new PouchDB(`http://127.0.0.1:5984/${db}`, { live: true })
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// replicateLocal()
|
||||
|
||||
module.exports = Pouch
|
||||
|
|
|
@ -322,7 +322,7 @@ class LinkController {
|
|||
// remove schema from other table
|
||||
let linkedTable = await this._db.get(field.tableId)
|
||||
delete linkedTable.schema[field.fieldName]
|
||||
this._db.put(linkedTable)
|
||||
await this._db.put(linkedTable)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -151,7 +151,9 @@ function buildRead(knex: Knex, json: QueryJson, limit: number): KnexQuery {
|
|||
}
|
||||
// handle select
|
||||
if (resource.fields && resource.fields.length > 0) {
|
||||
query = query.select(resource.fields)
|
||||
// select the resources as the format "table.columnName" - this is what is provided
|
||||
// by the resource builder further up
|
||||
query = query.select(resource.fields.map(field => `${field} as ${field}`))
|
||||
} else {
|
||||
query = query.select("*")
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ const INTEGRATIONS = {
|
|||
[SourceNames.MONGODB]: mongodb.integration,
|
||||
[SourceNames.ELASTICSEARCH]: elasticsearch.integration,
|
||||
[SourceNames.COUCHDB]: couchdb.integration,
|
||||
[SourceNames.SQL_SERVER]: s3.integration,
|
||||
[SourceNames.S3]: sqlServer.integration,
|
||||
[SourceNames.SQL_SERVER]: sqlServer.integration,
|
||||
[SourceNames.S3]: s3.integration,
|
||||
[SourceNames.AIRTABLE]: airtable.integration,
|
||||
[SourceNames.MYSQL]: mysql.integration,
|
||||
[SourceNames.ARANGODB]: arangodb.integration,
|
||||
|
|
|
@ -242,7 +242,7 @@ module MySQLModule {
|
|||
const input = this._query(json, { disableReturning: true })
|
||||
let row
|
||||
// need to manage returning, a feature mySQL can't do
|
||||
if (operation === "awdawd") {
|
||||
if (operation === operation.DELETE) {
|
||||
row = this.getReturningRow(json)
|
||||
}
|
||||
const results = await internalQuery(this.client, input, false)
|
||||
|
|
|
@ -62,12 +62,13 @@ describe("SQL query builder", () => {
|
|||
})
|
||||
|
||||
it("should test a read with specific columns", () => {
|
||||
const nameProp = `${TABLE_NAME}.name`, ageProp = `${TABLE_NAME}.age`
|
||||
const query = sql._query(generateReadJson({
|
||||
fields: ["name", "age"]
|
||||
fields: [nameProp, ageProp]
|
||||
}))
|
||||
expect(query).toEqual({
|
||||
bindings: [limit],
|
||||
sql: `select "name", "age" from "${TABLE_NAME}" limit $1`
|
||||
sql: `select "${TABLE_NAME}"."name" as "${nameProp}", "${TABLE_NAME}"."age" as "${ageProp}" from "${TABLE_NAME}" limit $1`
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -40,8 +40,13 @@ export function breakRowIdField(_id: string): any[] {
|
|||
// have to replace on the way back as we swapped out the double quotes
|
||||
// when encoding, but JSON can't handle the single quotes
|
||||
const decoded: string = decodeURIComponent(_id).replace(/'/g, '"')
|
||||
const parsed = JSON.parse(decoded)
|
||||
return Array.isArray(parsed) ? parsed : [parsed]
|
||||
try {
|
||||
const parsed = JSON.parse(decoded)
|
||||
return Array.isArray(parsed) ? parsed : [parsed]
|
||||
} catch (err) {
|
||||
// wasn't json - likely was handlebars for a many to many
|
||||
return [_id]
|
||||
}
|
||||
}
|
||||
|
||||
export function convertType(type: string, map: { [key: string]: any }) {
|
||||
|
|
|
@ -10,7 +10,7 @@ const CouchDB = require("../db")
|
|||
|
||||
module.exports = async (ctx, next) => {
|
||||
// try to get the appID from the request
|
||||
const requestAppId = getAppId(ctx)
|
||||
let requestAppId = getAppId(ctx)
|
||||
// get app cookie if it exists
|
||||
let appCookie = null
|
||||
try {
|
||||
|
@ -29,6 +29,8 @@ module.exports = async (ctx, next) => {
|
|||
clearCookie(ctx, Cookies.CurrentApp)
|
||||
return next()
|
||||
}
|
||||
// if the request app ID wasn't set, update it with the cookie
|
||||
requestAppId = requestAppId || appId
|
||||
}
|
||||
|
||||
let appId,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const env = require("../environment")
|
||||
const { OBJ_STORE_DIRECTORY, ObjectStoreBuckets } = require("../constants")
|
||||
const { OBJ_STORE_DIRECTORY } = require("../constants")
|
||||
const { sanitizeKey } = require("@budibase/auth/src/objectStore")
|
||||
|
||||
const BB_CDN = "https://cdn.app.budi.live/assets"
|
||||
|
@ -52,6 +52,6 @@ exports.clientLibraryPath = appId => {
|
|||
|
||||
exports.attachmentsRelativeURL = attachmentKey => {
|
||||
return exports.checkSlashesInUrl(
|
||||
`/${ObjectStoreBuckets.APPS}/${attachmentKey}`
|
||||
`${exports.objectStoreUrl()}/${attachmentKey}`
|
||||
)
|
||||
}
|
||||
|
|
|
@ -184,7 +184,13 @@ exports.inputProcessing = (user = {}, table, row) => {
|
|||
}
|
||||
continue
|
||||
}
|
||||
clonedRow[key] = exports.coerce(value, field.type)
|
||||
// specific case to delete formula values if they get saved
|
||||
// type coercion cannot completely remove the field, so have to do it here
|
||||
if (field.type === FieldTypes.FORMULA) {
|
||||
delete clonedRow[key]
|
||||
} else {
|
||||
clonedRow[key] = exports.coerce(value, field.type)
|
||||
}
|
||||
}
|
||||
// handle auto columns - this returns an object like {table, row}
|
||||
return processAutoColumn(user, copiedTable, clonedRow)
|
||||
|
|
|
@ -1146,11 +1146,12 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/auth@^0.9.79-alpha.4":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.79.tgz#416271ffc55e84116550469656bf151a7734a90f"
|
||||
integrity sha512-ENh099tYeUfVExsAeoxwMh2ODioKQGPteK9LJiU5hMdM4Oi7pyImu287BgKpTIheB+WtadT4e21VpPaJ62APEw==
|
||||
"@budibase/auth@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.102.tgz#86bb653686a311858b6ab6a048c6a4746bd5ced4"
|
||||
integrity sha512-Wov1vWAkWQn2P/gVapMBDdGKE1OwbpyD+3LV9E1HqZ3AASWZztqAFfnUaF6kKsHeem8S69uZ3vBU6uuyn9Sp+w==
|
||||
dependencies:
|
||||
"@techpass/passport-openidconnect" "^0.3.0"
|
||||
aws-sdk "^2.901.0"
|
||||
bcryptjs "^2.4.3"
|
||||
ioredis "^4.27.1"
|
||||
|
@ -1167,10 +1168,10 @@
|
|||
uuid "^8.3.2"
|
||||
zlib "^1.0.5"
|
||||
|
||||
"@budibase/bbui@^0.9.79":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.79.tgz#c033ba0af41cb584d2657a8353f9887328f6633f"
|
||||
integrity sha512-XxUJSPGd2FZDFdbNOeMUXohhID5h3DVq9XyKTe6WhYax4m2da/2WTENJ16UFvmfA+yxLN1qSDeweq9vw2zCahQ==
|
||||
"@budibase/bbui@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.102.tgz#e27a1763086651c6a9832a81b3695c10b0d52079"
|
||||
integrity sha512-DKtfEoUdDm7aApfMHQi53TB18Qj4+c/CYWTyWP8T7+G/h4pCDdYEsjokn1MT2pbouPzECcjelw2w3k78Ac3N2Q==
|
||||
dependencies:
|
||||
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||
"@spectrum-css/actionbutton" "^1.0.1"
|
||||
|
@ -1215,14 +1216,14 @@
|
|||
svelte-flatpickr "^3.1.0"
|
||||
svelte-portal "^1.0.0"
|
||||
|
||||
"@budibase/client@^0.9.79-alpha.4":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.79.tgz#d1c8d51e9121f81902cfb31d3b685c8061f272a2"
|
||||
integrity sha512-//Yqm5Qki6BmBe5W2Tz8GONdkFjdD1jkIU7pcLYKqdZJWEQIrX6T/xNvYvZVhw7Dx5bwSZRjFwzm7jLoiyHBIA==
|
||||
"@budibase/client@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.102.tgz#4f1d5f84671182ecb65c1d09f691584dbd687fd3"
|
||||
integrity sha512-Uu7DzFOKlIKGF4IO24kS8ANiN5rf7i90KRqLfPDh1I8vdEj5L9sYQYyyI9YwUJ48keuoGfqHHlcH48dPJU+cxQ==
|
||||
dependencies:
|
||||
"@budibase/bbui" "^0.9.79"
|
||||
"@budibase/standard-components" "^0.9.79"
|
||||
"@budibase/string-templates" "^0.9.79"
|
||||
"@budibase/bbui" "^0.9.102"
|
||||
"@budibase/standard-components" "^0.9.102"
|
||||
"@budibase/string-templates" "^0.9.102"
|
||||
regexparam "^1.3.0"
|
||||
shortid "^2.2.15"
|
||||
svelte-spa-router "^3.0.5"
|
||||
|
@ -1255,24 +1256,26 @@
|
|||
to-gfm-code-block "^0.1.1"
|
||||
year "^0.2.1"
|
||||
|
||||
"@budibase/standard-components@^0.9.79", "@budibase/standard-components@^0.9.79-alpha.4":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.79.tgz#24206642e0cdc655ea3a99ed5e9402ec4f6b3ba8"
|
||||
integrity sha512-ZWhmBZ1iG+CjGMEvT/jtugMMgA1n88UYcOfP3BSP2P3eA16DubyU9hH9OyJHbGPzDHLoBF6vuS/5ZPZCkOKppw==
|
||||
"@budibase/standard-components@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.102.tgz#4158eb5e2c46a403f2968cfa6a47751f402e776f"
|
||||
integrity sha512-N8PcMzktBThMOb+LLBUdVi4WI2LxhEgWEXQr6tD0wKigxL734wWxRf2QWskFSJb/YvJoSP74jR9LF5P0zt1oTw==
|
||||
dependencies:
|
||||
"@budibase/bbui" "^0.9.79"
|
||||
"@budibase/bbui" "^0.9.102"
|
||||
"@spectrum-css/card" "^3.0.3"
|
||||
"@spectrum-css/link" "^3.1.3"
|
||||
"@spectrum-css/page" "^3.0.1"
|
||||
"@spectrum-css/typography" "^3.0.2"
|
||||
"@spectrum-css/vars" "^3.0.1"
|
||||
apexcharts "^3.22.1"
|
||||
dayjs "^1.10.5"
|
||||
svelte-apexcharts "^1.0.2"
|
||||
svelte-flatpickr "^3.1.0"
|
||||
|
||||
"@budibase/string-templates@^0.9.79", "@budibase/string-templates@^0.9.79-alpha.4":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.79.tgz#bb75a7433a7cfda1fc488283f35e47879b799fcc"
|
||||
integrity sha512-hkAne5mx7mj8+osXFt45VwgLKSa94uQOGOb4R8uv9WNzvk4RzcjBfRzJxggv29FUemItrAeZpSh+Um6yugFI+w==
|
||||
"@budibase/string-templates@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.102.tgz#5beb1dac696781b404020d5ab6bb91cbe4dcd10a"
|
||||
integrity sha512-cDDh5tyGYtA2sr8VDaRMLp9Ff+icXKNZ5BredePfES5du3GOWjFeVe0h1WFsR12Yq1dH1WWKR1XKc9CNwoQ8YA==
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.11.4"
|
||||
dayjs "^1.10.4"
|
||||
|
@ -2111,6 +2114,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@spectrum-css/buttongroup/-/buttongroup-3.0.3.tgz#719d868845ac9d2c4f939c1b9f6044507902d5aa"
|
||||
integrity sha512-eXl8U4QWMWXqyTu654FdQdEGnmczgOYlpIFSHyCMVjhtPqZp2xwnLFiGh6LKw+bLio6eeOZ0L+vpk1GcoYqgkw==
|
||||
|
||||
"@spectrum-css/card@^3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@spectrum-css/card/-/card-3.0.3.tgz#56b2e2da6b80c1583228baa279de7407383bfb6b"
|
||||
integrity sha512-+oKLUI2a0QmQP9EzySeq/G4FpUkkdaDNbuEbqCj2IkPMc/2v/nwzsPhh1fj2UIghGAiiUwXfPpzax1e8fyhQUg==
|
||||
|
||||
"@spectrum-css/checkbox@^3.0.2":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@spectrum-css/checkbox/-/checkbox-3.0.3.tgz#8577067fc8b97e4609f92bd242364937a533a7bb"
|
||||
|
@ -2270,7 +2278,7 @@
|
|||
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":
|
||||
"@spectrum-css/typography@^3.0.1", "@spectrum-css/typography@^3.0.2":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@spectrum-css/typography/-/typography-3.0.2.tgz#ea3ca0a60e18064527819d48c8c4364cab4fcd38"
|
||||
integrity sha512-5ZOLmQe0edzsDMyhghUd4hBb5uxGsFrxzf+WasfcUw9klSfTsRZ09n1BsaaWbgrLjlMQ+EEHS46v5VNo0Ms2CA==
|
||||
|
@ -2292,6 +2300,17 @@
|
|||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@techpass/passport-openidconnect@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.0.tgz#a60b2bbf3f262649a5a02d5d186219944acc3010"
|
||||
integrity sha512-bVsPwl66s7J7GHxTPlW/RJYhZol9SshNznQsx83OOh9G+JWFGoeWxh+xbX+FTdJNoUvGIGbJnpWPY2wC6NOHPw==
|
||||
dependencies:
|
||||
base64url "^3.0.1"
|
||||
oauth "^0.9.15"
|
||||
passport-strategy "^1.0.0"
|
||||
request "^2.88.0"
|
||||
webfinger "^0.4.2"
|
||||
|
||||
"@tootallnate/once@1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
|
@ -3286,7 +3305,7 @@ base64-js@^1.0.2, base64-js@^1.3.1:
|
|||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
base64url@3.x.x:
|
||||
base64url@3.x.x, base64url@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
|
||||
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
|
||||
|
@ -8707,7 +8726,7 @@ oauth-sign@~0.9.0:
|
|||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
oauth@0.9.x:
|
||||
oauth@0.9.x, oauth@^0.9.15:
|
||||
version "0.9.15"
|
||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
|
||||
|
@ -10081,7 +10100,7 @@ request-promise-native@^1.0.5:
|
|||
stealthy-require "^1.1.1"
|
||||
tough-cookie "^2.3.3"
|
||||
|
||||
"request@>= 2.52.0", request@^2.72.0, request@^2.74.0, request@^2.87.0:
|
||||
"request@>= 2.52.0", request@^2.72.0, request@^2.74.0, request@^2.87.0, request@^2.88.0:
|
||||
version "2.88.2"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
|
||||
|
@ -10205,7 +10224,7 @@ rimraf@2.6.3:
|
|||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^3.0.0:
|
||||
rimraf@^3.0.0, rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
|
@ -10290,7 +10309,7 @@ sax@1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"
|
||||
integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o=
|
||||
|
||||
sax@>=0.6.0, sax@^1.2.4:
|
||||
sax@>=0.1.1, sax@>=0.6.0, sax@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
@ -10745,6 +10764,11 @@ stealthy-require@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
|
||||
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
|
||||
|
||||
step@0.0.x:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2"
|
||||
integrity sha1-FD54SaXX0/SgiP4pr5SRUhbu7eI=
|
||||
|
||||
strict-uri-encode@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
|
@ -11786,6 +11810,14 @@ walker@^1.0.7, walker@~1.0.5:
|
|||
dependencies:
|
||||
makeerror "1.0.x"
|
||||
|
||||
webfinger@^0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d"
|
||||
integrity sha1-NHem2XeZRhiWA5/P/GULc0aO520=
|
||||
dependencies:
|
||||
step "0.0.x"
|
||||
xml2js "0.1.x"
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
|
@ -11992,6 +12024,13 @@ xml-parse-from-string@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28"
|
||||
integrity sha1-qQKekp09vN7RafPG4oI42VpdWig=
|
||||
|
||||
xml2js@0.1.x:
|
||||
version "0.1.14"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c"
|
||||
integrity sha1-UnTmf1pkxfkpdM2FE54DMq3GuQw=
|
||||
dependencies:
|
||||
sax ">=0.1.1"
|
||||
|
||||
xml2js@0.4.19:
|
||||
version "0.4.19"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
|
||||
|
|
|
@ -1892,7 +1892,6 @@
|
|||
"booleanfield": {
|
||||
"name": "Checkbox",
|
||||
"icon": "Checkmark",
|
||||
"styles": ["size"],
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
|
@ -1910,6 +1909,30 @@
|
|||
"label": "Text",
|
||||
"key": "text"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Size",
|
||||
"key": "size",
|
||||
"options": [
|
||||
{
|
||||
"label": "Small",
|
||||
"value": "S"
|
||||
},
|
||||
{
|
||||
"label": "Medium",
|
||||
"value": "M"
|
||||
},
|
||||
{
|
||||
"label": "Large",
|
||||
"value": "L"
|
||||
},
|
||||
{
|
||||
"label": "Extra large",
|
||||
"value": "XL"
|
||||
}
|
||||
],
|
||||
"defaultValue": "M"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"label": "Default value",
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
"keywords": [
|
||||
"svelte"
|
||||
],
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"license": "MIT",
|
||||
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^0.9.97-alpha.0",
|
||||
"@budibase/bbui": "^0.9.105-alpha.3",
|
||||
"@spectrum-css/card": "^3.0.3",
|
||||
"@spectrum-css/divider": "^1.0.3",
|
||||
"@spectrum-css/link": "^3.1.3",
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
export let label
|
||||
export let text
|
||||
export let disabled = false
|
||||
export let size
|
||||
export let defaultValue
|
||||
|
||||
let fieldState
|
||||
|
@ -40,6 +41,7 @@
|
|||
disabled={$fieldState.disabled}
|
||||
error={$fieldState.error}
|
||||
id={$fieldState.fieldId}
|
||||
{size}
|
||||
on:change={e => fieldApi.setValue(e.detail)}
|
||||
{text}
|
||||
/>
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
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.97-alpha.0":
|
||||
version "0.9.98"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.98.tgz#8fe80cc573df204d1a4147ebda5c20322f4616df"
|
||||
integrity sha512-T03xRq/Kz0/goMNfqsfXymvqhm9jHJQbzWx4oqPtgwIJlb/spx4kEgHS7MWuf3uyagAaFbW2x56Lauoiha8uLQ==
|
||||
"@budibase/bbui@^0.9.105-alpha.3":
|
||||
version "0.9.105-alpha.3"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.105-alpha.3.tgz#19a773df87511fe58ff347d0499f368bc777d50e"
|
||||
integrity sha512-Xm3jT89COeYu9JXb3woZXov9ae9mNHBD5YRxPTs7jyjcD2obyfIt/q6TIPvl9x4qkCi8v5fWiXpBv0cEqR8u/A==
|
||||
dependencies:
|
||||
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||
"@spectrum-css/actionbutton" "^1.0.1"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/string-templates",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"description": "Handlebars wrapper for Budibase templating.",
|
||||
"main": "src/index.cjs",
|
||||
"module": "dist/bundle.mjs",
|
||||
|
|
|
@ -126,6 +126,7 @@ module.exports.isValid = string => {
|
|||
"object",
|
||||
"array",
|
||||
"cannot read property",
|
||||
"undefined",
|
||||
]
|
||||
// this is a portion of a specific string always output by handlebars in the case of a syntax error
|
||||
const invalidCases = [`expecting '`]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/worker",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "0.9.97-alpha.0",
|
||||
"version": "0.9.105-alpha.3",
|
||||
"description": "Budibase background service",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
|
@ -23,8 +23,8 @@
|
|||
"author": "Budibase",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@budibase/auth": "^0.9.97-alpha.0",
|
||||
"@budibase/string-templates": "^0.9.97-alpha.0",
|
||||
"@budibase/auth": "^0.9.105-alpha.3",
|
||||
"@budibase/string-templates": "^0.9.105-alpha.3",
|
||||
"@koa/router": "^8.0.0",
|
||||
"@techpass/passport-openidconnect": "^0.3.0",
|
||||
"aws-sdk": "^2.811.0",
|
||||
|
|
|
@ -4,14 +4,9 @@ const CouchDB = require("../../db")
|
|||
const URL_REGEX_SLASH = /\/|\\/g
|
||||
|
||||
exports.getApps = async ctx => {
|
||||
const tenantId = ctx.user.tenantId
|
||||
const apps = await getAllApps(CouchDB, { tenantId })
|
||||
|
||||
const apps = await getAllApps(CouchDB, { dev: true })
|
||||
const body = {}
|
||||
for (let app of apps) {
|
||||
if (app.status !== "fulfilled") {
|
||||
continue
|
||||
}
|
||||
app = app.value
|
||||
let url = app.url || encodeURI(`${app.name}`)
|
||||
url = `/${url.replace(URL_REGEX_SLASH, "")}`
|
||||
|
|
|
@ -15,7 +15,11 @@ const {
|
|||
} = require("@budibase/auth/tenancy")
|
||||
const env = require("../../../environment")
|
||||
|
||||
function googleCallbackUrl() {
|
||||
function googleCallbackUrl(config) {
|
||||
// incase there is a callback URL from before
|
||||
if (config && config.callbackURL) {
|
||||
return config.callbackURL
|
||||
}
|
||||
let callbackUrl = `/api/global/auth`
|
||||
if (isMultiTenant()) {
|
||||
callbackUrl += `/${getTenantId()}`
|
||||
|
@ -116,12 +120,12 @@ exports.logout = async ctx => {
|
|||
*/
|
||||
exports.googlePreAuth = async (ctx, next) => {
|
||||
const db = getGlobalDB()
|
||||
let callbackUrl = googleCallbackUrl()
|
||||
|
||||
const config = await authPkg.db.getScopedConfig(db, {
|
||||
type: Configs.GOOGLE,
|
||||
workspace: ctx.query.workspace,
|
||||
})
|
||||
let callbackUrl = googleCallbackUrl(config)
|
||||
const strategy = await google.strategyFactory(config, callbackUrl)
|
||||
|
||||
return passport.authenticate(strategy, {
|
||||
|
@ -131,12 +135,12 @@ exports.googlePreAuth = async (ctx, next) => {
|
|||
|
||||
exports.googleAuth = async (ctx, next) => {
|
||||
const db = getGlobalDB()
|
||||
const callbackUrl = googleCallbackUrl()
|
||||
|
||||
const config = await authPkg.db.getScopedConfig(db, {
|
||||
type: Configs.GOOGLE,
|
||||
workspace: ctx.query.workspace,
|
||||
})
|
||||
const callbackUrl = googleCallbackUrl(config)
|
||||
const strategy = await google.strategyFactory(config, callbackUrl)
|
||||
|
||||
return passport.authenticate(
|
||||
|
|
|
@ -223,7 +223,7 @@ exports.configChecklist = async function (ctx) {
|
|||
// TODO: Watch get started video
|
||||
|
||||
// Apps exist
|
||||
const apps = await getAllApps(CouchDB)
|
||||
const apps = await getAllApps(CouchDB, { idsOnly: true })
|
||||
|
||||
// They have set up SMTP
|
||||
const smtpConfig = await getScopedFullConfig(db, {
|
||||
|
|
|
@ -6,6 +6,15 @@ const { buildAuthMiddleware, auditLog, buildTenancyMiddleware } =
|
|||
require("@budibase/auth").auth
|
||||
|
||||
const PUBLIC_ENDPOINTS = [
|
||||
// old deprecated endpoints kept for backwards compat
|
||||
{
|
||||
route: "/api/admin/auth/google/callback",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
route: "/api/admin/auth/oidc/callback",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
// this covers all of the POST auth routes
|
||||
route: "/api/global/auth/:tenantId",
|
||||
|
|
|
@ -30,7 +30,9 @@ function buildResetUpdateValidation() {
|
|||
}
|
||||
|
||||
function updateTenant(ctx, next) {
|
||||
updateTenantId(ctx.params.tenantId)
|
||||
if (ctx.params) {
|
||||
updateTenantId(ctx.params.tenantId)
|
||||
}
|
||||
return next()
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ if (env.isTest()) {
|
|||
|
||||
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
|
||||
|
||||
// have to still have pouch alldbs for testing
|
||||
allDbs(Pouch)
|
||||
|
||||
module.exports = Pouch
|
||||
|
|
|
@ -287,11 +287,12 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/auth@^0.9.79-alpha.4":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.79.tgz#416271ffc55e84116550469656bf151a7734a90f"
|
||||
integrity sha512-ENh099tYeUfVExsAeoxwMh2ODioKQGPteK9LJiU5hMdM4Oi7pyImu287BgKpTIheB+WtadT4e21VpPaJ62APEw==
|
||||
"@budibase/auth@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.102.tgz#86bb653686a311858b6ab6a048c6a4746bd5ced4"
|
||||
integrity sha512-Wov1vWAkWQn2P/gVapMBDdGKE1OwbpyD+3LV9E1HqZ3AASWZztqAFfnUaF6kKsHeem8S69uZ3vBU6uuyn9Sp+w==
|
||||
dependencies:
|
||||
"@techpass/passport-openidconnect" "^0.3.0"
|
||||
aws-sdk "^2.901.0"
|
||||
bcryptjs "^2.4.3"
|
||||
ioredis "^4.27.1"
|
||||
|
@ -336,10 +337,10 @@
|
|||
to-gfm-code-block "^0.1.1"
|
||||
year "^0.2.1"
|
||||
|
||||
"@budibase/string-templates@^0.9.79-alpha.4":
|
||||
version "0.9.79"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.79.tgz#bb75a7433a7cfda1fc488283f35e47879b799fcc"
|
||||
integrity sha512-hkAne5mx7mj8+osXFt45VwgLKSa94uQOGOb4R8uv9WNzvk4RzcjBfRzJxggv29FUemItrAeZpSh+Um6yugFI+w==
|
||||
"@budibase/string-templates@^0.9.102":
|
||||
version "0.9.102"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.102.tgz#5beb1dac696781b404020d5ab6bb91cbe4dcd10a"
|
||||
integrity sha512-cDDh5tyGYtA2sr8VDaRMLp9Ff+icXKNZ5BredePfES5du3GOWjFeVe0h1WFsR12Yq1dH1WWKR1XKc9CNwoQ8YA==
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.11.4"
|
||||
dayjs "^1.10.4"
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
|
||||
const MONOREPO_ROOT = "packages"
|
||||
|
||||
const packages = fs.readdirSync(MONOREPO_ROOT)
|
||||
|
||||
function pinDeps(dependencies) {
|
||||
for (let dependency in dependencies) {
|
||||
if (dependency.startsWith("@budibase")) {
|
||||
dependencies[dependency] = dependencies[dependency].replace("^", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate over the monorepo packages
|
||||
for (let pkg of packages) {
|
||||
const pkgPath = path.join(MONOREPO_ROOT, pkg)
|
||||
|
||||
// only directories
|
||||
if (fs.statSync(pkgPath).isDirectory()) {
|
||||
|
||||
|
||||
// get the package JSON file
|
||||
const pkgJsonPath = path.join(pkgPath, "package.json")
|
||||
const pkgJson = require(`../${pkgJsonPath}`)
|
||||
|
||||
// find any budibase dependencies, and pin them
|
||||
pinDeps(pkgJson.dependencies)
|
||||
pinDeps(pkgJson.devDependencies)
|
||||
|
||||
// update the package JSON files
|
||||
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2))
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Pinned dev versions for budibase packages successfully.")
|
Loading…
Reference in New Issue