Merge branch 'develop' of github.com:Budibase/budibase into new-design-ui
This commit is contained in:
commit
949ab2dac6
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
const generic = require("./src/cache/generic")
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
user: require("./src/cache/user"),
|
user: require("./src/cache/user"),
|
||||||
app: require("./src/cache/appMetadata"),
|
app: require("./src/cache/appMetadata"),
|
||||||
|
...generic,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
|
@ -42,8 +42,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ioredis-mock": "^5.5.5",
|
"ioredis-mock": "^5.5.5",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"pouchdb-adapter-memory": "^7.2.2",
|
"pouchdb-adapter-memory": "^7.2.2"
|
||||||
"pouchdb-all-dbs": "^1.0.2"
|
|
||||||
},
|
},
|
||||||
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc"
|
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc"
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ passport.deserializeUser(async (user, done) => {
|
||||||
const user = await db.get(user._id)
|
const user = await db.get(user._id)
|
||||||
return done(null, user)
|
return done(null, user)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("User not found", err)
|
console.error(`User not found`, err)
|
||||||
return done(null, false, { message: "User not found" })
|
return done(null, false, { message: "User not found" })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
const redis = require("../redis/authRedis")
|
||||||
|
const env = require("../environment")
|
||||||
|
const { getTenantId } = require("../context")
|
||||||
|
|
||||||
|
exports.CacheKeys = {
|
||||||
|
CHECKLIST: "checklist",
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.TTL = {
|
||||||
|
ONE_MINUTE: 600,
|
||||||
|
ONE_HOUR: 3600,
|
||||||
|
ONE_DAY: 86400,
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateTenantKey(key) {
|
||||||
|
const tenantId = getTenantId()
|
||||||
|
return `${key}:${tenantId}`
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.withCache = async (key, ttl, fetchFn) => {
|
||||||
|
key = generateTenantKey(key)
|
||||||
|
const client = await redis.getCacheClient()
|
||||||
|
const cachedValue = await client.get(key)
|
||||||
|
if (cachedValue) {
|
||||||
|
return cachedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fetchedValue = await fetchFn()
|
||||||
|
|
||||||
|
if (!env.isTest()) {
|
||||||
|
await client.store(key, fetchedValue, ttl)
|
||||||
|
}
|
||||||
|
return fetchedValue
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching before cache - ", err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.bustCache = async key => {
|
||||||
|
const client = await redis.getCacheClient()
|
||||||
|
try {
|
||||||
|
await client.delete(generateTenantKey(key))
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error busting cache - ", err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,7 @@ exports.isMultiTenant = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for automations, API endpoints should always be in context already
|
// used for automations, API endpoints should always be in context already
|
||||||
exports.doInTenant = (tenantId, task) => {
|
exports.doInTenant = (tenantId, task, { forceNew } = {}) => {
|
||||||
// the internal function is so that we can re-use an existing
|
// the internal function is so that we can re-use an existing
|
||||||
// context - don't want to close DB on a parent context
|
// context - don't want to close DB on a parent context
|
||||||
async function internal(opts = { existing: false }) {
|
async function internal(opts = { existing: false }) {
|
||||||
|
@ -98,7 +98,11 @@ exports.doInTenant = (tenantId, task) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const using = cls.getFromContext(ContextKeys.IN_USE)
|
const using = cls.getFromContext(ContextKeys.IN_USE)
|
||||||
if (using && cls.getFromContext(ContextKeys.TENANT_ID) === tenantId) {
|
if (
|
||||||
|
!forceNew &&
|
||||||
|
using &&
|
||||||
|
cls.getFromContext(ContextKeys.TENANT_ID) === tenantId
|
||||||
|
) {
|
||||||
cls.setOnContext(ContextKeys.IN_USE, using + 1)
|
cls.setOnContext(ContextKeys.IN_USE, using + 1)
|
||||||
return internal({ existing: true })
|
return internal({ existing: true })
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,7 +139,7 @@ const setAppTenantId = appId => {
|
||||||
exports.updateTenantId(appTenantId)
|
exports.updateTenantId(appTenantId)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.doInAppContext = (appId, task) => {
|
exports.doInAppContext = (appId, task, { forceNew } = {}) => {
|
||||||
if (!appId) {
|
if (!appId) {
|
||||||
throw new Error("appId is required")
|
throw new Error("appId is required")
|
||||||
}
|
}
|
||||||
|
@ -162,7 +166,7 @@ exports.doInAppContext = (appId, task) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const using = cls.getFromContext(ContextKeys.IN_USE)
|
const using = cls.getFromContext(ContextKeys.IN_USE)
|
||||||
if (using && cls.getFromContext(ContextKeys.APP_ID) === appId) {
|
if (!forceNew && using && cls.getFromContext(ContextKeys.APP_ID) === appId) {
|
||||||
cls.setOnContext(ContextKeys.IN_USE, using + 1)
|
cls.setOnContext(ContextKeys.IN_USE, using + 1)
|
||||||
return internal({ existing: true })
|
return internal({ existing: true })
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,13 +3,13 @@ const env = require("../environment")
|
||||||
|
|
||||||
let PouchDB
|
let PouchDB
|
||||||
let initialised = false
|
let initialised = false
|
||||||
|
const dbList = new Set()
|
||||||
|
|
||||||
const put =
|
const put =
|
||||||
dbPut =>
|
dbPut =>
|
||||||
async (doc, options = {}) => {
|
async (doc, options = {}) => {
|
||||||
const response = await dbPut(doc, options)
|
|
||||||
// TODO: add created / updated
|
// TODO: add created / updated
|
||||||
return response
|
return await dbPut(doc, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkInitialised = () => {
|
const checkInitialised = () => {
|
||||||
|
@ -28,6 +28,9 @@ exports.init = opts => {
|
||||||
// in situations that using the function doWithDB does not work
|
// in situations that using the function doWithDB does not work
|
||||||
exports.dangerousGetDB = (dbName, opts) => {
|
exports.dangerousGetDB = (dbName, opts) => {
|
||||||
checkInitialised()
|
checkInitialised()
|
||||||
|
if (env.isTest()) {
|
||||||
|
dbList.add(dbName)
|
||||||
|
}
|
||||||
const db = new PouchDB(dbName, opts)
|
const db = new PouchDB(dbName, opts)
|
||||||
const dbPut = db.put
|
const dbPut = db.put
|
||||||
db.put = put(dbPut)
|
db.put = put(dbPut)
|
||||||
|
@ -63,6 +66,9 @@ exports.doWithDB = async (dbName, cb, opts) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.allDbs = () => {
|
exports.allDbs = () => {
|
||||||
|
if (!env.isTest()) {
|
||||||
|
throw new Error("Cannot be used outside test environment.")
|
||||||
|
}
|
||||||
checkInitialised()
|
checkInitialised()
|
||||||
return PouchDB.allDbs()
|
return [...dbList]
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,11 +92,5 @@ exports.getPouch = (opts = {}) => {
|
||||||
PouchDB.plugin(find)
|
PouchDB.plugin(find)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
|
return PouchDB.defaults(POUCH_DB_DEFAULTS)
|
||||||
if (opts.allDbs) {
|
|
||||||
const allDbs = require("pouchdb-all-dbs")
|
|
||||||
allDbs(Pouch)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pouch
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ exports.authenticate = async function (ctx, email, password, done) {
|
||||||
|
|
||||||
const dbUser = await getGlobalUserByEmail(email)
|
const dbUser = await getGlobalUserByEmail(email)
|
||||||
if (dbUser == null) {
|
if (dbUser == null) {
|
||||||
return authError(done, "User not found")
|
return authError(done, `User not found: [${email}]`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the user is currently inactive, if this is the case throw invalid
|
// check that the user is currently inactive, if this is the case throw invalid
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
const Client = require("./index")
|
const Client = require("./index")
|
||||||
const utils = require("./utils")
|
const utils = require("./utils")
|
||||||
|
|
||||||
let userClient, sessionClient, appClient
|
let userClient, sessionClient, appClient, cacheClient
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
userClient = await new Client(utils.Databases.USER_CACHE).init()
|
userClient = await new Client(utils.Databases.USER_CACHE).init()
|
||||||
sessionClient = await new Client(utils.Databases.SESSIONS).init()
|
sessionClient = await new Client(utils.Databases.SESSIONS).init()
|
||||||
appClient = await new Client(utils.Databases.APP_METADATA).init()
|
appClient = await new Client(utils.Databases.APP_METADATA).init()
|
||||||
|
cacheClient = await new Client(utils.Databases.GENERIC_CACHE).init()
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on("exit", async () => {
|
process.on("exit", async () => {
|
||||||
if (userClient) await userClient.finish()
|
if (userClient) await userClient.finish()
|
||||||
if (sessionClient) await sessionClient.finish()
|
if (sessionClient) await sessionClient.finish()
|
||||||
if (appClient) await appClient.finish()
|
if (appClient) await appClient.finish()
|
||||||
|
if (cacheClient) await cacheClient.finish()
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -34,4 +36,10 @@ module.exports = {
|
||||||
}
|
}
|
||||||
return appClient
|
return appClient
|
||||||
},
|
},
|
||||||
|
getCacheClient: async () => {
|
||||||
|
if (!cacheClient) {
|
||||||
|
await init()
|
||||||
|
}
|
||||||
|
return cacheClient
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ exports.Databases = {
|
||||||
APP_METADATA: "appMetadata",
|
APP_METADATA: "appMetadata",
|
||||||
QUERY_VARS: "queryVars",
|
QUERY_VARS: "queryVars",
|
||||||
LICENSES: "license",
|
LICENSES: "license",
|
||||||
|
GENERIC_CACHE: "data_cache",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.SEPARATOR = SEPARATOR
|
exports.SEPARATOR = SEPARATOR
|
||||||
|
|
|
@ -197,11 +197,16 @@ exports.getBuildersCount = async () => {
|
||||||
return builders.length
|
return builders.length
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.saveUser = async (
|
const DEFAULT_SAVE_USER = {
|
||||||
|
hashPassword: true,
|
||||||
|
requirePassword: true,
|
||||||
|
bulkCreate: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.internalSaveUser = async (
|
||||||
user,
|
user,
|
||||||
tenantId,
|
tenantId,
|
||||||
hashPassword = true,
|
{ hashPassword, requirePassword, bulkCreate } = DEFAULT_SAVE_USER
|
||||||
requirePassword = true
|
|
||||||
) => {
|
) => {
|
||||||
if (!tenantId) {
|
if (!tenantId) {
|
||||||
throw "No tenancy specified."
|
throw "No tenancy specified."
|
||||||
|
@ -213,7 +218,10 @@ exports.saveUser = async (
|
||||||
let { email, password, _id } = user
|
let { email, password, _id } = user
|
||||||
// make sure another user isn't using the same email
|
// make sure another user isn't using the same email
|
||||||
let dbUser
|
let dbUser
|
||||||
if (email) {
|
// user can't exist in bulk creation
|
||||||
|
if (bulkCreate) {
|
||||||
|
dbUser = null
|
||||||
|
} else if (email) {
|
||||||
// check budibase users inside the tenant
|
// check budibase users inside the tenant
|
||||||
dbUser = await exports.getGlobalUserByEmail(email)
|
dbUser = await exports.getGlobalUserByEmail(email)
|
||||||
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
|
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
|
||||||
|
@ -267,11 +275,17 @@ exports.saveUser = async (
|
||||||
user.status = UserStatus.ACTIVE
|
user.status = UserStatus.ACTIVE
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await db.put({
|
const putOpts = {
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
...user,
|
...user,
|
||||||
})
|
}
|
||||||
|
if (bulkCreate) {
|
||||||
|
return putOpts
|
||||||
|
}
|
||||||
|
const response = await db.put(putOpts)
|
||||||
|
if (env.MULTI_TENANCY) {
|
||||||
await tryAddTenant(tenantId, _id, email)
|
await tryAddTenant(tenantId, _id, email)
|
||||||
|
}
|
||||||
await userCache.invalidateUser(response.id)
|
await userCache.invalidateUser(response.id)
|
||||||
return {
|
return {
|
||||||
_id: response.id,
|
_id: response.id,
|
||||||
|
@ -288,6 +302,19 @@ exports.saveUser = async (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maintained for api compat, don't want to change function signature
|
||||||
|
exports.saveUser = async (
|
||||||
|
user,
|
||||||
|
tenantId,
|
||||||
|
hashPassword = true,
|
||||||
|
requirePassword = true
|
||||||
|
) => {
|
||||||
|
return exports.internalSaveUser(user, tenantId, {
|
||||||
|
hashPassword,
|
||||||
|
requirePassword,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a user out from budibase. Re-used across account portal and builder.
|
* Logs a user out from budibase. Re-used across account portal and builder.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -661,11 +661,6 @@ acorn-walk@^7.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
||||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||||
|
|
||||||
acorn@^5.2.1:
|
|
||||||
version "5.7.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
|
|
||||||
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
|
|
||||||
|
|
||||||
acorn@^7.1.1:
|
acorn@^7.1.1:
|
||||||
version "7.4.1"
|
version "7.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||||
|
@ -701,11 +696,6 @@ ajv@^6.12.3:
|
||||||
json-schema-traverse "^0.4.1"
|
json-schema-traverse "^0.4.1"
|
||||||
uri-js "^4.2.2"
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
amdefine@>=0.0.4:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
|
||||||
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
|
|
||||||
|
|
||||||
ansi-escapes@^4.2.1:
|
ansi-escapes@^4.2.1:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
||||||
|
@ -800,11 +790,6 @@ assign-symbols@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
||||||
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
|
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
|
||||||
|
|
||||||
ast-types@0.9.6:
|
|
||||||
version "0.9.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
|
|
||||||
integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=
|
|
||||||
|
|
||||||
async@~2.1.4:
|
async@~2.1.4:
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc"
|
resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc"
|
||||||
|
@ -938,11 +923,6 @@ balanced-match@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||||
|
|
||||||
base62@^1.1.0:
|
|
||||||
version "1.2.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/base62/-/base62-1.2.8.tgz#1264cb0fb848d875792877479dbe8bae6bae3428"
|
|
||||||
integrity sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==
|
|
||||||
|
|
||||||
base64-js@^1.0.2, base64-js@^1.3.1:
|
base64-js@^1.0.2, base64-js@^1.3.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
|
@ -1259,26 +1239,6 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@^2.5.0:
|
|
||||||
version "2.20.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
|
||||||
|
|
||||||
commoner@^0.10.1:
|
|
||||||
version "0.10.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5"
|
|
||||||
integrity sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=
|
|
||||||
dependencies:
|
|
||||||
commander "^2.5.0"
|
|
||||||
detective "^4.3.1"
|
|
||||||
glob "^5.0.15"
|
|
||||||
graceful-fs "^4.1.2"
|
|
||||||
iconv-lite "^0.4.5"
|
|
||||||
mkdirp "^0.5.0"
|
|
||||||
private "^0.1.6"
|
|
||||||
q "^1.1.2"
|
|
||||||
recast "^0.11.17"
|
|
||||||
|
|
||||||
component-emitter@^1.2.1:
|
component-emitter@^1.2.1:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||||
|
@ -1445,11 +1405,6 @@ define-property@^2.0.2:
|
||||||
is-descriptor "^1.0.2"
|
is-descriptor "^1.0.2"
|
||||||
isobject "^3.0.1"
|
isobject "^3.0.1"
|
||||||
|
|
||||||
defined@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
|
||||||
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
|
|
||||||
|
|
||||||
delayed-stream@~1.0.0:
|
delayed-stream@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
@ -1465,14 +1420,6 @@ detect-newline@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||||
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
|
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
|
||||||
|
|
||||||
detective@^4.3.1:
|
|
||||||
version "4.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e"
|
|
||||||
integrity sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==
|
|
||||||
dependencies:
|
|
||||||
acorn "^5.2.1"
|
|
||||||
defined "^1.0.0"
|
|
||||||
|
|
||||||
diff-sequences@^26.6.2:
|
diff-sequences@^26.6.2:
|
||||||
version "26.6.2"
|
version "26.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
|
||||||
|
@ -1577,15 +1524,6 @@ error-ex@^1.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
es3ify@^0.2.2:
|
|
||||||
version "0.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/es3ify/-/es3ify-0.2.2.tgz#5dae3e650e5be3684b88066513d528d092629862"
|
|
||||||
integrity sha1-Xa4+ZQ5b42hLiAZlE9Uo0JJimGI=
|
|
||||||
dependencies:
|
|
||||||
esprima "^2.7.1"
|
|
||||||
jstransform "~11.0.0"
|
|
||||||
through "~2.3.4"
|
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||||
|
@ -1613,26 +1551,11 @@ escodegen@^2.0.0:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
esprima-fb@^15001.1.0-dev-harmony-fb:
|
|
||||||
version "15001.1.0-dev-harmony-fb"
|
|
||||||
resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz#30a947303c6b8d5e955bee2b99b1d233206a6901"
|
|
||||||
integrity sha1-MKlHMDxrjV6VW+4rmbHSMyBqaQE=
|
|
||||||
|
|
||||||
esprima@^2.7.1:
|
|
||||||
version "2.7.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
|
|
||||||
integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=
|
|
||||||
|
|
||||||
esprima@^4.0.0, esprima@^4.0.1:
|
esprima@^4.0.0, esprima@^4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||||
|
|
||||||
esprima@~3.1.0:
|
|
||||||
version "3.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
|
||||||
integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
|
|
||||||
|
|
||||||
estraverse@^5.2.0:
|
estraverse@^5.2.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
|
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
|
||||||
|
@ -1950,17 +1873,6 @@ getpass@^0.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
glob@^5.0.15:
|
|
||||||
version "5.0.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
|
|
||||||
integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
|
|
||||||
dependencies:
|
|
||||||
inflight "^1.0.4"
|
|
||||||
inherits "2"
|
|
||||||
minimatch "2 || 3"
|
|
||||||
once "^1.3.0"
|
|
||||||
path-is-absolute "^1.0.0"
|
|
||||||
|
|
||||||
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
||||||
|
@ -2004,7 +1916,7 @@ googleapis@^16.0.0:
|
||||||
google-auth-library "~0.10.0"
|
google-auth-library "~0.10.0"
|
||||||
string-template "~1.0.0"
|
string-template "~1.0.0"
|
||||||
|
|
||||||
graceful-fs@^4.1.2, graceful-fs@^4.2.4:
|
graceful-fs@^4.2.4:
|
||||||
version "4.2.8"
|
version "4.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
|
||||||
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
|
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
|
||||||
|
@ -2170,7 +2082,7 @@ human-signals@^1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
|
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
|
||||||
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
|
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
|
||||||
|
|
||||||
iconv-lite@0.4.24, iconv-lite@^0.4.5:
|
iconv-lite@0.4.24:
|
||||||
version "0.4.24"
|
version "0.4.24"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||||
|
@ -2993,17 +2905,6 @@ jsprim@^1.2.2:
|
||||||
json-schema "0.2.3"
|
json-schema "0.2.3"
|
||||||
verror "1.3.6"
|
verror "1.3.6"
|
||||||
|
|
||||||
jstransform@~11.0.0:
|
|
||||||
version "11.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223"
|
|
||||||
integrity sha1-CaeJk+CuTU70SH9hVakfYZDLQiM=
|
|
||||||
dependencies:
|
|
||||||
base62 "^1.1.0"
|
|
||||||
commoner "^0.10.1"
|
|
||||||
esprima-fb "^15001.1.0-dev-harmony-fb"
|
|
||||||
object-assign "^2.0.0"
|
|
||||||
source-map "^0.4.2"
|
|
||||||
|
|
||||||
jwa@^1.1.4:
|
jwa@^1.1.4:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.5.tgz#a0552ce0220742cd52e153774a32905c30e756e5"
|
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.5.tgz#a0552ce0220742cd52e153774a32905c30e756e5"
|
||||||
|
@ -3392,7 +3293,7 @@ mimic-fn@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||||
|
|
||||||
"minimatch@2 || 3", minimatch@^3.0.4:
|
minimatch@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||||
|
@ -3417,13 +3318,6 @@ mkdirp-classic@^0.5.2:
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||||
|
|
||||||
mkdirp@^0.5.0:
|
|
||||||
version "0.5.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
|
||||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
|
||||||
dependencies:
|
|
||||||
minimist "^1.2.5"
|
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
|
@ -3586,11 +3480,6 @@ oauth@0.9.x, oauth@^0.9.15:
|
||||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||||
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
|
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
|
||||||
|
|
||||||
object-assign@^2.0.0:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa"
|
|
||||||
integrity sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=
|
|
||||||
|
|
||||||
object-copy@^0.1.0:
|
object-copy@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
|
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
|
||||||
|
@ -3923,17 +3812,6 @@ pouchdb-adapter-utils@7.2.2:
|
||||||
pouchdb-merge "7.2.2"
|
pouchdb-merge "7.2.2"
|
||||||
pouchdb-utils "7.2.2"
|
pouchdb-utils "7.2.2"
|
||||||
|
|
||||||
pouchdb-all-dbs@^1.0.2:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/pouchdb-all-dbs/-/pouchdb-all-dbs-1.1.1.tgz#85f04a39cafda52497ec49abf1c93bb5e72813f6"
|
|
||||||
integrity sha512-UUnsdmcnRSQ8MAOYSJjfTwKkQNb/6fvOfd/f7dNNivWZ2YDYVuMfgw1WQdL634yEtcXTxAENZ/EyLRdzPCB41A==
|
|
||||||
dependencies:
|
|
||||||
argsarray "0.0.1"
|
|
||||||
es3ify "^0.2.2"
|
|
||||||
inherits "~2.0.1"
|
|
||||||
pouchdb-promise "6.4.3"
|
|
||||||
tiny-queue "^0.2.0"
|
|
||||||
|
|
||||||
pouchdb-binary-utils@7.2.2:
|
pouchdb-binary-utils@7.2.2:
|
||||||
version "7.2.2"
|
version "7.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-7.2.2.tgz#0690b348052c543b1e67f032f47092ca82bcb10e"
|
resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-7.2.2.tgz#0690b348052c543b1e67f032f47092ca82bcb10e"
|
||||||
|
@ -4010,7 +3888,7 @@ pouchdb-merge@7.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz#940d85a2b532d6a93a6cab4b250f5648511bcc16"
|
resolved "https://registry.yarnpkg.com/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz#940d85a2b532d6a93a6cab4b250f5648511bcc16"
|
||||||
integrity sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==
|
integrity sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==
|
||||||
|
|
||||||
pouchdb-promise@6.4.3, pouchdb-promise@^6.0.4:
|
pouchdb-promise@^6.0.4:
|
||||||
version "6.4.3"
|
version "6.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz#74516f4acf74957b54debd0fb2c0e5b5a68ca7b3"
|
resolved "https://registry.yarnpkg.com/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz#74516f4acf74957b54debd0fb2c0e5b5a68ca7b3"
|
||||||
integrity sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==
|
integrity sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==
|
||||||
|
@ -4093,11 +3971,6 @@ pretty-format@^26.6.2:
|
||||||
ansi-styles "^4.0.0"
|
ansi-styles "^4.0.0"
|
||||||
react-is "^17.0.1"
|
react-is "^17.0.1"
|
||||||
|
|
||||||
private@^0.1.6, private@~0.1.5:
|
|
||||||
version "0.1.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
|
||||||
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
|
|
||||||
|
|
||||||
process-nextick-args@~2.0.0:
|
process-nextick-args@~2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
|
@ -4144,11 +4017,6 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
|
||||||
q@^1.1.2:
|
|
||||||
version "1.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
|
||||||
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
|
||||||
|
|
||||||
qs@~6.4.0:
|
qs@~6.4.0:
|
||||||
version "6.4.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
||||||
|
@ -4230,16 +4098,6 @@ readline-sync@^1.4.9:
|
||||||
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
|
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
|
||||||
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
|
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
|
||||||
|
|
||||||
recast@^0.11.17:
|
|
||||||
version "0.11.23"
|
|
||||||
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
|
|
||||||
integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=
|
|
||||||
dependencies:
|
|
||||||
ast-types "0.9.6"
|
|
||||||
esprima "~3.1.0"
|
|
||||||
private "~0.1.5"
|
|
||||||
source-map "~0.5.0"
|
|
||||||
|
|
||||||
redis-commands@1.7.0:
|
redis-commands@1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
|
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
|
||||||
|
@ -4597,14 +4455,7 @@ source-map-url@^0.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
||||||
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
|
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
|
||||||
|
|
||||||
source-map@^0.4.2:
|
source-map@^0.5.0, source-map@^0.5.6:
|
||||||
version "0.4.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
|
|
||||||
integrity sha1-66T12pwNyZneaAMti092FzZSA2s=
|
|
||||||
dependencies:
|
|
||||||
amdefine ">=0.0.4"
|
|
||||||
|
|
||||||
source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0:
|
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||||
|
@ -4884,16 +4735,6 @@ through2@^2.0.0, through2@^2.0.2, through2@^2.0.3:
|
||||||
readable-stream "~2.3.6"
|
readable-stream "~2.3.6"
|
||||||
xtend "~4.0.1"
|
xtend "~4.0.1"
|
||||||
|
|
||||||
through@~2.3.4:
|
|
||||||
version "2.3.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
|
||||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
|
||||||
|
|
||||||
tiny-queue@^0.2.0:
|
|
||||||
version "0.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046"
|
|
||||||
integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY=
|
|
||||||
|
|
||||||
tmp@^0.0.33:
|
tmp@^0.0.33:
|
||||||
version "0.0.33"
|
version "0.0.33"
|
||||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||||
|
|
|
@ -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": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"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": "^1.0.167-alpha.8",
|
"@budibase/string-templates": "^1.0.176-alpha.0",
|
||||||
"@spectrum-css/actionbutton": "^1.0.1",
|
"@spectrum-css/actionbutton": "^1.0.1",
|
||||||
"@spectrum-css/actiongroup": "^1.0.1",
|
"@spectrum-css/actiongroup": "^1.0.1",
|
||||||
"@spectrum-css/avatar": "^3.0.2",
|
"@spectrum-css/avatar": "^3.0.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -69,10 +69,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.167-alpha.8",
|
"@budibase/bbui": "^1.0.176-alpha.0",
|
||||||
"@budibase/client": "^1.0.167-alpha.8",
|
"@budibase/client": "^1.0.176-alpha.0",
|
||||||
"@budibase/frontend-core": "^1.0.167-alpha.8",
|
"@budibase/frontend-core": "^1.0.176-alpha.0",
|
||||||
"@budibase/string-templates": "^1.0.167-alpha.8",
|
"@budibase/string-templates": "^1.0.176-alpha.0",
|
||||||
"@sentry/browser": "5.19.1",
|
"@sentry/browser": "5.19.1",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
|
|
|
@ -105,9 +105,7 @@ const automationActions = store => ({
|
||||||
},
|
},
|
||||||
select: automation => {
|
select: automation => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
let testResults = state.selectedAutomation?.testResults
|
|
||||||
state.selectedAutomation = new Automation(cloneDeep(automation))
|
state.selectedAutomation = new Automation(cloneDeep(automation))
|
||||||
state.selectedAutomation.testResults = testResults
|
|
||||||
state.selectedBlock = null
|
state.selectedBlock = null
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
|
|
||||||
export let automation
|
export let automation
|
||||||
|
|
||||||
let testDataModal
|
let testDataModal
|
||||||
let blocks
|
let blocks
|
||||||
let confirmDeleteDialog
|
let confirmDeleteDialog
|
||||||
|
@ -41,12 +40,12 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="canvas">
|
<div class="canvas">
|
||||||
<div class="content">
|
<div style="float: left; padding-left: var(--spacing-xl);">
|
||||||
<div class="title">
|
|
||||||
<div class="subtitle">
|
|
||||||
<Heading size="S">{automation.name}</Heading>
|
<Heading size="S">{automation.name}</Heading>
|
||||||
|
</div>
|
||||||
|
<div style="float: right; padding-right: var(--spacing-xl);" class="title">
|
||||||
|
<div class="subtitle">
|
||||||
<div style="display:flex; align-items: center;">
|
<div style="display:flex; align-items: center;">
|
||||||
<div class="iconPadding">
|
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
on:click={confirmDeleteDialog.show}
|
on:click={confirmDeleteDialog.show}
|
||||||
|
@ -55,7 +54,6 @@
|
||||||
name="DeleteOutline"
|
name="DeleteOutline"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<ActionButton
|
<ActionButton
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
testDataModal.show()
|
testDataModal.show()
|
||||||
|
@ -63,44 +61,49 @@
|
||||||
icon="MultipleCheck"
|
icon="MultipleCheck"
|
||||||
size="M">Run test</ActionButton
|
size="M">Run test</ActionButton
|
||||||
>
|
>
|
||||||
|
<div style="padding-left: var(--spacing-m);">
|
||||||
|
<ActionButton
|
||||||
|
disabled={!$automationStore.selectedAutomation?.testResults}
|
||||||
|
on:click={() => {
|
||||||
|
$automationStore.selectedAutomation.automation.showTestPanel = true
|
||||||
|
}}
|
||||||
|
size="M">Test Details</ActionButton
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
{#each blocks as block, idx (block.id)}
|
{#each blocks as block, idx (block.id)}
|
||||||
<div
|
<div
|
||||||
class="block"
|
class="block"
|
||||||
animate:flip={{ duration: 500 }}
|
animate:flip={{ duration: 500 }}
|
||||||
in:fly|local={{ x: 500, duration: 1500 }}
|
in:fly|local={{ x: 500, duration: 500 }}
|
||||||
|
out:fly|local={{ x: 500, duration: 500 }}
|
||||||
>
|
>
|
||||||
{#if block.stepId !== "LOOP"}
|
{#if block.stepId !== "LOOP"}
|
||||||
<FlowItem {testDataModal} {block} />
|
<FlowItem {testDataModal} {block} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={confirmDeleteDialog}
|
bind:this={confirmDeleteDialog}
|
||||||
okText="Delete Automation"
|
okText="Delete Automation"
|
||||||
onOk={deleteAutomation}
|
onOk={deleteAutomation}
|
||||||
title="Confirm Deletion"
|
title="Confirm Deletion"
|
||||||
>
|
>
|
||||||
Are you sure you wish to delete the automation
|
Are you sure you wish to delete the automation
|
||||||
<i>{automation.name}?</i>
|
<i>{automation.name}?</i>
|
||||||
This action cannot be undone.
|
This action cannot be undone.
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<Modal bind:this={testDataModal} width="30%">
|
<Modal bind:this={testDataModal} width="30%">
|
||||||
<TestDataModal />
|
<TestDataModal />
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.canvas {
|
|
||||||
margin: 0 -40px calc(-1 * var(--spacing-l)) -40px;
|
|
||||||
overflow-y: auto;
|
|
||||||
text-align: center;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
/* Fix for firefox not respecting bottom padding in scrolling containers */
|
/* Fix for firefox not respecting bottom padding in scrolling containers */
|
||||||
.canvas > *:last-child {
|
.canvas > *:last-child {
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
|
@ -128,10 +131,6 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.iconPadding {
|
|
||||||
padding-top: var(--spacing-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding-right: var(--spacing-m);
|
padding-right: var(--spacing-m);
|
||||||
|
|
|
@ -1,30 +1,27 @@
|
||||||
<script>
|
<script>
|
||||||
|
import FlowItemHeader from "./FlowItemHeader.svelte"
|
||||||
|
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
import {
|
import {
|
||||||
Icon,
|
Icon,
|
||||||
Divider,
|
Divider,
|
||||||
Layout,
|
Layout,
|
||||||
Body,
|
|
||||||
Detail,
|
Detail,
|
||||||
Modal,
|
Modal,
|
||||||
Button,
|
Button,
|
||||||
StatusLight,
|
|
||||||
Select,
|
Select,
|
||||||
ActionButton,
|
ActionButton,
|
||||||
notifications,
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte"
|
import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte"
|
||||||
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
||||||
import ResultsModal from "./ResultsModal.svelte"
|
|
||||||
import ActionModal from "./ActionModal.svelte"
|
import ActionModal from "./ActionModal.svelte"
|
||||||
import { externalActions } from "./ExternalActions"
|
|
||||||
|
|
||||||
export let block
|
export let block
|
||||||
export let testDataModal
|
export let testDataModal
|
||||||
let selected
|
let selected
|
||||||
let webhookModal
|
let webhookModal
|
||||||
let actionModal
|
let actionModal
|
||||||
let resultsModal
|
|
||||||
let blockComplete
|
let blockComplete
|
||||||
let showLooping = false
|
let showLooping = false
|
||||||
|
|
||||||
|
@ -32,9 +29,6 @@
|
||||||
$: showBindingPicker =
|
$: showBindingPicker =
|
||||||
block.stepId === "CREATE_ROW" || block.stepId === "UPDATE_ROW"
|
block.stepId === "CREATE_ROW" || block.stepId === "UPDATE_ROW"
|
||||||
|
|
||||||
$: testResult = $automationStore.selectedAutomation.testResults?.steps.filter(
|
|
||||||
step => (block.id ? step.id === block.id : step.stepId === block.stepId)
|
|
||||||
)
|
|
||||||
$: isTrigger = block.type === "TRIGGER"
|
$: isTrigger = block.type === "TRIGGER"
|
||||||
|
|
||||||
$: selected = $automationStore.selectedBlock?.id === block.id
|
$: selected = $automationStore.selectedBlock?.id === block.id
|
||||||
|
@ -182,63 +176,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="blockSection">
|
<FlowItemHeader bind:blockComplete {block} {testDataModal} />
|
||||||
<div
|
|
||||||
on:click={() => {
|
|
||||||
blockComplete = !blockComplete
|
|
||||||
}}
|
|
||||||
class="splitHeader"
|
|
||||||
>
|
|
||||||
<div class="center-items">
|
|
||||||
{#if externalActions[block.stepId]}
|
|
||||||
<img
|
|
||||||
alt={externalActions[block.stepId].name}
|
|
||||||
width="28px"
|
|
||||||
height="28px"
|
|
||||||
src={externalActions[block.stepId].icon}
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<svg
|
|
||||||
width="28px"
|
|
||||||
height="28px"
|
|
||||||
class="spectrum-Icon"
|
|
||||||
style="color:grey;"
|
|
||||||
focusable="false"
|
|
||||||
>
|
|
||||||
<use xlink:href="#spectrum-icon-18-{block.icon}" />
|
|
||||||
</svg>
|
|
||||||
{/if}
|
|
||||||
<div class="iconAlign">
|
|
||||||
{#if isTrigger}
|
|
||||||
<Body size="XS">When this happens:</Body>
|
|
||||||
{:else}
|
|
||||||
<Body size="XS">Do this:</Body>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<Detail size="S">{block?.name?.toUpperCase() || ""}</Detail>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="blockTitle">
|
|
||||||
{#if testResult && testResult[0]}
|
|
||||||
<div style="float: right;" on:click={() => resultsModal.show()}>
|
|
||||||
<StatusLight
|
|
||||||
positive={isTrigger || testResult[0].outputs?.success}
|
|
||||||
negative={!testResult[0].outputs?.success}
|
|
||||||
><Body size="XS">View response</Body></StatusLight
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div
|
|
||||||
style="margin-left: 10px;"
|
|
||||||
on:click={() => {
|
|
||||||
onSelect(block)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon name={blockComplete ? "ChevronDown" : "ChevronUp"} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{#if !blockComplete}
|
{#if !blockComplete}
|
||||||
<Divider noMargin />
|
<Divider noMargin />
|
||||||
<div class="blockSection">
|
<div class="blockSection">
|
||||||
|
@ -283,10 +221,6 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Modal bind:this={resultsModal} width="30%">
|
|
||||||
<ResultsModal {isTrigger} {testResult} />
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal bind:this={actionModal} width="30%">
|
<Modal bind:this={actionModal} width="30%">
|
||||||
<ActionModal {blockIdx} bind:blockComplete />
|
<ActionModal {blockIdx} bind:blockComplete />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
<script>
|
||||||
|
import { automationStore } from "builderStore"
|
||||||
|
import { Icon, Body, Detail, StatusLight } from "@budibase/bbui"
|
||||||
|
import { externalActions } from "./ExternalActions"
|
||||||
|
|
||||||
|
export let block
|
||||||
|
export let blockComplete
|
||||||
|
export let showTestStatus = false
|
||||||
|
export let showParameters = {}
|
||||||
|
|
||||||
|
$: testResult =
|
||||||
|
$automationStore.selectedAutomation?.testResults?.steps.filter(step =>
|
||||||
|
block.id ? step.id === block.id : step.stepId === block.stepId
|
||||||
|
)
|
||||||
|
$: isTrigger = block.type === "TRIGGER"
|
||||||
|
|
||||||
|
async function onSelect(block) {
|
||||||
|
await automationStore.update(state => {
|
||||||
|
state.selectedBlock = block
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="blockSection">
|
||||||
|
<div
|
||||||
|
on:click={() => {
|
||||||
|
blockComplete = !blockComplete
|
||||||
|
showParameters[block.id] = blockComplete
|
||||||
|
}}
|
||||||
|
class="splitHeader"
|
||||||
|
>
|
||||||
|
<div class="center-items">
|
||||||
|
{#if externalActions[block.stepId]}
|
||||||
|
<img
|
||||||
|
alt={externalActions[block.stepId].name}
|
||||||
|
width="28px"
|
||||||
|
height="28px"
|
||||||
|
src={externalActions[block.stepId].icon}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<svg
|
||||||
|
width="28px"
|
||||||
|
height="28px"
|
||||||
|
class="spectrum-Icon"
|
||||||
|
style="color:grey;"
|
||||||
|
focusable="false"
|
||||||
|
>
|
||||||
|
<use xlink:href="#spectrum-icon-18-{block.icon}" />
|
||||||
|
</svg>
|
||||||
|
{/if}
|
||||||
|
<div class="iconAlign">
|
||||||
|
{#if isTrigger}
|
||||||
|
<Body size="XS">When this happens:</Body>
|
||||||
|
{:else}
|
||||||
|
<Body size="XS">Do this:</Body>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<Detail size="S">{block?.name?.toUpperCase() || ""}</Detail>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="blockTitle">
|
||||||
|
{#if showTestStatus && testResult && testResult[0]}
|
||||||
|
<div style="float: right;">
|
||||||
|
<StatusLight
|
||||||
|
positive={isTrigger || testResult[0].outputs?.success}
|
||||||
|
negative={!testResult[0].outputs?.success}
|
||||||
|
><Body size="XS"
|
||||||
|
>{testResult[0].outputs?.success || isTrigger
|
||||||
|
? "Success"
|
||||||
|
: "Error"}</Body
|
||||||
|
></StatusLight
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div
|
||||||
|
style="margin-left: 10px; margin-bottom: var(--spacing-xs);"
|
||||||
|
on:click={() => {
|
||||||
|
onSelect(block)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon name={blockComplete ? "ChevronUp" : "ChevronDown"} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.center-items {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.splitHeader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.iconAlign {
|
||||||
|
padding: 0 0 0 var(--spacing-m);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blockSection {
|
||||||
|
padding: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blockTitle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,133 +0,0 @@
|
||||||
<script>
|
|
||||||
import { ModalContent, Icon, Detail, TextArea, Label } from "@budibase/bbui"
|
|
||||||
|
|
||||||
export let testResult
|
|
||||||
export let isTrigger
|
|
||||||
let inputToggled
|
|
||||||
let outputToggled
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ModalContent
|
|
||||||
showCloseIcon={false}
|
|
||||||
showConfirmButton={false}
|
|
||||||
cancelText="Close"
|
|
||||||
>
|
|
||||||
<div slot="header" class="result-modal-header">
|
|
||||||
<span>Test Results</span>
|
|
||||||
<div>
|
|
||||||
{#if isTrigger || testResult[0].outputs.success}
|
|
||||||
<div class="iconSuccess">
|
|
||||||
<Icon size="S" name="CheckmarkCircle" />
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="iconFailure">
|
|
||||||
<Icon size="S" name="CloseCircle" />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
{#if testResult[0].outputs.iterations}
|
|
||||||
<div style="display: flex;">
|
|
||||||
<Icon name="Reuse" />
|
|
||||||
<div style="margin-left: 10px;">
|
|
||||||
<Label>
|
|
||||||
This loop ran {testResult[0].outputs.iterations} times.</Label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
<div
|
|
||||||
on:click={() => {
|
|
||||||
inputToggled = !inputToggled
|
|
||||||
}}
|
|
||||||
class="toggle splitHeader"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div style="display: flex; align-items: center;">
|
|
||||||
<span style="padding-left: var(--spacing-s);">
|
|
||||||
<Detail size="S">Input</Detail>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{#if inputToggled}
|
|
||||||
<Icon size="M" name="ChevronDown" />
|
|
||||||
{:else}
|
|
||||||
<Icon size="M" name="ChevronRight" />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{#if inputToggled}
|
|
||||||
<div class="text-area-container">
|
|
||||||
<TextArea
|
|
||||||
disabled
|
|
||||||
value={JSON.stringify(testResult[0].inputs, null, 2)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div
|
|
||||||
on:click={() => {
|
|
||||||
outputToggled = !outputToggled
|
|
||||||
}}
|
|
||||||
class="toggle splitHeader"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div style="display: flex; align-items: center;">
|
|
||||||
<span style="padding-left: var(--spacing-s);">
|
|
||||||
<Detail size="S">Output</Detail>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{#if outputToggled}
|
|
||||||
<Icon size="M" name="ChevronDown" />
|
|
||||||
{:else}
|
|
||||||
<Icon size="M" name="ChevronRight" />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{#if outputToggled}
|
|
||||||
<div class="text-area-container">
|
|
||||||
<TextArea
|
|
||||||
disabled
|
|
||||||
value={JSON.stringify(testResult[0].outputs, null, 2)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</ModalContent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.result-modal-header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconSuccess {
|
|
||||||
color: var(--spectrum-global-color-green-600);
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconFailure {
|
|
||||||
color: var(--spectrum-global-color-red-600);
|
|
||||||
}
|
|
||||||
|
|
||||||
.splitHeader {
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-area-container :global(textarea) {
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -51,6 +51,7 @@
|
||||||
$automationStore.selectedAutomation?.automation,
|
$automationStore.selectedAutomation?.automation,
|
||||||
testData
|
testData
|
||||||
)
|
)
|
||||||
|
$automationStore.selectedAutomation.automation.showTestPanel = true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error testing notification")
|
notifications.error("Error testing notification")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
<script>
|
||||||
|
import { Icon, Divider, Tabs, Tab, TextArea, Label } from "@budibase/bbui"
|
||||||
|
import FlowItemHeader from "./FlowChart/FlowItemHeader.svelte"
|
||||||
|
import { automationStore } from "builderStore"
|
||||||
|
|
||||||
|
export let automation
|
||||||
|
|
||||||
|
let showParameters
|
||||||
|
let blocks
|
||||||
|
|
||||||
|
$: {
|
||||||
|
blocks = []
|
||||||
|
if (automation) {
|
||||||
|
if (automation.definition.trigger) {
|
||||||
|
blocks.push(automation.definition.trigger)
|
||||||
|
}
|
||||||
|
blocks = blocks
|
||||||
|
.concat(automation.definition.steps || [])
|
||||||
|
.filter(x => x.stepId !== "LOOP")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: testResults =
|
||||||
|
$automationStore.selectedAutomation?.testResults?.steps.filter(
|
||||||
|
x => x.stepId !== "LOOP" || []
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<div class="title-text">
|
||||||
|
<Icon name="MultipleCheck" />
|
||||||
|
<div style="padding-left: var(--spacing-l)">Test Details</div>
|
||||||
|
</div>
|
||||||
|
<div style="padding-right: var(--spacing-xl)">
|
||||||
|
<Icon
|
||||||
|
on:click={async () => {
|
||||||
|
$automationStore.selectedAutomation.automation.showTestPanel = false
|
||||||
|
}}
|
||||||
|
hoverable
|
||||||
|
name="Close"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
{#each blocks as block, idx}
|
||||||
|
<div class="block">
|
||||||
|
{#if block.stepId !== "LOOP"}
|
||||||
|
<FlowItemHeader showTestStatus={true} bind:showParameters {block} />
|
||||||
|
{#if showParameters && showParameters[block.id]}
|
||||||
|
<Divider noMargin />
|
||||||
|
{#if testResults?.[idx]?.outputs.iterations}
|
||||||
|
<div style="display: flex; padding: 10px 10px 0px 12px;">
|
||||||
|
<Icon name="Reuse" />
|
||||||
|
<div style="margin-left: 10px;">
|
||||||
|
<Label>
|
||||||
|
This loop ran {testResults?.[idx]?.outputs.iterations} times.</Label
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="tabs">
|
||||||
|
<Tabs quiet noPadding selected="Input">
|
||||||
|
<Tab title="Input">
|
||||||
|
<div style="padding: 10px 10px 10px 10px;">
|
||||||
|
<TextArea
|
||||||
|
minHeight="80px"
|
||||||
|
disabled
|
||||||
|
value={JSON.stringify(testResults?.[idx]?.inputs, null, 2)}
|
||||||
|
/>
|
||||||
|
</div></Tab
|
||||||
|
>
|
||||||
|
<Tab title="Output">
|
||||||
|
<div style="padding: 10px 10px 10px 10px;">
|
||||||
|
<TextArea
|
||||||
|
minHeight="100px"
|
||||||
|
disabled
|
||||||
|
value={JSON.stringify(testResults?.[idx]?.outputs, null, 2)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#if blocks.length - 1 !== idx}
|
||||||
|
<div class="separator" />
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
padding: 0px 30px 0px 30px;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
padding-left: var(--spacing-xl);
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
position: relative;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title :global(h1) {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: inline-block;
|
||||||
|
width: 400px;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: var(--background);
|
||||||
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
|
border-radius: 4px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
width: 1px;
|
||||||
|
height: 40px;
|
||||||
|
border-left: 1px dashed var(--grey-4);
|
||||||
|
color: var(--grey-4);
|
||||||
|
/* center horizontally */
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,7 +4,12 @@
|
||||||
import AutomationPanel from "components/automation/AutomationPanel/AutomationPanel.svelte"
|
import AutomationPanel from "components/automation/AutomationPanel/AutomationPanel.svelte"
|
||||||
import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte"
|
import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte"
|
||||||
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
||||||
$: automation = $automationStore.automations[0]
|
import TestPanel from "components/automation/AutomationBuilder/TestPanel.svelte"
|
||||||
|
|
||||||
|
$: automation =
|
||||||
|
$automationStore.selectedAutomation?.automation ||
|
||||||
|
$automationStore.automations[0]
|
||||||
|
|
||||||
let modal
|
let modal
|
||||||
let webhookModal
|
let webhookModal
|
||||||
</script>
|
</script>
|
||||||
|
@ -39,6 +44,12 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if automation?.showTestPanel}
|
||||||
|
<div class="setup">
|
||||||
|
<TestPanel {automation} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
<CreateAutomationModal {webhookModal} />
|
<CreateAutomationModal {webhookModal} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -52,7 +63,9 @@
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
height: 0;
|
height: 0;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 260px minmax(510px, 1fr);
|
grid-auto-flow: column dense;
|
||||||
|
grid-template-columns: 260px minmax(510px, 1fr) fit-content(500px);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav {
|
.nav {
|
||||||
|
@ -64,17 +77,18 @@
|
||||||
border-right: var(--border-light);
|
border-right: var(--border-light);
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
padding-bottom: 60px;
|
padding-bottom: 60px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: var(--spacing-l) 40px;
|
padding-top: var(--spacing-l);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: var(--spacing-l);
|
gap: var(--spacing-l);
|
||||||
overflow: hidden;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.centered {
|
.centered {
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -92,4 +106,17 @@
|
||||||
.main {
|
.main {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.setup {
|
||||||
|
padding-top: var(--spectrum-global-dimension-size-200);
|
||||||
|
border-left: var(--border-light);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: var(--spacing-l);
|
||||||
|
background-color: var(--background);
|
||||||
|
grid-column: 3;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
async function login() {
|
async function login() {
|
||||||
try {
|
try {
|
||||||
await auth.login({
|
await auth.login({
|
||||||
username,
|
username: username.trim(),
|
||||||
password,
|
password,
|
||||||
})
|
})
|
||||||
if ($auth?.user?.forceResetPassword) {
|
if ($auth?.user?.forceResetPassword) {
|
||||||
|
@ -80,7 +80,9 @@
|
||||||
/>
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
<Layout gap="XS" noPadding>
|
<Layout gap="XS" noPadding>
|
||||||
<Button cta on:click={login}>Sign in to {company}</Button>
|
<Button cta disabled={!username && !password} on:click={login}
|
||||||
|
>Sign in to {company}</Button
|
||||||
|
>
|
||||||
<ActionButton quiet on:click={() => $goto("./forgot")}>
|
<ActionButton quiet on:click={() => $goto("./forgot")}>
|
||||||
Forgot password?
|
Forgot password?
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"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": "^1.0.167-alpha.8",
|
"@budibase/bbui": "^1.0.176-alpha.0",
|
||||||
"@budibase/frontend-core": "^1.0.167-alpha.8",
|
"@budibase/frontend-core": "^1.0.176-alpha.0",
|
||||||
"@budibase/string-templates": "^1.0.167-alpha.8",
|
"@budibase/string-templates": "^1.0.176-alpha.0",
|
||||||
"@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": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"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": "^1.0.167-alpha.8",
|
"@budibase/bbui": "^1.0.176-alpha.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ ENV BUDIBASE_ENVIRONMENT=PRODUCTION
|
||||||
# copy files and install dependencies
|
# copy files and install dependencies
|
||||||
COPY . ./
|
COPY . ./
|
||||||
RUN yarn
|
RUN yarn
|
||||||
|
RUN yarn global add pm2
|
||||||
RUN yarn build
|
RUN yarn build
|
||||||
|
|
||||||
# Install client for oracle datasource
|
# Install client for oracle datasource
|
||||||
|
@ -28,4 +29,5 @@ EXPOSE 4001
|
||||||
# due to this causing yarn to stop installing dev dependencies
|
# due to this causing yarn to stop installing dev dependencies
|
||||||
# which are actually needed to get this environment up and running
|
# which are actually needed to get this environment up and running
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
CMD ["yarn", "run:docker"]
|
ENV CLUSTER_MODE=${CLUSTER_MODE}
|
||||||
|
CMD ["./docker_run.sh"]
|
||||||
|
|
|
@ -14,7 +14,9 @@ module PgMock {
|
||||||
function Client() {}
|
function Client() {}
|
||||||
|
|
||||||
Client.prototype.query = query
|
Client.prototype.query = query
|
||||||
Client.prototype.end = jest.fn()
|
Client.prototype.end = jest.fn(cb => {
|
||||||
|
if (cb) cb()
|
||||||
|
})
|
||||||
Client.prototype.connect = jest.fn()
|
Client.prototype.connect = jest.fn()
|
||||||
Client.prototype.release = jest.fn()
|
Client.prototype.release = jest.fn()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
if [ -z $CLUSTER_MODE ]; then
|
||||||
|
yarn run:docker
|
||||||
|
else
|
||||||
|
yarn run:docker:cluster
|
||||||
|
fi
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
"build:docker": "yarn run predocker && docker build . -t app-service --label version=$BUDIBASE_RELEASE_VERSION",
|
"build:docker": "yarn run predocker && docker build . -t app-service --label version=$BUDIBASE_RELEASE_VERSION",
|
||||||
"build:docs": "node ./scripts/docs/generate.js open",
|
"build:docs": "node ./scripts/docs/generate.js open",
|
||||||
"run:docker": "node dist/index.js",
|
"run:docker": "node dist/index.js",
|
||||||
|
"run:docker:cluster": "pm2-runtime start pm2.config.js",
|
||||||
"dev:stack:up": "node scripts/dev/manage.js up",
|
"dev:stack:up": "node scripts/dev/manage.js up",
|
||||||
"dev:stack:down": "node scripts/dev/manage.js down",
|
"dev:stack:down": "node scripts/dev/manage.js down",
|
||||||
"dev:stack:nuke": "node scripts/dev/manage.js nuke",
|
"dev:stack:nuke": "node scripts/dev/manage.js nuke",
|
||||||
|
@ -69,10 +70,10 @@
|
||||||
"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": "^1.0.167-alpha.8",
|
"@budibase/backend-core": "^1.0.176-alpha.0",
|
||||||
"@budibase/client": "^1.0.167-alpha.8",
|
"@budibase/client": "^1.0.176-alpha.0",
|
||||||
"@budibase/pro": "1.0.167-alpha.8",
|
"@budibase/pro": "1.0.176-alpha.0",
|
||||||
"@budibase/string-templates": "^1.0.167-alpha.8",
|
"@budibase/string-templates": "^1.0.176-alpha.0",
|
||||||
"@bull-board/api": "^3.7.0",
|
"@bull-board/api": "^3.7.0",
|
||||||
"@bull-board/koa": "^3.7.0",
|
"@bull-board/koa": "^3.7.0",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
script: "dist/index.js",
|
||||||
|
instances: "max",
|
||||||
|
exec_mode: "cluster",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
// get the JWT secret etc
|
||||||
|
require("../../src/environment")
|
||||||
|
require("@budibase/backend-core").init()
|
||||||
|
const {
|
||||||
|
getProdAppID,
|
||||||
|
generateGlobalUserID,
|
||||||
|
} = require("@budibase/backend-core/db")
|
||||||
|
const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||||
|
const { internalSaveUser } = require("@budibase/backend-core/utils")
|
||||||
|
const { publicApiUserFix } = require("../../src/utilities/users")
|
||||||
|
const { hash } = require("@budibase/backend-core/utils")
|
||||||
|
|
||||||
|
const USER_LOAD_NUMBER = 10000
|
||||||
|
const BATCH_SIZE = 200
|
||||||
|
const PASSWORD = "test"
|
||||||
|
const TENANT_ID = "default"
|
||||||
|
|
||||||
|
const APP_ID = process.argv[2]
|
||||||
|
|
||||||
|
const words = [
|
||||||
|
"test",
|
||||||
|
"testing",
|
||||||
|
"budi",
|
||||||
|
"mail",
|
||||||
|
"age",
|
||||||
|
"risk",
|
||||||
|
"load",
|
||||||
|
"uno",
|
||||||
|
"arm",
|
||||||
|
"leg",
|
||||||
|
"pen",
|
||||||
|
"glass",
|
||||||
|
"box",
|
||||||
|
"chicken",
|
||||||
|
"bottle",
|
||||||
|
]
|
||||||
|
|
||||||
|
if (!APP_ID) {
|
||||||
|
console.error("Must supply app ID as first CLI option!")
|
||||||
|
process.exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const WORD_1 = words[Math.floor(Math.random() * words.length)]
|
||||||
|
const WORD_2 = words[Math.floor(Math.random() * words.length)]
|
||||||
|
let HASHED_PASSWORD
|
||||||
|
|
||||||
|
function generateUser(count) {
|
||||||
|
return {
|
||||||
|
_id: generateGlobalUserID(),
|
||||||
|
password: HASHED_PASSWORD,
|
||||||
|
email: `${WORD_1}${count}@${WORD_2}.com`,
|
||||||
|
roles: {
|
||||||
|
[getProdAppID(APP_ID)]: "BASIC",
|
||||||
|
},
|
||||||
|
status: "active",
|
||||||
|
forceResetPassword: false,
|
||||||
|
firstName: "John",
|
||||||
|
lastName: "Smith",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
HASHED_PASSWORD = await hash(PASSWORD)
|
||||||
|
return doInTenant(TENANT_ID, async () => {
|
||||||
|
const db = getGlobalDB()
|
||||||
|
for (let i = 0; i < USER_LOAD_NUMBER; i += BATCH_SIZE) {
|
||||||
|
let userSavePromises = []
|
||||||
|
for (let j = 0; j < BATCH_SIZE; j++) {
|
||||||
|
// like the public API
|
||||||
|
const ctx = publicApiUserFix({
|
||||||
|
request: {
|
||||||
|
body: generateUser(i + j),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
userSavePromises.push(
|
||||||
|
internalSaveUser(ctx.request.body, TENANT_ID, {
|
||||||
|
hashPassword: false,
|
||||||
|
requirePassword: true,
|
||||||
|
bulkCreate: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const users = await Promise.all(userSavePromises)
|
||||||
|
await db.bulkDocs(users)
|
||||||
|
console.log(`${i + BATCH_SIZE} users have been created.`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
.then(() => {
|
||||||
|
console.log(`Generated ${USER_LOAD_NUMBER} users!`)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Failed for reason: ", err)
|
||||||
|
process.exit(-1)
|
||||||
|
})
|
|
@ -25,6 +25,7 @@ const {
|
||||||
import { BASE_LAYOUTS } from "../../constants/layouts"
|
import { BASE_LAYOUTS } from "../../constants/layouts"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
const { processObject } = require("@budibase/string-templates")
|
const { processObject } = require("@budibase/string-templates")
|
||||||
|
const { CacheKeys, bustCache } = require("@budibase/backend-core/cache")
|
||||||
const {
|
const {
|
||||||
getAllApps,
|
getAllApps,
|
||||||
isDevAppID,
|
isDevAppID,
|
||||||
|
@ -326,6 +327,7 @@ const appPostCreate = async (ctx: any, appId: string) => {
|
||||||
export const create = async (ctx: any) => {
|
export const create = async (ctx: any) => {
|
||||||
const newApplication = await quotas.addApp(() => performAppCreate(ctx))
|
const newApplication = await quotas.addApp(() => performAppCreate(ctx))
|
||||||
await appPostCreate(ctx, newApplication.appId)
|
await appPostCreate(ctx, newApplication.appId)
|
||||||
|
await bustCache(CacheKeys.CHECKLIST)
|
||||||
ctx.body = newApplication
|
ctx.body = newApplication
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
@ -449,6 +451,15 @@ export const destroy = async (ctx: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sync = async (ctx: any, next: any) => {
|
export const sync = async (ctx: any, next: any) => {
|
||||||
|
if (env.DISABLE_AUTO_PROD_APP_SYNC) {
|
||||||
|
ctx.status = 200
|
||||||
|
ctx.body = {
|
||||||
|
message:
|
||||||
|
"App sync disabled. You can reenable with the DISABLE_AUTO_PROD_APP_SYNC environment variable.",
|
||||||
|
}
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
if (!isDevAppID(appId)) {
|
if (!isDevAppID(appId)) {
|
||||||
ctx.throw(400, "This action cannot be performed for production apps")
|
ctx.throw(400, "This action cannot be performed for production apps")
|
||||||
|
|
|
@ -4,30 +4,9 @@ import {
|
||||||
readGlobalUser,
|
readGlobalUser,
|
||||||
saveGlobalUser,
|
saveGlobalUser,
|
||||||
} from "../../../utilities/workerRequests"
|
} from "../../../utilities/workerRequests"
|
||||||
|
import { publicApiUserFix } from "../../../utilities/users"
|
||||||
import { search as stringSearch } from "./utils"
|
import { search as stringSearch } from "./utils"
|
||||||
|
|
||||||
const { getProdAppID } = require("@budibase/backend-core/db")
|
|
||||||
|
|
||||||
function fixUser(ctx: any) {
|
|
||||||
if (!ctx.request.body) {
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
if (!ctx.request.body._id && ctx.params.userId) {
|
|
||||||
ctx.request.body._id = ctx.params.userId
|
|
||||||
}
|
|
||||||
if (!ctx.request.body.roles) {
|
|
||||||
ctx.request.body.roles = {}
|
|
||||||
} else {
|
|
||||||
const newRoles: { [key: string]: string } = {}
|
|
||||||
for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
|
|
||||||
// @ts-ignore
|
|
||||||
newRoles[getProdAppID(appId)] = role
|
|
||||||
}
|
|
||||||
ctx.request.body.roles = newRoles
|
|
||||||
}
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUser(ctx: any, userId?: string) {
|
function getUser(ctx: any, userId?: string) {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
ctx.params = { userId }
|
ctx.params = { userId }
|
||||||
|
@ -45,7 +24,7 @@ export async function search(ctx: any, next: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create(ctx: any, next: any) {
|
export async function create(ctx: any, next: any) {
|
||||||
const response = await saveGlobalUser(fixUser(ctx))
|
const response = await saveGlobalUser(publicApiUserFix(ctx))
|
||||||
ctx.body = await getUser(ctx, response._id)
|
ctx.body = await getUser(ctx, response._id)
|
||||||
await next()
|
await next()
|
||||||
}
|
}
|
||||||
|
@ -61,7 +40,7 @@ export async function update(ctx: any, next: any) {
|
||||||
...ctx.request.body,
|
...ctx.request.body,
|
||||||
_rev: user._rev,
|
_rev: user._rev,
|
||||||
}
|
}
|
||||||
const response = await saveGlobalUser(fixUser(ctx))
|
const response = await saveGlobalUser(publicApiUserFix(ctx))
|
||||||
ctx.body = await getUser(ctx, response._id)
|
ctx.body = await getUser(ctx, response._id)
|
||||||
await next()
|
await next()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const { join } = require("path")
|
||||||
|
|
||||||
function isTest() {
|
function isTest() {
|
||||||
return (
|
return (
|
||||||
process.env.NODE_ENV === "jest" ||
|
process.env.NODE_ENV === "jest" ||
|
||||||
|
@ -20,7 +22,9 @@ function isCypress() {
|
||||||
|
|
||||||
let LOADED = false
|
let LOADED = false
|
||||||
if (!LOADED && isDev() && !isTest()) {
|
if (!LOADED && isDev() && !isTest()) {
|
||||||
require("dotenv").config()
|
require("dotenv").config({
|
||||||
|
path: join(__dirname, "..", ".env"),
|
||||||
|
})
|
||||||
LOADED = true
|
LOADED = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +59,7 @@ module.exports = {
|
||||||
BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT,
|
BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT,
|
||||||
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
|
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
|
||||||
TEMPLATE_REPOSITORY: process.env.TEMPLATE_REPOSITORY || "app",
|
TEMPLATE_REPOSITORY: process.env.TEMPLATE_REPOSITORY || "app",
|
||||||
|
DISABLE_AUTO_PROD_APP_SYNC: process.env.DISABLE_AUTO_PROD_APP_SYNC,
|
||||||
// minor
|
// minor
|
||||||
SALT_ROUNDS: process.env.SALT_ROUNDS,
|
SALT_ROUNDS: process.env.SALT_ROUNDS,
|
||||||
LOGGER: process.env.LOGGER,
|
LOGGER: process.env.LOGGER,
|
||||||
|
|
|
@ -136,7 +136,7 @@ module PostgresModule {
|
||||||
: undefined,
|
: undefined,
|
||||||
}
|
}
|
||||||
this.client = new Client(newConfig)
|
this.client = new Client(newConfig)
|
||||||
this.setSchema()
|
this.open = false
|
||||||
}
|
}
|
||||||
|
|
||||||
getBindingIdentifier(): string {
|
getBindingIdentifier(): string {
|
||||||
|
@ -147,7 +147,34 @@ module PostgresModule {
|
||||||
return parts.join(" || ")
|
return parts.join(" || ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async openConnection() {
|
||||||
|
await this.client.connect()
|
||||||
|
if (!this.config.schema) {
|
||||||
|
this.config.schema = "public"
|
||||||
|
}
|
||||||
|
this.client.query(`SET search_path TO ${this.config.schema}`)
|
||||||
|
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
|
||||||
|
this.open = true
|
||||||
|
}
|
||||||
|
|
||||||
|
closeConnection() {
|
||||||
|
const pg = this
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
this.client.end((err: any) => {
|
||||||
|
pg.open = false
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async internalQuery(query: SqlQuery, close: boolean = true) {
|
async internalQuery(query: SqlQuery, close: boolean = true) {
|
||||||
|
if (!this.open) {
|
||||||
|
await this.openConnection()
|
||||||
|
}
|
||||||
const client = this.client
|
const client = this.client
|
||||||
this.index = 1
|
this.index = 1
|
||||||
// need to handle a specific issue with json data types in postgres,
|
// need to handle a specific issue with json data types in postgres,
|
||||||
|
@ -164,21 +191,14 @@ module PostgresModule {
|
||||||
try {
|
try {
|
||||||
return await client.query(query.sql, query.bindings || [])
|
return await client.query(query.sql, query.bindings || [])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.client.end()
|
await this.closeConnection()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
throw new Error(err)
|
throw new Error(err)
|
||||||
} finally {
|
} finally {
|
||||||
if (close) await this.client.end()
|
if (close) {
|
||||||
|
await this.closeConnection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSchema() {
|
|
||||||
await this.client.connect()
|
|
||||||
if (!this.config.schema) {
|
|
||||||
this.config.schema = "public"
|
|
||||||
}
|
|
||||||
this.client.query(`SET search_path TO ${this.config.schema}`)
|
|
||||||
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,6 +208,7 @@ module PostgresModule {
|
||||||
*/
|
*/
|
||||||
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
||||||
let tableKeys: { [key: string]: string[] } = {}
|
let tableKeys: { [key: string]: string[] } = {}
|
||||||
|
await this.openConnection()
|
||||||
try {
|
try {
|
||||||
const primaryKeysResponse = await this.client.query(
|
const primaryKeysResponse = await this.client.query(
|
||||||
this.PRIMARY_KEYS_SQL
|
this.PRIMARY_KEYS_SQL
|
||||||
|
@ -251,7 +272,7 @@ module PostgresModule {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
throw new Error(err)
|
throw new Error(err)
|
||||||
} finally {
|
} finally {
|
||||||
await this.client.end()
|
await this.closeConnection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +304,7 @@ module PostgresModule {
|
||||||
for (let query of input) {
|
for (let query of input) {
|
||||||
responses.push(await this.internalQuery(query, false))
|
responses.push(await this.internalQuery(query, false))
|
||||||
}
|
}
|
||||||
await this.client.end()
|
await this.closeConnection()
|
||||||
return responses
|
return responses
|
||||||
} else {
|
} else {
|
||||||
const response = await this.internalQuery(input)
|
const response = await this.internalQuery(input)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const { InternalTables } = require("../db/utils")
|
const { InternalTables } = require("../db/utils")
|
||||||
const { getGlobalUser } = require("../utilities/global")
|
const { getGlobalUser } = require("../utilities/global")
|
||||||
const { getAppDB } = require("@budibase/backend-core/context")
|
const { getAppDB } = require("@budibase/backend-core/context")
|
||||||
|
const { getProdAppID } = require("@budibase/backend-core/db")
|
||||||
|
|
||||||
exports.getFullUser = async (ctx, userId) => {
|
exports.getFullUser = async (ctx, userId) => {
|
||||||
const global = await getGlobalUser(userId)
|
const global = await getGlobalUser(userId)
|
||||||
|
@ -22,3 +23,23 @@ exports.getFullUser = async (ctx, userId) => {
|
||||||
_id: userId,
|
_id: userId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.publicApiUserFix = ctx => {
|
||||||
|
if (!ctx.request.body) {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
if (!ctx.request.body._id && ctx.params.userId) {
|
||||||
|
ctx.request.body._id = ctx.params.userId
|
||||||
|
}
|
||||||
|
if (!ctx.request.body.roles) {
|
||||||
|
ctx.request.body.roles = {}
|
||||||
|
} else {
|
||||||
|
const newRoles = {}
|
||||||
|
for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
|
||||||
|
// @ts-ignore
|
||||||
|
newRoles[getProdAppID(appId)] = role
|
||||||
|
}
|
||||||
|
ctx.request.body.roles = newRoles
|
||||||
|
}
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
|
@ -1014,10 +1014,10 @@
|
||||||
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@1.0.167-alpha.8":
|
"@budibase/backend-core@1.0.176-alpha.0":
|
||||||
version "1.0.167-alpha.8"
|
version "1.0.176-alpha.0"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.8.tgz#e663928587cb3ec90d06b3c5766fce61c11e93a6"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.176-alpha.0.tgz#eca4d405f6a3feadc231ce851323005762b83b88"
|
||||||
integrity sha512-J4LtucuaJJd5lAs9mV6Rt9D5dCZhKNrrKajnFTXqOrjsyw0jsIfN2ku8ClV0C9J3NA3wAu2zjpfDaKSnNfg2OQ==
|
integrity sha512-7GFAO499/rX/066jpChEH2CwOo+UI88MrZcceWqfbv3hBcV4nDUtVFUtzG63z74vQb9SHi0B15/qOYB5mzVQLw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@techpass/passport-openidconnect" "^0.3.0"
|
"@techpass/passport-openidconnect" "^0.3.0"
|
||||||
aws-sdk "^2.901.0"
|
aws-sdk "^2.901.0"
|
||||||
|
@ -1092,12 +1092,12 @@
|
||||||
svelte-flatpickr "^3.2.3"
|
svelte-flatpickr "^3.2.3"
|
||||||
svelte-portal "^1.0.0"
|
svelte-portal "^1.0.0"
|
||||||
|
|
||||||
"@budibase/pro@1.0.167-alpha.8":
|
"@budibase/pro@1.0.176-alpha.0":
|
||||||
version "1.0.167-alpha.8"
|
version "1.0.176-alpha.0"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.8.tgz#dfcecb85550bc07a89b8e0bd2dbff13543d99117"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.176-alpha.0.tgz#416522800ef47b6ccc9e8bfc0e8d722db54f5c68"
|
||||||
integrity sha512-MPEtYLnHfFchBzQs5nZSAavCANh32hd1VSXUB5KJSkEdtpQ9eoJ+hOGThrM9PJtTVX3Jq31nsg0/PmUkswBdAQ==
|
integrity sha512-oe/HQsDpGZ3HO7t0TPqfKfh/FjZw5f9V22LxS45WXoOgL8b66U2WGwCaN7iF/zzxgPXlZ3h8TSHo9ai9d2UOgA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.0.167-alpha.8"
|
"@budibase/backend-core" "1.0.176-alpha.0"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@budibase/standard-components@^0.9.139":
|
"@budibase/standard-components@^0.9.139":
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"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",
|
||||||
|
|
|
@ -10,6 +10,7 @@ WORKDIR /app
|
||||||
# copy files and install dependencies
|
# copy files and install dependencies
|
||||||
COPY . ./
|
COPY . ./
|
||||||
RUN yarn
|
RUN yarn
|
||||||
|
RUN yarn global add pm2
|
||||||
|
|
||||||
EXPOSE 4001
|
EXPOSE 4001
|
||||||
|
|
||||||
|
@ -17,4 +18,5 @@ EXPOSE 4001
|
||||||
# due to this causing yarn to stop installing dev dependencies
|
# due to this causing yarn to stop installing dev dependencies
|
||||||
# which are actually needed to get this environment up and running
|
# which are actually needed to get this environment up and running
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
CMD ["yarn", "run:docker"]
|
ENV CLUSTER_MODE=${CLUSTER_MODE}
|
||||||
|
CMD ["./docker_run.sh"]
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
if [[ -z $CLUSTER_MODE ]]; then
|
||||||
|
yarn run:docker
|
||||||
|
else
|
||||||
|
yarn run:docker:cluster
|
||||||
|
fi
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.0.167-alpha.8",
|
"version": "1.0.176-alpha.0",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
"build": "rimraf dist/ && tsc",
|
"build": "rimraf dist/ && tsc",
|
||||||
"postbuild": "copyfiles -u 1 src/**/*.hbs dist/",
|
"postbuild": "copyfiles -u 1 src/**/*.hbs dist/",
|
||||||
"run:docker": "node dist/index.js",
|
"run:docker": "node dist/index.js",
|
||||||
|
"run:docker:cluster": "pm2-runtime start pm2.config.js",
|
||||||
"build:docker": "docker build . -t worker-service --label version=$BUDIBASE_RELEASE_VERSION",
|
"build:docker": "docker build . -t worker-service --label version=$BUDIBASE_RELEASE_VERSION",
|
||||||
"dev:stack:init": "node ./scripts/dev/manage.js init",
|
"dev:stack:init": "node ./scripts/dev/manage.js init",
|
||||||
"dev:builder": "npm run dev:stack:init && nodemon",
|
"dev:builder": "npm run dev:stack:init && nodemon",
|
||||||
|
@ -31,9 +32,9 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "^1.0.167-alpha.8",
|
"@budibase/backend-core": "^1.0.176-alpha.0",
|
||||||
"@budibase/pro": "1.0.167-alpha.8",
|
"@budibase/pro": "1.0.176-alpha.0",
|
||||||
"@budibase/string-templates": "^1.0.167-alpha.8",
|
"@budibase/string-templates": "^1.0.176-alpha.0",
|
||||||
"@koa/router": "^8.0.0",
|
"@koa/router": "^8.0.0",
|
||||||
"@sentry/node": "6.17.7",
|
"@sentry/node": "6.17.7",
|
||||||
"@techpass/passport-openidconnect": "^0.3.0",
|
"@techpass/passport-openidconnect": "^0.3.0",
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
script: "./dist/index.js",
|
||||||
|
instances: "max",
|
||||||
|
exec_mode: "cluster",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -14,6 +14,11 @@ const {
|
||||||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
const { googleCallbackUrl, oidcCallbackUrl } = require("./auth")
|
const { googleCallbackUrl, oidcCallbackUrl } = require("./auth")
|
||||||
|
const {
|
||||||
|
withCache,
|
||||||
|
CacheKeys,
|
||||||
|
bustCache,
|
||||||
|
} = require("@budibase/backend-core/cache")
|
||||||
|
|
||||||
const BB_TENANT_CDN = "https://tenants.cdn.budi.live"
|
const BB_TENANT_CDN = "https://tenants.cdn.budi.live"
|
||||||
|
|
||||||
|
@ -43,6 +48,7 @@ exports.save = async function (ctx) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await db.put(ctx.request.body)
|
const response = await db.put(ctx.request.body)
|
||||||
|
await bustCache(CacheKeys.CHECKLIST)
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
type,
|
type,
|
||||||
_id: response.id,
|
_id: response.id,
|
||||||
|
@ -249,8 +255,10 @@ exports.configChecklist = async function (ctx) {
|
||||||
const tenantId = getTenantId()
|
const tenantId = getTenantId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: Watch get started video
|
ctx.body = await withCache(
|
||||||
|
CacheKeys.CHECKLIST,
|
||||||
|
env.CHECKLIST_CACHE_TTL,
|
||||||
|
async () => {
|
||||||
let apps = []
|
let apps = []
|
||||||
if (!env.MULTI_TENANCY || tenantId) {
|
if (!env.MULTI_TENANCY || tenantId) {
|
||||||
// Apps exist
|
// Apps exist
|
||||||
|
@ -271,15 +279,15 @@ exports.configChecklist = async function (ctx) {
|
||||||
const oidcConfig = await getScopedFullConfig(db, {
|
const oidcConfig = await getScopedFullConfig(db, {
|
||||||
type: Configs.OIDC,
|
type: Configs.OIDC,
|
||||||
})
|
})
|
||||||
|
|
||||||
// They have set up an global user
|
// They have set up an global user
|
||||||
const users = await db.allDocs(
|
const users = await db.allDocs(
|
||||||
getGlobalUserParams(null, {
|
getGlobalUserParams(null, {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
|
limit: 1,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
const adminUser = users.rows.some(row => row.doc.admin)
|
return {
|
||||||
|
|
||||||
ctx.body = {
|
|
||||||
apps: {
|
apps: {
|
||||||
checked: apps.length > 0,
|
checked: apps.length > 0,
|
||||||
label: "Create your first app",
|
label: "Create your first app",
|
||||||
|
@ -291,7 +299,7 @@ exports.configChecklist = async function (ctx) {
|
||||||
link: "/builder/portal/manage/email",
|
link: "/builder/portal/manage/email",
|
||||||
},
|
},
|
||||||
adminUser: {
|
adminUser: {
|
||||||
checked: adminUser,
|
checked: users && users.rows.length >= 1,
|
||||||
label: "Create your first user",
|
label: "Create your first user",
|
||||||
link: "/builder/portal/manage/users",
|
link: "/builder/portal/manage/users",
|
||||||
},
|
},
|
||||||
|
@ -301,6 +309,8 @@ exports.configChecklist = async function (ctx) {
|
||||||
link: "/builder/portal/manage/auth",
|
link: "/builder/portal/manage/auth",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(err.status, err)
|
ctx.throw(err.status, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,6 @@ const {
|
||||||
StaticDatabases,
|
StaticDatabases,
|
||||||
} = require("@budibase/backend-core/db")
|
} = require("@budibase/backend-core/db")
|
||||||
const { getGlobalUserByEmail } = require("@budibase/backend-core/utils")
|
const { getGlobalUserByEmail } = require("@budibase/backend-core/utils")
|
||||||
import { EmailTemplatePurpose } from "../../../constants"
|
|
||||||
import { checkInviteCode } from "../../../utilities/redis"
|
|
||||||
import { sendEmail } from "../../../utilities/email"
|
|
||||||
const { user: userCache } = require("@budibase/backend-core/cache")
|
const { user: userCache } = require("@budibase/backend-core/cache")
|
||||||
const { invalidateSessions } = require("@budibase/backend-core/sessions")
|
const { invalidateSessions } = require("@budibase/backend-core/sessions")
|
||||||
const accounts = require("@budibase/backend-core/accounts")
|
const accounts = require("@budibase/backend-core/accounts")
|
||||||
|
@ -17,11 +14,15 @@ const {
|
||||||
doesTenantExist,
|
doesTenantExist,
|
||||||
} = require("@budibase/backend-core/tenancy")
|
} = require("@budibase/backend-core/tenancy")
|
||||||
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
|
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
|
||||||
|
const { errors } = require("@budibase/backend-core")
|
||||||
|
const { CacheKeys, bustCache } = require("@budibase/backend-core/cache")
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { syncUserInApps } from "../../../utilities/appService"
|
import { syncUserInApps } from "../../../utilities/appService"
|
||||||
import { quotas, users } from "@budibase/pro"
|
import { quotas, users } from "@budibase/pro"
|
||||||
const { errors } = require("@budibase/backend-core")
|
|
||||||
import { allUsers, getUser } from "../../utilities"
|
import { allUsers, getUser } from "../../utilities"
|
||||||
|
import { EmailTemplatePurpose } from "../../../constants"
|
||||||
|
import { checkInviteCode } from "../../../utilities/redis"
|
||||||
|
import { sendEmail } from "../../../utilities/email"
|
||||||
|
|
||||||
export const save = async (ctx: any) => {
|
export const save = async (ctx: any) => {
|
||||||
try {
|
try {
|
||||||
|
@ -93,7 +94,14 @@ export const adminUser = async (ctx: any) => {
|
||||||
tenantId,
|
tenantId,
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ctx.body = await users.save(user, tenantId, hashPassword, requirePassword)
|
const finalUser = await users.save(
|
||||||
|
user,
|
||||||
|
tenantId,
|
||||||
|
hashPassword,
|
||||||
|
requirePassword
|
||||||
|
)
|
||||||
|
await bustCache(CacheKeys.CHECKLIST)
|
||||||
|
ctx.body = finalUser
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
ctx.throw(err.status || 400, err)
|
ctx.throw(err.status || 400, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const { join } = require("path")
|
||||||
|
|
||||||
function isDev() {
|
function isDev() {
|
||||||
return process.env.NODE_ENV !== "production"
|
return process.env.NODE_ENV !== "production"
|
||||||
}
|
}
|
||||||
|
@ -12,10 +14,18 @@ function isTest() {
|
||||||
|
|
||||||
let LOADED = false
|
let LOADED = false
|
||||||
if (!LOADED && isDev() && !isTest()) {
|
if (!LOADED && isDev() && !isTest()) {
|
||||||
require("dotenv").config()
|
require("dotenv").config({
|
||||||
|
path: join(__dirname, "..", ".env"),
|
||||||
|
})
|
||||||
LOADED = true
|
LOADED = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseIntSafe(number) {
|
||||||
|
if (number) {
|
||||||
|
return parseInt(number)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// auth
|
// auth
|
||||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||||
|
@ -49,6 +59,8 @@ module.exports = {
|
||||||
SMTP_HOST: process.env.SMTP_HOST,
|
SMTP_HOST: process.env.SMTP_HOST,
|
||||||
SMTP_PORT: process.env.SMTP_PORT,
|
SMTP_PORT: process.env.SMTP_PORT,
|
||||||
SMTP_FROM_ADDRESS: process.env.SMTP_FROM_ADDRESS,
|
SMTP_FROM_ADDRESS: process.env.SMTP_FROM_ADDRESS,
|
||||||
|
// other
|
||||||
|
CHECKLIST_CACHE_TTL: parseIntSafe(process.env.CHECKLIST_CACHE_TTL) || 3600,
|
||||||
_set(key, value) {
|
_set(key, value) {
|
||||||
process.env[key] = value
|
process.env[key] = value
|
||||||
module.exports[key] = value
|
module.exports[key] = value
|
||||||
|
|
|
@ -61,6 +61,7 @@ exports.shutdown = async () => {
|
||||||
* Given a user ID this will store a code (that is returned) for an hour in redis.
|
* Given a user ID this will store a code (that is returned) for an hour in redis.
|
||||||
* The user can then return this code for resetting their password (through their reset link).
|
* The user can then return this code for resetting their password (through their reset link).
|
||||||
* @param {string} userId the ID of the user which is to be reset.
|
* @param {string} userId the ID of the user which is to be reset.
|
||||||
|
* @param {object} info Info about the user/the reset process.
|
||||||
* @return {Promise<string>} returns the code that was stored to redis.
|
* @return {Promise<string>} returns the code that was stored to redis.
|
||||||
*/
|
*/
|
||||||
exports.getResetPasswordCode = async (userId, info) => {
|
exports.getResetPasswordCode = async (userId, info) => {
|
||||||
|
|
|
@ -293,10 +293,10 @@
|
||||||
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@1.0.167-alpha.8":
|
"@budibase/backend-core@1.0.176-alpha.0":
|
||||||
version "1.0.167-alpha.8"
|
version "1.0.176-alpha.0"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.8.tgz#e663928587cb3ec90d06b3c5766fce61c11e93a6"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.176-alpha.0.tgz#eca4d405f6a3feadc231ce851323005762b83b88"
|
||||||
integrity sha512-J4LtucuaJJd5lAs9mV6Rt9D5dCZhKNrrKajnFTXqOrjsyw0jsIfN2ku8ClV0C9J3NA3wAu2zjpfDaKSnNfg2OQ==
|
integrity sha512-7GFAO499/rX/066jpChEH2CwOo+UI88MrZcceWqfbv3hBcV4nDUtVFUtzG63z74vQb9SHi0B15/qOYB5mzVQLw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@techpass/passport-openidconnect" "^0.3.0"
|
"@techpass/passport-openidconnect" "^0.3.0"
|
||||||
aws-sdk "^2.901.0"
|
aws-sdk "^2.901.0"
|
||||||
|
@ -322,12 +322,12 @@
|
||||||
uuid "^8.3.2"
|
uuid "^8.3.2"
|
||||||
zlib "^1.0.5"
|
zlib "^1.0.5"
|
||||||
|
|
||||||
"@budibase/pro@1.0.167-alpha.8":
|
"@budibase/pro@1.0.176-alpha.0":
|
||||||
version "1.0.167-alpha.8"
|
version "1.0.176-alpha.0"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.8.tgz#dfcecb85550bc07a89b8e0bd2dbff13543d99117"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.176-alpha.0.tgz#416522800ef47b6ccc9e8bfc0e8d722db54f5c68"
|
||||||
integrity sha512-MPEtYLnHfFchBzQs5nZSAavCANh32hd1VSXUB5KJSkEdtpQ9eoJ+hOGThrM9PJtTVX3Jq31nsg0/PmUkswBdAQ==
|
integrity sha512-oe/HQsDpGZ3HO7t0TPqfKfh/FjZw5f9V22LxS45WXoOgL8b66U2WGwCaN7iF/zzxgPXlZ3h8TSHo9ai9d2UOgA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.0.167-alpha.8"
|
"@budibase/backend-core" "1.0.176-alpha.0"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@cspotcode/source-map-consumer@0.8.0":
|
"@cspotcode/source-map-consumer@0.8.0":
|
||||||
|
|
Loading…
Reference in New Issue